From 7283efa5b5a302208aef699a81903d51cb3ab45d Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Thu, 26 Sep 2019 21:07:20 +0200 Subject: [PATCH] elements: Add amount_asset to support more than just plain satoshis Currently the only source for amount_asset is the value getter on a tx output, and we don't hand it too far around (mainly ignoring it if it isn't the chain's main currency). Eventually we could bubble them up to the wallet, use them to select outputs or actually support assets in the channels. Since we don't hand them around too widely I thought it was ok for them to be pass-by-value rather than having to allocate them and pass them around by reference. They're just 41 bytes currently so the overhead should be ok. Signed-off-by: Christian Decker <@cdecker> --- bitcoin/test/run-bitcoin_block_from_hex.c | 6 +++ bitcoin/test/run-tx-encode.c | 6 +++ bitcoin/tx.c | 42 ++++++++++----------- bitcoin/tx.h | 4 +- cli/test/run-large-input.c | 6 +++ cli/test/run-remove-hint.c | 6 +++ common/amount.c | 22 +++++++++++ common/amount.h | 12 ++++++ common/test/run-bigsize.c | 6 +++ common/test/run-cryptomsg.c | 6 +++ common/test/run-derive_basepoints.c | 6 +++ common/test/run-features.c | 6 +++ common/test/run-funding_tx.c | 5 ++- common/test/run-gossip_rcvd_filter.c | 6 +++ common/test/run-ip_port_parsing.c | 6 +++ common/test/run-json.c | 6 +++ common/test/run-json_remove.c | 6 +++ common/test/run-key_derive.c | 6 +++ common/test/run-lock.c | 6 +++ common/test/run-sphinx.c | 6 +++ connectd/test/run-initiator-success.c | 6 +++ connectd/test/run-responder-success.c | 6 +++ lightningd/bitcoind.c | 5 ++- lightningd/chaintopology.c | 6 +-- lightningd/closing_control.c | 10 ++++- lightningd/onchain_control.c | 12 ++++-- lightningd/peer_control.c | 9 +++-- onchaind/onchaind.c | 46 ++++++++++++++++++----- plugins/fundchannel.c | 10 ++++- wallet/wallet.c | 6 ++- wire/test/run-peer-wire.c | 6 +++ 31 files changed, 248 insertions(+), 49 deletions(-) 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,