static bool nc_msg_block(struct nc_conn *conn) { struct const_buffer buf = { conn->msg.data, conn->msg.hdr.data_len }; struct bp_block block; bp_block_init(&block); bool rc = false; if (!deser_bp_block(&block, &buf)) goto out; bp_block_calc_sha256(&block); char hexstr[BU256_STRSZ]; bu256_hex(hexstr, &block.sha256); log_debug("net: %s block %s", conn->addr_str, hexstr); if (!bp_block_valid(&block)) { log_info("net: %s invalid block %s", conn->addr_str, hexstr); goto out; } if (!conn->nci->block_process(&block, &conn->msg.hdr, &buf)) goto out; rc = true; out: bp_block_free(&block); return rc; }
static bool read_block_msg(struct p2p_message *msg, int64_t fpos) { /* unknown records are invalid */ if (strncmp(msg->hdr.command, "block", sizeof(msg->hdr.command))) return false; bool rc = false; struct bp_block block; bp_block_init(&block); struct const_buffer buf = { msg->data, msg->hdr.data_len }; if (!deser_bp_block(&block, &buf)) { fprintf(plog, "brd: block deser fail\n"); goto out; } bp_block_calc_sha256(&block); if (!bp_block_valid(&block)) { fprintf(plog, "brd: block not valid\n"); goto out; } rc = process_block(&block, fpos); out: bp_block_free(&block); return rc; }
static void read_test_msg(struct blkdb *db, struct bp_utxo_set *uset, const struct p2p_message *msg, int64_t fpos) { assert(strncmp(msg->hdr.command, "block", sizeof(msg->hdr.command)) == 0); struct bp_block block; bp_block_init(&block); struct const_buffer buf = { msg->data, msg->hdr.data_len }; assert(deser_bp_block(&block, &buf) == true); bp_block_calc_sha256(&block); assert(bp_block_valid(&block) == true); struct blkinfo *bi = bi_new(); bu256_copy(&bi->hash, &block.sha256); bp_block_copy_hdr(&bi->hdr, &block); bi->n_file = 0; bi->n_pos = fpos + P2P_HDR_SZ; assert(blkdb_add(db, bi) == true); /* if best chain, mark TX's as spent */ if (bu256_equal(&db->hashBestChain, &bi->hdr.sha256)) { if (!spend_block(uset, &block, bi->height)) { char hexstr[BU256_STRSZ]; bu256_hex(hexstr, &bi->hdr.sha256); fprintf(stderr, "chain-verf: block fail %u %s\n", bi->height, hexstr); assert(!"spend_block"); } } bp_block_free(&block); }
static void runtest(const char *json_fn_base, const char *ser_fn_base) { char *fn = test_filename(json_fn_base); json_t *meta = read_json(fn); assert(json_is_object(meta)); char *ser_fn = test_filename(ser_fn_base); int fd = file_seq_open(ser_fn); if (fd < 0) { perror(ser_fn); exit(1); } struct p2p_message msg = {}; bool read_ok = false; bool rc = fread_message(fd, &msg, &read_ok); assert(rc); assert(read_ok); assert(!strncmp(msg.hdr.command, "block", 12)); close(fd); const char *hashstr = json_string_value(json_object_get(meta, "hash")); assert(hashstr != NULL); unsigned int size = json_integer_value(json_object_get(meta, "size")); assert((24 + msg.hdr.data_len) == size); struct bp_block block; bp_block_init(&block); struct const_buffer buf = { msg.data, msg.hdr.data_len }; rc = deser_bp_block(&block, &buf); assert(rc); cstring *gs = cstr_new_sz(100000); ser_bp_block(gs, &block); if (gs->len != msg.hdr.data_len) { fprintf(stderr, "gs->len %ld, msg.hdr.data_len %u\n", (long)gs->len, msg.hdr.data_len); assert(gs->len == msg.hdr.data_len); } assert(memcmp(gs->str, msg.data, msg.hdr.data_len) == 0); bp_block_calc_sha256(&block); char hexstr[BU256_STRSZ]; bu256_hex(hexstr, &block.sha256); if (strcmp(hexstr, hashstr)) { fprintf(stderr, "block: wanted hash %s,\n got hash %s\n", hashstr, hexstr); assert(!strcmp(hexstr, hashstr)); } rc = bp_block_valid(&block); assert(rc); bp_block_free(&block); cstr_free(gs, true); free(msg.data); free(fn); free(ser_fn); json_decref(meta); }
static bool nc_msg_block(struct nc_conn *conn) { struct const_buffer buf = { conn->msg.data, conn->msg.hdr.data_len }; struct bp_block block; bp_block_init(&block); bool rc = false; if (!deser_bp_block(&block, &buf)) goto out; bp_block_calc_sha256(&block); char hexstr[BU256_STRSZ]; bu256_hex(hexstr, &block.sha256); if (debugging) { fprintf(plog, "net: %s block %s\n", conn->addr_str, hexstr); } if (!bp_block_valid(&block)) { fprintf(plog, "net: %s invalid block %s\n", conn->addr_str, hexstr); goto out; } /* check for duplicate block */ if (blkdb_lookup(&db, &block.sha256) || have_orphan(&block.sha256)) goto out_ok; struct iovec iov[2]; iov[0].iov_base = &conn->msg.hdr; // TODO: endian bug? iov[0].iov_len = sizeof(conn->msg.hdr); iov[1].iov_base = (void *) buf.p; // cast away 'const' iov[1].iov_len = buf.len; size_t total_write = iov[0].iov_len + iov[1].iov_len; /* store current file position */ off64_t fpos64 = lseek64(blocks_fd, 0, SEEK_CUR); if (fpos64 == (off64_t)-1) { fprintf(plog, "blocks: lseek64 failed %s\n", strerror(errno)); goto out; } /* write new block to disk */ errno = 0; ssize_t bwritten = writev(blocks_fd, iov, ARRAY_SIZE(iov)); if (bwritten != total_write) { fprintf(plog, "blocks: write failed %s\n", strerror(errno)); goto out; } /* process block */ if (!process_block(&block, fpos64)) { fprintf(plog, "blocks: process-block failed\n"); goto out; } out_ok: rc = true; out: bp_block_free(&block); return rc; }