mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 14:16:44 +00:00
166 lines
4.8 KiB
Go
166 lines
4.8 KiB
Go
package firehose_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math/big"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/math"
|
|
"github.com/ethereum/go-ethereum/consensus"
|
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
|
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
|
|
"github.com/ethereum/go-ethereum/core"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
|
"github.com/ethereum/go-ethereum/internal/cli/server/chains"
|
|
"github.com/ethereum/go-ethereum/params"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func readPrestateData(t *testing.T, path string) *prestateData {
|
|
t.Helper()
|
|
|
|
// Call tracer test found, read if from disk
|
|
blob, err := os.ReadFile(path)
|
|
require.NoError(t, err)
|
|
|
|
test := new(prestateData)
|
|
require.NoError(t, json.Unmarshal(blob, test))
|
|
|
|
var genesisWithTD struct {
|
|
Genesis struct {
|
|
TotalDifficulty *math.HexOrDecimal256 `json:"totalDifficulty"`
|
|
} `json:"genesis"`
|
|
}
|
|
if err := json.Unmarshal(blob, &genesisWithTD); err == nil {
|
|
test.TotalDifficulty = (*big.Int)(genesisWithTD.Genesis.TotalDifficulty)
|
|
}
|
|
|
|
// Polygon overrides time based hard fork with block number based hard fork, let's try to handle that
|
|
// here.
|
|
//
|
|
// We read the "old" genesis Ethereum format which is time based, and we try to infer
|
|
// if we should set the time based hard fork values or not based on current time.
|
|
var genesisTimeBased struct {
|
|
Genesis struct {
|
|
Config struct {
|
|
ShanghaiTime *math.HexOrDecimal64 `json:"shanghaiTime"`
|
|
CancunTime *math.HexOrDecimal64 `json:"cancunTime"`
|
|
PragueTime *math.HexOrDecimal64 `json:"pragueTime"`
|
|
} `json:"config"`
|
|
} `json:"genesis"`
|
|
}
|
|
|
|
if err := json.Unmarshal(blob, &genesisTimeBased); err == nil {
|
|
timeBasedConfig := genesisTimeBased.Genesis.Config
|
|
blockBasedConfig := test.Genesis.Config
|
|
|
|
blockBasedConfig.CancunBlock = timeBasedToBlockBasedHardFork(timeBasedConfig.CancunTime)
|
|
blockBasedConfig.ShanghaiBlock = timeBasedToBlockBasedHardFork(timeBasedConfig.ShanghaiTime)
|
|
blockBasedConfig.PragueBlock = timeBasedToBlockBasedHardFork(timeBasedConfig.PragueTime)
|
|
}
|
|
|
|
chain, err := chains.GetChain("mainnet")
|
|
require.NoError(t, err)
|
|
|
|
test.Genesis.Config.Bor = chain.Genesis.Config.Bor
|
|
|
|
return test
|
|
}
|
|
|
|
func timeBasedToBlockBasedHardFork(in *math.HexOrDecimal64) *big.Int {
|
|
if in == nil {
|
|
return nil
|
|
}
|
|
|
|
// If the fork is active, we return 0 as the block number to activate to
|
|
if time.Now().Unix() > int64(*in) {
|
|
return big.NewInt(0)
|
|
}
|
|
|
|
// Otherwise, we return the block number that would be mined at that time
|
|
return nil
|
|
}
|
|
|
|
var _ core.ChainContext = (*prestateData)(nil)
|
|
|
|
type prestateData struct {
|
|
Genesis *core.Genesis `json:"genesis"`
|
|
Context *callContext `json:"context"`
|
|
Input string `json:"input"`
|
|
TotalDifficulty *big.Int `json:"-"`
|
|
TracerConfig json.RawMessage `json:"tracerConfig"`
|
|
|
|
// Populated after loading
|
|
genesisBlock *types.Block
|
|
}
|
|
|
|
// Config implements core.ChainContext.
|
|
func (p *prestateData) Config() *params.ChainConfig {
|
|
return p.Genesis.Config
|
|
}
|
|
|
|
// Engine implements core.ChainContext.
|
|
func (p *prestateData) Engine() consensus.Engine {
|
|
return ethash.NewFullFaker()
|
|
}
|
|
|
|
// GetHeader implements core.ChainContext.
|
|
func (p *prestateData) GetHeader(hash common.Hash, number uint64) *types.Header {
|
|
if p.Genesis == nil {
|
|
return nil
|
|
}
|
|
|
|
if p.genesisBlock == nil {
|
|
p.genesisBlock = p.Genesis.ToBlock()
|
|
}
|
|
|
|
if hash == p.genesisBlock.Hash() {
|
|
return p.genesisBlock.Header()
|
|
}
|
|
|
|
if number == p.genesisBlock.NumberU64() {
|
|
return p.genesisBlock.Header()
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
type callContext struct {
|
|
Number math.HexOrDecimal64 `json:"number"`
|
|
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
|
Time math.HexOrDecimal64 `json:"timestamp"`
|
|
GasLimit math.HexOrDecimal64 `json:"gasLimit"`
|
|
Miner common.Address `json:"miner"`
|
|
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas"`
|
|
}
|
|
|
|
func (c *callContext) toBlockContext(genesis *core.Genesis) vm.BlockContext {
|
|
context := vm.BlockContext{
|
|
CanTransfer: core.CanTransfer,
|
|
Transfer: core.Transfer,
|
|
Coinbase: c.Miner,
|
|
BlockNumber: new(big.Int).SetUint64(uint64(c.Number)),
|
|
Time: uint64(c.Time),
|
|
Difficulty: (*big.Int)(c.Difficulty),
|
|
GasLimit: uint64(c.GasLimit),
|
|
}
|
|
if genesis.Config.IsLondon(context.BlockNumber) {
|
|
context.BaseFee = (*big.Int)(c.BaseFee)
|
|
}
|
|
|
|
if genesis.Config.TerminalTotalDifficulty != nil && genesis.Config.TerminalTotalDifficulty.Sign() == 0 {
|
|
context.Random = &genesis.Mixhash
|
|
}
|
|
|
|
if genesis.ExcessBlobGas != nil && genesis.BlobGasUsed != nil {
|
|
header := &types.Header{Number: genesis.Config.CancunBlock, Time: 0}
|
|
excess := eip4844.CalcExcessBlobGas(genesis.Config, header, genesis.Timestamp)
|
|
header.ExcessBlobGas = &excess
|
|
context.BlobBaseFee = eip4844.CalcBlobFee(genesis.Config, header)
|
|
}
|
|
return context
|
|
}
|