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
4 changes: 4 additions & 0 deletions bitcoin/tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include <wally_transaction.h>

#define BITCOIN_TX_DEFAULT_SEQUENCE 0xFFFFFFFF

/* BIP 125: Any nsequence < 0xFFFFFFFE is replacable.
* And bitcoind uses this value. */
#define BITCOIN_TX_RBF_SEQUENCE 0xFFFFFFFD
struct wally_psbt;

struct bitcoin_txid {
Expand Down
1 change: 0 additions & 1 deletion common/utxo.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ struct bitcoin_tx *tx_spending_utxos(const tal_t *ctx,
struct pubkey key;
u8 *scriptSig, *scriptPubkey, *redeemscript;

assert(num_output);
size_t outcount = add_change_output ? 1 + num_output : num_output;
struct bitcoin_tx *tx = bitcoin_tx(ctx, chainparams, tal_count(utxos),
outcount, nlocktime);
Expand Down
3 changes: 3 additions & 0 deletions common/utxo.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ struct utxo {
/* NULL if not spent yet, otherwise, the block the spending transaction is in */
const u32 *spendheight;

/* Block this utxo becomes unreserved, if applicable */
u32 *reserved_til;

/* The scriptPubkey if it is known */
u8 *scriptPubkey;

Expand Down
25 changes: 17 additions & 8 deletions contrib/pyln-client/pyln/client/lightning.py
Original file line number Diff line number Diff line change
Expand Up @@ -1107,28 +1107,37 @@ def txsend(self, txid):
}
return self.call("txsend", payload)

def reserveinputs(self, outputs, feerate=None, minconf=None, utxos=None):
def reserveinputs(self, psbt, exclusive=True):
"""
Reserve UTXOs and return a psbt for a 'stub' transaction that
spends the reserved UTXOs.
Reserve any inputs in this psbt.
"""
payload = {
"outputs": outputs,
"feerate": feerate,
"minconf": minconf,
"utxos": utxos,
"psbt": psbt,
"exclusive": exclusive,
}
return self.call("reserveinputs", payload)

def unreserveinputs(self, psbt):
"""
Unreserve UTXOs that were previously reserved.
Unreserve (or reduce reservation) on any UTXOs in this psbt were previously reserved.
"""
payload = {
"psbt": psbt,
}
return self.call("unreserveinputs", payload)

def fundpsbt(self, satoshi, feerate, minconf=None, reserve=True):
"""
Create a PSBT with inputs sufficient to give an output of satoshi.
"""
payload = {
"satoshi": satoshi,
"feerate": feerate,
"minconf": minconf,
"reserve": reserve,
}
return self.call("fundpsbt", payload)

def signpsbt(self, psbt):
"""
Add internal wallet's signatures to PSBT
Expand Down
1 change: 1 addition & 0 deletions doc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ MANPAGES := doc/lightning-cli.1 \
doc/lightning-fundchannel_start.7 \
doc/lightning-fundchannel_complete.7 \
doc/lightning-fundchannel_cancel.7 \
doc/lightning-fundpsbt.7 \
doc/lightning-getroute.7 \
doc/lightning-getsharedsecret.7 \
doc/lightning-hsmtool.8 \
Expand Down
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ c-lightning Documentation
lightning-fundchannel_cancel <lightning-fundchannel_cancel.7.md>
lightning-fundchannel_complete <lightning-fundchannel_complete.7.md>
lightning-fundchannel_start <lightning-fundchannel_start.7.md>
lightning-fundpsbt <lightning-fundpsbt.7.md>
lightning-getroute <lightning-getroute.7.md>
lightning-getsharedsecret <lightning-getsharedsecret.7.md>
lightning-hsmtool <lightning-hsmtool.8.md>
Expand Down
76 changes: 76 additions & 0 deletions doc/lightning-fundpsbt.7

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

69 changes: 69 additions & 0 deletions doc/lightning-fundpsbt.7.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
lightning-fundpsbt -- Command to populate PSBT inputs from the wallet
================================================================

SYNOPSIS
--------

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

DESCRIPTION
-----------

`fundpsbt` is a low-level RPC command which creates a PSBT using unreserved
inputs in the wallet, optionally reserving them as well.

*satoshi* is the minimum satoshi value of the output(s) needed (or the
string "all" meaning use all unreserved inputs). If a value, it can
be a whole number, a whole number ending in *sat*, a whole number
ending in *000msat*, or a number with 1 to 8 decimal places ending in
*btc*.
Copy link
Contributor

@ZmnSCPxj ZmnSCPxj Jul 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably mention that:

  • fundpsbt factors in the fees needed for each input it proposes to add.
  • the given satoshi value should include the fee for the outputs, plus the fee for the common parts (nLockTime, nVersion etc) of the transaction.

The latter point implies that plugins need access to the fee estimates. While plugins can call the bcli estimatefees directly, I think it is best if lightningd/chaintopology also exposes the actual feerates it would use, especially since estimatefees is allowed to return null and chaintopology, to my understanding, papers over that case. (I think? @darosior )

Alternately, since e.g. Liquid apparently has explicit fee outputs, maybe we can add another parameter, outputs, which is an array of strings or nulls:

  • An entry can be an address, in which case fundpsbt allocates fees enough for an output going to that address.
  • An entry can be any of the following strings, indicating fundpsbt allocates fees enough for an output going to that kind of address:
    • p2pkh
    • p2pk - or not who uses this nowadays
    • p2sh
    • p2wpkh
    • p2wsh
    • op-return-# where # is a number from 0 to 64 (or whatever the OP_RETURN max is).
  • An entry can be null, in which case fundpsbt will allocate fees for the largest known valid address type scriptPubKey..

Then fundpsbt can consider whether there is some excess and see if it is large enough to (1) pay for its existence as a change output and (2) remains large enough to keep itself above the dust limit. If not, it adds the excess to fees (which it adds as an explicit output for Liquid txes).

With this outputs parameter we can also have fundpsbt consider the common parts of the transaction (nLockTime and friends). This removes any remaining reasons that a robust plugin would want to loop around fundpsbt.

Copy link
Contributor

@darosior darosior Jul 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latter point implies that plugins need access to the fee estimates. While plugins can call the bcli estimatefees directly, I think it is best if lightningd/chaintopology also exposes the actual feerates it would use, especially since estimatefees is allowed to return null and chaintopology, to my understanding, papers over that case. (I think? @darosior )

Right, better to use the feerate command which returns a human error in case of estimation failure and smoothed estimation otherwise.

estimatefees could fail (and we allow it to), while feerates would still return a result based on our cached history (if we have one, ie not startup).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, right, feerates. Will go document it for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably mention that:

* `fundpsbt` factors in the fees needed for each input it proposes to add.

* the given `satoshi` value should include the fee for the outputs, plus the fee for the common parts (`nLockTime`, `nVersion` etc) of the transaction.

The next paragraph does exactly this:

You calculate the value by starting with the amount you want to pay
and adding the fee which will be needed to pay for the base of the
transaction plus that output, and any other outputs and inputs you
will add to the final transaction.

With this outputs parameter we can also have fundpsbt consider the common parts of the transaction (nLockTime and friends). This removes any remaining reasons that a robust plugin would want to loop around fundpsbt.

Indeed. My draft txprepare-as-plugin patch does exactly this, and it's pretty simple (now we have the helpers in place!).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. My draft txprepare-as-plugin patch does exactly this, and it's pretty simple (now we have the helpers in place!).

Is the code in txprepare or in fundpsbt? I cannot find txprepare-as-plugin branch in your repo or in the ElementsProject repo. My concern is that I believe you mentioned deprecation of txprepare, and in any case fundchannel/multifundchannel will want to move away from txprepare anyway. So a command which wraps fundpsbt and handles as well the common and output weight fees would be quite convenient; if txprepare will be deprecated later, it would be useful for both withdraw and fundchannel (and their multi versions) to use that rather than the existing base fundpsbt.


You calculate the value by starting with the amount you want to pay
and adding the fee which will be needed to pay for the base of the
transaction plus that output, and any other outputs and inputs you
will add to the final transaction.

*feerate* is a number, with an optional suffix: *perkw* means the
number is interpreted as satoshi-per-kilosipa (weight), and *perkb*
means it is interpreted bitcoind-style as
satoshi-per-kilobyte. Omitting the suffix is equivalent to *perkb*.

*minconf* specifies the minimum number of confirmations that used
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.

RETURN VALUE
------------

On success, returns the *psbt* containing the inputs, and
*excess_msat* containing the amount above *satoshi* which is
available. This could be zero, or dust. If *satoshi* was "all",
then *excess_msat* is the entire amount once fees are subtracted
for the weights of the inputs.

If *reserve* was true, then a *reservations* array is returned,
exactly like *reserveinputs*.

On error the returned object will contain `code` and `message` properties,
with `code` being one of the following:

- -32602: If the given parameters are wrong.
- -1: Catchall nonspecific error.
- 301: Insufficient UTXOs to meet *satoshi* value.

AUTHOR
------

Rusty Russell <<rusty@rustcorp.com.au>> is mainly responsible.

SEE ALSO
--------

lightning-reserveinputs(7), lightning-unreserveinputs(7).

RESOURCES
---------

Main web site: <https://github.com/ElementsProject/lightning>
73 changes: 24 additions & 49 deletions doc/lightning-reserveinputs.7

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

Loading