chanfunding

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 22, 2024 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrRemoteCanceled is the error that is returned to the user if the
	// funding flow was canceled by the remote peer.
	ErrRemoteCanceled = errors.New("remote canceled funding, possibly " +
		"timed out")

	// ErrUserCanceled is the error that is returned through the PsbtReady
	// channel if the user canceled the funding flow.
	ErrUserCanceled = errors.New("user canceled funding")
)

Functions

func DisableLog

func DisableLog()

DisableLog disables all library log output. Logging output is disabled by default until UseLogger is called.

func UseLogger

func UseLogger(logger slog.Logger)

UseLogger uses a specified Logger to output package logging info. This should be used in preference to SetLogWriter if the caller is also using slog.

Types

type Assembler

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)
}

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 CannedAssembler

type CannedAssembler struct {
	// contains filtered or unexported fields
}

CannedAssembler is a type of chanfunding.Assembler wherein the funding transaction is constructed outside of lnd, and may already exist. This Assembler serves as a shim which gives the funding flow the only thing it actually needs to proceed: the channel point.

func NewCannedAssembler

func NewCannedAssembler(thawHeight uint32, chanPoint wire.OutPoint,
	fundingAmt dcrutil.Amount, localKey *keychain.KeyDescriptor,
	remoteKey *secp256k1.PublicKey, initiator bool) *CannedAssembler

NewCannedAssembler creates a new CannedAssembler from the material required to construct a funding output and channel point.

func (*CannedAssembler) ProvisionChannel

func (c *CannedAssembler) ProvisionChannel(req *Request) (Intent, error)

ProvisionChannel creates a new ShimIntent given the passed funding Request. The returned intent is immediately able to provide the channel point and funding output as they've already been created outside lnd.

NOTE: This method satisfies the chanfunding.Assembler interface.

type Coin

type Coin struct {
	wire.TxOut

	wire.OutPoint
}

Coin represents a spendable UTXO which is available for channel funding. This UTXO need not reside in our internal wallet as an example, and instead may be derived from an existing watch-only wallet. It wraps both the output present within the UTXO set, and also the outpoint that generates this coin.

func CoinSelect

func CoinSelect(feeRate chainfee.AtomPerKByte, amt, dustLimit dcrutil.Amount,
	coins []Coin) ([]Coin, dcrutil.Amount, error)

CoinSelect attempts to select a sufficient amount of coins, including a change output to fund amt satoshis, adhering to the specified fee rate. The specified fee rate should be expressed in sat/kw for coin selection to function properly.

func CoinSelectSubtractFees

func CoinSelectSubtractFees(feeRate chainfee.AtomPerKByte, amt,
	dustLimit dcrutil.Amount, coins []Coin) ([]Coin, dcrutil.Amount,
	dcrutil.Amount, error)

CoinSelectSubtractFees attempts to select coins such that we'll spend up to amt in total after fees, adhering to the specified fee rate. The selected coins, the final output and change values are returned.

type CoinSelectionLocker

type CoinSelectionLocker interface {
	// WithCoinSelectLock will execute the passed function closure in a
	// synchronized manner preventing any coin selection operations from
	// proceeding while the closure is executing. This can be seen as the
	// ability to execute a function closure under an exclusive coin
	// selection lock.
	WithCoinSelectLock(func() error) 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 CoinSource

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)
}

CoinSource is an interface that allows a caller to access a source of UTXOs to use when attempting to fund a new channel.

type ConditionalPublishAssembler

type ConditionalPublishAssembler interface {
	Assembler

	// ShouldPublishFundingTx is a method of the assembler that signals if
	// the funding transaction should be published after the channel
	// negotiations are completed with the remote peer.
	ShouldPublishFundingTx() bool
}

ConditionalPublishAssembler is an assembler that can dynamically define if the funding transaction should be published after channel negotiations or not. Not publishing the transaction is only useful if the particular channel the assembler is in charge of is part of a batch of channels. In that case it is only safe to wait for all channel negotiations of the batch to complete before publishing the batch transaction.

type ErrInsufficientFunds

type ErrInsufficientFunds struct {
	// contains filtered or unexported fields
}

ErrInsufficientFunds is a type matching the error interface which is returned when coin selection for a new funding transaction fails to due having an insufficient amount of confirmed funds.

func (*ErrInsufficientFunds) Error

func (e *ErrInsufficientFunds) Error() string

Error returns a human readable string describing the error.

type FullIntent

type FullIntent struct {
	ShimIntent

	// InputCoins are the set of coins selected as inputs to this funding
	// transaction.
	InputCoins []Coin

	// ChangeOutputs are the set of outputs that the Assembler will use as
	// change from the main funding transaction.
	ChangeOutputs []*wire.TxOut
	// contains filtered or unexported fields
}

FullIntent is an intent that is fully backed by the internal wallet. This intent differs from the ShimIntent, in that the funding transaction will be constructed internally, and will consist of only inputs we wholly control. This Intent implements a basic state machine that must be executed in order before CompileFundingTx can be called.

Steps to final channel provisioning:

  1. Call BindKeys to notify the intent which keys to use when constructing the multi-sig output.
  2. Call CompileFundingTx afterwards to obtain the funding transaction.

If either of these steps fail, then the Cancel method MUST be called.

func (*FullIntent) BindKeys

func (f *FullIntent) BindKeys(localKey *keychain.KeyDescriptor,
	remoteKey *secp256k1.PublicKey)

BindKeys is a method unique to the FullIntent variant. This allows the caller to decide precisely which keys are used in the final funding transaction. This is kept out of the main Assembler as these may may not necessarily be under full control of the wallet. Only after this method has been executed will CompileFundingTx succeed.

func (*FullIntent) Cancel

func (f *FullIntent) Cancel()

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.

NOTE: Part of the chanfunding.Intent interface.

func (*FullIntent) CompileFundingTx

func (f *FullIntent) CompileFundingTx(extraInputs []*wire.TxIn,
	extraOutputs []*wire.TxOut) (*wire.MsgTx, error)

CompileFundingTx is to be called after BindKeys on the sub-intent has been called. This method will construct the final funding transaction, and fully sign all inputs that are known by the backing CoinSource. After this method returns, the Intent is assumed to be complete, as the output can be created at any point.

func (*FullIntent) Inputs added in v0.5.0

func (f *FullIntent) Inputs() []wire.OutPoint

Inputs returns all inputs to the final funding transaction that we know about. Since this funding transaction is created all from our wallet, it will be all inputs.

func (*FullIntent) Outputs added in v0.5.0

func (f *FullIntent) Outputs() []*wire.TxOut

Outputs returns all outputs of the final funding transaction that we know about. This will be the funding output and the change outputs going back to our wallet.

type FundingKeys

type FundingKeys struct {
	// LocalKey is our multi-sig key.
	LocalKey *keychain.KeyDescriptor

	// RemoteKey is the multi-sig key of the remote party.
	RemoteKey *secp256k1.PublicKey
}

FundingKeys couples our multi-sig key along with the remote party's key.

type FundingTxAssembler

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()
}

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 produces.

type Intent

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() dcrutil.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() dcrutil.Amount

	// Inputs returns all inputs to the final funding transaction that we
	// know about. Note that there might be more, but we are not (yet)
	// aware of.
	Inputs() []wire.OutPoint

	// Outputs returns all outputs of the final funding transaction that we
	// know about. Note that there might be more, but we are not (yet)
	// aware of.
	Outputs() []*wire.TxOut

	// 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()
}

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 OutpointLocker

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)
}

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 PsbtAssembler

type PsbtAssembler struct {
	// contains filtered or unexported fields
}

PsbtAssembler is a type of chanfunding.Assembler wherein the funding transaction is constructed outside of lnd by using partially signed bitcoin transactions (PSBT).

func NewPsbtAssembler

func NewPsbtAssembler(fundingAmt dcrutil.Amount, basePsbt *psbt.Packet,
	netParams *chaincfg.Params, shouldPublish bool) *PsbtAssembler

NewPsbtAssembler creates a new CannedAssembler from the material required to construct a funding output and channel point. An optional base PSBT can be supplied which will be used to add the channel output to instead of creating a new one.

func (*PsbtAssembler) ProvisionChannel

func (p *PsbtAssembler) ProvisionChannel(req *Request) (Intent, error)

ProvisionChannel creates a new ShimIntent given the passed funding Request. The returned intent is immediately able to provide the channel point and funding output as they've already been created outside lnd.

NOTE: This method satisfies the chanfunding.Assembler interface.

func (*PsbtAssembler) ShouldPublishFundingTx

func (p *PsbtAssembler) ShouldPublishFundingTx() bool

ShouldPublishFundingTx is a method of the assembler that signals if the funding transaction should be published after the channel negotiations are completed with the remote peer.

NOTE: This method is a part of the ConditionalPublishAssembler interface.

type PsbtIntent

type PsbtIntent struct {
	// ShimIntent is the wrapped basic intent that contains common fields
	// we also use in the PSBT funding case.
	ShimIntent

	// State is the current state the intent state machine is in.
	State PsbtState

	// BasePsbt is the user-supplied base PSBT the channel output should be
	// added to. If this is nil we will create a new, empty PSBT as the base
	// for the funding transaction.
	BasePsbt *psbt.Packet

	// PendingPsbt is the parsed version of the current PSBT. This can be
	// in two stages: If the user has not yet provided any PSBT, this is
	// nil. Once the user sends us an unsigned funded PSBT, we verify that
	// we have a valid transaction that sends to the channel output PK
	// script and has an input large enough to pay for it. We keep this
	// verified but not yet signed version around until the fully signed
	// transaction is submitted by the user. At that point we make sure the
	// inputs and outputs haven't changed to what was previously verified.
	// Only witness data should be added after the verification process.
	PendingPsbt *psbt.Packet

	// FinalTX is the final, signed and ready to be published wire format
	// transaction. This is only set after the PsbtFinalize step was
	// completed successfully.
	FinalTX *wire.MsgTx

	// PsbtReady is an error channel the funding manager will listen for
	// a signal about the PSBT being ready to continue the funding flow. In
	// the normal, happy flow, this channel is only ever closed. If a
	// non-nil error is sent through the channel, the funding flow will be
	// canceled.
	//
	// NOTE: This channel must always be buffered.
	PsbtReady chan error
	// contains filtered or unexported fields
}

PsbtIntent is an intent created by the PsbtAssembler which represents a funding output to be created by a PSBT. This might be used when a hardware wallet, or a channel factory is the entity crafting the funding transaction, and not lnd.

func (*PsbtIntent) BindKeys

func (i *PsbtIntent) BindKeys(localKey *keychain.KeyDescriptor,
	remoteKey *secp256k1.PublicKey)

BindKeys sets both the remote and local node's keys that will be used for the channel funding multisig output.

func (*PsbtIntent) Cancel

func (i *PsbtIntent) Cancel()

Cancel allows the caller to cancel a funding Intent at any time. This will return make sure the channel funding flow with the remote peer is failed and any reservations are canceled.

NOTE: Part of the chanfunding.Intent interface.

func (*PsbtIntent) CompileFundingTx

func (i *PsbtIntent) CompileFundingTx() (*wire.MsgTx, error)

CompileFundingTx finalizes the previously verified PSBT and returns the extracted binary serialized transaction from it. It also prepares the channel point for which this funding intent was initiated for.

func (*PsbtIntent) Finalize

func (i *PsbtIntent) Finalize(packet *psbt.Packet) error

Finalize makes sure the final PSBT that is given to the intent is fully valid and signed but still contains the same UTXOs and outputs as the pending transaction we previously verified. If everything checks out, the funding manager is informed that the channel can now be opened and the funding transaction be broadcast.

func (*PsbtIntent) FinalizeRawTX

func (i *PsbtIntent) FinalizeRawTX(rawTx *wire.MsgTx) error

FinalizeRawTX makes sure the final raw transaction that is given to the intent is fully valid and signed but still contains the same UTXOs and outputs as the pending transaction we previously verified. If everything checks out, the funding manager is informed that the channel can now be opened and the funding transaction be broadcast.

func (*PsbtIntent) FundingParams

func (i *PsbtIntent) FundingParams() (stdaddr.Address, int64, *psbt.Packet,
	error)

FundingParams returns the parameters that are necessary to start funding the channel output this intent was created for. It returns the P2WSH funding address, the exact funding amount and a PSBT packet that contains exactly one output that encodes the previous two parameters.

func (*PsbtIntent) Inputs added in v0.5.0

func (i *PsbtIntent) Inputs() []wire.OutPoint

Inputs returns all inputs to the final funding transaction that we know about. These are only known after the PSBT has been verified.

func (*PsbtIntent) Outputs added in v0.5.0

func (i *PsbtIntent) Outputs() []*wire.TxOut

Outputs returns all outputs of the final funding transaction that we know about. These are only known after the PSBT has been verified.

func (*PsbtIntent) RemoteCanceled

func (i *PsbtIntent) RemoteCanceled()

RemoteCanceled informs the listener of the PSBT ready channel that the funding has been canceled by the remote peer and that we can no longer continue with it.

func (*PsbtIntent) ShouldPublishFundingTX added in v0.6.0

func (i *PsbtIntent) ShouldPublishFundingTX() bool

ShouldPublishFundingTX returns true if the intent assumes that its assembler should publish the funding TX once the funding negotiation is complete.

func (*PsbtIntent) Verify

func (i *PsbtIntent) Verify(packet *psbt.Packet, skipFinalize bool) error

Verify makes sure the PSBT that is given to the intent has an output that sends to the channel funding multisig address with the correct amount. A simple check that at least a single input has been specified is performed.

type PsbtState

type PsbtState uint8

PsbtState is a type for the state of the PSBT intent state machine.

const (
	// PsbtShimRegistered denotes a channel funding process has started with
	// a PSBT shim attached. This is the default state for a PsbtIntent. We
	// don't use iota here because the values have to be in sync with the
	// RPC constants.
	PsbtShimRegistered PsbtState = 1

	// PsbtOutputKnown denotes that the local and remote peer have
	// negotiated the multisig keys to be used as the channel funding output
	// and therefore the PSBT funding process can now start.
	PsbtOutputKnown PsbtState = 2

	// PsbtVerified denotes that a potential PSBT has been presented to the
	// intent and passed all checks. The verified PSBT can be given to a/the
	// signer(s).
	PsbtVerified PsbtState = 3

	// PsbtFinalized denotes that a fully signed PSBT has been given to the
	// intent that looks identical to the previously verified transaction
	// but has all witness data added and is therefore completely signed.
	PsbtFinalized PsbtState = 4

	// PsbtFundingTxCompiled denotes that the PSBT processed by this intent
	// has been successfully converted into a protocol transaction. It is
	// not yet completely certain that the resulting transaction will be
	// published because the commitment transactions between the channel
	// peers first need to be counter signed. But the job of the intent is
	// hereby completed.
	PsbtFundingTxCompiled PsbtState = 5

	// PsbtInitiatorCanceled denotes that the user has canceled the intent.
	PsbtInitiatorCanceled PsbtState = 6

	// PsbtResponderCanceled denotes that the remote peer has canceled the
	// funding, likely due to a timeout.
	PsbtResponderCanceled PsbtState = 7
)

func (PsbtState) String

func (s PsbtState) String() string

String returns a string representation of the PsbtState.

type Request

type Request struct {
	// LocalAmt is the amount of coins we're placing into the funding
	// output.
	LocalAmt dcrutil.Amount

	// RemoteAmt is the amount of coins the remote party is contributing to
	// the funding output.
	RemoteAmt dcrutil.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.AtomPerKByte

	// ChangeAddr is a closure that will provide the Assembler with a
	// change address for the funding transaction if needed.
	ChangeAddr func() (stdaddr.Address, error)
}

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 ShimIntent

type ShimIntent struct {
	// contains filtered or unexported fields
}

ShimIntent is an intent created by the CannedAssembler which represents a funding output to be created that was constructed outside the wallet. This might be used when a hardware wallet, or a channel factory is the entity crafting the funding transaction, and not lnd.

func (*ShimIntent) Cancel

func (s *ShimIntent) Cancel()

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.

NOTE: This method satisfies the chanfunding.Intent interface.

func (*ShimIntent) ChanPoint

func (s *ShimIntent) ChanPoint() (*wire.OutPoint, error)

ChanPoint returns the final outpoint that will create the funding output described above.

NOTE: This method satisfies the chanfunding.Intent interface.

func (*ShimIntent) FundingOutput

func (s *ShimIntent) FundingOutput() ([]byte, *wire.TxOut, error)

FundingOutput returns the witness script, and the output that creates the funding output.

NOTE: This method satisfies the chanfunding.Intent interface.

func (*ShimIntent) Inputs added in v0.5.0

func (s *ShimIntent) Inputs() []wire.OutPoint

Inputs returns all inputs to the final funding transaction that we know about. For the ShimIntent this will always be none, since it is funded externally.

func (*ShimIntent) LocalFundingAmt

func (s *ShimIntent) LocalFundingAmt() dcrutil.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.

NOTE: This method satisfies the chanfunding.Intent interface.

func (*ShimIntent) MultiSigKeys

func (s *ShimIntent) MultiSigKeys() (*FundingKeys, error)

MultiSigKeys returns the committed multi-sig keys, but only if they've been specified/provided.

func (*ShimIntent) Outputs added in v0.5.0

func (s *ShimIntent) Outputs() []*wire.TxOut

Outputs returns all outputs of the final funding transaction that we know about. Since this is an externally funded channel, the channel output is the only known one.

func (*ShimIntent) RemoteFundingAmt

func (s *ShimIntent) RemoteFundingAmt() dcrutil.Amount

RemoteFundingAmt is the amount the remote party put into the channel.

NOTE: This method satisfies the chanfunding.Intent interface.

func (*ShimIntent) ThawHeight

func (s *ShimIntent) ThawHeight() uint32

ThawHeight returns the height where this channel goes back to being a normal channel.

type WalletAssembler

type WalletAssembler struct {
	// contains filtered or unexported fields
}

WalletAssembler is an instance of the Assembler interface that is backed by a full wallet. This variant of the Assembler interface will produce the entirety of the funding transaction within the wallet. This implements the typical funding flow that is initiated either on the p2p level or using the CLi.

func NewWalletAssembler

func NewWalletAssembler(cfg WalletConfig) *WalletAssembler

NewWalletAssembler creates a new instance of the WalletAssembler from a fully populated wallet config.

func (*WalletAssembler) FundingTxAvailable

func (w *WalletAssembler) FundingTxAvailable()

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.

NOTE: This method is a part of the FundingTxAssembler interface.

func (*WalletAssembler) ProvisionChannel

func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error)

ProvisionChannel is the main entry point to begin a funding workflow given a fully populated request. The internal WalletAssembler will perform coin selection in a goroutine safe manner, returning an Intent that will allow the caller to finalize the funding process.

NOTE: To cancel the funding flow the Cancel() method on the returned Intent, MUST be called.

NOTE: This is a part of the chanfunding.Assembler interface.

type WalletConfig

type WalletConfig struct {
	// CoinSource is what the WalletAssembler uses to list/locate coins.
	CoinSource CoinSource

	// CoinSelectionLocker allows the WalletAssembler to gain exclusive
	// access to the current set of coins returned by the CoinSource.
	CoinSelectLocker CoinSelectionLocker

	// CoinLocker is what the WalletAssembler uses to lock coins that may
	// be used as inputs for a new funding transaction.
	CoinLocker OutpointLocker

	// Signer allows the WalletAssembler to sign inputs on any potential
	// funding transactions.
	Signer input.Signer

	// DustLimit is the current dust limit. We'll use this to ensure that
	// we don't make dust outputs on the funding transaction.
	DustLimit dcrutil.Amount
}

WalletConfig is the main config of the WalletAssembler.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL