mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-22 15:57:49 +02:00
contractcourt: supplement resolvers with confirmed commit set HTLCs
In this commit, we fix an existing bug in the package, causing resolutions to be restarted without their required supplementary information. This can happen if a distinct HTLC set gets confirmed compared to the HTLCs that we may have had our commitment at time of close. Due to this bug, on restart certain HTLCS would be rejected as they would present their state to the invoice registry, but be rejected due to checks such as amount value. To fix this, we'll now pass in the set of confirmed HTLCs into the resolvers when we re-launch them, giving us access to all the information we need to supplement the HTLCS. We also add a new test that ensures that the proper fields of a resolver are set after a restart.
This commit is contained in:
@@ -415,7 +415,19 @@ func (c *ChannelArbitrator) Start() error {
|
||||
if startingState == StateWaitingFullResolution &&
|
||||
nextState == StateWaitingFullResolution {
|
||||
|
||||
if err := c.relaunchResolvers(); err != nil {
|
||||
// In order to relaunch the resolvers, we'll need to fetch the
|
||||
// set of HTLCs that were present in the commitment transaction
|
||||
// at the time it was confirmed. commitSet.ConfCommitKey can't
|
||||
// be nil at this point since we're in
|
||||
// StateWaitingFullResolution. We can only be in
|
||||
// StateWaitingFullResolution after we've transitioned from
|
||||
// StateContractClosed which can only be triggered by the local
|
||||
// or remote close trigger. This trigger is only fired when we
|
||||
// receive a chain event from the chain watcher than the
|
||||
// commitment has been confirmed on chain, and before we
|
||||
// advance our state step, we call InsertConfirmedCommitSet.
|
||||
confCommitSet := commitSet.HtlcSets[*commitSet.ConfCommitKey]
|
||||
if err := c.relaunchResolvers(confCommitSet); err != nil {
|
||||
c.cfg.BlockEpochs.Cancel()
|
||||
return err
|
||||
}
|
||||
@@ -431,7 +443,7 @@ func (c *ChannelArbitrator) Start() error {
|
||||
// starting the ChannelArbitrator. This information should ideally be stored in
|
||||
// the database, so this only serves as a intermediate work-around to prevent a
|
||||
// migration.
|
||||
func (c *ChannelArbitrator) relaunchResolvers() error {
|
||||
func (c *ChannelArbitrator) relaunchResolvers(confirmedHTLCs []channeldb.HTLC) error {
|
||||
// We'll now query our log to see if there are any active
|
||||
// unresolved contracts. If this is the case, then we'll
|
||||
// relaunch all contract resolvers.
|
||||
@@ -456,31 +468,22 @@ func (c *ChannelArbitrator) relaunchResolvers() error {
|
||||
// to prevent a db migration. We use all available htlc sets here in
|
||||
// order to ensure we have complete coverage.
|
||||
htlcMap := make(map[wire.OutPoint]*channeldb.HTLC)
|
||||
for _, htlcs := range c.activeHTLCs {
|
||||
for _, htlc := range htlcs.incomingHTLCs {
|
||||
htlc := htlc
|
||||
outpoint := wire.OutPoint{
|
||||
Hash: commitHash,
|
||||
Index: uint32(htlc.OutputIndex),
|
||||
}
|
||||
htlcMap[outpoint] = &htlc
|
||||
}
|
||||
|
||||
for _, htlc := range htlcs.outgoingHTLCs {
|
||||
htlc := htlc
|
||||
outpoint := wire.OutPoint{
|
||||
Hash: commitHash,
|
||||
Index: uint32(htlc.OutputIndex),
|
||||
}
|
||||
htlcMap[outpoint] = &htlc
|
||||
for _, htlc := range confirmedHTLCs {
|
||||
htlc := htlc
|
||||
outpoint := wire.OutPoint{
|
||||
Hash: commitHash,
|
||||
Index: uint32(htlc.OutputIndex),
|
||||
}
|
||||
htlcMap[outpoint] = &htlc
|
||||
}
|
||||
|
||||
log.Infof("ChannelArbitrator(%v): relaunching %v contract "+
|
||||
"resolvers", c.cfg.ChanPoint, len(unresolvedContracts))
|
||||
|
||||
for _, resolver := range unresolvedContracts {
|
||||
c.supplementResolver(resolver, htlcMap)
|
||||
if err := c.supplementResolver(resolver, htlcMap); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
c.launchResolvers(unresolvedContracts)
|
||||
|
Reference in New Issue
Block a user