Bulk onchain actions with PSBTs

PSBTs can be used to batch custom onchain transactions for maximum cost efficiency, for example to open multiple channels or send to multiple destinations in one transaction.

Partially Signed Bitcoin Transactions (PSBTs) are a standardized format to create, edit, amend, and sign Bitcoin transactions. This is useful when creating custom transactions, for example by specifying which inputs to consume, or including non-standard outputs.

An introductory guide to PSBTs and LND can be found here.

Bulk channel opens

PSBTs can be used to open multiple channels in a single onchain transaction, similar to lncli batchopenchannel.

To begin, a channel open is initiated using the OpenChan API, specifically the lnrpc.OpenChannelRequest. We specify all the parameters we need for the channel open, such as the channel size (local_funding_amount), the peer pubkey (node_pubkey) and whether the channel shall be announced (private).

For funding_shim we use lnrpc.PsbtShim and an empty base_pbst. We must not forget to set no_publish to true as well.

This will return a PSBT (psbt_fund.psbt). We repeat the above for the channel parameters of the second channel. This round, we pass the returned PSBT as the base_psbt, instead of an empty value.

We can repeat this as often as we need. For the final round, we will set no_publish to false.

To finalize the PSBT, we can use the FundPsbt call. If you want to use funds held in another application or device, remember to make sure that the wallet’s xpubs have been imported to LND.

To sign the transaction, we will have to pass the PSBT either to LND using the signPsbt RPC call. Alternatively, the PSBT will have to be signed by the external application or wallet.

Now we need the fundingStateStep API to verify the PSBT using the psbt_verify call with skip_finalize set to true for all channels except the last one (1 to n-1). The correct pending_chan_id has to be specified each time. This verifies that the transaction contains the correct outputs to fund the channel. These outputs have to be used to create the correct commitment transactions.

Only for the last channel do we repeat the above step with the latest pending_chan_id with skip_finalize set to false.

Finally, we repeat the above step one last time for the first channel, using the latest PSBT, the latest pending_chan_id and psbt_finalize set to true.

Bulk onchain transactions

The SendMany API lets you send an onchain transaction with multiple outputs, but it does not let you select specific inputs, and cannot be combined with a channel open.

We begin by calling the FundPsbt API. We can specify our raw inputs and outputs as part of the raw field. If we want to send this transaction from an external wallet, or have multiple onchain accounts imported to LND, we will also need to specify the account.

Using the PSBT returned in the above step, we call the FinalizePsbt API.

The resulting PSBT only needs to be signed. This is done with the signPsbt RPC call.

Finally, the PSBT needs to be published, which is done with the raw transaction and PublishTransaction.

Last updated