d422ebbc66
In this commit, we introduce a series of new abstractions for channel funding. The end goal is to enable uses cases that construct the funding transaction externally, eventually handing the funding outpoint to lnd. An example of such a use case includes channel factories and external channel funding using a hardware wallet. We also add a new chanfunding.Assembler meant to allow external channel funding in contexts similar to how channel factories can be constructed. With this channel funder, we'll only obtain the channel point and funding output from it, as this alone is enough to carry out a funding flow as normal.
138 lines
5.4 KiB
Go
138 lines
5.4 KiB
Go
package chanfunding
|
|
|
|
import (
|
|
"github.com/btcsuite/btcd/wire"
|
|
"github.com/btcsuite/btcutil"
|
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
|
)
|
|
|
|
// CoinSource is an interface that allows a caller to access a source of UTXOs
|
|
// to use when attempting to fund a new channel.
|
|
type CoinSource interface {
|
|
// ListCoins returns all UTXOs from the source that have between
|
|
// minConfs and maxConfs number of confirmations.
|
|
ListCoins(minConfs, maxConfs int32) ([]Coin, error)
|
|
|
|
// CoinFromOutPoint attempts to locate details pertaining to a coin
|
|
// based on its outpoint. If the coin isn't under the control of the
|
|
// backing CoinSource, then an error should be returned.
|
|
CoinFromOutPoint(wire.OutPoint) (*Coin, error)
|
|
}
|
|
|
|
// CoinSelectionLocker is an interface that allows the caller to perform an
|
|
// operation, which is synchronized with all coin selection attempts. This can
|
|
// be used when an operation requires that all coin selection operations cease
|
|
// forward progress. Think of this as an exclusive lock on coin selection
|
|
// operations.
|
|
type CoinSelectionLocker interface {
|
|
// WithCoinSelectLock will execute the passed function closure in a
|
|
// synchronized manner preventing any coin selection operations from
|
|
// proceeding while the closure if executing. This can be seen as the
|
|
// ability to execute a function closure under an exclusive coin
|
|
// selection lock.
|
|
WithCoinSelectLock(func() error) error
|
|
}
|
|
|
|
// OutpointLocker allows a caller to lock/unlock an outpoint. When locked, the
|
|
// outpoints shouldn't be used for any sort of channel funding of coin
|
|
// selection. Locked outpoints are not expected to be persisted between
|
|
// restarts.
|
|
type OutpointLocker interface {
|
|
// LockOutpoint locks a target outpoint, rendering it unusable for coin
|
|
// selection.
|
|
LockOutpoint(o wire.OutPoint)
|
|
|
|
// UnlockOutpoint unlocks a target outpoint, allowing it to be used for
|
|
// coin selection once again.
|
|
UnlockOutpoint(o wire.OutPoint)
|
|
}
|
|
|
|
// Request is a new request for funding a channel. The items in the struct
|
|
// governs how the final channel point will be provisioned by the target
|
|
// Assembler.
|
|
type Request struct {
|
|
// LocalAmt is the amount of coins we're placing into the funding
|
|
// output.
|
|
LocalAmt btcutil.Amount
|
|
|
|
// RemoteAmt is the amount of coins the remote party is contributing to
|
|
// the funding output.
|
|
RemoteAmt btcutil.Amount
|
|
|
|
// MinConfs controls how many confirmations a coin need to be eligible
|
|
// to be used as an input to the funding transaction. If this value is
|
|
// set to zero, then zero conf outputs may be spent.
|
|
MinConfs int32
|
|
|
|
// SubtractFees should be set if we intend to spend exactly LocalAmt
|
|
// when opening the channel, subtracting the fees from the funding
|
|
// output. This can be used for instance to use all our remaining funds
|
|
// to open the channel, since it will take fees into
|
|
// account.
|
|
SubtractFees bool
|
|
|
|
// FeeRate is the fee rate in sat/kw that the funding transaction
|
|
// should carry.
|
|
FeeRate chainfee.SatPerKWeight
|
|
|
|
// ChangeAddr is a closure that will provide the Assembler with a
|
|
// change address for the funding transaction if needed.
|
|
ChangeAddr func() (btcutil.Address, error)
|
|
}
|
|
|
|
// Intent is returned by an Assembler and represents the base functionality the
|
|
// caller needs to proceed with channel funding on a higher level. If the
|
|
// Cancel method is called, then all resources assembled to fund the channel
|
|
// will be released back to the eligible pool.
|
|
type Intent interface {
|
|
// FundingOutput returns the witness script, and the output that
|
|
// creates the funding output.
|
|
FundingOutput() ([]byte, *wire.TxOut, error)
|
|
|
|
// ChanPoint returns the final outpoint that will create the funding
|
|
// output described above.
|
|
ChanPoint() (*wire.OutPoint, error)
|
|
|
|
// RemoteFundingAmt is the amount the remote party put into the
|
|
// channel.
|
|
RemoteFundingAmt() btcutil.Amount
|
|
|
|
// LocalFundingAmt is the amount we put into the channel. This may
|
|
// differ from the local amount requested, as depending on coin
|
|
// selection, we may bleed from of that LocalAmt into fees to minimize
|
|
// change.
|
|
LocalFundingAmt() btcutil.Amount
|
|
|
|
// Cancel allows the caller to cancel a funding Intent at any time.
|
|
// This will return any resources such as coins back to the eligible
|
|
// pool to be used in order channel fundings.
|
|
Cancel()
|
|
}
|
|
|
|
// Assembler is an abstract object that is capable of assembling everything
|
|
// needed to create a new funding output. As an example, this assembler may be
|
|
// our core backing wallet, an interactive PSBT based assembler, an assembler
|
|
// than can aggregate multiple intents into a single funding transaction, or an
|
|
// external protocol that creates a funding output out-of-band such as channel
|
|
// factories.
|
|
type Assembler interface {
|
|
// ProvisionChannel returns a populated Intent that can be used to
|
|
// further the channel funding workflow. Depending on the
|
|
// implementation of Assembler, additional state machine (Intent)
|
|
// actions may be required before the FundingOutput and ChanPoint are
|
|
// made available to the caller.
|
|
ProvisionChannel(*Request) (Intent, error)
|
|
}
|
|
|
|
// FundingTxAssembler is a super-set of the regular Assembler interface that's
|
|
// also able to provide a fully populated funding transaction via the intents
|
|
// that it produuces.
|
|
type FundingTxAssembler interface {
|
|
Assembler
|
|
|
|
// FundingTxAvailable is an empty method that an assembler can
|
|
// implement to signal to callers that its able to provide the funding
|
|
// transaction for the channel via the intent it returns.
|
|
FundingTxAvailable()
|
|
}
|