Skip to content

Commit

Permalink
fundpsbt: let caller specify locktime.
Browse files Browse the repository at this point in the history
Required for dual funding where the opener sets it.

Changelog-Added: JSON-RPC: `fundpsbt` takes a new `locktime` parameter
Signed-off-by: Rusty Russell <[email protected]>
  • Loading branch information
rustyrussell authored and niftynei committed Aug 18, 2020
1 parent bf5e994 commit 14baaaa
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 15 deletions.
3 changes: 2 additions & 1 deletion contrib/pyln-client/pyln/client/lightning.py
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ def unreserveinputs(self, psbt):
}
return self.call("unreserveinputs", payload)

def fundpsbt(self, satoshi, feerate, startweight, minconf=None, reserve=True):
def fundpsbt(self, satoshi, feerate, startweight, minconf=None, reserve=True, locktime=None):
"""
Create a PSBT with inputs sufficient to give an output of satoshi.
"""
Expand All @@ -1136,6 +1136,7 @@ def fundpsbt(self, satoshi, feerate, startweight, minconf=None, reserve=True):
"startweight": startweight,
"minconf": minconf,
"reserve": reserve,
"locktime": locktime,
}
return self.call("fundpsbt", payload)

Expand Down
6 changes: 5 additions & 1 deletion doc/lightning-fundpsbt.7

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion doc/lightning-fundpsbt.7.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ lightning-fundpsbt -- Command to populate PSBT inputs from the wallet
SYNOPSIS
--------

**fundpsbt** *satoshi* *feerate* *startweight* \[*minconf*\] \[*reserve*\]
**fundpsbt** *satoshi* *feerate* *startweight* \[*minconf*\] \[*reserve*\] \[*locktime*\]

DESCRIPTION
-----------
Expand Down Expand Up @@ -36,6 +36,9 @@ outputs should have. Default is 1.
*reserve* is a boolean: if true (the default), then *reserveinputs* is
called (successfully, with *exclusive* true) on the returned PSBT.

*locktime* is an optional locktime: if not set, it is set to a recent
block height.

EXAMPLE USAGE
-------------

Expand Down
8 changes: 6 additions & 2 deletions tests/test_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,16 +508,20 @@ def test_fundpsbt(node_factory, bitcoind, chainparams):
# Should get one input, plus some excess
funding = l1.rpc.fundpsbt(amount // 2, feerate, 0, reserve=False)
psbt = bitcoind.rpc.decodepsbt(funding['psbt'])
# We can fuzz this up to 99 blocks back.
assert psbt['tx']['locktime'] > bitcoind.rpc.getblockcount() - 100
assert psbt['tx']['locktime'] <= bitcoind.rpc.getblockcount()
assert len(psbt['tx']['vin']) == 1
assert funding['excess_msat'] > Millisatoshi(0)
assert funding['excess_msat'] < Millisatoshi(amount // 2 * 1000)
assert funding['feerate_per_kw'] == 7500
assert 'estimated_final_weight' in funding
assert 'reservations' not in funding

# This should add 99 to the weight, but otherwise be identical (might choose different inputs though!)
funding2 = l1.rpc.fundpsbt(amount // 2, feerate, 99, reserve=False)
# This should add 99 to the weight, but otherwise be identical (might choose different inputs though!) except for locktime.
funding2 = l1.rpc.fundpsbt(amount // 2, feerate, 99, reserve=False, locktime=bitcoind.rpc.getblockcount() + 1)
psbt2 = bitcoind.rpc.decodepsbt(funding2['psbt'])
assert psbt2['tx']['locktime'] == bitcoind.rpc.getblockcount() + 1
assert len(psbt2['tx']['vin']) == 1
assert funding2['excess_msat'] < funding['excess_msat']
assert funding2['feerate_per_kw'] == 7500
Expand Down
25 changes: 15 additions & 10 deletions wallet/reservation.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,11 @@ static struct command_result *finish_psbt(struct command *cmd,
u32 feerate_per_kw,
size_t weight,
struct amount_sat excess,
bool reserve)
bool reserve,
u32 *locktime)
{
struct json_stream *response;
struct bitcoin_tx *tx;
u32 locktime;
u32 current_height = get_block_height(cmd->ld->topology);

/* Setting the locktime to the next block to be mined has multiple
Expand All @@ -229,18 +229,21 @@ static struct command_result *finish_psbt(struct command *cmd,
* 0xFFFFFFFD by default. Other wallets are likely to implement
* this too).
*/
locktime = current_height;
if (!locktime) {
locktime = tal(cmd, u32);
*locktime = current_height;

/* Eventually fuzz it too. */
if (locktime > 100 && pseudorand(10) == 0)
locktime -= pseudorand(100);
/* Eventually fuzz it too. */
if (*locktime > 100 && pseudorand(10) == 0)
*locktime -= pseudorand(100);
}

/* FIXME: tx_spending_utxos does more than we need, but there
* are other users right now. */
tx = tx_spending_utxos(cmd, chainparams,
cast_const2(const struct utxo **, utxos),
cmd->ld->wallet->bip32_base,
false, 0, locktime,
false, 0, *locktime,
BITCOIN_TX_RBF_SEQUENCE);

response = json_stream_success(cmd);
Expand All @@ -264,14 +267,15 @@ static struct command_result *json_fundpsbt(struct command *cmd,
u32 *minconf, *weight;
struct amount_sat *amount, input, diff;
bool all, *reserve;
u32 maxheight;
u32 *locktime, maxheight;

if (!param(cmd, buffer, params,
p_req("satoshi", param_sat_or_all, &amount),
p_req("feerate", param_feerate, &feerate_per_kw),
p_req("startweight", param_number, &weight),
p_opt_def("minconf", param_number, &minconf, 1),
p_opt_def("reserve", param_bool, &reserve, true),
p_opt("locktime", param_number, &locktime),
NULL))
return command_param_failed();

Expand Down Expand Up @@ -336,7 +340,8 @@ static struct command_result *json_fundpsbt(struct command *cmd,
tal_count(utxos));
}

return finish_psbt(cmd, utxos, *feerate_per_kw, *weight, diff, *reserve);
return finish_psbt(cmd, utxos, *feerate_per_kw, *weight, diff, *reserve,
locktime);
}

static const struct json_command fundpsbt_command = {
Expand Down Expand Up @@ -474,7 +479,7 @@ static struct command_result *json_utxopsbt(struct command *cmd,
}

return finish_psbt(cmd, utxos, *feerate_per_kw, *weight, excess,
*reserve);
*reserve, NULL);
}
static const struct json_command utxopsbt_command = {
"utxopsbt",
Expand Down

0 comments on commit 14baaaa

Please sign in to comment.