mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 23:24:27 +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 <stdbool.h>
|
||||
|
||||
#define ELEMENTS_ASSET_LEN 33
|
||||
|
||||
struct chainparams {
|
||||
const char *network_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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -274,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));
|
||||
@@ -293,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,
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -333,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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
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) {
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,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);
|
||||
|
||||
@@ -1165,6 +1165,15 @@ void migrate_last_tx_to_psbt(struct lightningd *ld, struct db *db)
|
||||
funding_wscript = bitcoin_redeem_2of2(stmt, &local_funding_pubkey,
|
||||
&remote_funding_pubkey);
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user