u32 find_matching_input(const union protocol_tx *tx, const struct protocol_input *inp) { unsigned int i; /* Figure out which input of other did the spend. */ for (i = 0; i < num_inputs(tx); i++) { if (structeq(&tx_input(tx, i)->input, &inp->input) && tx_input(tx, i)->output == inp->output) return i; } abort(); }
void complain_bad_amount(struct state *state, struct block *block, const struct protocol_proof *proof, const union protocol_tx *tx, const struct protocol_input_ref *refs, const union protocol_tx *intx[]) { struct protocol_pkt_complain_tx_bad_amount *pkt; unsigned int i; assert(num_inputs(tx)); log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->depth)); log_add_struct(state->log, struct protocol_double_sha, &block->sha); log_add(state->log, " invalid amounts in tx %u of shard %u ", proof->pos.txoff, le16_to_cpu(proof->pos.shard)); log_add_struct(state->log, union protocol_tx, tx); log_add(state->log, " with inputs: "); pkt = tal_packet(block, struct protocol_pkt_complain_tx_bad_amount, PROTOCOL_PKT_COMPLAIN_TX_BAD_AMOUNT); tal_packet_append_proven_tx(&pkt, proof, tx, refs); for (i = 0; i < num_inputs(tx); i++) { log_add_struct(state->log, union protocol_tx, intx[i]); log_add(state->log, " (output %u)", le16_to_cpu(tx_input(tx, i)->output)); tal_packet_append_tx(&pkt, intx[i]); } publish_complaint(state, block, pkt, NULL); }
void complain_bad_input(struct state *state, struct block *block, const struct protocol_proof *proof, const union protocol_tx *tx, const struct protocol_input_ref *refs, unsigned int bad_input, const union protocol_tx *intx) { struct protocol_pkt_complain_tx_bad_input *pkt; assert(tx_input(tx, bad_input)); log_unusual(state->log, "Block %u ", le32_to_cpu(block->hdr->depth)); log_add_struct(state->log, struct protocol_double_sha, &block->sha); log_add(state->log, " invalid due to tx %u in shard %u ", proof->pos.txoff, le16_to_cpu(proof->pos.shard)); log_add_struct(state->log, union protocol_tx, tx); log_add(state->log, " with bad input %u ", bad_input); log_add_struct(state->log, union protocol_tx, intx); pkt = tal_packet(block, struct protocol_pkt_complain_tx_bad_input, PROTOCOL_PKT_COMPLAIN_TX_BAD_INPUT); pkt->inputnum = cpu_to_le32(bad_input); tal_packet_append_proven_tx(&pkt, proof, tx, refs); tal_packet_append_tx(&pkt, intx); publish_complaint(state, block, pkt, NULL); }
static void json_add_inputs(struct json_result *response, const union protocol_tx *tx) { unsigned int i; json_array_start(response, "vin"); for (i = 0; i < num_inputs(tx); i++) json_add_input(response, NULL, tx_input(tx, i)); json_array_end(response); }
static bool find_pending_doublespend(struct state *state, const union protocol_tx *tx) { unsigned int i; for (i = 0; i < num_inputs(tx); i++) { struct inputhash_elem *ie; struct inputhash_iter iter; const struct protocol_input *inp = tx_input(tx, i); for (ie = inputhash_firstval(&state->inputhash, &inp->input, le16_to_cpu(inp->output), &iter); ie; ie = inputhash_nextval(&state->inputhash, &inp->input, le16_to_cpu(inp->output), &iter)) { /* OK, is the tx which spend it pending? */ if (txhash_get_pending_tx(state, &ie->used_by)) return true; } } return false; }
enum ref_ecode check_tx_refs(struct state *state, const struct block *block, const union protocol_tx *tx, const struct protocol_input_ref *refs, unsigned int *bad_ref, struct block **block_referred_to) { unsigned int i, num = num_inputs(tx); bool all_known = true; assert(check_refs(state, block, refs, num) == PROTOCOL_ECODE_NONE); for (i = 0; i < num; i++) { struct block *b; struct protocol_txrefhash scratch; const struct protocol_txrefhash *txp; b = block_ancestor(block, le32_to_cpu(refs[i].blocks_ago)); txp = txrefhash_in_shard(b->shard[le16_to_cpu(refs[i].shard)], refs[i].txoff, &scratch); if (!txp) { *bad_ref = i; *block_referred_to = b; all_known = false; /* Keep looking in case there are worse issues. */ continue; } if (!structeq(&txp->txhash, &tx_input(tx, i)->input)) { *bad_ref = i; *block_referred_to = b; return ECODE_REF_BAD_HASH; } } if (!all_known) return ECODE_REF_UNKNOWN; return ECODE_REF_OK; }