Пример #1
0
/* This allocates the block but doesn't sew it into data structures. */
static struct block *new_block(const tal_t *ctx,
			       BIGNUM *prev_work,
			       const struct protocol_block_id *sha,
			       const struct block_info *bi)
{
	struct block *block = tal(ctx, struct block);
	unsigned int i;

	total_work_done(le32_to_cpu(bi->tailer->difficulty),
			prev_work, &block->total_work);

	block->bi = *bi;
	block->all_known = false;
	list_head_init(&block->children);
	block->sha = *sha;
	block->shard = tal_arr(block, struct block_shard *,
			       num_shards(bi->hdr));
	for (i = 0; i < num_shards(bi->hdr); i++)
		block->shard[i] = new_block_shard(block->shard, i,
						  bi->num_txs[i]);

	/* In case we destroy before block_add(), eg. testing. */
	block->prev = NULL;

	tal_add_destructor(block, destroy_block);
	return block;
}
Пример #2
0
int main(int argc, char *argv[])
{
	struct state *s;
	struct working_block *w;
	unsigned int i;
	union protocol_tx *t;
	struct protocol_gateway_payment payment;
	struct block *prev, *b;
	struct block_shard *shard;
	u8 *prev_txhashes;
	enum protocol_ecode e;
	struct gen_update update;
	struct protocol_input_ref *refs;
	struct protocol_block_id sha;
	struct protocol_block_id prevs[PROTOCOL_NUM_PREV_IDS];

	/* We need enough of state to use the real init function here. */
	pseudorand_init();
	s = new_state(true);
	check_chains(s, true);

	fake_time = le32_to_cpu(genesis_tlr.timestamp) + 1;

	/* Create a block after that, with a gateway tx in it. */
	prev_txhashes = make_prev_txhashes(s, &genesis, helper_addr(1));

	/* We should need 1 prev_merkle per shard per block. */
	assert(num_prev_txhashes(&genesis) == (1 << genesis.bi.hdr->shard_order));
	assert(tal_count(prev_txhashes) == num_prev_txhashes(&genesis));

	memset(prevs, 0, sizeof(prevs));
	prevs[0] = genesis.sha;
	w = new_working_block(s, 0x1ffffff0,
			      prev_txhashes, tal_count(prev_txhashes),
			      block_height(&genesis.bi) + 1,
			      next_shard_order(&genesis),
			      prevs, helper_addr(1));

	payment.send_amount = cpu_to_le32(1000);
	payment.output_addr = *helper_addr(0);
	t = create_from_gateway_tx(s, helper_gateway_public_key(),
				   1, &payment, false, helper_gateway_key(s));
	/* Gateway txs have empty refs, so this gives 0-len array. */
	refs = create_refs(s, &genesis, t, 1);

	update.shard = shard_of_tx(t, next_shard_order(&genesis));
	update.txoff = 0;
	update.features = 0;
	update.unused = 0;
	hash_tx_and_refs(t, refs, &update.hashes);
	assert(add_tx(w, &update));
	for (i = 0; !solve_block(w); i++);

	e = check_block_header(s, &w->bi, &prev, &sha.sha);
	assert(e == PROTOCOL_ECODE_NONE);
	assert(prev == &genesis);

	b = block_add(s, prev, &sha, &w->bi);

	/* This is a NOOP, so should succeed. */
	assert(check_prev_txhashes(s, b, NULL, NULL));

	/* Put the single tx into the shard. */
	shard = new_block_shard(s, update.shard, 1);
	shard->txcount = 1;
	shard->u[0].txp = txptr_with_ref(shard, t, refs);

	/* This should all be correct. */
	check_block_shard(s, b, shard);
	b->shard[shard->shardnum] = shard;

	/* Should require a prev_merkle per shard for each of 2 prev blocks. */
	assert(num_prev_txhashes(b) == (2 << genesis.bi.hdr->shard_order));
	prev_txhashes = make_prev_txhashes(s, b, helper_addr(1));
	assert(tal_count(prev_txhashes) == num_prev_txhashes(b));

	/* Solve third block. */
	fake_time++;
	prevs[0] = b->sha;
	prevs[1] = genesis.sha;
	w = new_working_block(s, 0x1ffffff0, prev_txhashes, num_prev_txhashes(b),
			      block_height(&b->bi) + 1,
			      next_shard_order(b),
			      prevs, helper_addr(1));
	for (i = 0; !solve_block(w); i++);

	e = check_block_header(s, &w->bi, &prev, &sha.sha);
	assert(e == PROTOCOL_ECODE_NONE);
	assert(prev == b);

	b = block_add(s, prev, &sha, &w->bi);

	/* This should be correct. */
	assert(check_prev_txhashes(s, b, NULL, NULL));

	tal_free(s);
	return 0;
}