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;
}
Beispiel #2
0
/* We've added a whole heap of transactions, recheck them and set input refs. */
void recheck_pending_txs(struct state *state)
{
	unsigned int unknown, known, total;
	unsigned int i, shard;
	const union protocol_tx **txs;
	struct pending_unknown_tx *utx;

	if (!state->pending->needs_recheck)
		return;

	state->pending->needs_recheck = false;

	/* Size up and allocate an array. */
	unknown = state->pending->num_unknown;
	known = num_pending_known(state);

	/* Avoid logging if nothing pending. */
	if (unknown == 0 && known == 0)
		return;
	
	txs = tal_arr(state, const union protocol_tx *, unknown + known);

	log_info(state->log, "Rechecking pending (%u known, %u unknown)",
		  known, unknown);

	/* Now move pending from shards. */
	total = 0;
	for (shard = 0; shard < ARRAY_SIZE(state->pending->pend); shard++) {
		struct pending_tx **pend = state->pending->pend[shard];
		unsigned int i;

		for (i = 0; i < tal_count(pend); i++) {
			remove_pending_tx_from_hashes(state, pend[i]->tx);
			txs[total++] = tal_steal(txs, pend[i]->tx);
		}
	}

	/* And last we move the unknown ones. */
	while ((utx = list_pop(&state->pending->unknown_tx,
			       struct pending_unknown_tx, list)) != NULL) {
		remove_pending_tx_from_hashes(state, utx->tx);
		txs[total++] = tal_steal(txs, utx->tx);
	}

	assert(total == unknown + known);

	/* Clean up pending (frees everything above as a side effect). */
	tal_free(state->pending);
	state->pending = new_pending_block(state);

	/* Now re-add them */
	for (i = 0; i < tal_count(txs); i++) {
		unsigned int bad_input_num;
		struct protocol_double_sha sha;

		hash_tx(txs[i], &sha);
		add_pending_tx(state, txs[i], &sha, &bad_input_num, NULL);
	}

	/* Just to print the debug! */		
	known = 0;
	for (shard = 0; shard < ARRAY_SIZE(state->pending->pend); shard++)
		known += tal_count(state->pending->pend[shard]);

	log_info(state->log, "Now have %u known, %u unknown",
		  known, state->pending->num_unknown);

	/* Restart generator on this block. */
	restart_generating(state);
}