Exemplo n.º 1
0
static bool insert_pending_tx(struct state *state, const union protocol_tx *tx)
{
	struct pending_block *pending = state->pending;
	struct pending_tx *pend;
	u16 shard;
	size_t num, pos;

	shard = shard_of_tx(tx, next_shard_order(state->longest_knowns[0]));
	num = tal_count(pending->pend[shard]);

	if (num == 255) {
		log_unusual(state->log,
			    "Too many pending txs in shard %u", shard);
		/* Treat it as unknown, so it will get in next time. */
		add_to_unknown_pending(state, tx);
		return true;
	}

	/* Caller checks it isn't a dup! */
	if (find_pending_in_arr(pending->pend[shard], tx, &pos))
		abort();

	pend = new_pending_tx(state->pending, tx);
	pend->refs = create_refs(state, state->longest_knowns[0], tx, 1);

	/* If inputs are too *old*, we can fail to make references. */
	if (!pend->refs)
		return false;

	/* Insert into array at pos. */
	tal_arr_add(&pending->pend[shard], pos, pend);

	log_debug(state->log, "Added tx to shard %u position %zu",
		  shard, pos);
	tell_generator_new_pending(state, shard, pos);
	return true;
}
Exemplo n.º 2
0
int main(void)
{
	struct state *state;
	union protocol_tx *t, *t2;
	struct protocol_gateway_payment payment;
	u8 *prev_txhashes;
	enum input_ecode e;
	struct protocol_tx_id txid;
	unsigned int bad_input;
	bool too_old, already_known;
	const struct block *b;
	struct protocol_block_id prevs[PROTOCOL_NUM_PREV_IDS];
	struct protocol_input inputs[1];
	
	pseudorand_init();
	state = new_state(true);

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

	/* Create a block with a gateway tx in it. */
	payment.send_amount = cpu_to_le32(1000);
	payment.output_addr = *helper_addr(0);
	t = create_from_gateway_tx(state, helper_gateway_public_key(),
				   1, &payment, false, helper_gateway_key(state));
	hash_tx(t, &txid);
	log_unusual(state->log, "Gateway tx is ");
	log_add_struct(state->log, struct protocol_tx_id, &txid);

	e = add_pending_tx(state, t, &txid, &bad_input,
			   &too_old, &already_known);
	assert(e == ECODE_INPUT_OK);
	assert(!already_known);

	assert(state->pending->num_unknown == 0);
	assert(num_pending_known(state) == 1);

	b = solve_pending(state);

	/* Now we can spend it. */
	prev_txhashes = make_prev_txhashes(state, b, helper_addr(1));
	prevs[0] = b->sha;
	prevs[1] = genesis.sha;
	w = new_working_block(state, block_difficulty(&b->bi),
			      prev_txhashes, tal_count(prev_txhashes),
			      block_height(&b->bi) + 1,
			      next_shard_order(b),
			      prevs, helper_addr(1));

	hash_tx(t, &inputs[0].input);
	inputs[0].output = 0;
	inputs[0].unused = 0;

	t2 = t = create_normal_tx(state, helper_addr(1),
				  500, 500 - PROTOCOL_FEE(500), 1, true, inputs,
				  helper_private_key(state, 0));
	
	hash_tx(t, &txid);
	e = add_pending_tx(state, t, &txid, &bad_input,
			   &too_old, &already_known);
	assert(e == ECODE_INPUT_OK);
	assert(!already_known);
	assert(state->pending->num_unknown == 0);
	assert(num_pending_known(state) == 1);

	log_unusual(state->log, "Normal tx is ");
	log_add_struct(state->log, struct protocol_tx_id, &txid);

	/* Should recognize double spend */
	t = create_normal_tx(state, helper_addr(2),
			     300, 700 - PROTOCOL_FEE(300), 1, true, inputs,
			     helper_private_key(state, 0));
	
	hash_tx(t, &txid);
	e = add_pending_tx(state, t, &txid, &bad_input,
			   &too_old, &already_known);
	assert(e == ECODE_INPUT_DOUBLESPEND);
	assert(!already_known);

	assert(state->pending->num_unknown == 0);
	assert(num_pending_known(state) == 1);

	b = solve_pending(state);
	/* The first should be included. */
	assert(num_txs(b) == 1);

	/* There should be nothing left. */ 
	assert(state->pending->num_unknown == 0);
	assert(num_pending_known(state) == 0);

	/* Now retry double spend. */
	t = create_normal_tx(state, helper_addr(2),
			     300, 700 - PROTOCOL_FEE(300), 1, true, inputs,
			     helper_private_key(state, 0));
	
	hash_tx(t, &txid);
	e = add_pending_tx(state, t, &txid, &bad_input,
			   &too_old, &already_known);
	assert(e == ECODE_INPUT_DOUBLESPEND);
	assert(!too_old);
	assert(!already_known);

	/* Clear inputhash manually. */
	inputhash_del_tx(&state->inputhash, t2);

	dump_inputhash(state, &state->inputhash);
	tal_free(state);
	return 0;
}
Exemplo n.º 3
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;
}