static void test_checkpoints(void) { bool rc; const char *hexstr; bu256_t tmp; hexstr = "0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d"; rc = hex_bu256(&tmp, hexstr); assert(rc == true); // in list; pass rc = bitc_ckpt_block(CHAIN_BITCOIN, 11111, &tmp); assert(rc == true); // not in list; pass rc = bitc_ckpt_block(CHAIN_BITCOIN, 11112, &tmp); assert(rc == true); hexstr = "0x11111111111111111111111111111111111111111111192559f542fdb26e7c1d"; rc = hex_bu256(&tmp, hexstr); assert(rc == true); // in list, mismatch hash; fail rc = bitc_ckpt_block(CHAIN_BITCOIN, 11111, &tmp); assert(rc == false); assert(bitc_ckpt_last(CHAIN_BITCOIN) == 295000); assert(bitc_ckpt_last(CHAIN_TESTNET3) == 546); }
static void runtest(bool use_testnet, const char *blocks_fn) { const struct chain_info *chain = &chain_metadata[use_testnet ? CHAIN_TESTNET3 : CHAIN_BITCOIN]; struct blkdb blkdb; bu256_t blk0; hex_bu256(&blk0, chain->genesis_hash); assert(blkdb_init(&blkdb, chain->netmagic, &blk0) == true); struct bp_utxo_set uset; bp_utxo_set_init(&uset); fprintf(stderr, "chain-verf: validating %s chainfile %s\n", use_testnet ? "testnet3" : "mainnet", blocks_fn); int fd = open(blocks_fn, O_RDONLY); if (fd < 0) { perror(blocks_fn); assert(fd >= 0); } #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L posix_fadvise(fd, 0, 0, POSIX_FADV_SEQUENTIAL); #endif struct p2p_message msg = {}; bool read_ok = true; int64_t fpos = 0; unsigned int records = 0; while (fread_message(fd, &msg, &read_ok)) { assert(memcmp(msg.hdr.netmagic, chain->netmagic, 4) == 0); read_test_msg(&blkdb, &uset, &msg, fpos); fpos += P2P_HDR_SZ; fpos += msg.hdr.data_len; records++; } assert(read_ok == true); close(fd); free(msg.data); blkdb_free(&blkdb); bp_utxo_set_free(&uset); fprintf(stderr, "chain-verf: %u records validated\n", records); }
static void chain_set(void) { char *name = setting("chain"); const struct chain_info *new_chain = chain_find(name); if (!new_chain) { fprintf(stderr, "chain-set: unknown chain '%s'\n", name); exit(1); } bu256_t new_genesis; if (!hex_bu256(&new_genesis, new_chain->genesis_hash)) { fprintf(stderr, "chain-set: invalid genesis hash %s\n", new_chain->genesis_hash); exit(1); } chain = new_chain; bu256_copy(&chain_genesis, &new_genesis); }
static void append_input(char *txid_str, char *vout_str) { bu256_t txid; if (!hex_bu256(&txid, txid_str)) { fprintf(stderr, "invalid txid hex\n"); exit(1); } unsigned int vout = atoi(vout_str); struct bp_txin *txin = calloc(1, sizeof(struct bp_txin)); if (!txin) { fprintf(stderr, "OOM\n"); exit(1); } bp_txin_init(txin); bu256_copy(&txin->prevout.hash, &txid); txin->prevout.n = vout; txin->scriptSig = cstr_new(NULL); txin->nSequence = SEQUENCE_FINAL; parr_add(tx.vin, txin); }
static void runtest(const char *json_base_fn, const char *ser_in_fn, const char *block_in_hash, const char *tx_in_hash) { /* read wallet data */ char *json_fn = test_filename(json_base_fn); json_t *wallet = read_json(json_fn); assert(wallet != NULL); /* read block data containing incoming payment */ char *fn = test_filename(ser_in_fn); void *data; size_t data_len; assert(bu_read_file(fn, &data, &data_len, 1 * 1024 * 1024) == true); struct bp_block block_in; bp_block_init(&block_in); struct const_buffer buf = { data, data_len }; assert(deser_bp_block(&block_in, &buf) == true); bp_block_calc_sha256(&block_in); /* verify block-in data matches expected block-in hash */ bu256_t check_hash; assert(hex_bu256(&check_hash, block_in_hash) == true); assert(bu256_equal(&block_in.sha256, &check_hash) == true); /* load key that has received an incoming payment */ struct bp_key key; assert(bp_key_init(&key) == true); load_json_key(wallet, &key); /* load key into keyset */ struct bp_keyset ks; bpks_init(&ks); assert(bpks_add(&ks, &key) == true); /* find key matches in block */ parr *matches; matches = bp_block_match(&block_in, &ks); assert(matches != NULL); assert(matches->len == 1); struct bp_block_match *match = parr_idx(matches, 0); assert(match->n == 1); /* match 2nd tx, index 1 */ /* get matching transaction */ struct bp_tx *tx = parr_idx(block_in.vtx, match->n); bp_tx_calc_sha256(tx); /* verify txid matches expected */ char tx_hexstr[BU256_STRSZ]; bu256_hex(tx_hexstr, &tx->sha256); assert(strcmp(tx_hexstr, tx_in_hash) == 0); /* verify mask matches 2nd txout (1 << 1) */ BIGNUM tmp_mask; BN_init(&tmp_mask); BN_one(&tmp_mask); BN_lshift(&tmp_mask, &tmp_mask, 1); assert(BN_cmp(&tmp_mask, &match->mask) == 0); /* build merkle tree, tx's branch */ parr *mtree = bp_block_merkle_tree(&block_in); assert(mtree != NULL); parr *mbranch = bp_block_merkle_branch(&block_in, mtree, match->n); assert(mbranch != NULL); /* verify merkle branch for tx matches expected */ bu256_t mrk_check; bp_check_merkle_branch(&mrk_check, &tx->sha256, mbranch, match->n); assert(bu256_equal(&mrk_check, &block_in.hashMerkleRoot) == true); /* release resources */ parr_free(mtree, true); parr_free(mbranch, true); BN_clear_free(&tmp_mask); parr_free(matches, true); bpks_free(&ks); bp_key_free(&key); bp_block_free(&block_in); json_decref(wallet); free(data); free(fn); free(json_fn); }
static void runtest(bool is_valid, const char *basefn) { char *fn = test_filename(basefn); json_t *tests = read_json(fn); assert(json_is_array(tests)); struct bp_hashtab *input_map = bp_hashtab_new_ext( input_hash, input_equal, free, input_value_free); comments = parr_new(8, free); unsigned int idx; for (idx = 0; idx < json_array_size(tests); idx++) { json_t *test = json_array_get(tests, idx); if (!json_is_array(json_array_get(test, 0))) { const char *cmt = json_string_value(json_array_get(test, 0)); if (cmt) parr_add(comments, strdup(cmt)); continue; /* comments */ } assert(json_is_array(test)); assert(json_array_size(test) == 3); assert(json_is_string(json_array_get(test, 1))); assert(json_is_boolean(json_array_get(test, 2))); json_t *inputs = json_array_get(test, 0); assert(json_is_array(inputs)); bp_hashtab_clear(input_map); unsigned int i; for (i = 0; i < json_array_size(inputs); i++) { json_t *input = json_array_get(inputs, i); assert(json_is_array(input)); const char *prev_hashstr = json_string_value(json_array_get(input, 0)); int prev_n = json_integer_value(json_array_get(input, 1)); const char *prev_pubkey_enc = json_string_value(json_array_get(input, 2)); assert(prev_hashstr != NULL); assert(json_is_integer(json_array_get(input, 1))); assert(prev_pubkey_enc != NULL); struct bp_outpt *outpt; outpt = malloc(sizeof(*outpt)); hex_bu256(&outpt->hash, prev_hashstr); outpt->n = prev_n; cstring *script = parse_script_str(prev_pubkey_enc); assert(script != NULL); bp_hashtab_put(input_map, outpt, script); } const char *tx_hexser = json_string_value(json_array_get(test, 1)); assert(tx_hexser != NULL); bool enforce_p2sh = json_is_true(json_array_get(test, 2)); cstring *tx_ser = hex2str(tx_hexser); assert(tx_ser != NULL); test_tx_valid(is_valid, input_map, tx_ser, enforce_p2sh); cstr_free(tx_ser, true); if (comments->len > 0) { parr_free(comments, true); comments = parr_new(8, free); } } parr_free(comments, true); comments = NULL; bp_hashtab_unref(input_map); json_decref(tests); free(fn); }