Dev

From Obyte Wiki
Revision as of 22:35, 10 March 2018 by Slackjore (talk | contribs) (copypasta: needs dev tweaking to show correct code colours)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Byteball address validation in C++

<syntaxhighlight lang="cpp">
#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#include <type_traits>

bool is_byteball_addr(const char *addr) {
    static const unsigned char offsets[] = {
          1,   5,   6,  11,  20,  22,  28,  33,
         36,  41,  49,  58,  65,  74,  77,  79,
         82,  90,  94, 100, 102, 108, 112, 115,
        118, 126, 129, 131, 138, 147, 152, 154
    };
    const size_t offsets_sz = std::extent<decltype(offsets)>::value;
    bool bits[32*5];
    unsigned char data[16];
    unsigned char checksum[4];

    { // Base32 validation and decoding.
        auto b32 = [](char c) -> unsigned char {
            return ( (c >= 65 && c <= 90) ? (unsigned char) (     c - 65) :
                     (c >= 50 && c <= 55) ? (unsigned char) (26 + c - 50) : 255 );
        };

        auto isb32 = [](char c) -> bool {
            return ( (c >= 65 && c <= 90) || (c >= 50 && c <= 55) );
        };

        size_t i = 0;
        char *c = (char *) &(*addr);
        while (isb32(*c) && i < 32) {
            unsigned char value = b32(*c++);
            for (size_t j=0; j<5; ++j) {
                bool bit = (value % 2);
                value /= 2;
                bits[5*i + (4-j)] = bit;
            }
            ++i;
        }
        if (i != 32 || *c) return false;
    }

    { // Separation of the checksum from the clean data.
        auto bits2bytes = [](bool *b, unsigned char *B, size_t sz) -> void {
            for (size_t i=0; i<sz; ++i) {
                unsigned char byte = 0;
                for (size_t j=0; j<8; ++j) {
                    bool bit = b[i*8 + j];
                    byte ^= (unsigned char) ( (-bit ^ byte) & (1 << (7-j)) );
                }
                B[i] = byte;
            }
        };

        bool data_bits[128];
        bool checksum_bits[32];
        size_t start = 0;
        size_t data_bit_i = 0;
        size_t checksum_bit_i = 0;
        for (size_t i=0; i<offsets_sz; ++i) {
            for (size_t j=start; j<offsets[i]; ++j) {
                data_bits[data_bit_i++] = bits[j];
            }
            checksum_bits[checksum_bit_i++] = bits[offsets[i]];
            start = offsets[i]+1;
        }
        memcpy(data_bits+123, bits+155, 5); // Add last fragment.

        bits2bytes(data_bits, data, 16);
        bits2bytes(checksum_bits, checksum, 4);
    }

    { // Validate the checksum (requires the openssl/sha.h header).
        SHA256_CTX context;
        unsigned char md[SHA256_DIGEST_LENGTH];

        SHA256_Init(&context);
        SHA256_Update(&context, (unsigned char*) data, 16);
        SHA256_Final(md, &context);

        if (md[ 5] == checksum[0]
        &&  md[13] == checksum[1]
        &&  md[21] == checksum[2]
        &&  md[29] == checksum[3]) return true;
    }

    return false;
}

int main( int argc, char * argv [] ) {
    int i;

    for (i = 1; i < argc; ++i ) {
        bool valid = is_byteball_addr(argv[i]);
        printf( "%s is %s\n", argv[i], valid ? "VALID." : "INVALID!");
    }

    return 0;
}

</syntaxhighlight>

byteball github repo[1]

References