Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dual-funding, accepter side only #3973

Merged
merged 22 commits into from
Sep 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
264fcb0
amount: fix typo in parse_amount_msat doc
niftynei Sep 9, 2020
e3b4435
psbt: enforce const on max_witness_len
niftynei Sep 9, 2020
f9e1be7
feerate: add a 'common_weight' calculation for a tx
niftynei Sep 9, 2020
4a3a1cb
channel_id: save to database, dont derive from funding_txid
niftynei Sep 9, 2020
6dd6f76
openingd: pull out common code, rename some things
niftynei Sep 9, 2020
15064b9
openingd: pull out check_configs into a common place
niftynei Sep 9, 2020
d845c8e
channel_id: add v2 channel_id derivtion helper
niftynei Sep 9, 2020
ad7878f
dual-fund: add interactive dual-funding wires
niftynei Sep 9, 2020
fed246d
dualopend: new `dualopend` daemon, containing most of accepter side
niftynei Sep 9, 2020
c9c9d96
peer-control: send set of messages to start, not just one
niftynei Sep 9, 2020
468d637
opening: pass two messages to channeld to send to peer
niftynei Sep 9, 2020
ec749d9
dual-fund: accepter side implementation on lightningd
niftynei Sep 9, 2020
5f8286d
dualfund: add feature flag for dual-funding
niftynei Sep 9, 2020
8785f23
df: add needed info to any PSBT we produce
niftynei Sep 9, 2020
cc31de3
tests: plugin for dual-funding tests in ln-prototest
niftynei Sep 9, 2020
00a6534
psbt: only compare a subset of psbt input/output fields
niftynei Sep 9, 2020
b4b25c7
psbt: clean up interface for setting metadata on PSBT inputs
niftynei Sep 9, 2020
68dd54b
build: exclude dualopend from non-experimental builds
niftynei Sep 9, 2020
a355cf6
psbt: pull out changeset logic into common, update API
niftynei Sep 9, 2020
8dcb1b2
psbt: psbt_has_serial_id -> psbt_find_serial_id
niftynei Sep 9, 2020
867a854
spec-update: handle tx_signatures in channeld (accepter side only,rea…
niftynei Sep 9, 2020
a8acab8
spec-update: get rid of max-witness-len
niftynei Sep 9, 2020
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
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,11 @@ PKGLIBEXEC_PROGRAMS = \
lightningd/lightning_onchaind \
lightningd/lightning_openingd

# Only build dualopend if experimental features is on
ifeq ($(EXPERIMENTAL_FEATURES),1)
PKGLIBEXEC_PROGRAMS += lightningd/lightning_dualopend
endif

# $(PLUGINS) is defined in plugins/Makefile.

install-program: installdirs $(BIN_PROGRAMS) $(PKGLIBEXEC_PROGRAMS) $(PLUGINS)
Expand Down
10 changes: 10 additions & 0 deletions bitcoin/feerate.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <bitcoin/feerate.h>
#include <bitcoin/varint.h>
#include <limits.h>
#include <stdlib.h>

Expand Down Expand Up @@ -38,3 +39,12 @@ const char *feerate_style_name(enum feerate_style style)
}
abort();
}

size_t common_weight(size_t num_inputs, size_t num_outputs)
{
/*(nVersion + num inputs + num outputs + locktime) * 4
* + SegWit marker + SegWit flag */
return (4 + varint_size(num_inputs) +
varint_size(num_outputs) + 4) * 4
+ 1 + 1;
}
5 changes: 5 additions & 0 deletions bitcoin/feerate.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@
*/
#define FEERATE_FLOOR 253

/*
* This is the net common weight of a transaction.
*/
size_t common_weight(size_t num_inputs, size_t num_outputs);

rustyrussell marked this conversation as resolved.
Show resolved Hide resolved
enum feerate_style {
FEERATE_PER_KSIPA,
FEERATE_PER_KBYTE
Expand Down
193 changes: 20 additions & 173 deletions bitcoin/psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt,
const struct bitcoin_txid *txid,
u32 outnum, u32 sequence,
const u8 *scriptSig,
struct amount_sat amount,
const u8 *scriptPubkey,
const u8 *input_wscript,
const u8 *redeemscript)
{
Expand Down Expand Up @@ -145,52 +143,7 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt,

if (input_wscript) {
/* Add the prev output's data into the PSBT struct */
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(psbt, input_num,
input_wscript,
&asset, NULL);
} else
psbt_input_set_prev_utxo_wscript(psbt, input_num,
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 */
is_p2sh(scriptPubkey, NULL)) {
/* the only way to get here currently with
* a p2sh script is via a p2sh-p2wpkh script
* that we've created ...*/
/* 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.
*/
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(psbt, input_num,
scriptPubkey,
&asset, NULL);
} else
psbt_input_set_prev_utxo(psbt, input_num,
scriptPubkey,
amount);
}
psbt_input_set_witscript(psbt, input_num, input_wscript);
}

if (redeemscript) {
Expand Down Expand Up @@ -284,149 +237,43 @@ bool psbt_input_set_signature(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,
const struct wally_tx_output *txout)
void psbt_input_set_wit_utxo(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey, struct amount_sat amt)
{
struct wally_tx_output tx_out;
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;

if (scriptPubkey) {
assert(is_p2wsh(scriptPubkey, NULL) || is_p2wpkh(scriptPubkey, NULL)
|| is_p2sh(scriptPubkey, NULL));
scriptpk = cast_const(u8 *, scriptPubkey);
} else {
/* Adding a NULL scriptpubkey is an error, *however* there is the
* possiblity we're spending a UTXO that we didn't save the
* scriptpubkey data for. in this case we set it to an 'empty'
* or zero-len script */
scriptpk = tal_arr(psbt, u8, 1);
scriptpk[0] = 0x00;
}

assert(in < psbt->num_inputs);
assert(tal_bytelen(scriptPubkey) > 0);
wally_err = wally_tx_output_init(amt.satoshis, /* Raw: type conv */
scriptpk,
tal_bytelen(scriptpk),
&prev_out);
scriptPubkey,
tal_bytelen(scriptPubkey),
&tx_out);
assert(wally_err == WALLY_OK);
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(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);
wally_err = wally_psbt_input_set_witness_utxo(&psbt->inputs[in],
&tx_out);
assert(wally_err == WALLY_OK);
psbt_input_set_witness_utxo(psbt, in, &prev_out);
}

void psbt_input_set_prev_utxo_wscript(struct wally_psbt *psbt, size_t in,
const u8 *wscript, struct amount_sat amt)
{
int wally_err;
const u8 *scriptPubkey;

if (wscript) {
scriptPubkey = scriptpubkey_p2wsh(psbt, wscript);
wally_err = wally_psbt_input_set_witness_script(&psbt->inputs[in],
wscript,
tal_bytelen(wscript));
assert(wally_err == WALLY_OK);
} else
scriptPubkey = NULL;
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)
void psbt_input_set_witscript(struct wally_psbt *psbt, size_t in, const u8 *wscript)
{
int wally_err;
const u8 *scriptPubkey;

if (wscript) {
scriptPubkey = scriptpubkey_p2wsh(psbt, wscript);
wally_err = wally_psbt_input_set_witness_script(
&psbt->inputs[in],
wscript, tal_bytelen(wscript));
assert(wally_err == WALLY_OK);
} else
scriptPubkey = NULL;

psbt_input_set_elements_prev_utxo(psbt, in, scriptPubkey,
asset, nonce);
wally_err = wally_psbt_input_set_witness_script(&psbt->inputs[in],
wscript,
tal_bytelen(wscript));
assert(wally_err == WALLY_OK);
}

void psbt_elements_input_init_witness(struct wally_psbt *psbt, size_t in,
const u8 *witscript,
struct amount_asset *asset,
const u8 *nonce)
void psbt_elements_input_set_asset(struct wally_psbt *psbt, size_t in,
struct amount_asset *asset)
{
psbt_input_set_elements_prev_utxo_wscript(
psbt, in, witscript,
asset, nonce);

if (asset->value > 0)
wally_psbt_input_set_value(&psbt->inputs[in], asset->value);

/* PSET expects an asset tag without the prefix */
if (wally_psbt_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_input_set_value(
&psbt->inputs[in],
asset->value) != WALLY_OK)
if (wally_psbt_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_input_set_asset(&psbt->inputs[in],
asset->asset + 1,
ELEMENTS_ASSET_LEN - 1) != WALLY_OK)
Expand Down
19 changes: 10 additions & 9 deletions bitcoin/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,18 @@ struct wally_psbt_input *psbt_append_input(struct wally_psbt *psbt,
const struct bitcoin_txid *txid,
u32 outnum, u32 sequence,
const u8 *scriptSig,
struct amount_sat amount,
const u8 *scriptPubkey,
const u8 *input_wscript,
const u8 *redeemscript);

/* psbt_input_set_wit_utxo - Set the witness_utxo field for this PSBT */
void psbt_input_set_wit_utxo(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey, struct amount_sat amt);

/* psbt_elements_input_set_asset - Set the asset/value fields for an
* Elements PSBT (PSET, technically */
void psbt_elements_input_set_asset(struct wally_psbt *psbt, size_t in,
struct amount_asset *asset);

void psbt_rm_input(struct wally_psbt *psbt,
size_t remove_at);

Expand Down Expand Up @@ -123,13 +130,7 @@ WARN_UNUSED_RESULT bool psbt_input_set_signature(struct wally_psbt *psbt, size_t
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);
void psbt_input_set_witscript(struct wally_psbt *psbt, size_t in, const u8 *wscript);
void psbt_elements_input_init(struct wally_psbt *psbt, size_t in,
const u8 *scriptPubkey,
struct amount_asset *asset,
Expand Down
12 changes: 0 additions & 12 deletions bitcoin/test/run-bitcoin_block_from_hex.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
#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 Down Expand Up @@ -66,15 +63,6 @@ u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for is_anchor_witness_script */
bool is_anchor_witness_script(const u8 *script UNNEEDED, size_t script_len UNNEEDED)
{ fprintf(stderr, "is_anchor_witness_script called!\n"); abort(); }
/* Generated stub for is_p2sh */
bool is_p2sh(const u8 *script UNNEEDED, struct ripemd160 *addr UNNEEDED)
{ fprintf(stderr, "is_p2sh called!\n"); abort(); }
/* Generated stub for is_p2wpkh */
bool is_p2wpkh(const u8 *script UNNEEDED, struct bitcoin_address *addr UNNEEDED)
{ fprintf(stderr, "is_p2wpkh called!\n"); abort(); }
/* Generated stub for is_p2wsh */
bool is_p2wsh(const u8 *script UNNEEDED, struct sha256 *addr UNNEEDED)
{ fprintf(stderr, "is_p2wsh called!\n"); abort(); }
/* Generated stub for pubkey_to_der */
void pubkey_to_der(u8 der[PUBKEY_CMPR_LEN] UNNEEDED, const struct pubkey *key UNNEEDED)
{ fprintf(stderr, "pubkey_to_der called!\n"); abort(); }
Expand Down
12 changes: 0 additions & 12 deletions bitcoin/test/run-tx-encode.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
#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 Down Expand Up @@ -67,15 +64,6 @@ u32 fromwire_u32(const u8 **cursor UNNEEDED, size_t *max UNNEEDED)
/* Generated stub for is_anchor_witness_script */
bool is_anchor_witness_script(const u8 *script UNNEEDED, size_t script_len UNNEEDED)
{ fprintf(stderr, "is_anchor_witness_script called!\n"); abort(); }
/* Generated stub for is_p2sh */
bool is_p2sh(const u8 *script UNNEEDED, struct ripemd160 *addr UNNEEDED)
{ fprintf(stderr, "is_p2sh called!\n"); abort(); }
/* Generated stub for is_p2wpkh */
bool is_p2wpkh(const u8 *script UNNEEDED, struct bitcoin_address *addr UNNEEDED)
{ fprintf(stderr, "is_p2wpkh called!\n"); abort(); }
/* Generated stub for is_p2wsh */
bool is_p2wsh(const u8 *script UNNEEDED, struct sha256 *addr UNNEEDED)
{ fprintf(stderr, "is_p2wsh called!\n"); abort(); }
/* Generated stub for pubkey_to_der */
void pubkey_to_der(u8 der[PUBKEY_CMPR_LEN] UNNEEDED, const struct pubkey *key UNNEEDED)
{ fprintf(stderr, "pubkey_to_der called!\n"); abort(); }
Expand Down
21 changes: 19 additions & 2 deletions bitcoin/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,31 @@ int bitcoin_tx_add_input(struct bitcoin_tx *tx, const struct bitcoin_txid *txid,
int input_num = tx->wtx->num_inputs;

psbt_append_input(tx->psbt, txid, outnum, sequence, scriptSig,
amount, scriptPubkey, input_wscript, NULL);
input_wscript, NULL);

if (input_wscript) {
scriptPubkey = scriptpubkey_p2wsh(tx->psbt, input_wscript);
}

assert(scriptPubkey);
psbt_input_set_wit_utxo(tx->psbt, input_num,
scriptPubkey, amount);
wally_err = wally_tx_add_input(tx->wtx,
&tx->psbt->tx->inputs[input_num]);
assert(wally_err == WALLY_OK);
/* scriptsig isn't actually store in psbt input, so add that now */

/* scriptsig isn't actually stored in psbt input, so add that now */
wally_tx_set_input_script(tx->wtx, input_num,
scriptSig, tal_bytelen(scriptSig));

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_set_asset(tx->psbt, input_num, &asset);
}
return input_num;
}

Expand Down
Loading