bool deser_msg_addr(unsigned int protover, struct msg_addr *ma, struct const_buffer *buf) { memset(ma, 0, sizeof(*ma)); uint32_t vlen; if (!deser_varlen(&vlen, buf)) return false; ma->addrs = parr_new(vlen, free); unsigned int i; for (i = 0; i < vlen; i++) { struct bp_address *addr; addr = calloc(1, sizeof(*addr)); if (!deser_bp_addr(protover, addr, buf)) { free(addr); goto err_out; } parr_add(ma->addrs, addr); } return true; err_out: msg_addr_free(ma); return false; }
bool deser_msg_vinv(struct msg_vinv *mv, struct const_buffer *buf) { msg_vinv_free(mv); uint32_t vlen; if (!deser_varlen(&vlen, buf)) return false; mv->invs = parr_new(vlen, free); unsigned int i; for (i = 0; i < vlen; i++) { struct bp_inv *inv; inv = calloc(1, sizeof(*inv)); if (!deser_bp_inv(inv, buf)) { free(inv); goto err_out; } parr_add(mv->invs, inv); } return true; err_out: msg_vinv_free(mv); return false; }
bool deser_msg_headers(struct msg_headers *mh, struct const_buffer *buf) { msg_headers_free(mh); uint32_t vlen; if (!deser_varlen(&vlen, buf)) return false; mh->headers = parr_new(vlen, free); unsigned int i; for (i = 0; i < vlen; i++) { struct bp_block *block; block = calloc(1, sizeof(*block)); if (!deser_bp_block(block, buf)) { free(block); goto err_out; } parr_add(mh->headers, block); } return true; err_out: msg_headers_free(mh); return false; }
static void stack_insert(parr *stack, const struct buffer *buf, int index_) { int index = stack->len + index_; parr_add(stack, NULL); memmove(&stack->data[index + 1], &stack->data[index], sizeof(void *) * (stack->len - index - 1)); stack->data[index] = buffer_copy(buf->p, buf->len); }
void msg_vinv_push(struct msg_vinv *mv, uint32_t msg_type, const bu256_t *hash_in) { if (!mv->invs) mv->invs = parr_new(512, free); struct bp_inv *inv = malloc(sizeof(struct bp_inv)); inv->type = msg_type; bu256_copy(&inv->hash, hash_in); parr_add(mv->invs, inv); }
static bool deser_wallet_account(struct wallet *wlt, struct const_buffer *buf) { struct wallet_account *acct; acct = calloc(1, sizeof(*acct)); if (!acct) return false; if (!deser_varstr(&acct->name, buf) || !deser_u32(&acct->acct_idx, buf) || !deser_u32(&acct->next_key_idx, buf)) goto err_out; parr_add(wlt->accounts, acct); return true; err_out: account_free(acct); return false; }
parr *bp_block_match(const struct bp_block *block, const struct bp_keyset *ks) { if (!block || !block->vtx || !ks) return NULL; parr *arr = parr_new(block->vtx->len, bbm_free); if (!arr) return NULL; BIGNUM tmp_mask; BN_init(&tmp_mask); unsigned int n; for (n = 0; n < block->vtx->len; n++) { struct bp_tx *tx; tx = parr_idx(block->vtx, n); if (!bp_tx_match_mask(&tmp_mask, tx, ks)) goto err_out; if (!BN_is_zero(&tmp_mask)) { struct bp_block_match *match; match = bbm_new(); match->n = n; BN_copy(&match->mask, &tmp_mask); parr_add(arr, match); } } BN_clear_free(&tmp_mask); return arr; err_out: BN_clear_free(&tmp_mask); parr_free(arr, true); return NULL; }
static void append_output(char *addr_str, char *amount_str) { unsigned char addrtype = 0; cstring *payload = base58_decode_check(&addrtype, addr_str); bool is_script = is_script_addr(addrtype); uint64_t amt = (uint64_t) strtoull(amount_str, NULL, 10); struct bp_txout *txout = calloc(1, sizeof(struct bp_txout)); if (!txout || !payload) { fprintf(stderr, "OOM\n"); exit(1); } txout->nValue = amt; if (is_script) txout->scriptPubKey = bsp_make_scripthash(payload); else txout->scriptPubKey = bsp_make_pubkeyhash(payload); parr_add(tx.vout, txout); }
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 nc_conns_open(struct net_child_info *nci) { log_debug("net: open connections (have %zu, want %zu more)", nci->conns->len, NC_MAX_CONN - nci->conns->len); while ((bp_hashtab_size(nci->peers->map_addr) > 0) && (nci->conns->len < NC_MAX_CONN)) { /* delete peer from front of address list. it will be * re-added before writing peer file, if successful */ struct peer *peer = peerman_pop(nci->peers); struct nc_conn *conn = nc_conn_new(peer); conn->nci = nci; peer_free(peer); free(peer); log_debug("net: connecting to %s", conn->addr_str); /* are we already connected to this IP? */ if (nc_conn_ip_active(nci, conn->peer.addr.ip)) { log_info("net: already connected to %s", conn->addr_str); goto err_loop; } /* are we already connected to this network group? */ if (nc_conn_group_active(nci, &conn->peer)) { log_info("net: already grouped to %s", conn->addr_str); goto err_loop; } /* initiate non-blocking connect(2) */ if (!nc_conn_start(conn)) { log_info("net: failed to start connection to %s", conn->addr_str); goto err_loop; } /* add to our list of monitored event sources */ conn->ev = event_new(nci->eb, conn->fd, EV_WRITE, nc_conn_evt_connected, conn); if (!conn->ev) { log_info("net: event_new failed on %s", conn->addr_str); goto err_loop; } struct timeval timeout = { conn->nci->net_conn_timeout, }; if (event_add(conn->ev, &timeout) != 0) { log_info("net: event_add failed on %s", conn->addr_str); goto err_loop; } /* add to our list of active connections */ parr_add(nci->conns, conn); continue; err_loop: nc_conn_kill(conn); } }
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 void stack_push_str(parr *stack, cstring *s) { parr_add(stack, buffer_copy(s->str, s->len)); cstr_free(s, true); }
static void stack_push_char(parr *stack, unsigned char ch) { parr_add(stack, buffer_copy(&ch, 1)); }
static void stack_push_nocopy(parr *stack, struct buffer *buf) { parr_add(stack, buf); }
static void stack_push(parr *stack, const struct buffer *buf) { parr_add(stack, buffer_copy(buf->p, buf->len)); }