Exemplo n.º 1
0
void remove_tx_from_hashes(struct state *state,
                           struct block *block, u16 shard, u8 txoff)
{
    struct protocol_double_sha scratch;
    const struct protocol_double_sha *txhash;
    const union protocol_tx *tx;
    union txhash_block_or_tx u;

    u.block = block;

    if (shard_is_tx(block->shard[shard], txoff)) {
        tx = tx_for(block->shard[shard], txoff);
        hash_tx(tx, &scratch);
        txhash = &scratch;
    } else {
        txhash = &block->shard[shard]->u[txoff].hash->txhash;
        tx = NULL;
    }

    txhash_del_tx(&state->txhash, u, shard, txoff, TX_IN_BLOCK, txhash);

    /* If this tx is no longer known at *all*, we can remove from
     * input hash too. */
    if (tx && !txhash_gettx(&state->txhash, txhash, TX_PENDING))
        inputhash_del_tx(&state->inputhash, tx);
}
Exemplo n.º 2
0
void hash_tx_and_refs(const union protocol_tx *tx,
		      const struct protocol_input_ref *refs,
		      struct protocol_txrefhash *txrefhash)
{
	hash_tx(tx, &txrefhash->txhash);
	hash_refs(refs, num_inputs(tx), &txrefhash->refhash);
}
Exemplo n.º 3
0
void remove_pending_tx_from_hashes(struct state *state,
                                   const union protocol_tx *tx)
{
    struct protocol_double_sha txhash;
    union txhash_block_or_tx u;

    hash_tx(tx, &txhash);
    u.tx = tx;
    txhash_del_tx(&state->txhash, u, 0, 0, TX_PENDING, &txhash);

    /* If this tx is no longer known at *all*, we can remove from
     * input hash too. */
    if (!txhash_gettx(&state->txhash, &txhash, TX_PENDING))
        inputhash_del_tx(&state->inputhash, tx);
}
Exemplo n.º 4
0
void add_tx_to_hashes(struct state *state,
                      const tal_t *ctx,
                      struct block *block, u16 shard, u8 txoff,
                      const union protocol_tx *tx)
{
    struct protocol_double_sha txhash;

    hash_tx(tx, &txhash);

    /* First time we heard of full transaction?  Add inputs. */
    if (!txhash_gettx(&state->txhash, &txhash, TX_PENDING))
        inputhash_add_tx(&state->inputhash, ctx, tx);

    add_txhash_to_hashes(state, ctx, block, shard, txoff, &txhash);
}
Exemplo n.º 5
0
void add_pending_tx_to_hashes(struct state *state,
                              const tal_t *ctx,
                              const union protocol_tx *tx)
{
    struct protocol_double_sha txhash;
    union txhash_block_or_tx u;

    hash_tx(tx, &txhash);

    assert(!txhash_get_pending_tx(state, &txhash));

    /* First time we heard of full transaction?  Add inputs. */
    if (!txhash_gettx(&state->txhash, &txhash, TX_PENDING))
        inputhash_add_tx(&state->inputhash, ctx, tx);

    u.tx = tx;
    txhash_add_tx(&state->txhash, ctx, u, 0, 0, TX_PENDING, &txhash);
}
Exemplo n.º 6
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.º 7
0
void json_add_tx(struct json_result *response, const char *fieldname,
		 struct state *state,
		 const union protocol_tx *tx,
		 const struct block *block,
		 unsigned int confirms)
{
	struct protocol_tx_id sha;

	json_object_start(response, fieldname);
	hash_tx(tx, &sha);
	json_add_tx_id(response, "txid", &sha);
	if (block)
		json_add_block_id(response, "block", &block->sha);
	json_add_num(response, "confirmations", confirms);
	json_add_num(response, "version", tx->hdr.version);
	json_add_num(response, "features", tx->hdr.features);

	switch (tx_type(tx)) {
	case TX_NORMAL:
		json_add_string(response, "type", "TX_NORMAL");
		json_add_pubkey(response, "input_key", &tx->normal.input_key);
		json_add_address(response, "output_addr",
				 state->test_net, &tx->normal.output_addr);
		json_add_num(response, "send_amount",
			     le32_to_cpu(tx->normal.send_amount));
		json_add_num(response, "change_amount",
			     le32_to_cpu(tx->normal.change_amount));
		json_add_signature(response, "signature",
				   &tx->normal.signature);
		json_add_inputs(response, tx);
		goto finish;
	case TX_FROM_GATEWAY:
		json_add_string(response, "type", "TX_FROM_GATEWAY");
		json_add_pubkey(response, "gateway_key",
				&tx->from_gateway.gateway_key);
		json_add_signature(response, "signature",
				   &tx->normal.signature);
		json_add_outputs(response, state, tx);
		goto finish;
	case TX_TO_GATEWAY:
		json_add_string(response, "type", "TX_TO_GATEWAY");
		json_add_pubkey(response, "input_key",
				&tx->to_gateway.input_key);
		json_add_address(response, "output_addr",
				 state->test_net,
				 &tx->to_gateway.to_gateway_addr);
		json_add_num(response, "send_amount",
			     le32_to_cpu(tx->to_gateway.send_amount));
		json_add_num(response, "change_amount",
			     le32_to_cpu(tx->to_gateway.change_amount));
		json_add_signature(response, "signature",
				   &tx->to_gateway.signature);
		json_add_inputs(response, tx);
		goto finish;
	case TX_CLAIM:
		json_add_string(response, "type", "TX_CLAIM");
		json_add_pubkey(response, "input_key", &tx->claim.input_key);
		json_add_num(response, "amount", le32_to_cpu(tx->claim.amount));
		json_add_signature(response, "claim", &tx->claim.signature);
		json_add_input(response, "input", &tx->claim.input);
		goto finish;
	}
	abort();

finish:
	json_object_end(response);
}
Exemplo n.º 8
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);
}