mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 15:14:23 +01:00
elements,pset: populate elements specific data for PSBTs
PSETs have a bit different requirements. The witness_utxo needs the asset tag + values, and these should also be added to the PSET struct separately as well. To do this, we create a new 'init' method for elements inputs, which takes care of the elements specific things.
This commit is contained in:
@@ -9,6 +9,8 @@
|
|||||||
#include <common/bip32.h>
|
#include <common/bip32.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define ELEMENTS_ASSET_LEN 33
|
||||||
|
|
||||||
struct chainparams {
|
struct chainparams {
|
||||||
const char *network_name;
|
const char *network_name;
|
||||||
const char *bip173_name;
|
const char *bip173_name;
|
||||||
|
|||||||
116
bitcoin/psbt.c
116
bitcoin/psbt.c
@@ -267,6 +267,16 @@ bool psbt_input_set_partial_sig(struct wally_psbt *psbt, size_t in,
|
|||||||
sizeof(sig->s.data)) == WALLY_OK;
|
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,
|
void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in,
|
||||||
const u8 *scriptPubkey, struct amount_sat amt)
|
const u8 *scriptPubkey, struct amount_sat amt)
|
||||||
{
|
{
|
||||||
@@ -274,7 +284,6 @@ void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in,
|
|||||||
int wally_err;
|
int wally_err;
|
||||||
u8 *scriptpk;
|
u8 *scriptpk;
|
||||||
|
|
||||||
assert(psbt->num_inputs > in);
|
|
||||||
if (scriptPubkey) {
|
if (scriptPubkey) {
|
||||||
assert(is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL)
|
assert(is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL)
|
||||||
|| is_p2sh(scriptPubkey, NULL));
|
|| is_p2sh(scriptPubkey, NULL));
|
||||||
@@ -293,10 +302,34 @@ void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in,
|
|||||||
tal_bytelen(scriptpk),
|
tal_bytelen(scriptpk),
|
||||||
&prev_out);
|
&prev_out);
|
||||||
assert(wally_err == WALLY_OK);
|
assert(wally_err == WALLY_OK);
|
||||||
wally_err = wally_psbt_input_set_witness_utxo(&psbt->inputs[in],
|
psbt_input_set_witness_utxo(psbt, in, prev_out);
|
||||||
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);
|
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,
|
void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in,
|
||||||
@@ -316,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);
|
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,
|
bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in,
|
||||||
const u8 *redeemscript)
|
const u8 *redeemscript)
|
||||||
{
|
{
|
||||||
@@ -333,7 +436,10 @@ struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt,
|
|||||||
struct amount_sat val;
|
struct amount_sat val;
|
||||||
assert(in < psbt->num_inputs);
|
assert(in < psbt->num_inputs);
|
||||||
if (psbt->inputs[in].witness_utxo) {
|
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) {
|
} else if (psbt->inputs[in].non_witness_utxo) {
|
||||||
int idx = psbt->tx->inputs[in].index;
|
int idx = psbt->tx->inputs[in].index;
|
||||||
struct wally_tx *prev_tx = psbt->inputs[in].non_witness_utxo;
|
struct wally_tx *prev_tx = psbt->inputs[in].non_witness_utxo;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ struct wally_tx_output;
|
|||||||
struct wally_psbt;
|
struct wally_psbt;
|
||||||
struct wally_psbt_input;
|
struct wally_psbt_input;
|
||||||
struct wally_tx;
|
struct wally_tx;
|
||||||
|
struct amount_asset;
|
||||||
struct amount_sat;
|
struct amount_sat;
|
||||||
struct bitcoin_signature;
|
struct bitcoin_signature;
|
||||||
struct pubkey;
|
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 pubkey *pubkey,
|
||||||
const struct bitcoin_signature *sig);
|
const struct bitcoin_signature *sig);
|
||||||
|
|
||||||
void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in,
|
void psbt_input_set_prev_utxo(struct wally_psbt *psbt,
|
||||||
const u8 *wscript, struct amount_sat amt);
|
size_t in,
|
||||||
|
const u8 *wscript,
|
||||||
|
struct amount_sat amt);
|
||||||
void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in,
|
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,
|
bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in,
|
||||||
const u8 *redeemscript);
|
const u8 *redeemscript);
|
||||||
struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt,
|
struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt,
|
||||||
|
|||||||
56
bitcoin/tx.c
56
bitcoin/tx.c
@@ -207,18 +207,51 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_txid *txid,
|
|||||||
|
|
||||||
if (input_wscript) {
|
if (input_wscript) {
|
||||||
/* Add the prev output's data into the PSBT struct */
|
/* 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) {
|
} else if (scriptPubkey) {
|
||||||
if (is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL) ||
|
if (is_p2wsh(scriptPubkey, NULL) ||
|
||||||
/* FIXME: assert that p2sh inputs are witness/are accompanied by a redeemscript+witnessscript */
|
is_p2wpkh(scriptPubkey, NULL) ||
|
||||||
|
/* FIXME: assert that p2sh inputs are
|
||||||
|
* witness/are accompanied by a
|
||||||
|
* redeemscript+witnessscript */
|
||||||
is_p2sh(scriptPubkey, NULL)) {
|
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 ...*/
|
* that we've created ...*/
|
||||||
/* Relevant section from bip-0174, emphasis mine:
|
/* BIP0174:
|
||||||
* ** Value: The entire transaction output in network serialization which the current input spends from.
|
* ** Value: The entire transaction output in
|
||||||
* This should only be present for inputs which spend segwit outputs, _including P2SH embedded ones._
|
* 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,10 +755,9 @@ wally_tx_output_get_amount(const struct wally_tx_output *output)
|
|||||||
if (chainparams->is_elements) {
|
if (chainparams->is_elements) {
|
||||||
assert(output->asset_len == sizeof(amount.asset));
|
assert(output->asset_len == sizeof(amount.asset));
|
||||||
memcpy(&amount.asset, output->asset, sizeof(amount.asset));
|
memcpy(&amount.asset, output->asset, sizeof(amount.asset));
|
||||||
|
/* We currently only support explicit value
|
||||||
/* We currently only support explicit value asset tags, others
|
* asset tags, others are confidential, so
|
||||||
* are confidential, so don't even try to assign a value to
|
* don't even try to assign a value to it. */
|
||||||
* it. */
|
|
||||||
if (output->asset[0] == 0x01) {
|
if (output->asset[0] == 0x01) {
|
||||||
memcpy(&raw, output->value + 1, sizeof(raw));
|
memcpy(&raw, output->value + 1, sizeof(raw));
|
||||||
amount.value = be64_to_cpu(raw);
|
amount.value = be64_to_cpu(raw);
|
||||||
|
|||||||
15
wallet/db.c
15
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,
|
funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey,
|
||||||
&remote_funding_pubkey);
|
&remote_funding_pubkey);
|
||||||
|
|
||||||
psbt_input_set_prev_utxo_wscript(last_tx->psbt,
|
if (is_elements(chainparams)) {
|
||||||
0, funding_wscript,
|
/*FIXME: persist asset tags */
|
||||||
funding_sat);
|
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))
|
if (!db_column_signature(stmt, 5, &last_sig.s))
|
||||||
abort();
|
abort();
|
||||||
|
|||||||
Reference in New Issue
Block a user