cnct: create channel interface for arbitrator
Allows unit testing of the channel arbitrator with fewer dependencies. This is a preparation for the addition of anchor sweeping.
This commit is contained in:
parent
c0b1b3be14
commit
7f3d4e7d49
@ -220,6 +220,61 @@ func NewChainArbitrator(cfg ChainArbitratorConfig,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// arbChannel is a wrapper around an open channel that channel arbitrators
|
||||||
|
// interact with.
|
||||||
|
type arbChannel struct {
|
||||||
|
// channel is the in-memory channel state.
|
||||||
|
channel *channeldb.OpenChannel
|
||||||
|
|
||||||
|
// c references the chain arbitrator and is used by arbChannel
|
||||||
|
// internally.
|
||||||
|
c *ChainArbitrator
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// NOTE: Part of the ArbChannel interface.
|
||||||
|
func (a *arbChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error) {
|
||||||
|
// First, we mark the channel as borked, this ensure
|
||||||
|
// that no new state transitions can happen, and also
|
||||||
|
// that the link won't be loaded into the switch.
|
||||||
|
if err := a.channel.MarkBorked(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// With the channel marked as borked, we'll now remove
|
||||||
|
// the link from the switch if its there. If the link
|
||||||
|
// is active, then this method will block until it
|
||||||
|
// exits.
|
||||||
|
chanPoint := a.channel.FundingOutpoint
|
||||||
|
|
||||||
|
if err := a.c.cfg.MarkLinkInactive(chanPoint); err != nil {
|
||||||
|
log.Errorf("unable to mark link inactive: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we know the link can't mutate the channel
|
||||||
|
// state, we'll read the channel from disk the target
|
||||||
|
// channel according to its channel point.
|
||||||
|
channel, err := a.c.chanSource.FetchChannel(chanPoint)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we'll force close the channel completing
|
||||||
|
// the force close workflow.
|
||||||
|
chanMachine, err := lnwallet.NewLightningChannel(
|
||||||
|
a.c.cfg.Signer, channel, nil,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return chanMachine.ForceClose()
|
||||||
|
}
|
||||||
|
|
||||||
// newActiveChannelArbitrator creates a new instance of an active channel
|
// newActiveChannelArbitrator creates a new instance of an active channel
|
||||||
// arbitrator given the state of the target channel.
|
// arbitrator given the state of the target channel.
|
||||||
func newActiveChannelArbitrator(channel *channeldb.OpenChannel,
|
func newActiveChannelArbitrator(channel *channeldb.OpenChannel,
|
||||||
@ -247,42 +302,10 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel,
|
|||||||
// all interfaces and methods the arbitrator needs to do its job.
|
// all interfaces and methods the arbitrator needs to do its job.
|
||||||
arbCfg := ChannelArbitratorConfig{
|
arbCfg := ChannelArbitratorConfig{
|
||||||
ChanPoint: chanPoint,
|
ChanPoint: chanPoint,
|
||||||
|
Channel: c.getArbChannel(channel),
|
||||||
ShortChanID: channel.ShortChanID(),
|
ShortChanID: channel.ShortChanID(),
|
||||||
BlockEpochs: blockEpoch,
|
BlockEpochs: blockEpoch,
|
||||||
ForceCloseChan: func() (*lnwallet.LocalForceCloseSummary, error) {
|
|
||||||
// First, we mark the channel as borked, this ensure
|
|
||||||
// that no new state transitions can happen, and also
|
|
||||||
// that the link won't be loaded into the switch.
|
|
||||||
if err := channel.MarkBorked(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the channel marked as borked, we'll now remove
|
|
||||||
// the link from the switch if its there. If the link
|
|
||||||
// is active, then this method will block until it
|
|
||||||
// exits.
|
|
||||||
if err := c.cfg.MarkLinkInactive(chanPoint); err != nil {
|
|
||||||
log.Errorf("unable to mark link inactive: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now that we know the link can't mutate the channel
|
|
||||||
// state, we'll read the channel from disk the target
|
|
||||||
// channel according to its channel point.
|
|
||||||
channel, err := c.chanSource.FetchChannel(chanPoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we'll force close the channel completing
|
|
||||||
// the force close workflow.
|
|
||||||
chanMachine, err := lnwallet.NewLightningChannel(
|
|
||||||
c.cfg.Signer, channel, nil,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return chanMachine.ForceClose()
|
|
||||||
},
|
|
||||||
MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted,
|
MarkCommitmentBroadcasted: channel.MarkCommitmentBroadcasted,
|
||||||
MarkChannelClosed: func(summary *channeldb.ChannelCloseSummary,
|
MarkChannelClosed: func(summary *channeldb.ChannelCloseSummary,
|
||||||
statuses ...channeldb.ChannelStatus) error {
|
statuses ...channeldb.ChannelStatus) error {
|
||||||
@ -339,6 +362,16 @@ func newActiveChannelArbitrator(channel *channeldb.OpenChannel,
|
|||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getArbChannel returns an open channel wrapper for use by channel arbitrators.
|
||||||
|
func (c *ChainArbitrator) getArbChannel(
|
||||||
|
channel *channeldb.OpenChannel) *arbChannel {
|
||||||
|
|
||||||
|
return &arbChannel{
|
||||||
|
channel: channel,
|
||||||
|
c: c,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ResolveContract marks a contract as fully resolved within the database.
|
// ResolveContract marks a contract as fully resolved within the database.
|
||||||
// This is only to be done once all contracts which were live on the channel
|
// This is only to be done once all contracts which were live on the channel
|
||||||
// before hitting the chain have been resolved.
|
// before hitting the chain have been resolved.
|
||||||
|
@ -64,6 +64,18 @@ type WitnessBeacon interface {
|
|||||||
AddPreimages(preimages ...lntypes.Preimage) error
|
AddPreimages(preimages ...lntypes.Preimage) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArbChannel is an abstraction that allows the channel arbitrator to interact
|
||||||
|
// with an open channel.
|
||||||
|
type ArbChannel interface {
|
||||||
|
// 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() (*lnwallet.LocalForceCloseSummary, error)
|
||||||
|
}
|
||||||
|
|
||||||
// ChannelArbitratorConfig contains all the functionality that the
|
// ChannelArbitratorConfig contains all the functionality that the
|
||||||
// ChannelArbitrator needs in order to properly arbitrate any contract dispute
|
// ChannelArbitrator needs in order to properly arbitrate any contract dispute
|
||||||
// on chain.
|
// on chain.
|
||||||
@ -72,6 +84,10 @@ type ChannelArbitratorConfig struct {
|
|||||||
// channel.
|
// channel.
|
||||||
ChanPoint wire.OutPoint
|
ChanPoint wire.OutPoint
|
||||||
|
|
||||||
|
// Channel is the full channel data structure. For legacy channels, this
|
||||||
|
// field may not always be set after a restart.
|
||||||
|
Channel ArbChannel
|
||||||
|
|
||||||
// ShortChanID describes the exact location of the channel within the
|
// ShortChanID describes the exact location of the channel within the
|
||||||
// chain. We'll use this to address any messages that we need to send
|
// chain. We'll use this to address any messages that we need to send
|
||||||
// to the switch during contract resolution.
|
// to the switch during contract resolution.
|
||||||
@ -88,14 +104,6 @@ type ChannelArbitratorConfig struct {
|
|||||||
// channel.
|
// channel.
|
||||||
ChainEvents *ChainEventSubscription
|
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
|
// MarkCommitmentBroadcasted should mark the channel as the commitment
|
||||||
// being broadcast, and we are waiting for the commitment to confirm.
|
// being broadcast, and we are waiting for the commitment to confirm.
|
||||||
MarkCommitmentBroadcasted func(*wire.MsgTx, bool) error
|
MarkCommitmentBroadcasted func(*wire.MsgTx, bool) error
|
||||||
@ -791,7 +799,7 @@ func (c *ChannelArbitrator) stateStep(
|
|||||||
// We'll tell the switch that it should remove the link for
|
// We'll tell the switch that it should remove the link for
|
||||||
// this channel, in addition to fetching the force close
|
// this channel, in addition to fetching the force close
|
||||||
// summary needed to close this channel on chain.
|
// summary needed to close this channel on chain.
|
||||||
closeSummary, err := c.cfg.ForceCloseChan()
|
closeSummary, err := c.cfg.Channel.ForceCloseChan()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("ChannelArbitrator(%v): unable to "+
|
log.Errorf("ChannelArbitrator(%v): unable to "+
|
||||||
"force close: %v", c.cfg.ChanPoint, err)
|
"force close: %v", c.cfg.ChanPoint, err)
|
||||||
|
@ -360,13 +360,7 @@ func createTestChannelArbitrator(t *testing.T, log ArbitratorLog,
|
|||||||
resolvedChan <- struct{}{}
|
resolvedChan <- struct{}{}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
ForceCloseChan: func() (*lnwallet.LocalForceCloseSummary, error) {
|
Channel: &mockChannel{},
|
||||||
summary := &lnwallet.LocalForceCloseSummary{
|
|
||||||
CloseTx: &wire.MsgTx{},
|
|
||||||
HtlcResolutions: &lnwallet.HtlcResolutions{},
|
|
||||||
}
|
|
||||||
return summary, nil
|
|
||||||
},
|
|
||||||
MarkCommitmentBroadcasted: func(_ *wire.MsgTx, _ bool) error {
|
MarkCommitmentBroadcasted: func(_ *wire.MsgTx, _ bool) error {
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
@ -2088,3 +2082,13 @@ func TestRemoteCloseInitiator(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mockChannel struct{}
|
||||||
|
|
||||||
|
func (m *mockChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error) {
|
||||||
|
summary := &lnwallet.LocalForceCloseSummary{
|
||||||
|
CloseTx: &wire.MsgTx{},
|
||||||
|
HtlcResolutions: &lnwallet.HtlcResolutions{},
|
||||||
|
}
|
||||||
|
return summary, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user