chainwatcher: only continue breach handling after successfully marked
closed This commit makes the handoff procedure between the breachabiter and chainwatcher use a function closure to mark the channel pending closed in the DB. Doing it this way we know that the channel has been markd pending closed in the DB when ProcessACK returns. The reason we do this is that we really need a "two-way ACK" to have the breacharbiter know it can go on with the breach handling. Earlier it would just send the ACK on the channel and continue. This lead to a race where breach handling could finish before the chain watcher had marked the channel pending closed in the database, which again lead to the breacharbiter failing to mark the channel fully closed. We saw this causing flakes during itests.
This commit is contained in:
3 files changed
+58
-35
No files matched your search
@@ -100,11 +100,14 @@ type ChainArbitratorConfig struct {
|
||||
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
|
||||
// use to notify the breachArbiter about a contract breach. A callback
|
||||
// should be passed that when called will mark the channel pending
|
||||
// close in the databae. It should only return a non-nil error when the
|
||||
// breachArbiter has preserved the necessary breach info for this
|
||||
// channel point, and the callback has succeeded, meaning it is safe to
|
||||
// stop watching the channel.
|
||||
ContractBreach func(wire.OutPoint, *lnwallet.BreachRetribution,
|
||||
func() error) error
|
||||
|
||||
// IsOurAddress is a function that returns true if the passed address
|
||||
// is known to the underlying wallet. Otherwise, false should be
|
||||
@@ -488,8 +491,12 @@ func (c *ChainArbitrator) Start() error {
|
||||
notifier: c.cfg.Notifier,
|
||||
signer: c.cfg.Signer,
|
||||
isOurAddr: c.cfg.IsOurAddress,
|
||||
contractBreach: func(retInfo *lnwallet.BreachRetribution) error {
|
||||
return c.cfg.ContractBreach(chanPoint, retInfo)
|
||||
contractBreach: func(retInfo *lnwallet.BreachRetribution,
|
||||
markClosed func() error) error {
|
||||
|
||||
return c.cfg.ContractBreach(
|
||||
chanPoint, retInfo, markClosed,
|
||||
)
|
||||
},
|
||||
extractStateNumHint: lnwallet.GetStateNumHint,
|
||||
},
|
||||
@@ -1078,8 +1085,12 @@ func (c *ChainArbitrator) WatchNewChannel(newChan *channeldb.OpenChannel) error
|
||||
notifier: c.cfg.Notifier,
|
||||
signer: c.cfg.Signer,
|
||||
isOurAddr: c.cfg.IsOurAddress,
|
||||
contractBreach: func(retInfo *lnwallet.BreachRetribution) error {
|
||||
return c.cfg.ContractBreach(chanPoint, retInfo)
|
||||
contractBreach: func(retInfo *lnwallet.BreachRetribution,
|
||||
markClosed func() error) error {
|
||||
|
||||
return c.cfg.ContractBreach(
|
||||
chanPoint, retInfo, markClosed,
|
||||
)
|
||||
},
|
||||
extractStateNumHint: lnwallet.GetStateNumHint,
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user