core: add better debug logging

This commit is contained in:
MariusVanDerWijden 2026-05-01 01:42:54 +02:00
parent 6dddd29936
commit cd2c443b56
2 changed files with 48 additions and 1 deletions

View file

@ -2861,6 +2861,18 @@ func (bc *BlockChain) reportBadBlock(block *types.Block, res *ProcessResult, err
} }
rawdb.WriteBadBlock(bc.db, block) rawdb.WriteBadBlock(bc.db, block)
log.Error(summarizeBadBlock(block, receipts, bc.Config(), err)) log.Error(summarizeBadBlock(block, receipts, bc.Config(), err))
// Post-Amsterdam, dump the remote and locally-computed BALs to aid diagnosis
// of any mismatch between what the network produced and what we computed.
if bc.Config().IsAmsterdam(block.Number(), block.Time()) {
if remote := block.AccessList(); remote != nil {
log.Error("Bad block: remote BAL", "number", block.Number(), "hash", block.Hash(), "bal", remote.JSONString())
}
if res != nil && res.AccessList != nil {
local := res.AccessList.ToEncodingObj()
log.Error("Bad block: local BAL", "number", block.Number(), "hash", block.Hash(), "bal", local.JSONString())
}
}
} }
// logForkReadiness will write a log when a future fork is scheduled, but not // logForkReadiness will write a log when a future fork is scheduled, but not

View file

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types/bal"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@ -555,15 +556,49 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
// StandardTraceBadBlockToFile dumps the structured logs created during the // StandardTraceBadBlockToFile dumps the structured logs created during the
// execution of EVM against a block pulled from the pool of bad ones to the // execution of EVM against a block pulled from the pool of bad ones to the
// local file system and returns a list of files to the caller. // local file system and returns a list of files to the caller. After Amsterdam,
// the block (header + body + access list) is also RLP-dumped to a temporary
// file to allow offline post-mortem of BAL mismatches.
func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) { func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Hash, config *StdTraceConfig) ([]string, error) {
block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash) block := rawdb.ReadBadBlock(api.backend.ChainDb(), hash)
if block == nil { if block == nil {
return nil, fmt.Errorf("bad block %#x not found", hash) return nil, fmt.Errorf("bad block %#x not found", hash)
} }
if api.backend.ChainConfig().IsAmsterdam(block.Number(), block.Time()) {
if name, err := dumpBadBlockWithBAL(block); err != nil {
log.Warn("Failed to dump bad block with BAL", "hash", block.Hash(), "err", err)
} else {
log.Info("Dumped bad block (header+body+BAL)", "hash", block.Hash(), "file", name)
}
}
return api.standardTraceBlockToFile(ctx, block, config) return api.standardTraceBlockToFile(ctx, block, config)
} }
// dumpBadBlockWithBAL writes an RLP encoding of the block header, body, and
// (if attached) the block access list to a temporary file. This is intended
// for post-mortem analysis of BAL mismatches.
func dumpBadBlockWithBAL(block *types.Block) (string, error) {
prefix := fmt.Sprintf("badblock_%d_%#x-", block.NumberU64(), block.Hash().Bytes()[:4])
f, err := os.CreateTemp(os.TempDir(), prefix+"*.rlp")
if err != nil {
return "", err
}
defer f.Close()
payload := struct {
Header *types.Header
Body *types.Body
AccessList *bal.BlockAccessList `rlp:"optional"`
}{
Header: block.Header(),
Body: block.Body(),
AccessList: block.AccessList(),
}
if err := rlp.Encode(f, &payload); err != nil {
return "", err
}
return f.Name(), nil
}
// traceBlock configures a new tracer according to the provided configuration, and // traceBlock configures a new tracer according to the provided configuration, and
// executes all the transactions contained within. The return value will be one item // executes all the transactions contained within. The return value will be one item
// per transaction, dependent on the requested tracer. // per transaction, dependent on the requested tracer.