diff --git a/bitcoin/test/run-bitcoin_block_from_hex.c b/bitcoin/test/run-bitcoin_block_from_hex.c index b263f408d..fd9f1bf15 100644 --- a/bitcoin/test/run-bitcoin_block_from_hex.c +++ b/bitcoin/test/run-bitcoin_block_from_hex.c @@ -6,6 +6,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/bitcoin/test/run-tx-encode.c b/bitcoin/test/run-tx-encode.c index 105b93c91..172930d7e 100644 --- a/bitcoin/test/run-tx-encode.c +++ b/bitcoin/test/run-tx-encode.c @@ -7,6 +7,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 5a1888a72..73a50ed26 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -75,6 +75,7 @@ static bool elements_tx_output_is_fee(const struct bitcoin_tx *tx, int outnum) static struct amount_sat bitcoin_tx_compute_fee(const struct bitcoin_tx *tx) { struct amount_sat fee = AMOUNT_SAT(0), value; + struct amount_asset asset; bool ok; for (size_t i = 0; i < tal_count(tx->input_amounts); i++) { @@ -84,10 +85,12 @@ static struct amount_sat bitcoin_tx_compute_fee(const struct bitcoin_tx *tx) } for (size_t i = 0; i < tx->wtx->num_outputs; i++) { - if (elements_tx_output_is_fee(tx, i)) + asset = bitcoin_tx_output_get_amount(tx, i); + if (elements_tx_output_is_fee(tx, i) || + !amount_asset_is_main(&asset)) continue; - value = bitcoin_tx_output_get_amount(tx, i); + value = amount_asset_to_sat(&asset); ok = amount_sat_sub(&fee, fee, value); assert(ok); } @@ -201,34 +204,31 @@ const u8 *bitcoin_tx_output_get_script(const tal_t *ctx, return res; } -struct amount_sat bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx, - int outnum) +struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx, + int outnum) { - struct amount_sat amount; + struct amount_asset amount; struct wally_tx_output *output; - u64 satoshis; - const u8 *fee_asset_tag; + be64 raw; + assert(tx->chainparams); assert(outnum < tx->wtx->num_outputs); output = &tx->wtx->outputs[outnum]; - fee_asset_tag = tx->chainparams->fee_asset_tag; - if (fee_asset_tag) { - if (memeq(fee_asset_tag, 33, output->asset, output->asset_len)) { - be64 raw; - memcpy(&raw, output->value + 1, sizeof(raw)); - satoshis = be64_to_cpu(raw); - } else { - /* If this is an asset based tx, and we don't know the - * asset type, i.e., it's not bitcoin, return a 0 - * amount */ - satoshis = 0; - } + if (chainparams->is_elements) { + /* We currently only support v1 asset tags */ + assert(output->asset_len == sizeof(amount.asset) && + output->asset[0] == 0x01); + memcpy(&amount.asset, output->asset, sizeof(amount.asset)); + memcpy(&raw, output->value + 1, sizeof(raw)); + amount.value = be64_to_cpu(raw); + } else { - satoshis = tx->wtx->outputs[outnum].satoshi; + /* Do not assign amount.asset, we should never touch it in + * non-elements scenarios. */ + amount.value = tx->wtx->outputs[outnum].satoshi; } - amount.satoshis = satoshis; /* Raw: helper */ return amount; } diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 015bd897e..5e8f8d275 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -110,8 +110,8 @@ const u8 *bitcoin_tx_output_get_script(const tal_t *ctx, const struct bitcoin_tx /** * Helper to just get an amount_sat for the output amount. */ -struct amount_sat bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx, - int outnum); +struct amount_asset bitcoin_tx_output_get_amount(const struct bitcoin_tx *tx, + int outnum); /** * Set the input witness. diff --git a/cli/test/run-large-input.c b/cli/test/run-large-input.c index 9179158b2..f1791de7d 100644 --- a/cli/test/run-large-input.c +++ b/cli/test/run-large-input.c @@ -27,6 +27,12 @@ int test_printf(const char *format, ...); #undef main /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/cli/test/run-remove-hint.c b/cli/test/run-remove-hint.c index dfbec7a80..4e03dd16e 100644 --- a/cli/test/run-remove-hint.c +++ b/cli/test/run-remove-hint.c @@ -30,6 +30,12 @@ int test_fputc(int c, FILE *stream); #undef main /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/amount.c b/common/amount.c index ce38eaa53..7bb2e6d40 100644 --- a/common/amount.c +++ b/common/amount.c @@ -1,9 +1,11 @@ #include +#include #include #include #include #include #include +#include #include bool amount_sat_to_msat(struct amount_msat *msat, @@ -427,3 +429,23 @@ struct amount_sat amount_tx_fee(u32 fee_per_kw, size_t weight) return fee; } + +bool amount_asset_is_main(struct amount_asset *amount) +{ + /* If we're not on elements, there is only one asset. */ + if (!chainparams->is_elements) + return true; + + /* If we are on elements we better check against the chainparams. */ + return memeq(amount->asset, sizeof(amount->asset), + chainparams->fee_asset_tag, sizeof(amount->asset)); +} + +/* Convert from a generic asset to the fee-paying asset if possible. */ +struct amount_sat amount_asset_to_sat(struct amount_asset *amount) +{ + struct amount_sat sats; + assert(amount_asset_is_main(amount)); + sats.satoshis = amount->value; /* Raw: low-level conversion */ + return sats; +} diff --git a/common/amount.h b/common/amount.h index b05b16146..c401d272e 100644 --- a/common/amount.h +++ b/common/amount.h @@ -22,6 +22,11 @@ struct amount_msat { u64 millisatoshis; }; +struct amount_asset { + u64 value; + u8 asset[33]; /* 1 version byte + 32 byte asset_tag */ +}; + /* For constants only: others must be built from primitives! */ #if HAVE_BUILTIN_CONSTANT_P #define AMOUNT_MUST_BE_CONST(c) BUILD_ASSERT_OR_ZERO(IS_COMPILE_CONSTANT(c)) @@ -98,6 +103,13 @@ bool amount_msat_less_sat(struct amount_msat msat, struct amount_sat sat); /* Is msat <= sat? */ bool amount_msat_less_eq_sat(struct amount_msat msat, struct amount_sat sat); +/* Check whether this asset is actually the main / fee-paying asset of the + * current chain. */ +bool amount_asset_is_main(struct amount_asset *asset); + +/* Convert from a generic asset to the fee-paying asset if possible. */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset); + /* Returns true if msat fits in a u32 value. */ WARN_UNUSED_RESULT bool amount_msat_to_u32(struct amount_msat msat, u32 *millisatoshis); diff --git a/common/test/run-bigsize.c b/common/test/run-bigsize.c index 329dfb2d3..b29bf0f0d 100644 --- a/common/test/run-bigsize.c +++ b/common/test/run-bigsize.c @@ -12,6 +12,12 @@ static const char *reason; #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-cryptomsg.c b/common/test/run-cryptomsg.c index ee82b03dd..4165e80ba 100644 --- a/common/test/run-cryptomsg.c +++ b/common/test/run-cryptomsg.c @@ -8,6 +8,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-derive_basepoints.c b/common/test/run-derive_basepoints.c index 28990f84d..34dc8a6ad 100644 --- a/common/test/run-derive_basepoints.c +++ b/common/test/run-derive_basepoints.c @@ -8,6 +8,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-features.c b/common/test/run-features.c index 6f37a6085..5a994ac0f 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -7,6 +7,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-funding_tx.c b/common/test/run-funding_tx.c index 510eefbfd..24e04e397 100644 --- a/common/test/run-funding_tx.c +++ b/common/test/run-funding_tx.c @@ -110,6 +110,7 @@ int main(void) struct bitcoin_signature sig; struct bitcoin_address addr; struct amount_sat tmpamt; + struct amount_asset asset; secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); @@ -184,7 +185,9 @@ int main(void) printf("# fee: %s\n", type_to_string(tmpctx, struct amount_sat, &fee)); - tmpamt = bitcoin_tx_output_get_amount(funding, !funding_outnum); + asset = bitcoin_tx_output_get_amount(funding, !funding_outnum); + assert(amount_asset_is_main(&asset)); + tmpamt = amount_asset_to_sat(&asset); printf("change: %s\n", type_to_string(tmpctx, struct amount_sat, &tmpamt)); diff --git a/common/test/run-gossip_rcvd_filter.c b/common/test/run-gossip_rcvd_filter.c index 097917973..8b43b8074 100644 --- a/common/test/run-gossip_rcvd_filter.c +++ b/common/test/run-gossip_rcvd_filter.c @@ -5,6 +5,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-ip_port_parsing.c b/common/test/run-ip_port_parsing.c index ac43fd89f..51ae60cd5 100644 --- a/common/test/run-ip_port_parsing.c +++ b/common/test/run-ip_port_parsing.c @@ -6,6 +6,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-json.c b/common/test/run-json.c index 251c9681c..a65c0cc4c 100644 --- a/common/test/run-json.c +++ b/common/test/run-json.c @@ -6,6 +6,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-json_remove.c b/common/test/run-json_remove.c index 93624da81..202105a73 100644 --- a/common/test/run-json_remove.c +++ b/common/test/run-json_remove.c @@ -4,6 +4,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-key_derive.c b/common/test/run-key_derive.c index 88d7b30f2..2e63af3f0 100644 --- a/common/test/run-key_derive.c +++ b/common/test/run-key_derive.c @@ -9,6 +9,12 @@ #include "../key_derive.c" /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-lock.c b/common/test/run-lock.c index b36eaa0e6..4c62ebec0 100644 --- a/common/test/run-lock.c +++ b/common/test/run-lock.c @@ -8,6 +8,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c index 9748ad221..b79d24919 100644 --- a/common/test/run-sphinx.c +++ b/common/test/run-sphinx.c @@ -12,6 +12,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/connectd/test/run-initiator-success.c b/connectd/test/run-initiator-success.c index c8cf71976..588cd5f07 100644 --- a/connectd/test/run-initiator-success.c +++ b/connectd/test/run-initiator-success.c @@ -10,6 +10,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/connectd/test/run-responder-success.c b/connectd/test/run-responder-success.c index b2b157347..ca3dbc5b7 100644 --- a/connectd/test/run-responder-success.c +++ b/connectd/test/run-responder-success.c @@ -10,6 +10,12 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED, diff --git a/lightningd/bitcoind.c b/lightningd/bitcoind.c index 7df4e716f..e3f33a394 100644 --- a/lightningd/bitcoind.c +++ b/lightningd/bitcoind.c @@ -849,11 +849,12 @@ static void process_getfilteredblock_step2(struct bitcoind *bitcoind, tx = block->tx[i]; for (size_t j = 0; j < tx->wtx->num_outputs; j++) { const u8 *script = bitcoin_tx_output_get_script(NULL, tx, j); - if (is_p2wsh(script, NULL)) { + struct amount_asset amount = bitcoin_tx_output_get_amount(tx, j); + if (amount_asset_is_main(&amount) && is_p2wsh(script, NULL)) { /* This is an interesting output, remember it. */ o = tal(call->outpoints, struct filteredblock_outpoint); bitcoin_txid(tx, &o->txid); - o->amount = bitcoin_tx_output_get_amount(tx, j); + o->amount = amount_asset_to_sat(&amount); o->txindex = i; o->outnum = j; o->scriptPubKey = tal_steal(o, script); diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 4838243c2..e163e6736 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -658,12 +658,12 @@ static void topo_add_utxos(struct chain_topology *topo, struct block *b) continue; const u8 *script = bitcoin_tx_output_get_script(tmpctx, tx, j); - struct amount_sat amt = bitcoin_tx_output_get_amount(tx, j); + struct amount_asset amt = bitcoin_tx_output_get_amount(tx, j); - if (is_p2wsh(script, NULL)) { + if (amount_asset_is_main(&amt) && is_p2wsh(script, NULL)) { wallet_utxoset_add(topo->ld->wallet, tx, j, b->height, i, script, - amt); + amount_asset_to_sat(&amt)); } } } diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 94f576b09..0d3c972b9 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -22,7 +22,8 @@ static struct amount_sat calc_tx_fee(struct amount_sat sat_in, const struct bitcoin_tx *tx) { - struct amount_sat amt, fee = sat_in; + struct amount_asset amt; + struct amount_sat fee = sat_in; const u8 *oscript; size_t scriptlen; for (size_t i = 0; i < tx->wtx->num_outputs; i++) { @@ -34,7 +35,12 @@ static struct amount_sat calc_tx_fee(struct amount_sat sat_in, if (chainparams->is_elements && scriptlen == 0) continue; - if (!amount_sat_sub(&fee, fee, amt)) + /* Ignore outputs that are not denominated in our main + * currency. */ + if (!amount_asset_is_main(&amt)) + continue; + + if (!amount_sat_sub(&fee, fee, amount_asset_to_sat(&amt))) fatal("Tx spends more than input %s? %s", type_to_string(tmpctx, struct amount_sat, &sat_in), type_to_string(tmpctx, struct bitcoin_tx, tx)); diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index e81dd8c7a..7673cc64b 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -489,10 +489,13 @@ enum watch_result onchaind_funding_spent(struct channel *channel, if (!feerate) { /* We have at least one data point: the last tx's feerate. */ struct amount_sat fee = channel->funding; - for (size_t i = 0; i < channel->last_tx->wtx->num_outputs; i++) - if (!amount_sat_sub(&fee, fee, - bitcoin_tx_output_get_amount( - channel->last_tx, i))) { + for (size_t i = 0; i < channel->last_tx->wtx->num_outputs; i++) { + struct amount_asset asset = + bitcoin_tx_output_get_amount(channel->last_tx, i); + struct amount_sat amt; + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); + if (!amount_sat_sub(&fee, fee, amt)) { log_broken(channel->log, "Could not get fee" " funding %s tx %s", type_to_string(tmpctx, @@ -503,6 +506,7 @@ enum watch_result onchaind_funding_spent(struct channel *channel, channel->last_tx)); return KEEP_WATCHING; } + } feerate = fee.satoshis / bitcoin_tx_weight(tx); /* Raw: reverse feerate extraction */ if (feerate < feerate_floor()) diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 13021ffe0..2ba796205 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -967,13 +967,16 @@ static bool check_funding_tx(const struct bitcoin_tx *tx, const struct channel *channel) { u8 *wscript; + struct amount_asset asset = + bitcoin_tx_output_get_amount(tx, channel->funding_outnum); + + if (!amount_asset_is_main(&asset)) + return false; if (channel->funding_outnum >= tx->wtx->num_outputs) return false; - if (!amount_sat_eq(bitcoin_tx_output_get_amount(tx, - channel->funding_outnum), - channel->funding)) + if (!amount_sat_eq(amount_asset_to_sat(&asset), channel->funding)) return false; wscript = bitcoin_redeem_2of2(tmpctx, diff --git a/onchaind/onchaind.c b/onchaind/onchaind.c index 9ff92e594..b391751f8 100644 --- a/onchaind/onchaind.c +++ b/onchaind/onchaind.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -163,11 +164,14 @@ static bool set_htlc_timeout_fee(struct bitcoin_tx *tx, const struct bitcoin_signature *remotesig, const u8 *wscript) { - static struct amount_sat fee = AMOUNT_SAT_INIT(UINT64_MAX); - struct amount_sat amount = bitcoin_tx_output_get_amount(tx, 0); + static struct amount_sat amount, fee = AMOUNT_SAT_INIT(UINT64_MAX); + struct amount_asset asset = bitcoin_tx_output_get_amount(tx, 0); size_t weight = elements_add_overhead(663, tx->wtx->num_inputs, tx->wtx->num_outputs); + assert(amount_asset_is_main(&asset)); + amount = amount_asset_to_sat(&asset); + /* BOLT #3: * * The fee for an HTLC-timeout transaction: @@ -202,6 +206,7 @@ static void set_htlc_success_fee(struct bitcoin_tx *tx, const u8 *wscript) { static struct amount_sat amt, fee = AMOUNT_SAT_INIT(UINT64_MAX); + struct amount_asset asset; size_t weight = elements_add_overhead(703, tx->wtx->num_inputs, tx->wtx->num_outputs); /* BOLT #3: @@ -225,7 +230,10 @@ static void set_htlc_success_fee(struct bitcoin_tx *tx, return; } - amt = bitcoin_tx_output_get_amount(tx, 0); + asset = bitcoin_tx_output_get_amount(tx, 0); + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); + if (!amount_sat_sub(&amt, amt, fee)) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Cannot deduct htlc-success fee %s from tx %s", @@ -934,6 +942,7 @@ static void resolve_htlc_tx(const struct chainparams *chainparams, struct tracked_output *out; struct bitcoin_tx *tx; struct amount_sat amt; + struct amount_asset asset; enum tx_type tx_type = OUR_DELAYED_RETURN_TO_WALLET; u8 *wscript = bitcoin_wscript_htlc_tx(htlc_tx, to_self_delay[LOCAL], &keyset->self_revocation_key, @@ -949,7 +958,9 @@ static void resolve_htlc_tx(const struct chainparams *chainparams, * `to_self_delay` field) before spending that HTLC-timeout * output. */ - amt = bitcoin_tx_output_get_amount(htlc_tx, 0); + asset = bitcoin_tx_output_get_amount(htlc_tx, 0); + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); out = new_tracked_output(chainparams, outs, htlc_txid, tx_blockheight, (*outs)[out_index]->resolved->tx_type, 0, amt, @@ -1796,7 +1807,11 @@ static void handle_our_unilateral(const struct bitcoin_tx *tx, const size_t *matches; size_t which_htlc; const u8 *oscript = bitcoin_tx_output_get_script(tmpctx, tx, i); - struct amount_sat amt = bitcoin_tx_output_get_amount(tx, i); + struct amount_asset asset = bitcoin_tx_output_get_amount(tx, i); + struct amount_sat amt; + + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); if (chainparams->is_elements && (oscript == NULL || tal_bytelen(oscript) == 0)) { @@ -2007,7 +2022,11 @@ static void tell_wallet_to_remote(const struct bitcoin_tx *tx, const struct pubkey *per_commit_point, bool option_static_remotekey) { - struct amount_sat amt = bitcoin_tx_output_get_amount(tx, outnum); + struct amount_asset asset = bitcoin_tx_output_get_amount(tx, outnum); + struct amount_sat amt; + + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); /* A NULL per_commit_point is how we indicate the pubkey doesn't need * changing. */ @@ -2157,7 +2176,10 @@ static void handle_their_cheat(const struct bitcoin_tx *tx, const size_t *matches; size_t which_htlc; const u8 *oscript = bitcoin_tx_output_get_script(tmpctx, tx, i); - struct amount_sat amt = bitcoin_tx_output_get_amount(tx, i); + struct amount_asset asset = bitcoin_tx_output_get_amount(tx, i); + struct amount_sat amt; + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); if (chainparams->is_elements && (oscript == NULL || tal_bytelen(oscript) == 0)) { @@ -2391,7 +2413,10 @@ static void handle_their_unilateral(const struct bitcoin_tx *tx, const size_t *matches; size_t which_htlc; const u8 *oscript = bitcoin_tx_output_get_script(tmpctx, tx, i); - struct amount_sat amt = bitcoin_tx_output_get_amount(tx, i); + struct amount_asset asset = bitcoin_tx_output_get_amount(tx, i); + struct amount_sat amt; + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); if (chainparams->is_elements && (oscript == NULL || tal_bytelen(oscript) == 0)) { @@ -2556,7 +2581,10 @@ static void handle_unknown_commitment(const struct bitcoin_tx *tx, for (size_t i = 0; i < tx->wtx->num_outputs; i++) { struct tracked_output *out; const u8 *oscript = bitcoin_tx_output_get_script(tmpctx, tx, i); - struct amount_sat amt = bitcoin_tx_output_get_amount(tx, i); + struct amount_asset asset = bitcoin_tx_output_get_amount(tx, i); + struct amount_sat amt; + assert(amount_asset_is_main(&asset)); + amt = amount_asset_to_sat(&asset); if (oscript != NULL && local_script && scripteq(oscript, local_script)) { diff --git a/plugins/fundchannel.c b/plugins/fundchannel.c index 0f22acd82..456f07505 100644 --- a/plugins/fundchannel.c +++ b/plugins/fundchannel.c @@ -340,6 +340,7 @@ static struct command_result *tx_prepare_dryrun(struct command *cmd, struct amount_sat funding; bool funding_found; u8 *placeholder = tal_hexdata(tmpctx, placeholder_script, strlen(placeholder_script)); + struct amount_asset asset; /* Stash the 'reserved' txid to unreserve later */ hex = json_strdup(tmpctx, buf, json_get_member(buf, result, "txid")); @@ -355,8 +356,15 @@ static struct command_result *tx_prepare_dryrun(struct command *cmd, funding_found = false; for (size_t i = 0; i < tx->wtx->num_outputs; i++) { const u8 *output_script = bitcoin_tx_output_get_script(tmpctx, tx, i); + asset = bitcoin_tx_output_get_amount(tx, i); + + /* We do not support funding a channel with anything but the + * main asset, for now. */ + if (!amount_asset_is_main(&asset)) + continue; + if (scripteq(output_script, placeholder)) { - funding = bitcoin_tx_output_get_amount(tx, i); + funding = amount_asset_to_sat(&asset); funding_found = true; break; } diff --git a/wallet/wallet.c b/wallet/wallet.c index ea4fcb467..0e24a68c1 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1520,6 +1520,10 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, u32 index; bool is_p2sh; const u8 *script; + struct amount_asset asset = bitcoin_tx_output_get_amount(tx, output); + + if (!amount_asset_is_main(&asset)) + continue; script = bitcoin_tx_output_get_script(tmpctx, tx, output); if (!script) @@ -1531,7 +1535,7 @@ int wallet_extract_owned_outputs(struct wallet *w, const struct bitcoin_tx *tx, utxo = tal(w, struct utxo); utxo->keyindex = index; utxo->is_p2sh = is_p2sh; - utxo->amount = bitcoin_tx_output_get_amount(tx, output); + utxo->amount = amount_asset_to_sat(&asset); utxo->status = output_state_available; bitcoin_txid(tx, &utxo->txid); utxo->outnum = output; diff --git a/wire/test/run-peer-wire.c b/wire/test/run-peer-wire.c index 0151a8117..dfe3e2741 100644 --- a/wire/test/run-peer-wire.c +++ b/wire/test/run-peer-wire.c @@ -12,6 +12,12 @@ secp256k1_context *secp256k1_ctx; /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_is_main */ +bool amount_asset_is_main(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_is_main called!\n"); abort(); } +/* Generated stub for amount_asset_to_sat */ +struct amount_sat amount_asset_to_sat(struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_to_sat called!\n"); abort(); } /* Generated stub for amount_sat_add */ bool amount_sat_add(struct amount_sat *val UNNEEDED, struct amount_sat a UNNEEDED,