-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
chanfunding: create new package to abstract over funding workflows #3659
Changes from all commits
6753a02
f9d22cd
9eefdef
4e955df
d422ebb
7a64a7d
c3157ae
6e9cbc1
9926259
c3a7da5
6b729ec
b1940d6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
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) | ||
Roasbeef marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// 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 | ||
halseth marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
// 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 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a blocker for this PR, but some of these interfaces are already defined within There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They were purposefully copied over as they're pretty small interfaces, so would rather not create additional dependancies. It's also the case that if the interfaces in the sweeper are used, then a circular dependency cycle is created. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no circular dependency here since this is the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also agree that it is nice for a package to define its own set of interfaces, since it has it own set of requirements separate from the other package that might diverge in the future. |
||
// LockOutpoint locks a target outpoint, rendering it unusable for coin | ||
// selection. | ||
LockOutpoint(o wire.OutPoint) | ||
Roasbeef marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// 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) | ||
Roasbeef marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// 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() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might actually be a bit dangerous, as old channels which we are not initiator will not have the funding tx on disk, but also the bit won't be set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the bit isn't set, then that means we have the funding transaction. If it's set, then it means we don't. As written, if we're about to attempt to handle the funding transaction, we also check if we're the initiator or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the confusion arises from the method name.
HasFundingTx
makes it sound like it's the only check needed to retrieve the transaction, perhaps something likeCraftedExternally
is better?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this needs to be done which is why I think
HasFundingTx
is a dangerous name, as there is no guarantee we have it even though it returns true.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it makes sense since it is the channel type that has the funding tx, not the channel. I'm okay with keeping the name, but adding to the godoc that it is only the initiator that has the tx strored locally, but I agree with @wpaulino that a more descriptive name could lessen the confusion.