Ejemplo n.º 1
0
void test_ecc()
{
    unsigned char r_buf[32];
    memset(r_buf, 0, 32);
    random_init();

    while (btc_ecc_verify_privatekey(r_buf) == 0) {
        random_bytes(r_buf, 32, 0);
    }

    memset(r_buf, 0xFF, 32);
    u_assert_int_eq(btc_ecc_verify_privatekey(r_buf), 0); //secp256k1 overflow

    uint8_t pub_key33[33], pub_key33_invalid[33], pub_key65[65], pub_key65_invalid[65];

    memcpy(pub_key33, utils_hex_to_uint8("02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f"), 33);
    memcpy(pub_key33_invalid, utils_hex_to_uint8("999999999941bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f"), 33);
    memcpy(pub_key65, utils_hex_to_uint8("044054fd18aeb277aeedea01d3f3986ff4e5be18092a04339dcf4e524e2c0a09746c7083ed2097011b1223a17a644e81f59aa3de22dac119fd980b36a8ff29a244"), 65);
    memcpy(pub_key65_invalid, utils_hex_to_uint8("044054fd18aeb277aeedea01d3f3986ff4e5be18092a04339dcf4e524e2c0a09746c7083ed2097011b1223a17a644e81f59aa3de22dac119fd980b39999f29a244"), 65);


    u_assert_int_eq(btc_ecc_verify_pubkey(pub_key33, 1), 1);
    u_assert_int_eq(btc_ecc_verify_pubkey(pub_key65, 0), 1);

    u_assert_int_eq(btc_ecc_verify_pubkey(pub_key33_invalid, 1), 0);
    u_assert_int_eq(btc_ecc_verify_pubkey(pub_key65_invalid, 0), 0);

    btc_key key;
    btc_privkey_init(&key);
    assert(btc_privkey_is_valid(&key) == 0);
    btc_privkey_gen(&key);

    uint8_t* hash = utils_hex_to_uint8((const char*)"26db47a48a10b9b0b697b793f5c0231aa35fe192c9d063d7b03a55e3c302850a");
    unsigned char sig[74];
    size_t outlen = 74;
    btc_key_sign_hash(&key, hash, sig, &outlen);

    uint8_t sigcomp[64];
    unsigned char sigder[74];
    size_t sigderlen = 74;
    u_assert_int_eq(btc_ecc_der_to_compact(sig, outlen, sigcomp), true);
    u_assert_int_eq(btc_ecc_compact_to_der_normalized(sigcomp, sigder, &sigderlen),  true);
    u_assert_int_eq(outlen, sigderlen);
    u_assert_int_eq(memcmp(sig,sigder,sigderlen), 0);
}
Ejemplo n.º 2
0
void test_logdb(logdb_log_db* (*new_func)())
{
    logdb_log_db *db;
    enum logdb_error error = 0;
    struct buffer key = {"key0", 4};
    struct buffer value = {"val0", 4};
    struct buffer key1;
    struct buffer value1;
    cstring *outtest;
    cstring *value_test;
    unsigned char testbin[4] = {0x00, 0x10, 0x20, 0x30};
    struct buffer value0_new = {"dumb", 4};
    struct buffer key2 = {"pkey", 4};
    struct buffer value2;
    struct buffer smp_value;
    struct buffer smp_key;
    uint8_t txbin[10240];
    uint8_t txbin_rev[10240];
    char hexrev[98];
    int outlenrev;
    long fsize;
    char *buf;
    char *wrk_buf;
    FILE *f;
    unsigned int i;

    value2.p = testbin;
    value2.len = 4;

    key1.p = (char *)key1str;
    key1.len = strlen(key1str);
    value1.p = (char *)value1str;
    value1.len = strlen(value1str);

    unlink(dbtmpfile);
    db = new_func();
    u_assert_int_eq(logdb_load(db, "file_that_should_not_exists.dat", false, NULL), false);
    u_assert_int_eq(logdb_load(db, dbtmpfile, true, NULL), true);


    logdb_append(db, &key, &value);



    logdb_append(db, &key1, &value1);

    u_assert_int_eq(logdb_cache_size(db), 2);
    outtest = logdb_find_cache(db, &key1);
    u_assert_int_eq(strcmp(outtest->str, value1str),0);
    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);
    u_assert_int_eq(logdb_count_keys(db), 2);
    
    value_test = logdb_find(db, &key1);
    u_assert_int_eq(strcmp(value_test->str, value1str), 0);
    value_test = logdb_find(db, &key);
    u_assert_int_eq(memcmp(value_test->str, value.p, value.len), 0);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);



    logdb_append(db, &key2, &value2);
    logdb_flush(db);
    logdb_free(db);

    /* check if private key is available */
    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);

    value_test = logdb_find(db, &key2);
    u_assert_int_eq(memcmp(value_test->str, value2.p, value2.len), 0);
    value_test = logdb_find(db, &key);
    u_assert_int_eq(memcmp(value_test->str, value.p, value.len), 0);

    /* delete a record */
    logdb_delete(db, &key2);
    logdb_flush(db);
    logdb_free(db);

    /* find and check the deleted record */
    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);

    value_test = logdb_find(db, &key);
    u_assert_int_eq(memcmp(value_test->str, value.p, value.len), 0);

    value_test = logdb_find(db, &key2);
    u_assert_int_eq((int)value_test, 0); /* should be null */

    /* overwrite a key */
    logdb_append(db, &key, &value0_new);

    value_test = logdb_find(db, &key);
    u_assert_int_eq(memcmp(value_test->str, value0_new.p, value0_new.len), 0);

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);
    value_test = logdb_find(db, &key);
    u_assert_int_eq(memcmp(value_test->str, value0_new.p, value0_new.len), 0);

    logdb_flush(db);
    logdb_free(db);




    /* simulate corruption */
    f = fopen(dbtmpfile, "rb");
    fseek(f, 0, SEEK_END);
    fsize = ftell(f);
    fseek(f, 0, SEEK_SET);

    buf = malloc(fsize + 1);
    fread(buf, fsize, 1, f);
    fclose(f);

    /* ---------------------------------------------------- */
    wrk_buf = safe_malloc(fsize + 1);
    memcpy(wrk_buf, buf, fsize);
    wrk_buf[0] = 0x88; /* wrong header */

    unlink(dbtmpfile);
    f = fopen(dbtmpfile, "wb");
    fwrite(wrk_buf, 1, fsize, f);
    fclose(f);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), false);
    u_assert_int_eq(error, LOGDB_ERROR_WRONG_FILE_FORMAT);
    logdb_free(db);

    /* ---------------------------------------------------- */
    memcpy(wrk_buf, buf, fsize);
    wrk_buf[66] = 0x00; /* wrong checksum hash */

    unlink(dbtmpfile);
    f = fopen(dbtmpfile, "wb");
    fwrite(wrk_buf, 1, fsize, f);
    fclose(f);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), false);
    u_assert_int_eq(error, LOGDB_ERROR_CHECKSUM);
    logdb_free(db);

    /* ---------------------------------------------------- */
    memcpy(wrk_buf, buf, fsize);
    wrk_buf[42] = 0xFF; /* wrong value length */

    unlink(dbtmpfile);
    f = fopen(dbtmpfile, "wb");
    fwrite(wrk_buf, 1, fsize, f);
    fclose(f);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), false);
    u_assert_int_eq(error, LOGDB_ERROR_DATASTREAM_ERROR);
    logdb_free(db);

    free(buf);
    free(wrk_buf);


    /* --- large db test */
    unlink(dbtmpfile);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, true, NULL), true);

    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        smp_key.p = hashbin;
        smp_key.len = outlen;

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        smp_value.p = txbin;
        smp_value.len = outlen;

        logdb_append(db, &smp_key, &smp_value);
    }

    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    /* check all records */
    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        smp_key.p = hashbin;
        smp_key.len = outlen;
        outtest = logdb_find(db, &smp_key);

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        u_assert_int_eq(outlen, outtest->len);
    }

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    /* check all records */
    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        memcpy(hexrev, tx->txhash, sizeof(tx->txhash));
        utils_reverse_hex(hexrev, strlen(tx->txhash));
        outlenrev = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(hexrev, txbin_rev, strlen(hexrev), &outlenrev);

        smp_key.p = hashbin;
        smp_key.len = outlen;
        outtest = logdb_find(db, &smp_key);

        outlen = strlen(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);
        u_assert_int_eq(outlen, outtest->len);

        /*  hash transaction data and check hashes */
        if (strlen(tx->hextx) > 2)
        {
            uint8_t tx_hash_check[SHA256_DIGEST_LENGTH];
            sha256_Raw(txbin, outlen, tx_hash_check);
            sha256_Raw(tx_hash_check, 32, tx_hash_check);
            u_assert_int_eq(memcmp(tx_hash_check, txbin_rev, SHA256_DIGEST_LENGTH), 0);
        }

    }

    /* check all records */
    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        smp_key.p = hashbin;
        smp_key.len = outlen;
        logdb_delete(db, &smp_key);
    }
    u_assert_int_eq(logdb_count_keys(db), 0);

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(error, LOGDB_SUCCESS);
    u_assert_int_eq(logdb_count_keys(db), 0);

    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        smp_key.p = hashbin;
        smp_key.len = outlen;

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        smp_value.p = txbin;
        smp_value.len = outlen;

        logdb_append(db, &smp_key, &smp_value);
    }

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(error, LOGDB_SUCCESS);
    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(error, LOGDB_SUCCESS);
    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        smp_key.p = hashbin;
        smp_key.len = outlen;

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        smp_value.p = txbin;
        smp_value.len = outlen;

        logdb_append(db, &smp_key, &smp_value);
    }

    logdb_flush(db);
    logdb_free(db);
}
Ejemplo n.º 3
0
void test_protocol()
{
    /* get new string buffer */
    cstring *version_msg_cstr = cstr_new_sz(256);
    cstring *inv_msg_cstr = cstr_new_sz(256);

    struct sockaddr_in test_sa, test_sa_check;
    memset(&test_sa, 0, sizeof(test_sa));
    memset(&test_sa_check, 0, sizeof(test_sa_check));
    test_sa.sin_family = AF_INET;
    struct sockaddr_in6 test_sa6, test_sa6_check;
    test_sa6.sin6_family = AF_INET6;
    test_sa6.sin6_port = htons(1024);
    evutil_inet_pton(AF_INET, "10.0.0.1", &test_sa.sin_addr); // store IP in antelope

    char i6buf[1024];
    memset(&i6buf, 0, 1024);

    evutil_inet_pton(AF_INET6, "::1", &test_sa6.sin6_addr);
    btc_p2p_address ipv6Test;
    btc_p2p_address_init(&ipv6Test);
    btc_addr_to_p2paddr((struct sockaddr *)&test_sa6, &ipv6Test);
    btc_p2paddr_to_addr(&ipv6Test, (struct sockaddr *)&test_sa6_check);
    memset(&i6buf, 0, 1024);
    u_assert_int_eq(test_sa6.sin6_port, test_sa6_check.sin6_port);

    /* copy socket_addr to p2p addr */
    btc_p2p_address fromAddr;
    btc_p2p_address_init(&fromAddr);
    btc_p2p_address toAddr;
    btc_p2p_address_init(&toAddr);
    btc_addr_to_p2paddr((struct sockaddr *)&test_sa, &toAddr);
    btc_p2paddr_to_addr(&toAddr, (struct sockaddr *)&test_sa_check);
    u_assert_int_eq(test_sa.sin_port, test_sa_check.sin_port);
    evutil_inet_ntop(AF_INET, &test_sa_check.sin_addr, i6buf, 1024);
    u_assert_str_eq(i6buf, "10.0.0.1");

    /* create a inv message struct */
    btc_p2p_inv_msg inv_msg, inv_msg_check;
    memset(&inv_msg, 0, sizeof(inv_msg));

    uint256 hash = {0};

    btc_p2p_msg_inv_init(&inv_msg, 1, hash);
    btc_p2p_msg_inv_ser(&inv_msg, inv_msg_cstr);

    struct const_buffer buf_inv = {inv_msg_cstr->str, inv_msg_cstr->len};
    u_assert_int_eq(btc_p2p_msg_inv_deser(&inv_msg_check, &buf_inv), true);
    u_assert_int_eq(inv_msg_check.type, 1);
    u_assert_mem_eq(inv_msg_check.hash, inv_msg.hash, sizeof(inv_msg.hash));
    cstr_free(inv_msg_cstr, true);

    /* create a version message struct */
    btc_p2p_version_msg version_msg;
    memset(&version_msg, 0, sizeof(version_msg));

    /* create a serialized version message */
    btc_p2p_msg_version_init(&version_msg, &fromAddr, &toAddr, "client", false);
    btc_p2p_msg_version_ser(&version_msg, version_msg_cstr);

    /* create p2p message */
    cstring *p2p_msg = btc_p2p_message_new((unsigned const char *)&btc_chainparams_main.netmagic, BTC_MSG_VERSION, version_msg_cstr->str, version_msg_cstr->len);

    struct const_buffer buf = {p2p_msg->str, p2p_msg->len};
    btc_p2p_msg_hdr hdr;
    btc_p2p_deser_msghdr(&hdr, &buf);

    u_assert_mem_eq(hdr.netmagic, &btc_chainparams_main.netmagic, 4);
    u_assert_str_eq(hdr.command, BTC_MSG_VERSION);
    u_assert_int_eq(hdr.data_len, version_msg_cstr->len);
    u_assert_int_eq(buf.len, hdr.data_len);
    u_assert_int_eq(buf.len, hdr.data_len);
    u_assert_mem_eq(buf.p, version_msg_cstr->str, hdr.data_len);

    btc_p2p_version_msg v_msg_check;
    u_assert_int_eq(btc_p2p_msg_version_deser(&v_msg_check, &buf), true);

    u_assert_int_eq(v_msg_check.version, BTC_PROTOCOL_VERSION);
    u_assert_str_eq(v_msg_check.useragent, "client");
    u_assert_int_eq(v_msg_check.start_height, 0);

    cstr_free(p2p_msg, true);
    cstr_free(version_msg_cstr, true);

    /* getheaders */
    uint256 genesis_hash = {0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xd6, 0x68, 0x9c, 0x08, 0x5a, 0xe1, 0x65, 0x83, 0x1e, 0x93, 0x4f, 0xf7, 0x63, 0xae, 0x46, 0xa2, 0xa6, 0xc1, 0x72, 0xb3, 0xf1, 0xb6, 0x0a, 0x8c, 0xe2, 0x6f};
    vector *blocklocators = vector_new(1, NULL);
    vector_add(blocklocators, genesis_hash);
    cstring *getheader_msg = cstr_new_sz(256);
    btc_p2p_msg_getheaders(blocklocators, NULL, getheader_msg);
    p2p_msg = btc_p2p_message_new((unsigned const char *)&btc_chainparams_main.netmagic, BTC_MSG_GETHEADERS, getheader_msg->str, getheader_msg->len);


    buf.p = p2p_msg->str;
    buf.len = p2p_msg->len;
    btc_p2p_deser_msghdr(&hdr, &buf);
    u_assert_str_eq(hdr.command, BTC_MSG_GETHEADERS);
    u_assert_int_eq(hdr.data_len, getheader_msg->len);


    uint256 hashstop_check;
    vector *blocklocators_check = vector_new(1, free);
    btc_p2p_deser_msg_getheaders(blocklocators_check, hashstop_check, &buf);
    u_assert_mem_eq(NULLHASH, hashstop_check, sizeof(hashstop_check));
    uint8_t *hash_loc_0 = vector_idx(blocklocators_check, 0);
    u_assert_mem_eq(genesis_hash, hash_loc_0, sizeof(genesis_hash));


    /* cleanup */
    cstr_free(getheader_msg, true);
    vector_free(blocklocators, true);
    vector_free(blocklocators_check, true);
    cstr_free(p2p_msg, true);
}
Ejemplo n.º 4
0
void test_logdb(logdb_log_db* (*new_func)())
{
    logdb_log_db *db;
    enum logdb_error error = 0;
    cstring *key;// key= {"key0", 4};
    cstring *value;// = {"val0", 4};
    cstring *key1;
    cstring *value1;
    cstring *outtest;
    cstring *value_test;
    unsigned char testbin[4] = {0x00, 0x10, 0x20, 0x30};
    cstring *value0;// = {"dumb", 4};
    cstring *key2;// = {"pkey", 4};
    cstring *value2;
    cstring *smp_value;
    cstring *smp_key;
    uint8_t txbin[10240];
    uint8_t txbin_rev[10240];
    char hexrev[98];
    int outlenrev;
    long fsize;
    char *buf;
    char *wrk_buf;
    FILE *f;
    unsigned int i;
    char bufs[300][65];
    rb_red_blk_node *nodetest;
    unsigned int cnt = 0;
    logdb_record* rec;

    key = cstr_new("key0");
    value = cstr_new("val0");

    value0 = cstr_new("dumb");
    value1 = cstr_new_sz(10);
    value2 = cstr_new_sz(10);
    key1 = cstr_new_sz(10);
    key2 = cstr_new("key2");

    cstr_append_buf(value2, testbin, sizeof(testbin));
    cstr_append_buf(value2, testbin, sizeof(testbin));
    cstr_append_buf(key1, key1str, strlen(key1str));
    cstr_append_buf(value1, value1str, strlen(value1str));

    unlink(dbtmpfile);
    db = new_func();
    u_assert_int_eq(logdb_load(db, "file_that_should_not_exists.dat", false, NULL), false);
    u_assert_int_eq(logdb_load(db, dbtmpfile, true, NULL), true);

    logdb_append(db, NULL, key, value);
    logdb_append(db, NULL, key1, value1);

    u_assert_int_eq(logdb_cache_size(db), 2);
    outtest = logdb_find_cache(db, key1);
    u_assert_int_eq(strcmp(outtest->str, value1str),0);
    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);
    u_assert_int_eq(logdb_count_keys(db), 2);

    value_test = logdb_find(db, key1);
    u_assert_int_eq(strcmp(value_test->str, value1str), 0);
    value_test = logdb_find(db, key);
    u_assert_int_eq(memcmp(value_test->str, value->str, value->len), 0);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);



    logdb_append(db, NULL, key2, value2);
    logdb_flush(db);
    logdb_free(db);

    /* check if private key is available */
    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);

    value_test = logdb_find(db, key2);
    u_assert_int_eq(memcmp(value_test->str, value2->str, value2->len), 0);
    value_test = logdb_find(db, key);
    u_assert_int_eq(memcmp(value_test->str, value->str, value->len), 0);

    /* delete a record */
    logdb_delete(db, NULL, key2);
    logdb_flush(db);
    logdb_free(db);

    /* find and check the deleted record */
    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);

    value_test = logdb_find(db, key);
    u_assert_int_eq(memcmp(value_test->str, value->str, value->len), 0);

    value_test = logdb_find(db, key2);
    u_assert_int_eq((int)value_test, 0); /* should be null */

    /* overwrite a key */
    logdb_append(db, NULL, key, value0);

    value_test = logdb_find(db, key);
    u_assert_int_eq(memcmp(value_test->str, value0->str, value0->len), 0);

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);
    value_test = logdb_find(db, key);
    u_assert_int_eq(memcmp(value_test->str, value0->str, value0->len), 0);

    logdb_flush(db);
    logdb_free(db);




    /* simulate corruption */
    f = fopen(dbtmpfile, "rb");
    fseek(f, 0, SEEK_END);
    fsize = ftell(f);
    fseek(f, 0, SEEK_SET);

    buf = malloc(fsize + 1);
    fread(buf, fsize, 1, f);
    fclose(f);

    /* ---------------------------------------------------- */
    wrk_buf = safe_malloc(fsize + 1);
    memcpy(wrk_buf, buf, fsize);
    wrk_buf[0] = 0x88; /* wrong header */

    unlink(dbtmpfile);
    f = fopen(dbtmpfile, "wb");
    fwrite(wrk_buf, 1, fsize, f);
    fclose(f);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), false);
    u_assert_int_eq(error, LOGDB_ERROR_WRONG_FILE_FORMAT);
    logdb_free(db);

    /* ---------------------------------------------------- */
    memcpy(wrk_buf, buf, fsize);
    wrk_buf[66] = 0x00; /* wrong checksum hash */

    unlink(dbtmpfile);
    f = fopen(dbtmpfile, "wb");
    fwrite(wrk_buf, 1, fsize, f);
    fclose(f);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), false);
    u_assert_int_eq(error, LOGDB_ERROR_CHECKSUM);
    logdb_free(db);

    /* ---------------------------------------------------- */
    memcpy(wrk_buf, buf, fsize);
    wrk_buf[42] = 0xFF; /* wrong value length */

    unlink(dbtmpfile);
    f = fopen(dbtmpfile, "wb");
    fwrite(wrk_buf, 1, fsize, f);
    fclose(f);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), false);
    u_assert_int_eq(error, LOGDB_ERROR_DATASTREAM_ERROR);
    logdb_free(db);

    free(buf);
    free(wrk_buf);


    /* --- large db test */
    unlink(dbtmpfile);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, true, NULL), true);

    smp_key = cstr_new_sz(100);
    smp_value = cstr_new_sz(100);
    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        cstr_erase(smp_key, 0, smp_key->len);
        cstr_append_buf(smp_key, hashbin, outlen);

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        cstr_erase(smp_value, 0, smp_value->len);
        cstr_append_buf(smp_value, txbin, outlen);

        logdb_append(db, NULL, smp_key, smp_value);
    }

    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    /* check all records */
    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        cstr_erase(smp_key, 0, smp_key->len);
        cstr_append_buf(smp_key, hashbin, outlen);
        outtest = logdb_find(db, smp_key);

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        u_assert_int_eq(outlen, outtest->len);
    }

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    /* check all records */
    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        memcpy(hexrev, tx->txhash, sizeof(tx->txhash));
        utils_reverse_hex(hexrev, strlen(tx->txhash));
        outlenrev = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(hexrev, txbin_rev, strlen(hexrev), &outlenrev);

        cstr_erase(smp_key, 0, smp_key->len);
        cstr_append_buf(smp_key, hashbin, outlen);
        outtest = logdb_find(db, smp_key);

        outlen = strlen(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);
        u_assert_int_eq(outlen, outtest->len);

        /*  hash transaction data and check hashes */
        if (strlen(tx->hextx) > 2)
        {
            uint8_t tx_hash_check[SHA256_DIGEST_LENGTH];
            sha256_Raw(txbin, outlen, tx_hash_check);
            sha256_Raw(tx_hash_check, 32, tx_hash_check);
            u_assert_int_eq(memcmp(tx_hash_check, txbin_rev, SHA256_DIGEST_LENGTH), 0);
        }

    }

    /* check all records */
    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        cstr_erase(smp_key, 0, smp_key->len);
        cstr_append_buf(smp_key, hashbin, outlen);
        logdb_delete(db, NULL, smp_key);
    }
    u_assert_int_eq(logdb_count_keys(db), 0);

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(error, LOGDB_SUCCESS);
    u_assert_int_eq(logdb_count_keys(db), 0);

    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        cstr_erase(smp_key, 0, smp_key->len);
        cstr_append_buf(smp_key, hashbin, outlen);

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        cstr_erase(smp_value, 0, smp_value->len);
        cstr_append_buf(smp_value, txbin, outlen);

        logdb_append(db, NULL, smp_key, smp_value);
    }

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(error, LOGDB_SUCCESS);
    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    error = 0;
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, &error), true);
    u_assert_int_eq(error, LOGDB_SUCCESS);
    u_assert_int_eq(logdb_count_keys(db), (sizeof(sampledata) / sizeof(sampledata[0])));

    if(new_func == logdb_rbtree_new)
    {
        logdb_rbtree_db* handle = (logdb_rbtree_db *)db->cb_ctx;
        size_t size = rbtree_count(handle->tree);

        nodetest = NULL;
        while ((nodetest = rbtree_enumerate_next(handle->tree)))
        {
            rec = (logdb_record *)nodetest->info;
            utils_bin_to_hex((unsigned char *)rec->key->str, rec->key->len, bufs[cnt]);

            for(i = 0; i < cnt; i++)
            {
                u_assert_int_eq(strcmp(bufs[i], bufs[cnt]) != 0, 1);
            }
            cnt++;
        }
        u_assert_int_eq(size, cnt);
    }

    for (i = 0; i < (sizeof(sampledata) / sizeof(sampledata[0])); i++) {
        const struct txtest *tx = &sampledata[i];

        uint8_t hashbin[sizeof(tx->txhash) / 2];
        int outlen = sizeof(tx->txhash) / 2;
        utils_hex_to_bin(tx->txhash, hashbin, strlen(tx->txhash), &outlen);

        cstr_erase(smp_key, 0, smp_key->len);
        cstr_append_buf(smp_key, hashbin, outlen);

        outlen = sizeof(tx->hextx) / 2;
        utils_hex_to_bin(tx->hextx, txbin, strlen(tx->hextx), &outlen);

        cstr_erase(smp_value, 0, smp_value->len);
        cstr_append_buf(smp_value, txbin, outlen);

        logdb_append(db, NULL, smp_key, smp_value);
    }

    logdb_flush(db);
    logdb_free(db);

    /* test switch mem mapper after initialitaion. */
    db = logdb_new();
    logdb_set_memmapper(db, &logdb_rbtree_mapper, NULL);
    logdb_flush(db);
    logdb_free(db);


    unlink(dbtmpfile);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, true, NULL), true);

    // create transaction, don't store
    logdb_txn* txn = logdb_txn_new();
    logdb_append(db, txn, key, value);
    logdb_append(db, txn, key1, value1);
    u_assert_int_eq(logdb_cache_size(db), 0);
    logdb_txn_free(txn);

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);
    // db should still be empty
    u_assert_int_eq(logdb_count_keys(db), 0);

    // create transaction, store it this time
    txn = logdb_txn_new();
    logdb_append(db, txn, key, value);
    logdb_append(db, txn, key1, value1);
    logdb_txn_commit(db, txn);
    u_assert_int_eq(logdb_cache_size(db), 2);
    logdb_txn_free(txn);

    logdb_flush(db);
    logdb_free(db);

    db = new_func();
    u_assert_int_eq(logdb_load(db, dbtmpfile, false, NULL), true);
    // now we should have the two persisted items from the txn
    u_assert_int_eq(logdb_count_keys(db), 2);
    logdb_flush(db);
    logdb_free(db);

    cstr_free(key, true);
    cstr_free(value, true);
    cstr_free(value0, true);
    cstr_free(value1, true);
    cstr_free(value2, true);
    cstr_free(key1, true);
    cstr_free(key2, true);
    cstr_free(smp_key, true);
    cstr_free(smp_value, true);
}