Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions bitcoin/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
122 changes: 116 additions & 6 deletions bitcoin/psbt.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <assert.h>
#include <bitcoin/chainparams.h>
#include <bitcoin/psbt.h>
#include <bitcoin/pubkey.h>
#include <bitcoin/script.h>
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -263,14 +267,23 @@ 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)
{
struct wally_tx_output *prev_out;
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));
Expand All @@ -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,
Expand All @@ -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)
{
Expand All @@ -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;
Expand Down
18 changes: 15 additions & 3 deletions bitcoin/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions bitcoin/test/run-bitcoin_block_from_hex.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include <common/setup.h>

/* 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(); }
Expand All @@ -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(); }
Expand Down
6 changes: 6 additions & 0 deletions bitcoin/test/run-tx-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include <common/utils.h>

/* 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(); }
Expand All @@ -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(); }
Expand Down
65 changes: 53 additions & 12 deletions bitcoin/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions cli/test/run-large-input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(); }
Expand All @@ -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(); }
Expand Down
6 changes: 6 additions & 0 deletions cli/test/run-remove-hint.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(); }
Expand All @@ -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(); }
Expand Down
Loading