diff --git a/bitcoin/tx.c b/bitcoin/tx.c index d21a3c8e4..e1c04f329 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -492,6 +492,19 @@ void bitcoin_tx_finalize(struct bitcoin_tx *tx) assert(bitcoin_tx_check(tx)); } +char *bitcoin_tx_to_psbt_base64(const tal_t *ctx, struct bitcoin_tx *tx) +{ + char *serialized_psbt, *ret_val; + int ret; + + ret = wally_psbt_to_base64(tx->psbt, &serialized_psbt); + assert(ret == WALLY_OK); + + ret_val = tal_strdup(ctx, serialized_psbt); + wally_free_string(serialized_psbt); + return ret_val; +} + struct bitcoin_tx *pull_bitcoin_tx(const tal_t *ctx, const u8 **cursor, size_t *max) { diff --git a/bitcoin/tx.h b/bitcoin/tx.h index cd6a33b71..a46513887 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -195,4 +195,8 @@ void towire_bitcoin_txid(u8 **pptr, const struct bitcoin_txid *txid); void towire_bitcoin_tx(u8 **pptr, const struct bitcoin_tx *tx); void towire_bitcoin_tx_output(u8 **pptr, const struct bitcoin_tx_output *output); +/* + * Get the base64 string encoded PSBT of a bitcoin transaction. + */ +char *bitcoin_tx_to_psbt_base64(const tal_t *ctx, struct bitcoin_tx *tx); #endif /* LIGHTNING_BITCOIN_TX_H */ diff --git a/common/json_helpers.c b/common/json_helpers.c index a4daa12d5..42841b90e 100644 --- a/common/json_helpers.c +++ b/common/json_helpers.c @@ -240,6 +240,15 @@ void json_add_tx(struct json_stream *result, json_add_hex_talarr(result, fieldname, linearize_tx(tmpctx, tx)); } +void json_add_psbt(struct json_stream *stream, + const char *fieldname, + struct bitcoin_tx *tx) +{ + const char *psbt_b64; + psbt_b64 = bitcoin_tx_to_psbt_base64(tx, tx); + json_add_string(stream, fieldname, take(psbt_b64)); +} + void json_add_amount_msat_compat(struct json_stream *result, struct amount_msat msat, const char *rawfieldname, diff --git a/common/json_helpers.h b/common/json_helpers.h index d5e1de92f..230f1a5ba 100644 --- a/common/json_helpers.h +++ b/common/json_helpers.h @@ -137,4 +137,10 @@ void json_add_preimage(struct json_stream *result, const char *fieldname, void json_add_tx(struct json_stream *result, const char *fieldname, const struct bitcoin_tx *tx); + +/* '"fieldname" : "cHNidP8BAJoCAAAAAljo..." or "cHNidP8BAJoCAAAAAljo..." if fieldname is NULL */ +void json_add_psbt(struct json_stream *stream, + const char *fieldname, + struct bitcoin_tx *tx); + #endif /* LIGHTNING_COMMON_JSON_HELPERS_H */ diff --git a/tests/test_wallet.py b/tests/test_wallet.py index 9caa35332..82818418b 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -302,6 +302,7 @@ def test_txprepare(node_factory, bitcoind, chainparams): wait_for(lambda: len(l1.rpc.listfunds()['outputs']) == 10) prep = l1.rpc.txprepare(outputs=[{addr: Millisatoshi(amount * 3 * 1000)}]) + assert prep['psbt'] decode = bitcoind.rpc.decoderawtransaction(prep['unsigned_tx']) assert decode['txid'] == prep['txid'] # 4 inputs, 2 outputs (3 if we have a fee output). diff --git a/wallet/walletrpc.c b/wallet/walletrpc.c index ebd8e96c9..e308e933c 100644 --- a/wallet/walletrpc.c +++ b/wallet/walletrpc.c @@ -443,6 +443,7 @@ static struct command_result *json_txprepare(struct command *cmd, response = json_stream_success(cmd); json_add_tx(response, "unsigned_tx", utx->tx); json_add_txid(response, "txid", &utx->txid); + json_add_psbt(response, "psbt", utx->tx); return command_success(cmd, response); } static const struct json_command txprepare_command = {