From db58081b8d7f509c6cb9ed0761621d4be7ffcee9 Mon Sep 17 00:00:00 2001 From: Gerui Wang Date: Tue, 21 Dec 2021 10:19:17 +0800 Subject: [PATCH] refine race condition solution --- consensus/XDPoS/engines/engine_v1/engine.go | 14 +++++++------- tests/consensus/blockchain_race_condition_test.go | 13 ++++++++----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/consensus/XDPoS/engines/engine_v1/engine.go b/consensus/XDPoS/engines/engine_v1/engine.go index 9e2146b75b..d606c1aea3 100644 --- a/consensus/XDPoS/engines/engine_v1/engine.go +++ b/consensus/XDPoS/engines/engine_v1/engine.go @@ -249,7 +249,7 @@ func (x *XDPoS_v1) verifyCascadingFields(chain consensus.ChainReader, header *ty when it happens we get the signers list by requesting smart contract */ // Retrieve the snapshot needed to verify this header and cache it - snap, err := x.snapshot(chain, number-1, header.ParentHash, parents, header) + snap, err := x.snapshot(chain, number-1, header.ParentHash, parents, nil) if err != nil { return err } @@ -435,7 +435,7 @@ func (x *XDPoS_v1) YourTurn(chain consensus.ChainReader, parent *types.Header, s } // snapshot retrieves the authorization snapshot at a given point in time. -func (x *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header, currentHeader *types.Header) (*SnapshotV1, error) { +func (x *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header, selfHeader *types.Header) (*SnapshotV1, error) { // Search for a SnapshotV1 in memory or on disk for checkpoints var ( headers []*types.Header @@ -482,8 +482,8 @@ func (x *XDPoS_v1) snapshot(chain consensus.ChainReader, number uint64, hash com return nil, consensus.ErrUnknownAncestor } parents = parents[:len(parents)-1] - } else if currentHeader != nil && currentHeader.Hash() == hash { - header = currentHeader + } else if selfHeader != nil && selfHeader.Hash() == hash { + header = selfHeader } else { // No explicit parents (or no more left), reach out to the database header = chain.GetHeader(hash, number) @@ -542,7 +542,7 @@ func (x *XDPoS_v1) verifySeal(chain consensus.ChainReader, header *types.Header, return utils.ErrUnknownBlock } // Retrieve the snapshot needed to verify this header and cache it - snap, err := x.snapshot(chain, number-1, header.ParentHash, parents, header) + snap, err := x.snapshot(chain, number-1, header.ParentHash, parents, nil) if err != nil { return err } @@ -658,7 +658,7 @@ func (x *XDPoS_v1) Prepare(chain consensus.ChainReader, header *types.Header) er number := header.Number.Uint64() // Assemble the voting snapshot to check which votes make sense - snap, err := x.snapshot(chain, number-1, header.ParentHash, nil, header) + snap, err := x.snapshot(chain, number-1, header.ParentHash, nil, nil) if err != nil { return err } @@ -834,7 +834,7 @@ func (x *XDPoS_v1) Seal(chain consensus.ChainReader, block *types.Block, stop <- x.lock.RUnlock() // Bail out if we're unauthorized to sign a block - snap, err := x.snapshot(chain, number-1, header.ParentHash, nil, block.Header()) + snap, err := x.snapshot(chain, number-1, header.ParentHash, nil, nil) if err != nil { return nil, err } diff --git a/tests/consensus/blockchain_race_condition_test.go b/tests/consensus/blockchain_race_condition_test.go index ad0e88962f..d7c2b336d2 100644 --- a/tests/consensus/blockchain_race_condition_test.go +++ b/tests/consensus/blockchain_race_condition_test.go @@ -9,7 +9,7 @@ import ( ) // Snapshot try to read before blockchain is written -func TestRaceconditionOnBlockchainReadAndWrite(t *testing.T) { +func TestRaceConditionOnBlockchainReadAndWrite(t *testing.T) { blockchain, backend, parentBlock := PrepareXDCTestBlockChain(t, GAP-1, params.TestXDPoSMockChainConfig) @@ -78,22 +78,25 @@ func TestRaceconditionOnBlockchainReadAndWrite(t *testing.T) { if err != nil { t.Fatal(err) } + if blockchain.CurrentHeader().Hash() != block450B.Hash() { + t.Fatalf("the block with higher difficulty should be current header") + } state, err = blockchain.State() if err != nil { t.Fatalf("Failed while trying to get blockchain state") } if state.GetBalance(acc1Addr).Cmp(new(big.Int).SetUint64(10000000888)) != 0 { - t.Fatalf("account 1 should NOT have 10000000999 in balance as the block is forked, not on the main chain") + t.Fatalf("account 1 should have 10000000888 in balance as the block replace previous head block at number 450") } signers, err = GetSnapshotSigner(blockchain, block450B.Header()) if err != nil { t.Fatal(err) } - // Should run the `updateM1` for forked chain as it's now the mainchain, hence account3 NOT exit - if signers[acc3Addr.Hex()] == true { + // Should run the `updateM1` for forked chain as it's now the mainchain, hence account2 should exist + if signers[acc2Addr.Hex()] != true { debugMessage(backend, signers, t) - t.Fatalf("account 3 should NOT sit in the signer list as previos block result") + t.Fatalf("account 2 should sit in the signer list") } //Insert block 451 parent is 451 B