diff --git a/.gitmodules b/.gitmodules index 841626523a10..314d8c5d2590 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,5 +9,6 @@ url = https://github.com/ianlancetaylor/libbacktrace.git [submodule "external/libwally-core"] path = external/libwally-core - url = https://github.com/ElementsProject/libwally-core.git + url = https://github.com/niftynei/libwally-core.git ignore = dirty + branch = nifty/blessed-branch diff --git a/bitcoin/chainparams.h b/bitcoin/chainparams.h index 40a6ea8fad7e..eade2344b8dd 100644 --- a/bitcoin/chainparams.h +++ b/bitcoin/chainparams.h @@ -9,6 +9,8 @@ #include #include +#define ELEMENTS_ASSET_LEN 33 + struct chainparams { const char *network_name; const char *bip173_name; diff --git a/bitcoin/psbt.c b/bitcoin/psbt.c index a7cabe47f7bf..62e3f3522bd7 100644 --- a/bitcoin/psbt.c +++ b/bitcoin/psbt.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -47,7 +48,10 @@ struct wally_psbt *new_psbt(const tal_t *ctx, const struct wally_tx *wtx) size_t *script_lens; struct wally_tx_witness_stack **witnesses; - wally_err = wally_psbt_init_alloc(wtx->num_inputs, wtx->num_outputs, 0, &psbt); + if (is_elements(chainparams)) + wally_err = wally_psbt_elements_init_alloc(wtx->num_inputs, wtx->num_outputs, 0, &psbt); + else + wally_err = wally_psbt_init_alloc(wtx->num_inputs, wtx->num_outputs, 0, &psbt); assert(wally_err == WALLY_OK); tal_add_destructor(psbt, psbt_destroy); @@ -263,6 +267,16 @@ bool psbt_input_set_partial_sig(struct wally_psbt *psbt, size_t in, sizeof(sig->s.data)) == WALLY_OK; } +static void psbt_input_set_witness_utxo(struct wally_psbt *psbt, size_t in, + struct wally_tx_output *txout) +{ + int wally_err; + assert(psbt->num_inputs > in); + wally_err = wally_psbt_input_set_witness_utxo(&psbt->inputs[in], + txout); + assert(wally_err == WALLY_OK); +} + void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in, const u8 *scriptPubkey, struct amount_sat amt) { @@ -270,7 +284,6 @@ void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in, int wally_err; u8 *scriptpk; - assert(psbt->num_inputs > in); if (scriptPubkey) { assert(is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL) || is_p2sh(scriptPubkey, NULL)); @@ -289,10 +302,34 @@ void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in, tal_bytelen(scriptpk), &prev_out); assert(wally_err == WALLY_OK); - wally_err = wally_psbt_input_set_witness_utxo(&psbt->inputs[in], - prev_out); + psbt_input_set_witness_utxo(psbt, in, prev_out); +} + +static void psbt_input_set_elements_prev_utxo(struct wally_psbt *psbt, + size_t in, + const u8 *scriptPubkey, + struct amount_asset *asset, + const u8 *nonce) +{ + struct wally_tx_output *prev_out; + int wally_err; + + u8 *prefixed_value = amount_asset_extract_value(psbt, asset); + + wally_err = + wally_tx_elements_output_init_alloc(scriptPubkey, + tal_bytelen(scriptPubkey), + asset->asset, + sizeof(asset->asset), + prefixed_value, + tal_bytelen(prefixed_value), + nonce, + tal_bytelen(nonce), + NULL, 0, + NULL, 0, + &prev_out); assert(wally_err == WALLY_OK); - tal_steal(psbt, psbt->inputs[in].witness_utxo); + psbt_input_set_witness_utxo(psbt, in, prev_out); } void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in, @@ -312,6 +349,76 @@ void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in, psbt_input_set_prev_utxo(psbt, in, scriptPubkey, amt); } +static void +psbt_input_set_elements_prev_utxo_wscript(struct wally_psbt *psbt, + size_t in, + const u8 *wscript, + struct amount_asset *asset, + const u8 *nonce) +{ + int wally_err; + const u8 *scriptPubkey; + + if (wscript) { + scriptPubkey = scriptpubkey_p2wsh(psbt, wscript); + wally_err = wally_psbt_input_set_witness_script( + &psbt->inputs[in], + cast_const(u8 *, wscript), + tal_bytelen(wscript)); + assert(wally_err == WALLY_OK); + } else + scriptPubkey = NULL; + + psbt_input_set_elements_prev_utxo(psbt, in, scriptPubkey, + asset, nonce); +} + +void psbt_elements_input_init_witness(struct wally_psbt *psbt, size_t in, + const u8 *witscript, + struct amount_asset *asset, + const u8 *nonce) +{ + psbt_input_set_elements_prev_utxo_wscript( + psbt, in, witscript, + asset, nonce); + + if (asset->value > 0) + wally_psbt_elements_input_set_value(&psbt->inputs[in], + asset->value); + + /* PSET expects an asset tag without the prefix */ + if (wally_psbt_elements_input_set_asset(&psbt->inputs[in], + asset->asset + 1, + ELEMENTS_ASSET_LEN - 1) != WALLY_OK) + abort(); +} + +void psbt_elements_input_init(struct wally_psbt *psbt, size_t in, + const u8 *scriptPubkey, + struct amount_asset *asset, + const u8 *nonce) +{ + psbt_input_set_elements_prev_utxo(psbt, in, + scriptPubkey, + asset, nonce); + + if (asset->value > 0) { + if (wally_psbt_elements_input_set_value( + &psbt->inputs[in], + asset->value) != WALLY_OK) + abort(); + + } + + /* PSET expects an asset tag without the prefix */ + /* FIXME: Verify that we're sending unblinded asset tag */ + if (wally_psbt_elements_input_set_asset( + &psbt->inputs[in], + asset->asset + 1, + ELEMENTS_ASSET_LEN - 1) != WALLY_OK) + abort(); +} + bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in, const u8 *redeemscript) { @@ -329,7 +436,10 @@ struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt, struct amount_sat val; assert(in < psbt->num_inputs); if (psbt->inputs[in].witness_utxo) { - val.satoshis = psbt->inputs[in].witness_utxo->satoshi; /* Raw: type conversion */ + struct amount_asset amt_asset = + wally_tx_output_get_amount(psbt->inputs[in].witness_utxo); + assert(amount_asset_is_main(&amt_asset)); + val = amount_asset_to_sat(&amt_asset); } else if (psbt->inputs[in].non_witness_utxo) { int idx = psbt->tx->inputs[in].index; struct wally_tx *prev_tx = psbt->inputs[in].non_witness_utxo; diff --git a/bitcoin/psbt.h b/bitcoin/psbt.h index 1282e41a21c8..c47f185b1ecf 100644 --- a/bitcoin/psbt.h +++ b/bitcoin/psbt.h @@ -10,6 +10,7 @@ struct wally_tx_output; struct wally_psbt; struct wally_psbt_input; struct wally_tx; +struct amount_asset; struct amount_sat; struct bitcoin_signature; struct pubkey; @@ -55,10 +56,21 @@ WARN_UNUSED_RESULT bool psbt_input_set_partial_sig(struct wally_psbt *psbt, size const struct pubkey *pubkey, const struct bitcoin_signature *sig); -void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in, - const u8 *wscript, struct amount_sat amt); +void psbt_input_set_prev_utxo(struct wally_psbt *psbt, + size_t in, + const u8 *wscript, + struct amount_sat amt); void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in, - const u8 *wscript, struct amount_sat amt); + const u8 *wscript, + struct amount_sat amt); +void psbt_elements_input_init(struct wally_psbt *psbt, size_t in, + const u8 *scriptPubkey, + struct amount_asset *asset, + const u8 *nonce); +void psbt_elements_input_init_witness(struct wally_psbt *psbt, size_t in, + const u8 *witscript, + struct amount_asset *asset, + const u8 *nonce); bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in, const u8 *redeemscript); struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt, diff --git a/bitcoin/test/run-bitcoin_block_from_hex.c b/bitcoin/test/run-bitcoin_block_from_hex.c index e9a0216608d6..aacc5bac47a9 100644 --- a/bitcoin/test/run-bitcoin_block_from_hex.c +++ b/bitcoin/test/run-bitcoin_block_from_hex.c @@ -7,6 +7,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -29,6 +32,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/bitcoin/test/run-tx-encode.c b/bitcoin/test/run-tx-encode.c index 3437f9b5228f..6dcb159dac6a 100644 --- a/bitcoin/test/run-tx-encode.c +++ b/bitcoin/test/run-tx-encode.c @@ -8,6 +8,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -30,6 +33,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/bitcoin/tx.c b/bitcoin/tx.c index b2ea98c54fe6..7265ff6d5562 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -207,18 +207,51 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_txid *txid, if (input_wscript) { /* Add the prev output's data into the PSBT struct */ - psbt_input_set_prev_utxo_wscript(tx->psbt, i, input_wscript, amount); + if (is_elements(chainparams)) { + struct amount_asset asset; + /*FIXME: persist asset tags */ + asset = amount_sat_to_asset( + &amount, + chainparams->fee_asset_tag); + psbt_elements_input_init_witness(tx->psbt, i, + input_wscript, + &asset, NULL); + } else + psbt_input_set_prev_utxo_wscript(tx->psbt, i, + input_wscript, + amount); } else if (scriptPubkey) { - if (is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL) || - /* FIXME: assert that p2sh inputs are witness/are accompanied by a redeemscript+witnessscript */ + if (is_p2wsh(scriptPubkey, NULL) || + is_p2wpkh(scriptPubkey, NULL) || + /* FIXME: assert that p2sh inputs are + * witness/are accompanied by a + * redeemscript+witnessscript */ is_p2sh(scriptPubkey, NULL)) { - /* the only way to get here currently with a p2sh script is via a p2sh-p2wpkh script + /* the only way to get here currently with + * a p2sh script is via a p2sh-p2wpkh script * that we've created ...*/ - /* Relevant section from bip-0174, emphasis mine: - * ** Value: The entire transaction output in network serialization which the current input spends from. - * This should only be present for inputs which spend segwit outputs, _including P2SH embedded ones._ + /* BIP0174: + * ** Value: The entire transaction output in + * network serialization which the + * current input spends from. + * This should only be present for + * inputs which spend segwit outputs, + * including P2SH embedded ones. */ - psbt_input_set_prev_utxo(tx->psbt, i, scriptPubkey, amount); + if (is_elements(chainparams)) { + struct amount_asset asset; + /*FIXME: persist asset tags */ + asset = amount_sat_to_asset( + &amount, + chainparams->fee_asset_tag); + /* FIXME: persist nonces */ + psbt_elements_input_init(tx->psbt, i, + scriptPubkey, + &asset, NULL); + } else + psbt_input_set_prev_utxo(tx->psbt, i, + scriptPubkey, + amount); } } @@ -632,8 +665,17 @@ static char *fmt_bitcoin_txid(const tal_t *ctx, const struct bitcoin_txid *txid) return hexstr; } +static char *fmt_wally_tx(const tal_t *ctx, const struct wally_tx *tx) +{ + u8 *lin = linearize_wtx(ctx, tx); + char *s = tal_hex(ctx, lin); + tal_free(lin); + return s; +} + REGISTER_TYPE_TO_STRING(bitcoin_tx, fmt_bitcoin_tx); REGISTER_TYPE_TO_STRING(bitcoin_txid, fmt_bitcoin_txid); +REGISTER_TYPE_TO_STRING(wally_tx, fmt_wally_tx); void fromwire_bitcoin_txid(const u8 **cursor, size_t *max, struct bitcoin_txid *txid) @@ -713,10 +755,9 @@ wally_tx_output_get_amount(const struct wally_tx_output *output) if (chainparams->is_elements) { assert(output->asset_len == sizeof(amount.asset)); memcpy(&amount.asset, output->asset, sizeof(amount.asset)); - - /* We currently only support explicit value asset tags, others - * are confidential, so don't even try to assign a value to - * it. */ + /* We currently only support explicit value + * asset tags, others are confidential, so + * don't even try to assign a value to it. */ if (output->asset[0] == 0x01) { memcpy(&raw, output->value + 1, sizeof(raw)); amount.value = be64_to_cpu(raw); diff --git a/cli/test/run-large-input.c b/cli/test/run-large-input.c index 8add9a51cf0d..e10db714c008 100644 --- a/cli/test/run-large-input.c +++ b/cli/test/run-large-input.c @@ -33,6 +33,9 @@ int test_chdir(const char *path); #undef main /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -55,6 +58,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/cli/test/run-remove-hint.c b/cli/test/run-remove-hint.c index 02ab66cbffd5..1ac21dfa59e3 100644 --- a/cli/test/run-remove-hint.c +++ b/cli/test/run-remove-hint.c @@ -36,6 +36,9 @@ int test_chdir(const char *path); #undef main /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -58,6 +61,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/amount.c b/common/amount.c index 028b31763b05..680499f39a8e 100644 --- a/common/amount.c +++ b/common/amount.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -478,6 +479,29 @@ struct amount_sat amount_asset_to_sat(struct amount_asset *amount) return sats; } +struct amount_asset amount_sat_to_asset(struct amount_sat *sat, const u8 *asset) { + struct amount_asset amt_asset; + + assert(33 == sizeof(amt_asset.asset)); + memcpy(amt_asset.asset, asset, sizeof(amt_asset.asset)); + amt_asset.value = sat->satoshis; /* Raw: type conversion */ + return amt_asset; +} + +u8 *amount_asset_extract_value(const tal_t *ctx, struct amount_asset *asset) +{ + u8 *val = tal_arr(ctx, u8, 9); + + /* FIXME: persist blinded values */ + if (asset->value == 0) + return NULL; + + beint64_t be64 = cpu_to_be64(asset->value); + val[0] = 0x01; + memcpy(val + 1, &be64, sizeof(be64)); + return val; +} + struct amount_msat fromwire_amount_msat(const u8 **cursor, size_t *max) { struct amount_msat msat; diff --git a/common/amount.h b/common/amount.h index 792fba891bbd..3883e6320ff2 100644 --- a/common/amount.h +++ b/common/amount.h @@ -112,6 +112,15 @@ bool amount_msat_eq_sat(struct amount_msat msat, struct amount_sat sat); * current chain. */ bool amount_asset_is_main(struct amount_asset *asset); +/* Convert an amount_sat to an amount_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat, const u8 *asset); + +/* amount_asset_extract_value -Prefix the amount_asset's value + * to have the 'explicit' marker. Returns NULL if the + * asset was originally blinded. + * FIXME: pass through blinded amounts */ +u8 *amount_asset_extract_value(const tal_t *ctx, 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); diff --git a/common/test/run-bigsize.c b/common/test/run-bigsize.c index 64c0f1eaeef7..074e796e6560 100644 --- a/common/test/run-bigsize.c +++ b/common/test/run-bigsize.c @@ -13,6 +13,9 @@ static const char *reason; #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -35,6 +38,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-cryptomsg.c b/common/test/run-cryptomsg.c index 0694d7b48fb7..36f53de023e0 100644 --- a/common/test/run-cryptomsg.c +++ b/common/test/run-cryptomsg.c @@ -8,6 +8,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -30,6 +33,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-derive_basepoints.c b/common/test/run-derive_basepoints.c index 8279c832c2f7..d7d529ae0334 100644 --- a/common/test/run-derive_basepoints.c +++ b/common/test/run-derive_basepoints.c @@ -9,6 +9,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -31,6 +34,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-features.c b/common/test/run-features.c index 42fb4d72c48a..7cd107f53d23 100644 --- a/common/test/run-features.c +++ b/common/test/run-features.c @@ -8,6 +8,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -30,6 +33,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-gossip_rcvd_filter.c b/common/test/run-gossip_rcvd_filter.c index c0fc19a5cc35..a0e742f36919 100644 --- a/common/test/run-gossip_rcvd_filter.c +++ b/common/test/run-gossip_rcvd_filter.c @@ -5,6 +5,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -27,6 +30,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-ip_port_parsing.c b/common/test/run-ip_port_parsing.c index e04b18705946..4ac0ab737171 100644 --- a/common/test/run-ip_port_parsing.c +++ b/common/test/run-ip_port_parsing.c @@ -7,6 +7,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -29,6 +32,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-json_remove.c b/common/test/run-json_remove.c index 1f2fd1a06c7e..7c9c193d1577 100644 --- a/common/test/run-json_remove.c +++ b/common/test/run-json_remove.c @@ -5,6 +5,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -27,6 +30,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-key_derive.c b/common/test/run-key_derive.c index 039e320d08aa..581d147f9640 100644 --- a/common/test/run-key_derive.c +++ b/common/test/run-key_derive.c @@ -10,6 +10,9 @@ #include "../key_derive.c" /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -32,6 +35,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-lock.c b/common/test/run-lock.c index 268130d19031..7271f12e033d 100644 --- a/common/test/run-lock.c +++ b/common/test/run-lock.c @@ -9,6 +9,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -31,6 +34,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-softref.c b/common/test/run-softref.c index caa2a85140fa..acac56416029 100644 --- a/common/test/run-softref.c +++ b/common/test/run-softref.c @@ -6,6 +6,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -28,6 +31,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c index 84a355603eaa..baea842a254f 100644 --- a/common/test/run-sphinx.c +++ b/common/test/run-sphinx.c @@ -16,6 +16,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -44,6 +47,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/common/type_to_string.h b/common/type_to_string.h index ce134b946df2..440678d744b4 100644 --- a/common/type_to_string.h +++ b/common/type_to_string.h @@ -37,6 +37,7 @@ union printable_types { const struct fee_states *fee_states; const char *charp_; const struct wally_psbt *wally_psbt; + const struct wally_tx *wally_tx; }; #define type_to_string(ctx, type, ptr) \ diff --git a/connectd/test/run-initiator-success.c b/connectd/test/run-initiator-success.c index 904846c8c0e9..e5488799b2a9 100644 --- a/connectd/test/run-initiator-success.c +++ b/connectd/test/run-initiator-success.c @@ -12,6 +12,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -34,6 +37,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/connectd/test/run-responder-success.c b/connectd/test/run-responder-success.c index 34cf0c69230c..50254b118cea 100644 --- a/connectd/test/run-responder-success.c +++ b/connectd/test/run-responder-success.c @@ -12,6 +12,9 @@ #include /* AUTOGENERATED MOCKS START */ +/* Generated stub for amount_asset_extract_value */ +u8 *amount_asset_extract_value(const tal_t *ctx UNNEEDED, struct amount_asset *asset UNNEEDED) +{ fprintf(stderr, "amount_asset_extract_value called!\n"); abort(); } /* 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(); } @@ -34,6 +37,9 @@ bool amount_sat_greater_eq(struct amount_sat a UNNEEDED, struct amount_sat b UNN struct amount_sat a UNNEEDED, struct amount_sat b UNNEEDED) { fprintf(stderr, "amount_sat_sub called!\n"); abort(); } +/* Generated stub for amount_sat_to_asset */ +struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u8 *asset UNNEEDED) +{ fprintf(stderr, "amount_sat_to_asset called!\n"); abort(); } /* Generated stub for amount_tx_fee */ struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED) { fprintf(stderr, "amount_tx_fee called!\n"); abort(); } diff --git a/external/libwally-core b/external/libwally-core index e0d0634aea71..1f45aef1e990 160000 --- a/external/libwally-core +++ b/external/libwally-core @@ -1 +1 @@ -Subproject commit e0d0634aea716d813744326ea6c7590eb9fc381c +Subproject commit 1f45aef1e990e945710691e0e3637312f9a84e73 diff --git a/tests/test_plugin.py b/tests/test_plugin.py index c83abe119c5f..af8bf15e91df 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1389,10 +1389,10 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams): l2_wallet_mvts = [ {'type': 'chain_mvt', 'credit': 2000000000, 'debit': 0, 'tag': 'deposit'}, {'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'spend_track'}, - {'type': 'chain_mvt', 'credit': 0, 'debit': 991893000, 'tag': 'withdrawal'}, + {'type': 'chain_mvt', 'credit': 0, 'debit': 991900000, 'tag': 'withdrawal'}, {'type': 'chain_mvt', 'credit': 0, 'debit': 1000000000, 'tag': 'withdrawal'}, - {'type': 'chain_mvt', 'credit': 0, 'debit': 8107000, 'tag': 'chain_fees'}, - {'type': 'chain_mvt', 'credit': 991893000, 'debit': 0, 'tag': 'deposit'}, + {'type': 'chain_mvt', 'credit': 0, 'debit': 8100000, 'tag': 'chain_fees'}, + {'type': 'chain_mvt', 'credit': 991900000, 'debit': 0, 'tag': 'deposit'}, {'type': 'chain_mvt', 'credit': 100001000, 'debit': 0, 'tag': 'deposit'}, {'type': 'chain_mvt', 'credit': 941045000, 'debit': 0, 'tag': 'deposit'}, ] diff --git a/tests/test_wallet.py b/tests/test_wallet.py index bc1451ddc3ad..dc4f1e394428 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -474,6 +474,8 @@ def test_reserveinputs(node_factory, bitcoind, chainparams): # We should have two outputs for vout in psbt['tx']['vout']: + if chainparams['elements'] and vout['scriptPubKey']['type'] == 'fee': + continue if vout['scriptPubKey']['addresses'][0] == addr: assert vout['value'] == sent out_found = True @@ -710,8 +712,13 @@ def test_sign_and_send_psbt(node_factory, bitcoind, chainparams): # do proper acccounting for it. {'type': 'chain_mvt', 'credit': 0, 'debit': 4000000000, 'tag': 'withdrawal'}, {'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'chain_fees'}, - {'type': 'chain_mvt', 'credit': 988285000, 'debit': 0, 'tag': 'deposit'}, ] + + if chainparams['elements']: + wallet_coin_mvts.append({'type': 'chain_mvt', 'credit': 984625000, 'debit': 0, 'tag': 'deposit'}) + else: + wallet_coin_mvts.append({'type': 'chain_mvt', 'credit': 988285000, 'debit': 0, 'tag': 'deposit'}) + check_coin_moves(l1, 'wallet', wallet_coin_mvts, chainparams) diff --git a/wallet/db.c b/wallet/db.c index c97d2e08b28d..5ef666b0e2c0 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -1165,9 +1165,18 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db) funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey, &remote_funding_pubkey); - psbt_input_set_prev_utxo_wscript(last_tx->psbt, - 0, funding_wscript, - funding_sat); + if (is_elements(chainparams)) { + /*FIXME: persist asset tags */ + struct amount_asset asset; + asset = amount_sat_to_asset(&funding_sat, + chainparams->fee_asset_tag); + psbt_elements_input_init_witness(last_tx->psbt, + 0, funding_wscript, + &asset, NULL); + } else + psbt_input_set_prev_utxo_wscript(last_tx->psbt, + 0, funding_wscript, + funding_sat); if (!db_column_signature(stmt, 5, &last_sig.s)) abort(); diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index afbad92a9510..0644c7826936 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -99,8 +99,9 @@ static void wallet_withdrawal_broadcast(struct bitcoind *bitcoind UNUSED, was_pending(command_success(cmd, response)); } else { was_pending(command_fail(cmd, LIGHTNINGD, - "Error broadcasting transaction: %s. Unsent tx discarded", - output)); + "Error broadcasting transaction: %s. Unsent tx discarded %s", + output, + type_to_string(tmpctx, struct wally_tx, txb->wtx))); } }