contractcourt

package
v0.0.0-...-49584ae Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2019 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// NoAction is the min chainAction type, indicating that no action
	// needs to be taken for a given HTLC.
	NoAction ChainAction = 0

	// HtlcTimeoutAction indicates that the HTLC will timeout soon. As a
	// result, we should get ready to sweep it on chain after the timeout.
	HtlcTimeoutAction = 1

	// HtlcClaimAction indicates that we should claim the HTLC on chain
	// before its timeout period.
	HtlcClaimAction = 2

	// HtlcFailNowAction indicates that we should fail an outgoing HTLC
	// immediately by cancelling it backwards as it has no corresponding
	// output in our commitment transaction.
	HtlcFailNowAction = 3

	// HtlcOutgoingWatchAction indicates that we can't yet timeout this
	// HTLC, but we had to go to chain on order to resolve an existing
	// HTLC.  In this case, we'll either: time it out once it expires, or
	// will learn the pre-image if the remote party claims the output. In
	// this case, well add the pre-image to our global store.
	HtlcOutgoingWatchAction = 4

	// HtlcIncomingWatchAction indicates that we don't yet have the
	// pre-image to claim incoming HTLC, but we had to go to chain in order
	// to resolve and existing HTLC. In this case, we'll either: let the
	// other party time it out, or eventually learn of the pre-image, in
	// which case we'll claim on chain.
	HtlcIncomingWatchAction = 5
)

Variables

View Source
var ErrChainArbExiting = errors.New("ChainArbitrator exiting")

ErrChainArbExiting signals that the chain arbitrator is shutting down.

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

Types

type ArbitratorLog

type ArbitratorLog interface {

	// CurrentState returns the current state of the ChannelArbitrator.
	CurrentState() (ArbitratorState, error)

	// CommitState persists, the current state of the chain attendant.
	CommitState(ArbitratorState) error

	// InsertUnresolvedContracts inserts a set of unresolved contracts into
	// the log. The log will then persistently store each contract until
	// they've been swapped out, or resolved.
	InsertUnresolvedContracts(...ContractResolver) error

	// FetchUnresolvedContracts returns all unresolved contracts that have
	// been previously written to the log.
	FetchUnresolvedContracts() ([]ContractResolver, error)

	// SwapContract performs an atomic swap of the old contract for the new
	// contract. This method is used when after a contract has been fully
	// resolved, it produces another contract that needs to be resolved.
	SwapContract(old ContractResolver, new ContractResolver) error

	// ResolveContract marks a contract as fully resolved. Once a contract
	// has been fully resolved, it is deleted from persistent storage.
	ResolveContract(ContractResolver) error

	// LogContractResolutions stores a complete contract resolution for the
	// contract under watch. This method will be called once the
	// ChannelArbitrator either force closes a channel, or detects that the
	// remote party has broadcast their commitment on chain.
	LogContractResolutions(*ContractResolutions) error

	// FetchContractResolutions fetches the set of previously stored
	// contract resolutions from persistent storage.
	FetchContractResolutions() (*ContractResolutions, error)

	// LogChainActions stores a set of chain actions which are derived from
	// our set of active contracts, and the on-chain state. We'll write
	// this et of cations when: we decide to go on-chain to resolve a
	// contract, or we detect that the remote party has gone on-chain.
	LogChainActions(ChainActionMap) error

	// FetchChainActions attempts to fetch the set of previously stored
	// chain actions. We'll use this upon restart to properly advance our
	// state machine forward.
	FetchChainActions() (ChainActionMap, error)

	// WipeHistory is to be called ONLY once *all* contracts have been
	// fully resolved, and the channel closure if finalized. This method
	// will delete all on-disk state within the persistent log.
	WipeHistory() error
}

ArbitratorLog is the primary source of persistent storage for the ChannelArbitrator. The log stores the current state of the ChannelArbitrator's internal state machine, any items that are required to properly make a state transition, and any unresolved contracts.

type ArbitratorState

type ArbitratorState uint8

ArbitratorState is an enum that details the current state of the ChannelArbitrator's state machine.

const (
	// StateDefault is the default state. In this state, no major actions
	// need to be executed.
	StateDefault ArbitratorState = 0

	// StateBroadcastCommit is a state that indicates that the attendant
	// has decided to broadcast the commitment transaction, but hasn't done
	// so yet.
	StateBroadcastCommit ArbitratorState = 1

	// StateCommitmentBroadcasted is a state that indicates that the
	// attendant has broadcasted the commitment transaction, and is now
	// waiting for it to confirm.
	StateCommitmentBroadcasted ArbitratorState = 6

	// StateContractClosed is a state that indicates the contract has
	// already been "closed", meaning the commitment is confirmed on chain.
	// At this point, we can now examine our active contracts, in order to
	// create the proper resolver for each one.
	StateContractClosed ArbitratorState = 2

	// StateWaitingFullResolution is a state that indicates that the
	// commitment transaction has been confirmed, and the attendant is now
	// waiting for all unresolved contracts to be fully resolved.
	StateWaitingFullResolution ArbitratorState = 3

	// StateFullyResolved is the final state of the attendant. In this
	// state, all related contracts have been resolved, and the attendant
	// can now be garbage collected.
	StateFullyResolved ArbitratorState = 4

	// StateError is the only error state of the resolver. If we enter this
	// state, then we cannot proceed with manual intervention as a state
	// transition failed.
	StateError ArbitratorState = 5
)

func (ArbitratorState) String

func (a ArbitratorState) String() string

String returns a human readable string describing the ArbitratorState.

type ChainAction

type ChainAction uint8

ChainAction is an enum that encompasses all possible on-chain actions we'll take for a set of HTLC's.

func (ChainAction) String

func (c ChainAction) String() string

String returns a human readable string describing a chain action.

type ChainActionMap

type ChainActionMap map[ChainAction][]channeldb.HTLC

ChainActionMap is a map of a chain action, to the set of HTLC's that need to be acted upon for a given action type. The channel

type ChainArbitrator

type ChainArbitrator struct {
	sync.Mutex
	// contains filtered or unexported fields
}

ChainArbitrator is a sub-system that oversees the on-chain resolution of all active, and channel that are in the "pending close" state. Within the contractcourt package, the ChainArbitrator manages a set of active ContractArbitrators. Each ContractArbitrators is responsible for watching the chain for any activity that affects the state of the channel, and also for monitoring each contract in order to determine if any on-chain activity is required. Outside sub-systems interact with the ChainArbitrator in order to forcibly exit a contract, update the set of live signals for each contract, and to receive reports on the state of contract resolution.

func NewChainArbitrator

func NewChainArbitrator(cfg ChainArbitratorConfig,
	db *channeldb.DB) *ChainArbitrator

NewChainArbitrator returns a new instance of the ChainArbitrator using the passed config struct, and backing persistent database.

func (*ChainArbitrator) ForceCloseContract

func (c *ChainArbitrator) ForceCloseContract(chanPoint wire.OutPoint) (*wire.MsgTx, error)

ForceCloseContract attempts to force close the channel infield by the passed channel point. A force close will immediately terminate the contract, causing it to enter the resolution phase. If the force close was successful, then the force close transaction itself will be returned.

TODO(roasbeef): just return the summary itself?

func (*ChainArbitrator) Start

func (c *ChainArbitrator) Start() error

Start launches all goroutines that the ChainArbitrator needs to operate.

func (*ChainArbitrator) Stop

func (c *ChainArbitrator) Stop() error

Stop signals the ChainArbitrator to trigger a graceful shutdown. Any active channel arbitrators will be signalled to exit, and this method will block until they've all exited.

func (*ChainArbitrator) SubscribeChannelEvents

func (c *ChainArbitrator) SubscribeChannelEvents(
	chanPoint wire.OutPoint) (*ChainEventSubscription, error)

SubscribeChannelEvents returns a new active subscription for the set of possible on-chain events for a particular channel. The struct can be used by callers to be notified whenever an event that changes the state of the channel on-chain occurs. If syncDispatch is true, then the sender of the notification will wait until an error is sent over the ProcessACK before modifying any database state. This allows callers to request a reliable hand off.

TODO(roasbeef): can be used later to provide RPC hook for all channel lifetimes

func (*ChainArbitrator) UpdateContractSignals

func (c *ChainArbitrator) UpdateContractSignals(chanPoint wire.OutPoint,
	signals *ContractSignals) error

UpdateContractSignals sends a set of active, up to date contract signals to the ChannelArbitrator which is has been assigned to the channel infield by the passed channel point.

func (*ChainArbitrator) WatchNewChannel

func (c *ChainArbitrator) WatchNewChannel(newChan *channeldb.OpenChannel) error

WatchNewChannel sends the ChainArbitrator a message to create a ChannelArbitrator tasked with watching over a new channel. Once a new channel has finished its final funding flow, it should be registered with the ChainArbitrator so we can properly react to any on-chain events.

type ChainArbitratorConfig

type ChainArbitratorConfig struct {
	// ChainHash is the chain that this arbitrator is to operate within.
	ChainHash chainhash.Hash

	// BroadcastDelta is the delta that we'll use to decide when to
	// broadcast our commitment transaction.  This value should be set
	// based on our current fee estimation of the commitment transaction.
	// We use this to determine when we should broadcast instead of the
	// just the HTLC timeout, as we want to ensure that the commitment
	// transaction is already confirmed, by the time the HTLC expires.
	BroadcastDelta uint32

	// NewSweepAddr is a function that returns a new address under control
	// by the wallet. We'll use this to sweep any no-delay outputs as a
	// result of unilateral channel closes.
	//
	// NOTE: This SHOULD return a p2wkh script.
	NewSweepAddr func() ([]byte, error)

	// PublishTx reliably broadcasts a transaction to the network. Once
	// this function exits without an error, then they transaction MUST
	// continually be rebroadcast if needed.
	PublishTx func(*wire.MsgTx) error

	// DeliverResolutionMsg is a function that will append an outgoing
	// message to the "out box" for a ChannelLink. This is used to cancel
	// backwards any HTLC's that are either dust, we're timing out, or
	// settling on-chain to the incoming link.
	DeliverResolutionMsg func(...ResolutionMsg) error

	// MarkLinkInactive is a function closure that the ChainArbitrator will
	// use to mark that active HTLC's shouldn't be attempt ted to be routed
	// over a particular channel. This function will be called in that a
	// ChannelArbitrator decides that it needs to go to chain in order to
	// resolve contracts.
	//
	// TODO(roasbeef): rename, routing based
	MarkLinkInactive func(wire.OutPoint) error

	// ContractBreach is a function closure that the ChainArbitrator will
	// use to notify the breachArbiter about a contract breach. It should
	// only return a non-nil error when the breachArbiter has preserved the
	// necessary breach info for this channel point, and it is safe to mark
	// the channel as pending close in the database.
	ContractBreach func(wire.OutPoint, *lnwallet.BreachRetribution) error

	// IsOurAddress is a function that returns true if the passed address
	// is known to the underlying wallet. Otherwise, false should be
	// returned.
	IsOurAddress func(pfcutil.Address) bool

	// IncubateOutput sends either an incoming HTLC, an outgoing HTLC, or
	// both to the utxo nursery. Once this function returns, the nursery
	// should have safely persisted the outputs to disk, and should start
	// the process of incubation. This is used when a resolver wishes to
	// pass off the output to the nursery as we're only waiting on an
	// absolute/relative item block.
	IncubateOutputs func(wire.OutPoint, *lnwallet.CommitOutputResolution,
		*lnwallet.OutgoingHtlcResolution,
		*lnwallet.IncomingHtlcResolution, uint32) error

	// PreimageDB is a global store of all known pre-images. We'll use this
	// to decide if we should broadcast a commitment transaction to claim
	// an HTLC on-chain.
	PreimageDB WitnessBeacon

	// Notifier is an instance of a chain notifier we'll use to watch for
	// certain on-chain events.
	Notifier chainntnfs.ChainNotifier

	// Signer is a signer backed by the active lnd node. This should be
	// capable of producing a signature as specified by a valid
	// SignDescriptor.
	Signer lnwallet.Signer

	// FeeEstimator will be used to return fee estimates.
	FeeEstimator lnwallet.FeeEstimator

	// ChainIO allows us to query the state of the current main chain.
	ChainIO lnwallet.BlockChainIO

	// DisableChannel disables a channel, resulting in it not being able to
	// forward payments.
	DisableChannel func(wire.OutPoint) error

	// Sweeper allows resolvers to sweep their final outputs.
	Sweeper *sweep.UtxoSweeper
}

ChainArbitratorConfig is a configuration struct that contains all the function closures and interface that required to arbitrate on-chain contracts for a particular chain.

type ChainEventSubscription

type ChainEventSubscription struct {
	// ChanPoint is that channel that chain events will be dispatched for.
	ChanPoint wire.OutPoint

	// RemoteUnilateralClosure is a channel that will be sent upon in the
	// event that the remote party's commitment transaction is confirmed.
	RemoteUnilateralClosure chan *lnwallet.UnilateralCloseSummary

	// LocalUnilateralClosure is a channel that will be sent upon in the
	// event that our commitment transaction is confirmed.
	LocalUnilateralClosure chan *LocalUnilateralCloseInfo

	// CooperativeClosure is a signal that will be sent upon once a
	// cooperative channel closure has been detected confirmed.
	CooperativeClosure chan *CooperativeCloseInfo

	// ContractBreach is a channel that will be sent upon if we detect a
	// contract breach. The struct sent across the channel contains all the
	// material required to bring the cheating channel peer to justice.
	ContractBreach chan *lnwallet.BreachRetribution

	// Cancel cancels the subscription to the event stream for a particular
	// channel. This method should be called once the caller no longer needs to
	// be notified of any on-chain events for a particular channel.
	Cancel func()
}

ChainEventSubscription is a struct that houses a subscription to be notified for any on-chain events related to a channel. There are three types of possible on-chain events: a cooperative channel closure, a unilateral channel closure, and a channel breach. The fourth type: a force close is locally initiated, so we don't provide any event stream for said event.

type ChannelArbitrator

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

ChannelArbitrator is the on-chain arbitrator for a particular channel. The struct will keep in sync with the current set of HTLCs on the commitment transaction. The job of the attendant is to go on-chain to either settle or cancel an HTLC as necessary iff: an HTLC times out, or we known the pre-image to an HTLC, but it wasn't settled by the link off-chain. The ChannelArbitrator will factor in an expected confirmation delta when broadcasting to ensure that we avoid any possibility of race conditions, and sweep the output(s) without contest.

func NewChannelArbitrator

func NewChannelArbitrator(cfg ChannelArbitratorConfig,
	startingHTLCs []channeldb.HTLC, log ArbitratorLog) *ChannelArbitrator

NewChannelArbitrator returns a new instance of a ChannelArbitrator backed by the passed config struct.

func (*ChannelArbitrator) Start

func (c *ChannelArbitrator) Start() error

Start starts all the goroutines that the ChannelArbitrator needs to operate.

func (*ChannelArbitrator) Stop

func (c *ChannelArbitrator) Stop() error

Stop signals the ChannelArbitrator for a graceful shutdown.

func (*ChannelArbitrator) UpdateContractSignals

func (c *ChannelArbitrator) UpdateContractSignals(newSignals *ContractSignals)

UpdateContractSignals updates the set of signals the ChannelArbitrator needs to receive from a channel in real-time in order to keep in sync with the latest state of the contract.

type ChannelArbitratorConfig

type ChannelArbitratorConfig struct {
	// ChanPoint is the channel point that uniquely identifies this
	// channel.
	ChanPoint wire.OutPoint

	// ShortChanID describes the exact location of the channel within the
	// chain. We'll use this to address any messages that we need to send
	// to the switch during contract resolution.
	ShortChanID lnwire.ShortChannelID

	// BlockEpochs is an active block epoch event stream backed by an
	// active ChainNotifier instance. We will use new block notifications
	// sent over this channel to decide when we should go on chain to
	// reclaim/redeem the funds in an HTLC sent to/from us.
	BlockEpochs *chainntnfs.BlockEpochEvent

	// ChainEvents is an active subscription to the chain watcher for this
	// channel to be notified of any on-chain activity related to this
	// channel.
	ChainEvents *ChainEventSubscription

	// ForceCloseChan should force close the contract that this attendant
	// is watching over. We'll use this when we decide that we need to go
	// to chain. It should in addition tell the switch to remove the
	// corresponding link, such that we won't accept any new updates. The
	// returned summary contains all items needed to eventually resolve all
	// outputs on chain.
	ForceCloseChan func() (*lnwallet.LocalForceCloseSummary, error)

	// MarkCommitmentBroadcasted should mark the channel as the commitment
	// being broadcast, and we are waiting for the commitment to confirm.
	MarkCommitmentBroadcasted func() error

	// MarkChannelClosed marks the channel closed in the database, with the
	// passed close summary. After this method successfully returns we can
	// no longer expect to receive chain events for this channel, and must
	// be able to recover from a failure without getting the close event
	// again.
	MarkChannelClosed func(*channeldb.ChannelCloseSummary) error

	// IsPendingClose is a boolean indicating whether the channel is marked
	// as pending close in the database.
	IsPendingClose bool

	// ClosingHeight is the height at which the channel was closed. Note
	// that this value is only valid if IsPendingClose is true.
	ClosingHeight uint32

	// CloseType is the type of the close event in case IsPendingClose is
	// true. Otherwise this value is unset.
	CloseType channeldb.ClosureType

	// MarkChannelResolved is a function closure that serves to mark a
	// channel as "fully resolved". A channel itself can be considered
	// fully resolved once all active contracts have individually been
	// fully resolved.
	//
	// TODO(roasbeef): need RPC's to combine for pendingchannels RPC
	MarkChannelResolved func() error

	ChainArbitratorConfig
}

ChannelArbitratorConfig contains all the functionality that the ChannelArbitrator needs in order to properly arbitrate any contract dispute on chain.

type ContractResolutions

type ContractResolutions struct {
	// CommitHash is the txid of the commitment transaction.
	CommitHash chainhash.Hash

	// CommitResolution contains all data required to fully resolve a
	// commitment output.
	CommitResolution *lnwallet.CommitOutputResolution

	// HtlcResolutions contains all data required to fully resolve any
	// incoming+outgoing HTLC's present within the commitment transaction.
	HtlcResolutions lnwallet.HtlcResolutions
}

ContractResolutions is a wrapper struct around the two forms of resolutions we may need to carry out once a contract is closing: resolving the commitment output, and resolving any incoming+outgoing HTLC's still present in the commitment.

func (*ContractResolutions) IsEmpty

func (c *ContractResolutions) IsEmpty() bool

IsEmpty returns true if the set of resolutions is "empty". A resolution is empty if: our commitment output has been trimmed, and we don't have any incoming or outgoing HTLC's active.

type ContractResolver

type ContractResolver interface {
	// ResolverKey returns an identifier which should be globally unique
	// for this particular resolver within the chain the original contract
	// resides within.
	ResolverKey() []byte

	// Resolve instructs the contract resolver to resolve the output
	// on-chain. Once the output has been *fully* resolved, the function
	// should return immediately with a nil ContractResolver value for the
	// first return value.  In the case that the contract requires further
	// resolution, then another resolve is returned.
	//
	// NOTE: This function MUST be run as a goroutine.
	Resolve() (ContractResolver, error)

	// IsResolved returns true if the stored state in the resolve is fully
	// resolved. In this case the target output can be forgotten.
	IsResolved() bool

	// Encode writes an encoded version of the ContractResolver into the
	// passed Writer.
	Encode(w io.Writer) error

	// Decode attempts to decode an encoded ContractResolver from the
	// passed Reader instance, returning an active ContractResolver
	// instance.
	Decode(r io.Reader) error

	// AttachResolverKit should be called once a resolved is successfully
	// decoded from its stored format. This struct delivers a generic tool
	// kit that resolvers need to complete their duty.
	AttachResolverKit(ResolverKit)

	// Stop signals the resolver to cancel any current resolution
	// processes, and suspend.
	Stop()
}

ContractResolver is an interface which packages a state machine which is able to carry out the necessary steps required to fully resolve a Picfightcoin contract on-chain. Resolvers are fully encodable to ensure callers are able to persist them properly. A resolver may produce another resolver in the case that claiming an HTLC is a multi-stage process. In this case, we may partially resolve the contract, then persist, and set up for an additional resolution.

type ContractSignals

type ContractSignals struct {
	// HtlcUpdates is a channel that once we new commitment updates takes
	// place, the later set of HTLC's on the commitment transaction should
	// be sent over.
	HtlcUpdates chan []channeldb.HTLC

	// ShortChanID is the up to date short channel ID for a contract. This
	// can change either if when the contract was added it didn't yet have
	// a stable identifier, or in the case of a reorg.
	ShortChanID lnwire.ShortChannelID
}

ContractSignals wraps the two signals that affect the state of a channel being watched by an arbitrator. The two signals we care about are: the channel has a new set of HTLC's, and the remote party has just broadcast their version of the commitment transaction.

type CooperativeCloseInfo

type CooperativeCloseInfo struct {
	*channeldb.ChannelCloseSummary
}

CooperativeCloseInfo encapsulates all the informnation we need to act on a cooperative close that gets confirmed.

type LocalUnilateralCloseInfo

LocalUnilateralCloseInfo encapsulates all the informnation we need to act on a local force close that gets confirmed.

type ResolutionMsg

type ResolutionMsg struct {
	// SourceChan identifies the channel that this message is being sent
	// from. This is the channel's short channel ID.
	SourceChan lnwire.ShortChannelID

	// HtlcIndex is the index of the contract within the original
	// commitment trace.
	HtlcIndex uint64

	// Failure will be non-nil if the incoming contract should be cancelled
	// all together. This can happen if the outgoing contract was dust, if
	// if the outgoing HTLC timed out.
	Failure lnwire.FailureMessage

	// PreImage will be non-nil if the incoming contract can successfully
	// be redeemed. This can happen if we learn of the preimage from the
	// outgoing HTLC on-chain.
	PreImage *[32]byte
}

ResolutionMsg is a message sent by resolvers to outside sub-systems once an outgoing contract has been fully resolved. For multi-hop contracts, if we resolve the outgoing contract, we'll also need to ensure that the incoming contract is resolved as well. We package the items required to resolve the incoming contracts within this message.

type ResolverKit

type ResolverKit struct {
	// ChannelArbitratorConfig contains all the interfaces and closures
	// required for the resolver to interact with outside sub-systems.
	ChannelArbitratorConfig

	// Checkpoint allows a resolver to check point its state. This function
	// should write the state of the resolver to persistent storage, and
	// return a non-nil error upon success.
	Checkpoint func(ContractResolver) error

	Quit chan struct{}
}

ResolverKit is meant to be used as a mix-in struct to be embedded within a given ContractResolver implementation. It contains all the items that a resolver requires to carry out its duties.

type WitnessBeacon

type WitnessBeacon interface {
	// SubscribeUpdates returns a channel that will be sent upon *each* time
	// a new preimage is discovered.
	SubscribeUpdates() *WitnessSubscription

	// LookupPreImage attempts to lookup a preimage in the global cache.
	// True is returned for the second argument if the preimage is found.
	LookupPreimage(payhash []byte) ([]byte, bool)

	// AddPreImage adds a newly discovered preimage to the global cache.
	AddPreimage(pre []byte) error
}

WitnessBeacon is a global beacon of witnesses. Contract resolvers will use this interface to lookup witnesses (preimages typically) of contracts they're trying to resolve, add new preimages they resolve, and finally receive new updates each new time a preimage is discovered.

TODO(roasbeef): need to delete the pre-images once we've used them and have been sufficiently confirmed?

type WitnessSubscription

type WitnessSubscription struct {
	// WitnessUpdates is a channel that newly discovered witnesses will be
	// sent over.
	//
	// TODO(roasbeef): couple with WitnessType?
	WitnessUpdates <-chan []byte

	// CancelSubscription is a function closure that should be used by a
	// client to cancel the subscription once they are no longer interested
	// in receiving new updates.
	CancelSubscription func()
}

WitnessSubscription represents an intent to be notified once new witnesses are discovered by various active contract resolvers. A contract resolver may use this to be notified of when it can satisfy an incoming contract after we discover the witness for an outgoing contract.

Jump to

Keyboard shortcuts

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