diff --git a/app/protocol/flows/v5/blockrelay/ibd.go b/app/protocol/flows/v5/blockrelay/ibd.go index e1e68e4d6..fd5fcdcca 100644 --- a/app/protocol/flows/v5/blockrelay/ibd.go +++ b/app/protocol/flows/v5/blockrelay/ibd.go @@ -686,37 +686,28 @@ func (flow *handleIBDFlow) banIfBlockIsHeaderOnly(block *externalapi.DomainBlock } func (flow *handleIBDFlow) resolveVirtual(estimatedVirtualDAAScoreTarget uint64) error { - virtualDAAScoreStart, err := flow.Domain().Consensus().GetVirtualDAAScore() + err := flow.Domain().Consensus().ResolveVirtual(func(virtualDAAScoreStart uint64, virtualDAAScore uint64) { + var percents int + if estimatedVirtualDAAScoreTarget-virtualDAAScoreStart <= 0 { + percents = 100 + } else { + percents = int(float64(virtualDAAScore-virtualDAAScoreStart) / float64(estimatedVirtualDAAScoreTarget-virtualDAAScoreStart) * 100) + } + if percents < 0 { + percents = 0 + } else if percents > 100 { + percents = 100 + } + log.Infof("Resolving virtual. Estimated progress: %d%%", percents) + }) if err != nil { return err } - for i := 0; ; i++ { - if i%10 == 0 { - virtualDAAScore, err := flow.Domain().Consensus().GetVirtualDAAScore() - if err != nil { - return err - } - var percents int - if estimatedVirtualDAAScoreTarget-virtualDAAScoreStart <= 0 { - percents = 100 - } else { - percents = int(float64(virtualDAAScore-virtualDAAScoreStart) / float64(estimatedVirtualDAAScoreTarget-virtualDAAScoreStart) * 100) - } - log.Infof("Resolving virtual. Estimated progress: %d%%", percents) - } - isCompletelyResolved, err := flow.Domain().Consensus().ResolveVirtual() - if err != nil { - return err - } - - if isCompletelyResolved { - log.Infof("Resolved virtual") - err = flow.OnNewBlockTemplate() - if err != nil { - return err - } - return nil - } + log.Infof("Resolved virtual") + err = flow.OnNewBlockTemplate() + if err != nil { + return err } + return nil } diff --git a/domain/consensus/consensus.go b/domain/consensus/consensus.go index aaddf88e5..85a638cc3 100644 --- a/domain/consensus/consensus.go +++ b/domain/consensus/consensus.go @@ -888,15 +888,42 @@ func (s *consensus) PopulateMass(transaction *externalapi.DomainTransaction) { s.transactionValidator.PopulateMass(transaction) } -func (s *consensus) ResolveVirtual() (bool, error) { +func (s *consensus) ResolveVirtual(progressReportCallback func(uint64, uint64)) error { + virtualDAAScoreStart, err := s.GetVirtualDAAScore() + if err != nil { + return err + } + + for i := 0; ; i++ { + if i%10 == 0 { + virtualDAAScore, err := s.GetVirtualDAAScore() + if err != nil { + return err + } + progressReportCallback(virtualDAAScoreStart, virtualDAAScore) + } + + // In order to prevent a situation that the consensus lock is held for too much time, we + // release the lock each time resolve 100 blocks. + // Note: maxBlocksToResolve should be smaller than finality interval in order to avoid a situation + // where UpdatePruningPointByVirtual skips a pruning point. + isCompletelyResolved, err := s.resolveVirtualChunkWithLock(100) + if err != nil { + return err + } + if isCompletelyResolved { + break + } + } + + return nil +} + +func (s *consensus) resolveVirtualChunkWithLock(maxBlocksToResolve uint64) (bool, error) { s.lock.Lock() defer s.lock.Unlock() - // In order to prevent a situation that the consensus lock is held for too much time, we - // release the lock each time resolve 100 blocks. - // Note: maxBlocksToResolve should be smaller than finality interval in order to avoid a situation - // where UpdatePruningPointByVirtual skips a pruning point. - return s.resolveVirtualNoLock(100) + return s.resolveVirtualNoLock(maxBlocksToResolve) } func (s *consensus) resolveVirtualNoLock(maxBlocksToResolve uint64) (bool, error) { diff --git a/domain/consensus/finality_test.go b/domain/consensus/finality_test.go index 5e4e9824b..d507a03a0 100644 --- a/domain/consensus/finality_test.go +++ b/domain/consensus/finality_test.go @@ -590,7 +590,7 @@ func TestFinalityResolveVirtual(t *testing.T) { } for i := 0; ; i++ { - isCompletelyResolved, err := tc.ResolveVirtual() + err := tc.ResolveVirtual(nil) if err != nil { panic(err) } diff --git a/domain/consensus/model/externalapi/consensus.go b/domain/consensus/model/externalapi/consensus.go index adaa81bc4..89f8056eb 100644 --- a/domain/consensus/model/externalapi/consensus.go +++ b/domain/consensus/model/externalapi/consensus.go @@ -48,7 +48,7 @@ type Consensus interface { Anticone(blockHash *DomainHash) ([]*DomainHash, error) EstimateNetworkHashesPerSecond(startHash *DomainHash, windowSize int) (uint64, error) PopulateMass(transaction *DomainTransaction) - ResolveVirtual() (bool, error) + ResolveVirtual(progressReportCallback func(uint64, uint64)) error BlockDAAWindowHashes(blockHash *DomainHash) ([]*DomainHash, error) TrustedDataDataDAAHeader(trustedBlockHash, daaBlockHash *DomainHash, daaBlockWindowIndex uint64) (*TrustedDataDataDAAHeader, error) TrustedBlockAssociatedGHOSTDAGDataBlockHashes(blockHash *DomainHash) ([]*DomainHash, error) diff --git a/domain/migrate.go b/domain/migrate.go index c1804862e..ef75a0458 100644 --- a/domain/migrate.go +++ b/domain/migrate.go @@ -214,34 +214,19 @@ func syncConsensuses(syncer, syncee externalapi.Consensus) error { return err } - virtualDAAScoreStart, err := syncee.GetVirtualDAAScore() + err = syncer.ResolveVirtual(func(virtualDAAScoreStart uint64, virtualDAAScore uint64) { + if estimatedVirtualDAAScoreTarget-virtualDAAScoreStart <= 0 { + percents = 100 + } else { + percents = int(float64(virtualDAAScore-virtualDAAScoreStart) / float64(estimatedVirtualDAAScoreTarget-virtualDAAScoreStart) * 100) + } + log.Infof("Resolving virtual. Estimated progress: %d%%", percents) + }) if err != nil { return err } - percents = 0 - for i := 0; ; i++ { - if i%10 == 0 { - virtualDAAScore, err := syncee.GetVirtualDAAScore() - if err != nil { - return err - } - newPercents := int(float64(virtualDAAScore-virtualDAAScoreStart) / float64(estimatedVirtualDAAScoreTarget-virtualDAAScoreStart) * 100) - if newPercents > percents { - percents = newPercents - log.Infof("Resolving virtual. Estimated progress: %d%%", percents) - } - } - isCompletelyResolved, err := syncee.ResolveVirtual() - if err != nil { - return err - } - - if isCompletelyResolved { - log.Infof("Resolved virtual") - break - } - } + log.Infof("Resolved virtual") return nil }