From 5461c0f52d895d18865a0c1fe9110969bd089e74 Mon Sep 17 00:00:00 2001 From: calmbeing Date: Tue, 20 Jun 2023 00:55:37 +0800 Subject: [PATCH] solve the mismatch validator bug with final solution --- .gitignore | 3 ++- consensus/parlia/parlia.go | 7 +++++-- core/state/intra_block_state.go | 10 +++++----- core/state/state_object.go | 4 ++-- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index e246a0d1eea..2c0cbfc7393 100644 --- a/.gitignore +++ b/.gitignore @@ -81,4 +81,5 @@ docker-compose.*.yml coverage.out dist -__debug_bin \ No newline at end of file +__debug_bin +cmd/erigon/Users/ diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 74147fb7bc5..eb8d8cffef6 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -23,6 +23,7 @@ import ( "github.com/willf/bitset" "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/crypto/cryptopool" @@ -38,7 +39,6 @@ import ( "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/forkid" - "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/vm" "github.com/ledgerwatch/erigon/crypto" @@ -876,6 +876,7 @@ func (p *Parlia) verifyValidators(header, parentHeader *types.Header, state *sta } } else { if uint8(validatorsNumber) != header.Extra[extraVanity] { + log.Error("verifyValidators failed", "len(validatorsNumber)", validatorsNumber, "header.Extra[extraVanity]", header.Extra[extraVanity]) return errMismatchingEpochValidators } validatorsBytes = make([]byte, validatorsNumber*validatorBytesLength) @@ -949,6 +950,7 @@ func (p *Parlia) finalize(header *types.Header, state *state.IntraBlockState, tx // If the block is an epoch end block, verify the validator list // The verification can only be done when the state is ready, it can't be done in VerifyHeader. parentHeader := chain.GetHeader(header.ParentHash, number-1) + if err := p.verifyValidators(header, parentHeader, state); err != nil { return nil, nil, err } @@ -1339,7 +1341,8 @@ func (p *Parlia) getCurrentValidators(header *types.Header, ibs *state.IntraBloc } msgData := hexutility.Bytes(data) - _, returnData, err := p.systemCall(header.Coinbase, systemcontracts.ValidatorContract, msgData[:], ibs, header, u256.Num0) + ibsWithoutCache := state.New(ibs.StateReader) + _, returnData, err := p.systemCall(header.Coinbase, systemcontracts.ValidatorContract, msgData[:], ibsWithoutCache, header, u256.Num0) if err != nil { return nil, nil, err } diff --git a/core/state/intra_block_state.go b/core/state/intra_block_state.go index e916c4f1791..06433071573 100644 --- a/core/state/intra_block_state.go +++ b/core/state/intra_block_state.go @@ -52,7 +52,7 @@ type BalanceIncrease struct { // that occur during block's execution. // NOT THREAD SAFE! type IntraBlockState struct { - stateReader StateReader + StateReader StateReader // This map holds 'live' objects, which will get modified while processing a state transition. stateObjects map[libcommon.Address]*stateObject @@ -88,7 +88,7 @@ type IntraBlockState struct { // Create a new state from a given trie func New(stateReader StateReader) *IntraBlockState { return &IntraBlockState{ - stateReader: stateReader, + StateReader: stateReader, stateObjects: map[libcommon.Address]*stateObject{}, stateObjectsDirty: map[libcommon.Address]struct{}{}, nilAccounts: map[libcommon.Address]struct{}{}, @@ -235,7 +235,7 @@ func (sdb *IntraBlockState) GetCodeSize(addr libcommon.Address) int { if stateObject.code != nil { return len(stateObject.code) } - l, err := sdb.stateReader.ReadAccountCodeSize(addr, stateObject.data.Incarnation, stateObject.data.CodeHash) + l, err := sdb.StateReader.ReadAccountCodeSize(addr, stateObject.data.Incarnation, stateObject.data.CodeHash) if err != nil { sdb.setErrorUnsafe(err) } @@ -427,7 +427,7 @@ func (sdb *IntraBlockState) getStateObject(addr libcommon.Address) (stateObject } return nil } - account, err := sdb.stateReader.ReadAccountData(addr) + account, err := sdb.StateReader.ReadAccountData(addr) if err != nil { sdb.setErrorUnsafe(err) return nil @@ -503,7 +503,7 @@ func (sdb *IntraBlockState) CreateAccount(addr libcommon.Address, contractCreati if previous != nil && previous.selfdestructed { prevInc = previous.data.Incarnation } else { - if inc, err := sdb.stateReader.ReadAccountIncarnation(addr); err == nil { + if inc, err := sdb.StateReader.ReadAccountIncarnation(addr); err == nil { prevInc = inc } else { sdb.savedErr = err diff --git a/core/state/state_object.go b/core/state/state_object.go index e4302856ff1..64816720512 100644 --- a/core/state/state_object.go +++ b/core/state/state_object.go @@ -184,7 +184,7 @@ func (so *stateObject) GetCommittedState(key *libcommon.Hash, out *uint256.Int) return } // Load from DB in case it is missing. - enc, err := so.db.stateReader.ReadAccountStorage(so.address, so.data.GetIncarnation(), key) + enc, err := so.db.StateReader.ReadAccountStorage(so.address, so.data.GetIncarnation(), key) if err != nil { so.setError(err) out.Clear() @@ -328,7 +328,7 @@ func (so *stateObject) Code() []byte { if bytes.Equal(so.CodeHash(), emptyCodeHash) { return nil } - code, err := so.db.stateReader.ReadAccountCode(so.Address(), so.data.Incarnation, libcommon.BytesToHash(so.CodeHash())) + code, err := so.db.StateReader.ReadAccountCode(so.Address(), so.data.Incarnation, libcommon.BytesToHash(so.CodeHash())) if err != nil { so.setError(fmt.Errorf("can't load code hash %x: %w", so.CodeHash(), err)) }