예제 #1
0
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;
}
예제 #2
0
파일: net.c 프로젝트: aido/picocoin
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;
}
예제 #3
0
파일: blkdb.c 프로젝트: hsk81/picocoin
struct blkinfo *bi_new(void)
{
	struct blkinfo *bi;

	bi = calloc(1, sizeof(*bi));
	BN_init(&bi->work);
	bi->height = -1;
	bi->n_file = -1;
	bi->n_pos = -1LL;

	bp_block_init(&bi->hdr);

	return bi;
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
파일: block.c 프로젝트: aido/picocoin
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);
}
예제 #7
0
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;
}