static bool read_config_file(const char *cfg_fn) { FILE *cfg = fopen(cfg_fn, "r"); if (!cfg) return false; bool rc = false; char line[1024]; while (fgets(line, sizeof(line), cfg) != NULL) { char *key, *value; if (line[0] == '#') continue; while (line[0] && (isspace(line[strlen(line) - 1]))) line[strlen(line) - 1] = 0; if (!parse_kvstr(line, &key, &value)) continue; bp_hashtab_put(settings, key, value); } rc = ferror(cfg) == 0; fclose(cfg); return rc; }
static void __peerman_add(struct peer_manager *peers, struct peer *peer, bool prepend_front) { bn_group(peer->group, &peer->group_len, peer->addr.ip); if (prepend_front) peers->addrlist = clist_prepend(peers->addrlist, peer); else peers->addrlist = clist_append(peers->addrlist, peer); bp_hashtab_put(peers->map_addr, peer->addr.ip, peer); }
static bool do_setting(const char *arg) { char *key, *value; if (!parse_kvstr(arg, &key, &value)) return false; bp_hashtab_put(settings, key, value); /* * trigger special setting-specific behaviors */ if (!strcmp(key, "debug")) debugging = true; else if (!strcmp(key, "config") || !strcmp(key, "c")) return read_config_file(value); return true; }
static bool add_orphan(const bu256_t *hash_in, struct const_buffer *buf_in) { if (have_orphan(hash_in)) return false; bu256_t *hash = bu256_new(hash_in); if (!hash) { fprintf(plog, "OOM\n"); return false; } struct buffer *buf = buffer_copy(buf_in->p, buf_in->len); if (!buf) { bu256_free(hash); fprintf(plog, "OOM\n"); return false; } bp_hashtab_put(orphans, hash, buf); return true; }
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); }
static bool blkdb_connect(struct blkdb *db, struct blkinfo *bi, struct blkdb_reorg *reorg_info) { memset(reorg_info, 0, sizeof(*reorg_info)); if (blkdb_lookup(db, &bi->hash)) return false; bool rc = false; BIGNUM cur_work; BN_init(&cur_work); u256_from_compact(&cur_work, bi->hdr.nBits); bool best_chain = false; /* verify genesis block matches first record */ if (bp_hashtab_size(db->blocks) == 0) { if (!bu256_equal(&bi->hdr.sha256, &db->block0)) goto out; /* bi->prev = NULL; */ bi->height = 0; BN_copy(&bi->work, &cur_work); best_chain = true; } /* lookup and verify previous block */ else { struct blkinfo *prev = blkdb_lookup(db, &bi->hdr.hashPrevBlock); if (!prev) goto out; bi->prev = prev; bi->height = prev->height + 1; if (!BN_add(&bi->work, &cur_work, &prev->work)) goto out; if (BN_cmp(&bi->work, &db->best_chain->work) > 0) best_chain = true; } /* add to block map */ bp_hashtab_put(db->blocks, &bi->hash, bi); /* if new best chain found, update pointers */ if (best_chain) { struct blkinfo *old_best = db->best_chain; struct blkinfo *new_best = bi; reorg_info->old_best = old_best; /* likely case: new best chain has greater height */ if (!old_best) { while (new_best) { new_best = new_best->prev; reorg_info->conn++; } } else { while (new_best && (new_best->height > old_best->height)) { new_best = new_best->prev; reorg_info->conn++; } } /* unlikely case: old best chain has greater height */ while (old_best && new_best && (old_best->height > new_best->height)) { old_best = old_best->prev; reorg_info->disconn++; } /* height matches, but we are still walking parallel chains */ while (old_best && new_best && (old_best != new_best)) { new_best = new_best->prev; reorg_info->conn++; old_best = old_best->prev; reorg_info->disconn++; } /* reorg analyzed. update database's best-chain pointer */ db->best_chain = bi; } rc = true; out: BN_clear_free(&cur_work); return rc; }