From 9d1ea5940c14d245386813b81e94244d2910c335 Mon Sep 17 00:00:00 2001 From: andyzhang2023 Date: Tue, 8 Oct 2024 23:19:52 +0800 Subject: [PATCH] debug 'nonce too high' --- core/pevm_processor.go | 32 +++++++++++++++++++++++++++++--- core/state/pevm_statedb.go | 26 ++++++++++++++++++++++++++ core/state/statedb.go | 7 +++++++ 3 files changed, 62 insertions(+), 3 deletions(-) diff --git a/core/pevm_processor.go b/core/pevm_processor.go index 0dfa15b121..90d0477521 100644 --- a/core/pevm_processor.go +++ b/core/pevm_processor.go @@ -7,6 +7,7 @@ import ( "sync/atomic" "time" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/consensus" @@ -256,16 +257,41 @@ func (p *PEVMProcessor) Process(block *types.Block, statedb *state.StateDB, cfg buildLevelsDuration := time.Since(start) var executeDurations, confirmDurations int64 = 0, 0 err, txIndex := txLevels.Run(func(pr *PEVMTxRequest) (res *PEVMTxResult) { + // first build the message, to get the From address + if err := buildMessage(pr, signer, header); err != nil { + return &PEVMTxResult{txReq: pr, err: err} + } + // prepare some debug info + debugTrieAccount, debugTrieError := statedb.GetAccountFromTrie(pr.msg.From) + ptr := pr + to := common.Address{} + if pr.msg.To != nil { + to = *pr.msg.To + } defer func(t0 time.Time) { atomic.AddInt64(&executeDurations, time.Since(t0).Nanoseconds()) if res.err != nil { atomic.AddUint64(&p.debugConflictRedoNum, 1) + log.Error("ProcessParallel execute tx failed", "block", header.Number, "txIndex", ptr.txIndex, "txHash", ptr.tx.Hash().String(), "isDeposit", ptr.msg.IsDepositTx, "err", res.err, "from", res.slotDB.Debug(ptr.msg.From), "to", res.slotDB.Debug(to)) + if debugTrieAccount == nil { + log.Error("ProcessParallel execute tx debugger", "block", header.Number, "txIndex", ptr.txIndex, "txHash", ptr.tx.Hash().String(), "isDeposit", ptr.msg.IsDepositTx, "err", res.err, "from", debugTrieAccount, "fromError", debugTrieError) + } else { + log.Error("ProcessParallel execute tx debugger", "block", header.Number, "txIndex", ptr.txIndex, "txHash", ptr.tx.Hash().String(), "isDeposit", ptr.msg.IsDepositTx, "err", res.err, "from.nonce", debugTrieAccount.Nonce, "fromError", debugTrieError) + } + } + // record the vmerr, because it is uncommon and should be recorded for further analysis + if res.result != nil && res.result.Err != nil { + log.Info("ProcessParallel evm execute tx failed", + "block", header.Number, "txIndex", ptr.txIndex, "txHash", ptr.tx.Hash().String(), + "isDeposit", ptr.msg.IsDepositTx, "vmerr", res.result.Err.Error(), "err", res.err, + "from", res.slotDB.Debug(ptr.msg.From), "to", res.slotDB.Debug(to), + "gasUsed", res.result.UsedGas, "gasLimit", ptr.tx.Gas(), "msgGasLimit", ptr.msg.GasLimit, + "gasRefunded", res.result.RefundedGas, + ) } }(time.Now()) - if err := buildMessage(pr, signer, header); err != nil { - return &PEVMTxResult{txReq: pr, err: err} - } + // now we execute the tx in evm return p.executeInSlot(statedb, pr) }, func(pr *PEVMTxResult) (err error) { defer func(t0 time.Time) { diff --git a/core/state/pevm_statedb.go b/core/state/pevm_statedb.go index d8a075bf50..8bc0d49edc 100644 --- a/core/state/pevm_statedb.go +++ b/core/state/pevm_statedb.go @@ -666,6 +666,32 @@ func (pst *UncommittedDB) getDeletedObjectWithState(addr common.Address, maindb return o } +func (s *UncommittedDB) Debug(addr common.Address) string { + read := s.reads[addr] + write := s.cache[addr] + switch true { + case read == nil && write == nil: + return fmt.Sprintf("addr:%s, readState empty! cacheState empty!\n", addr.String()) + + case read == nil && write != nil: + // this should never happen, because the read should be recorded before each write + return fmt.Sprintf("addr:%s, readState empty! something very wrong! cacheState modified:%d, nonce:%d, balance:%d, codeHash:%s, codeLen:%d, state:%v, selfDestruct:%t, deleted:%t, created:%t \n", + addr.String(), write.modified, write.nonce, write.balance, common.Bytes2Hex(write.codeHash), write.codeSize, write.state, write.selfDestruct, write.deleted, write.created, + ) + + case read != nil && write == nil: + return fmt.Sprintf("addr:%s, readState nonce:%d, balance:%d, codeHash:%s, codeLen:%d, state:%v selfDestructed:%t, deleted:%t, created:%t ; cacheState nil\n", + addr.String(), read.nonce, read.balance, common.Bytes2Hex(read.codeHash), read.codeSize, read.state, read.selfDestruct, read.deleted, read.created, + ) + + default: + return fmt.Sprintf("addr:%s, readState nonce:%d, balance:%d, codeHash:%s, codeLen:%d, state:%v selfDestructed:%t, deleted:%t, created:%t ; cacheState modified:%d, nonce:%d, balance:%d, codeHash:%s, codeLen:%d, state:%v, selfDestruct:%t, deleted:%t, created:%t \n", + addr.String(), read.nonce, read.balance, common.Bytes2Hex(read.codeHash), read.codeSize, read.state, read.selfDestruct, read.deleted, read.created, + write.modified, write.nonce, write.balance, common.Bytes2Hex(write.codeHash), write.codeSize, write.state, write.selfDestruct, write.deleted, write.created, + ) + } +} + type state struct { // object states modified int32 //records all the modified fields diff --git a/core/state/statedb.go b/core/state/statedb.go index d71c675055..10c8d0ec77 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -2664,6 +2664,13 @@ func (s *StateDB) MergeSlotDB(slotDb *ParallelStateDB, slotReceipt *types.Receip return s } +func (s *StateDB) GetAccountFromTrie(addr common.Address) (*types.StateAccount, error) { + if s.trie == nil { + return nil, fmt.Errorf("trie is nil") + } + return s.trie.GetAccount(addr) +} + // NewParallelDBManager creates a new ParallelDBManager with the specified number of instance func NewParallelDBManager(initialCount int, newFunc func() *ParallelStateDB) *ParallelDBManager { manager := &ParallelDBManager{