Fixed a bug in the reported virtual changeset, and modified the test to verify it

This commit is contained in:
msutton 2022-07-14 18:30:30 +03:00
parent 9971f532a9
commit 9f9610df49
5 changed files with 45 additions and 22 deletions

View File

@ -916,7 +916,7 @@ func (s *consensus) ResolveVirtual(progressReportCallback func(uint64, uint64))
// release the lock each time we resolve 100 blocks. // release the lock each time we resolve 100 blocks.
// Note: maxBlocksToResolve should be smaller than `params.FinalityDuration` in order to avoid a situation // Note: maxBlocksToResolve should be smaller than `params.FinalityDuration` in order to avoid a situation
// where UpdatePruningPointByVirtual skips a pruning point. // where UpdatePruningPointByVirtual skips a pruning point.
isCompletelyResolved, err := s.resolveVirtualChunkWithLock(100) _, isCompletelyResolved, err := s.resolveVirtualChunkWithLock(100)
if err != nil { if err != nil {
return err return err
} }
@ -928,37 +928,37 @@ func (s *consensus) ResolveVirtual(progressReportCallback func(uint64, uint64))
return nil return nil
} }
func (s *consensus) resolveVirtualChunkWithLock(maxBlocksToResolve uint64) (bool, error) { func (s *consensus) resolveVirtualChunkWithLock(maxBlocksToResolve uint64) (*externalapi.VirtualChangeSet, bool, error) {
s.lock.Lock() s.lock.Lock()
defer s.lock.Unlock() defer s.lock.Unlock()
return s.resolveVirtualNoLock(maxBlocksToResolve) return s.resolveVirtualNoLock(maxBlocksToResolve)
} }
func (s *consensus) resolveVirtualNoLock(maxBlocksToResolve uint64) (bool, error) { func (s *consensus) resolveVirtualNoLock(maxBlocksToResolve uint64) (*externalapi.VirtualChangeSet, bool, error) {
virtualChangeSet, isCompletelyResolved, err := s.consensusStateManager.ResolveVirtual(maxBlocksToResolve) virtualChangeSet, isCompletelyResolved, err := s.consensusStateManager.ResolveVirtual(maxBlocksToResolve)
if err != nil { if err != nil {
return false, err return nil, false, err
} }
s.virtualNotUpdated = !isCompletelyResolved s.virtualNotUpdated = !isCompletelyResolved
stagingArea := model.NewStagingArea() stagingArea := model.NewStagingArea()
err = s.pruningManager.UpdatePruningPointByVirtual(stagingArea) err = s.pruningManager.UpdatePruningPointByVirtual(stagingArea)
if err != nil { if err != nil {
return false, err return nil, false, err
} }
err = staging.CommitAllChanges(s.databaseContext, stagingArea) err = staging.CommitAllChanges(s.databaseContext, stagingArea)
if err != nil { if err != nil {
return false, err return nil, false, err
} }
err = s.sendVirtualChangedEvent(virtualChangeSet, true) err = s.sendVirtualChangedEvent(virtualChangeSet, true)
if err != nil { if err != nil {
return false, err return nil, false, err
} }
return isCompletelyResolved, nil return virtualChangeSet, isCompletelyResolved, nil
} }
func (s *consensus) BuildPruningPointProof() (*externalapi.PruningPointProof, error) { func (s *consensus) BuildPruningPointProof() (*externalapi.PruningPointProof, error) {

View File

@ -49,7 +49,7 @@ type TestConsensus interface {
*externalapi.VirtualChangeSet, error) *externalapi.VirtualChangeSet, error)
UpdatePruningPointByVirtual() error UpdatePruningPointByVirtual() error
ResolveVirtualWithMaxParam(maxBlocksToResolve uint64) (bool, error) ResolveVirtualWithMaxParam(maxBlocksToResolve uint64) (*externalapi.VirtualChangeSet, bool, error)
MineJSON(r io.Reader, blockType MineJSONBlockType) (tips []*externalapi.DomainHash, err error) MineJSON(r io.Reader, blockType MineJSONBlockType) (tips []*externalapi.DomainHash, err error)
ToJSON(w io.Writer) error ToJSON(w io.Writer) error

View File

@ -203,7 +203,7 @@ func (csm *consensusStateManager) ResolveVirtual(maxBlocksToResolve uint64) (*ex
} }
selectedParentChainChanges, err := csm.dagTraversalManager. selectedParentChainChanges, err := csm.dagTraversalManager.
CalculateChainPath(updateVirtualStagingArea, previousVirtualSelectedParent, pendingTip) CalculateChainPath(updateVirtualStagingArea, previousVirtualSelectedParent, processingPoint)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }

View File

@ -56,7 +56,7 @@ func TestAddBlockBetweenResolveVirtualCalls(t *testing.T) {
} }
// Resolve one step // Resolve one step
_, err = tc.ResolveVirtualWithMaxParam(2) _, _, err = tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
@ -75,7 +75,7 @@ func TestAddBlockBetweenResolveVirtualCalls(t *testing.T) {
} }
// Resolve one more step // Resolve one more step
isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2) _, isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
@ -89,7 +89,7 @@ func TestAddBlockBetweenResolveVirtualCalls(t *testing.T) {
// Complete resolving virtual // Complete resolving virtual
for !isCompletelyResolved { for !isCompletelyResolved {
isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2) _, isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
@ -142,7 +142,7 @@ func TestAddGenesisChildAfterOneResolveVirtualCall(t *testing.T) {
} }
// Resolve one step // Resolve one step
isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2) _, isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
@ -154,7 +154,7 @@ func TestAddGenesisChildAfterOneResolveVirtualCall(t *testing.T) {
// Complete resolving virtual // Complete resolving virtual
for !isCompletelyResolved { for !isCompletelyResolved {
isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2) _, isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
@ -207,13 +207,13 @@ func TestAddGenesisChildAfterTwoResolveVirtualCalls(t *testing.T) {
} }
// Resolve one step // Resolve one step
_, err = tc.ResolveVirtualWithMaxParam(2) _, _, err = tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
// Resolve one more step // Resolve one more step
isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2) _, isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
@ -225,7 +225,7 @@ func TestAddGenesisChildAfterTwoResolveVirtualCalls(t *testing.T) {
// Complete resolving virtual // Complete resolving virtual
for !isCompletelyResolved { for !isCompletelyResolved {
isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2) _, isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(2)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
@ -296,22 +296,45 @@ func TestResolveVirtualBackAndForthReorgs(t *testing.T) {
printUtxoDiffChildren(t, tc, hashes, blocks) printUtxoDiffChildren(t, tc, hashes, blocks)
verifyUtxoDiffPaths(t, tc, hashes) verifyUtxoDiffPaths(t, tc, hashes)
previousVirtualSelectedParent, err := tc.GetVirtualSelectedParent()
if err != nil {
t.Fatal(err)
}
// Resolve one step // Resolve one step
_, err = tc.ResolveVirtualWithMaxParam(3) virtualChangeSet, _, err := tc.ResolveVirtualWithMaxParam(3)
if err != nil { if err != nil {
printUtxoDiffChildren(t, tc, hashes, blocks) printUtxoDiffChildren(t, tc, hashes, blocks)
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
newVirtualSelectedParent, err := tc.GetVirtualSelectedParent()
if err != nil {
t.Fatal(err)
}
// Make sure the reported change-set is compatible with actual changes.
// Checking this for one call should suffice to avoid possible bugs.
reportedPreviousVirtualSelectedParent := virtualChangeSet.VirtualSelectedParentChainChanges.Removed[0]
reportedNewVirtualSelectedParent := virtualChangeSet.VirtualSelectedParentChainChanges.
Added[len(virtualChangeSet.VirtualSelectedParentChainChanges.Added)-1]
if !previousVirtualSelectedParent.Equal(reportedPreviousVirtualSelectedParent) {
t.Fatalf("The reported changeset is incompatible with actual changes")
}
if !newVirtualSelectedParent.Equal(reportedNewVirtualSelectedParent) {
t.Fatalf("The reported changeset is incompatible with actual changes")
}
// Resolve one more step // Resolve one more step
isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(3) _, isCompletelyResolved, err := tc.ResolveVirtualWithMaxParam(3)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }
// Complete resolving virtual // Complete resolving virtual
for !isCompletelyResolved { for !isCompletelyResolved {
isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(3) _, isCompletelyResolved, err = tc.ResolveVirtualWithMaxParam(3)
if err != nil { if err != nil {
t.Fatalf("Error resolving virtual in re-org chain: %+v", err) t.Fatalf("Error resolving virtual in re-org chain: %+v", err)
} }

View File

@ -112,7 +112,7 @@ func (tc *testConsensus) AddUTXOInvalidBlock(parentHashes []*externalapi.DomainH
return consensushashing.BlockHash(block), virtualChangeSet, nil return consensushashing.BlockHash(block), virtualChangeSet, nil
} }
func (tc *testConsensus) ResolveVirtualWithMaxParam(maxBlocksToResolve uint64) (bool, error) { func (tc *testConsensus) ResolveVirtualWithMaxParam(maxBlocksToResolve uint64) (*externalapi.VirtualChangeSet, bool, error) {
tc.lock.Lock() tc.lock.Lock()
defer tc.lock.Unlock() defer tc.lock.Unlock()