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
114 changes: 99 additions & 15 deletions bitcoin/psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include <bitcoin/signature.h>
#include <ccan/cast/cast.h>
#include <ccan/ccan/array_size/array_size.h>
#include <ccan/tal/str/str.h>
#include <common/amount.h>
#include <common/type_to_string.h>
#include <common/utils.h>
#include <string.h>
#include <wally_psbt.h>
Expand Down Expand Up @@ -114,10 +116,32 @@ struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt,
{
struct wally_tx *tx;
struct wally_tx_input tmp_in;
u8 *script;
size_t scriptlen = 0;
struct wally_tx_witness_stack *witness = NULL;

tx = psbt->tx;
assert(insert_at <= tx->num_inputs);

/* Remove any script sig or witness info before adding it ! */
if (input->script_len > 0) {
scriptlen = input->script_len;
input->script_len = 0;
script = (u8 *)input->script;
input->script = NULL;
}
if (input->witness) {
witness = input->witness;
input->witness = NULL;
}
wally_tx_add_input(tx, input);
/* Put the script + witness info back */
if (scriptlen > 0) {
input->script_len = scriptlen;
input->script = script;
}
if (witness)
input->witness = witness;

tmp_in = tx->inputs[tx->num_inputs - 1];
MAKE_ROOM(tx->inputs, insert_at, tx->num_inputs);
Expand Down Expand Up @@ -219,29 +243,24 @@ void psbt_input_add_pubkey(struct wally_psbt *psbt, size_t in,
assert(wally_err == WALLY_OK);
}

void psbt_input_set_partial_sig(struct wally_psbt *psbt, size_t in,
bool psbt_input_set_partial_sig(struct wally_psbt *psbt, size_t in,
const struct pubkey *pubkey,
const struct bitcoin_signature *sig)
{
int wally_err;
u8 pk_der[PUBKEY_CMPR_LEN];

assert(in < psbt->num_inputs);
if (!psbt->inputs[in].partial_sigs)
if (wally_partial_sigs_map_init_alloc(1, &psbt->inputs[in].partial_sigs) != WALLY_OK)
abort();
return false;

/* we serialize the compressed version of the key, wally likes this */
pubkey_to_der(pk_der, pubkey);
wally_err = wally_add_new_partial_sig(psbt->inputs[in].partial_sigs,
pk_der, sizeof(pk_der),
cast_const(unsigned char *, sig->s.data),
sizeof(sig->s.data));
assert(wally_err == WALLY_OK);

wally_err = wally_psbt_input_set_sighash_type(&psbt->inputs[in],
sig->sighash_type);
assert(wally_err == WALLY_OK);
wally_psbt_input_set_sighash_type(&psbt->inputs[in], sig->sighash_type);
return wally_add_new_partial_sig(psbt->inputs[in].partial_sigs,
pk_der, sizeof(pk_der),
cast_const(unsigned char *, sig->s.data),
sizeof(sig->s.data)) == WALLY_OK;
}

void psbt_input_set_prev_utxo(struct wally_psbt *psbt, size_t in,
Expand Down Expand Up @@ -293,6 +312,17 @@ void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in,
psbt_input_set_prev_utxo(psbt, in, scriptPubkey, amt);
}

bool psbt_input_set_redeemscript(struct wally_psbt *psbt, size_t in,
const u8 *redeemscript)
{
int wally_err;
assert(psbt->num_inputs > in);
wally_err = wally_psbt_input_set_redeem_script(&psbt->inputs[in],
cast_const(u8 *, redeemscript),
tal_bytelen(redeemscript));
return wally_err == WALLY_OK;
}

struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt,
size_t in)
{
Expand All @@ -310,6 +340,60 @@ struct amount_sat psbt_input_get_amount(struct wally_psbt *psbt,
return val;
}

struct wally_tx *psbt_finalize(struct wally_psbt *psbt, bool finalize_in_place)
{
struct wally_psbt *tmppsbt;
struct wally_tx *wtx;

/* We want the 'finalized' tx since that includes any signature
* data, not the global tx. But 'finalizing' a tx destroys some fields
* so we 'clone' it first and then finalize it */
if (!finalize_in_place) {
if (wally_psbt_clone(psbt, &tmppsbt) != WALLY_OK)
return NULL;
} else
tmppsbt = cast_const(struct wally_psbt *, psbt);

if (wally_finalize_psbt(tmppsbt) != WALLY_OK) {
if (!finalize_in_place)
wally_psbt_free(tmppsbt);
return NULL;
}

if (psbt_is_finalized(tmppsbt)
&& wally_extract_psbt(tmppsbt, &wtx) == WALLY_OK) {
if (!finalize_in_place)
wally_psbt_free(tmppsbt);
return wtx;
}

if (!finalize_in_place)
wally_psbt_free(tmppsbt);
return NULL;
}

bool psbt_from_b64(const char *b64str, struct wally_psbt **psbt)
{
int wally_err;
wally_err = wally_psbt_from_base64(b64str, psbt);
return wally_err == WALLY_OK;
}

char *psbt_to_b64(const tal_t *ctx, const struct wally_psbt *psbt)
{
char *serialized_psbt, *ret_val;
int ret;

ret = wally_psbt_to_base64(cast_const(struct wally_psbt *, psbt),
&serialized_psbt);
assert(ret == WALLY_OK);

ret_val = tal_strdup(ctx, serialized_psbt);
wally_free_string(serialized_psbt);
return ret_val;
}
REGISTER_TYPE_TO_STRING(wally_psbt, psbt_to_b64);

const u8 *psbt_get_bytes(const tal_t *ctx, const struct wally_psbt *psbt,
size_t *bytes_written)
{
Expand Down Expand Up @@ -340,7 +424,7 @@ struct wally_psbt *psbt_from_bytes(const tal_t *ctx, const u8 *bytes,
return psbt;
}

void towire_psbt(u8 **pptr, const struct wally_psbt *psbt)
void towire_wally_psbt(u8 **pptr, const struct wally_psbt *psbt)
{
/* Let's include the PSBT bytes */
size_t bytes_written;
Expand All @@ -350,8 +434,8 @@ void towire_psbt(u8 **pptr, const struct wally_psbt *psbt)
tal_free(pbt_bytes);
}

struct wally_psbt *fromwire_psbt(const tal_t *ctx,
const u8 **cursor, size_t *max)
struct wally_psbt *fromwire_wally_psbt(const tal_t *ctx,
const u8 **cursor, size_t *max)
{
struct wally_psbt *psbt;
u32 psbt_byte_len;
Expand Down
18 changes: 12 additions & 6 deletions bitcoin/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ struct wally_psbt *new_psbt(const tal_t *ctx,
*/
bool psbt_is_finalized(struct wally_psbt *psbt);

struct wally_tx *psbt_finalize(struct wally_psbt *psbt, bool finalize_in_place);

struct wally_psbt_input *psbt_add_input(struct wally_psbt *psbt,
struct wally_tx_input *input,
size_t insert_at);
Expand All @@ -49,22 +51,26 @@ void psbt_rm_output(struct wally_psbt *psbt,
void psbt_input_add_pubkey(struct wally_psbt *psbt, size_t in,
const struct pubkey *pubkey);

void psbt_input_set_partial_sig(struct wally_psbt *psbt, size_t in,
const struct pubkey *pubkey,
const struct bitcoin_signature *sig);
WARN_UNUSED_RESULT bool psbt_input_set_partial_sig(struct wally_psbt *psbt, size_t in,
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_wscript(struct wally_psbt *psbt, size_t in,
const u8 *wscript, struct amount_sat amt);
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,
size_t in);

bool psbt_from_b64(const char *b64str, struct wally_psbt **psbt);
char *psbt_to_b64(const tal_t *ctx, const struct wally_psbt *psbt);
const u8 *psbt_get_bytes(const tal_t *ctx, const struct wally_psbt *psbt,
size_t *bytes_written);
struct wally_psbt *psbt_from_bytes(const tal_t *ctx, const u8 *bytes,
size_t byte_len);
void towire_psbt(u8 **pptr, const struct wally_psbt *psbt);
struct wally_psbt *fromwire_psbt(const tal_t *ctx,
const u8 **curosr, size_t *max);
void towire_wally_psbt(u8 **pptr, const struct wally_psbt *psbt);
struct wally_psbt *fromwire_wally_psbt(const tal_t *ctx,
const u8 **cursor, size_t *max);
#endif /* LIGHTNING_BITCOIN_PSBT_H */
50 changes: 16 additions & 34 deletions bitcoin/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ int wally_tx_clone(struct wally_tx *tx, struct wally_tx **output)
return ret;
}

struct bitcoin_tx_output *new_tx_output(const tal_t *ctx,
struct amount_sat amount,
const u8 *script)
{
struct bitcoin_tx_output *output = tal(ctx, struct bitcoin_tx_output);
output->amount = amount;
output->script = tal_dup_arr(output, u8, script, tal_count(script), 0);
return output;
}

int bitcoin_tx_add_output(struct bitcoin_tx *tx, const u8 *script,
u8 *wscript, struct amount_sat amount)
{
Expand Down Expand Up @@ -484,48 +494,20 @@ 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 *bitcoin_tx_with_psbt(const tal_t *ctx, struct wally_psbt *psbt STEALS)
{
struct wally_psbt *tmppsbt;
struct bitcoin_tx *tx = bitcoin_tx(ctx, chainparams,
psbt->tx->num_inputs,
psbt->tx->num_outputs,
psbt->tx->locktime);
wally_tx_free(tx->wtx);

/* We want the 'finalized' tx since that includes any signature
* data, not the global tx. But 'finalizing' a tx destroys some fields
* so we 'clone' it first and then finalize it */
if (wally_psbt_clone(psbt, &tmppsbt) != WALLY_OK)
abort();

if (wally_finalize_psbt(tmppsbt) != WALLY_OK)
abort();

if (psbt_is_finalized(tmppsbt)) {
if (wally_extract_psbt(tmppsbt, &tx->wtx) != WALLY_OK)
abort();
} else if (wally_tx_clone(psbt->tx, &tx->wtx) != WALLY_OK)
abort();


wally_psbt_free(tmppsbt);
tx->wtx = psbt_finalize(psbt, false);
if (!tx->wtx && wally_tx_clone(psbt->tx, &tx->wtx) != WALLY_OK)
return NULL;

tal_free(tx->psbt);
tx->psbt = tal_steal(tx, psbt);

return tx;
}

Expand Down Expand Up @@ -665,7 +647,7 @@ struct bitcoin_tx *fromwire_bitcoin_tx(const tal_t *ctx,

/* pull_bitcoin_tx sets the psbt */
tal_free(tx->psbt);
tx->psbt = fromwire_psbt(tx, cursor, max);
tx->psbt = fromwire_wally_psbt(tx, cursor, max);

return tx;
}
Expand All @@ -680,7 +662,7 @@ void towire_bitcoin_tx(u8 **pptr, const struct bitcoin_tx *tx)
u8 *lin = linearize_tx(tmpctx, tx);
towire_u8_array(pptr, lin, tal_count(lin));

towire_psbt(pptr, tx->psbt);
towire_wally_psbt(pptr, tx->psbt);
}

struct bitcoin_tx_output *fromwire_bitcoin_tx_output(const tal_t *ctx,
Expand Down
9 changes: 4 additions & 5 deletions bitcoin/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ struct bitcoin_tx_output {
u8 *script;
};

struct bitcoin_tx_output *new_tx_output(const tal_t *ctx,
struct amount_sat amount,
const u8 *script);

/* SHA256^2 the tx in legacy format. */
void bitcoin_txid(const struct bitcoin_tx *tx, struct bitcoin_txid *txid);
void wally_txid(const struct wally_tx *wtx, struct bitcoin_txid *txid);
Expand Down Expand Up @@ -216,10 +220,5 @@ 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);

int wally_tx_clone(struct wally_tx *tx, struct wally_tx **output);
#endif /* LIGHTNING_BITCOIN_TX_H */
7 changes: 5 additions & 2 deletions channeld/channeld.c
Original file line number Diff line number Diff line change
Expand Up @@ -1291,8 +1291,11 @@ static void handle_peer_commit_sig(struct peer *peer, const u8 *msg)
peer->next_index[LOCAL], LOCAL);

/* Set the commit_sig on the commitment tx psbt */
psbt_input_set_partial_sig(txs[0]->psbt, 0,
&peer->channel->funding_pubkey[REMOTE], &commit_sig);
if (!psbt_input_set_partial_sig(txs[0]->psbt, 0,
&peer->channel->funding_pubkey[REMOTE],
&commit_sig))
status_failed(STATUS_FAIL_INTERNAL_ERROR,
"Unable to set signature internally");

if (!derive_simple_key(&peer->channel->basepoints[REMOTE].htlc,
&peer->next_local_per_commit, &remote_htlckey))
Expand Down
5 changes: 3 additions & 2 deletions common/json_helpers.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <arpa/inet.h>
#include <bitcoin/preimage.h>
#include <bitcoin/privkey.h>
#include <bitcoin/psbt.h>
#include <bitcoin/pubkey.h>
#include <bitcoin/short_channel_id.h>
#include <ccan/ccan/str/hex/hex.h>
Expand Down Expand Up @@ -242,10 +243,10 @@ void json_add_tx(struct json_stream *result,

void json_add_psbt(struct json_stream *stream,
const char *fieldname,
struct bitcoin_tx *tx)
struct wally_psbt *psbt)
{
const char *psbt_b64;
psbt_b64 = bitcoin_tx_to_psbt_base64(tx, tx);
psbt_b64 = psbt_to_b64(NULL, psbt);
json_add_string(stream, fieldname, take(psbt_b64));
}

Expand Down
2 changes: 1 addition & 1 deletion common/json_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,6 @@ void json_add_tx(struct json_stream *result,
/* '"fieldname" : "cHNidP8BAJoCAAAAAljo..." or "cHNidP8BAJoCAAAAAljo..." if fieldname is NULL */
void json_add_psbt(struct json_stream *stream,
const char *fieldname,
struct bitcoin_tx *tx);
struct wally_psbt *psbt);

#endif /* LIGHTNING_COMMON_JSON_HELPERS_H */
2 changes: 2 additions & 0 deletions common/type_to_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "utils.h"
#include <ccan/autodata/autodata.h>
#include <secp256k1.h>
#include <wally_psbt.h>

/* This must match the type_to_string_ cases. */
union printable_types {
Expand Down Expand Up @@ -35,6 +36,7 @@ union printable_types {
const struct amount_sat *amount_sat;
const struct fee_states *fee_states;
const char *charp_;
const struct wally_psbt *wally_psbt;
};

#define type_to_string(ctx, type, ptr) \
Expand Down
Loading