size_t measure_tx_cost(const struct bitcoin_tx *tx) { size_t non_witness_len = 0, witness_len = 0; add_tx(tx, add_measure, &non_witness_len, false); if (uses_witness(tx)) add_witnesses(tx, add_measure, &witness_len); /* Witness bytes only add 1/4 of normal bytes, for cost. */ return non_witness_len * 4 + witness_len; }
static void add_tx(const struct bitcoin_tx *tx, void (*add)(const void *, size_t, void *), void *addp, bool extended) { varint_t i; u8 flag = 0; add_le32(tx->version, add, addp); if (extended) { u8 marker; /* BIP 144 */ /* marker char Must be zero */ /* flag char Must be nonzero */ marker = 0; add(&marker, 1, addp); /* BIP 141: The flag MUST be a 1-byte non-zero * value. Currently, 0x01 MUST be used. * * BUT: Current segwit4 branch breaks fundrawtransaction; * it sees 0 inputs and thinks it's extended format. * Make it really an extended format, but without * witness. */ if (uses_witness(tx)) flag = SEGREGATED_WITNESS_FLAG; add(&flag, 1, addp); } add_varint(tx->input_count, add, addp); for (i = 0; i < tx->input_count; i++) add_tx_input(&tx->input[i], add, addp); add_varint(tx->output_count, add, addp); for (i = 0; i < tx->output_count; i++) add_tx_output(&tx->output[i], add, addp); if (flag & SEGREGATED_WITNESS_FLAG) add_witnesses(tx, add, addp); add_le32(tx->lock_time, add, addp); }
static void push_tx(const struct bitcoin_tx *tx, void (*push)(const void *, size_t, void *), void *pushp, bool bip144) { varint_t i; u8 flag = 0; push_le32(tx->version, push, pushp); if (bip144 && uses_witness(tx)) flag |= SEGREGATED_WITNESS_FLAG; /* BIP 141: The flag MUST be a 1-byte non-zero value. */ /* ie. if no flags set, we fallback to pre-BIP144-style */ if (flag) { u8 marker = 0; /* BIP 144 */ /* marker char Must be zero */ /* flag char Must be nonzero */ push(&marker, 1, pushp); push(&flag, 1, pushp); } push_varint(tal_count(tx->input), push, pushp); for (i = 0; i < tal_count(tx->input); i++) push_tx_input(&tx->input[i], push, pushp); push_varint(tal_count(tx->output), push, pushp); for (i = 0; i < tal_count(tx->output); i++) push_tx_output(&tx->output[i], push, pushp); if (flag & SEGREGATED_WITNESS_FLAG) push_witnesses(tx, push, pushp); push_le32(tx->lock_time, push, pushp); }
u8 *linearize_tx(const tal_t *ctx, const struct bitcoin_tx *tx) { u8 *arr = tal_arr(ctx, u8, 0); add_tx(tx, add_linearize, &arr, uses_witness(tx)); return arr; }