Merge branch 'ethereum:master' into portal

This commit is contained in:
Chen Kai 2024-10-23 23:59:22 +08:00 committed by GitHub
commit 80ef312cb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
66 changed files with 1226 additions and 751 deletions

View file

@ -29,147 +29,69 @@ Fingerprint: `AE96 ED96 9E47 9B00 84F3 E17F E88D 3334 FA5F 6A0A`
``` ```
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
Version: SKS 1.1.6
Comment: Hostname: pgp.mit.edu
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 6F7hEeTW+gnXEI2gPjfb5w==
uSCxOysxC7Q1hZtjzFPKdljS81mRlYeUL4fHlJU9R57bg8mriSXLmn7eKrSEDm/EG5T8nRx7 =b5eA
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
=arte
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
``` ```

View file

@ -18,7 +18,6 @@
"shanghaiTime": 780, "shanghaiTime": 780,
"cancunTime": 840, "cancunTime": 840,
"terminalTotalDifficulty": 9454784, "terminalTotalDifficulty": 9454784,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
}, },
"nonce": "0x0", "nonce": "0x0",

View file

@ -29,7 +29,7 @@ var customGenesisTests = []struct {
query string query string
result string result string
}{ }{
// Genesis file with an empty chain configuration (ensure missing fields work) // Genesis file with a mostly-empty chain configuration (ensure missing fields work)
{ {
genesis: `{ genesis: `{
"alloc" : {}, "alloc" : {},
@ -41,8 +41,8 @@ var customGenesisTests = []struct {
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00", "timestamp" : "0x00",
"config" : { "config": {
"terminalTotalDifficultyPassed": true "terminalTotalDifficulty": 0
} }
}`, }`,
query: "eth.getBlock(0).nonce", query: "eth.getBlock(0).nonce",
@ -64,7 +64,7 @@ var customGenesisTests = []struct {
"homesteadBlock" : 42, "homesteadBlock" : 42,
"daoForkBlock" : 141, "daoForkBlock" : 141,
"daoForkSupport" : true, "daoForkSupport" : true,
"terminalTotalDifficultyPassed" : true "terminalTotalDifficulty": 0
} }
}`, }`,
query: "eth.getBlock(0).nonce", query: "eth.getBlock(0).nonce",
@ -114,8 +114,8 @@ func TestCustomBackend(t *testing.T) {
"mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00", "timestamp" : "0x00",
"config" : { "config": {
"terminalTotalDifficultyPassed": true "terminalTotalDifficulty": 0
} }
}` }`
type backendTest struct { type backendTest struct {

View file

@ -8,7 +8,7 @@
"byzantiumBlock": 0, "byzantiumBlock": 0,
"constantinopleBlock": 0, "constantinopleBlock": 0,
"petersburgBlock": 0, "petersburgBlock": 0,
"terminalTotalDifficultyPassed": true, "terminalTotalDifficulty": 0,
"clique": { "clique": {
"period": 5, "period": 5,
"epoch": 30000 "epoch": 30000
@ -22,4 +22,4 @@
"balance": "300000" "balance": "300000"
} }
} }
} }

View file

@ -1948,9 +1948,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if err != nil { if err != nil {
Fatalf("Could not read genesis from database: %v", err) Fatalf("Could not read genesis from database: %v", err)
} }
if !genesis.Config.TerminalTotalDifficultyPassed {
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficultyPassed must be true")
}
if genesis.Config.TerminalTotalDifficulty == nil { if genesis.Config.TerminalTotalDifficulty == nil {
Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified") Fatalf("Bad developer-mode genesis configuration: terminalTotalDifficulty must be specified")
} else if genesis.Config.TerminalTotalDifficulty.Cmp(big.NewInt(0)) != 0 { } else if genesis.Config.TerminalTotalDifficulty.Cmp(big.NewInt(0)) != 0 {

View file

@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
@ -115,9 +116,6 @@ func errOut(n int, err error) chan error {
func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) { func (beacon *Beacon) splitHeaders(chain consensus.ChainHeaderReader, headers []*types.Header) ([]*types.Header, []*types.Header, error) {
// TTD is not defined yet, all headers should be in legacy format. // TTD is not defined yet, all headers should be in legacy format.
ttd := chain.Config().TerminalTotalDifficulty ttd := chain.Config().TerminalTotalDifficulty
if ttd == nil {
return headers, nil, nil
}
ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1) ptd := chain.GetTd(headers[0].ParentHash, headers[0].Number.Uint64()-1)
if ptd == nil { if ptd == nil {
return nil, nil, consensus.ErrUnknownAncestor return nil, nil, consensus.ErrUnknownAncestor
@ -349,7 +347,7 @@ func (beacon *Beacon) Prepare(chain consensus.ChainHeaderReader, header *types.H
} }
// Finalize implements consensus.Engine and processes withdrawals on top. // Finalize implements consensus.Engine and processes withdrawals on top.
func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { func (beacon *Beacon) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
if !beacon.IsPoSHeader(header) { if !beacon.IsPoSHeader(header) {
beacon.ethone.Finalize(chain, header, state, body) beacon.ethone.Finalize(chain, header, state, body)
return return
@ -494,9 +492,6 @@ func (beacon *Beacon) SetThreads(threads int) {
// It depends on the parentHash already being stored in the database. // It depends on the parentHash already being stored in the database.
// If the parentHash is not stored in the database a UnknownAncestor error is returned. // If the parentHash is not stored in the database a UnknownAncestor error is returned.
func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) { func IsTTDReached(chain consensus.ChainHeaderReader, parentHash common.Hash, parentNumber uint64) (bool, error) {
if chain.Config().TerminalTotalDifficulty == nil {
return false, nil
}
td := chain.GetTd(parentHash, parentNumber) td := chain.GetTd(parentHash, parentNumber)
if td == nil { if td == nil {
return false, consensus.ErrUnknownAncestor return false, consensus.ErrUnknownAncestor

View file

@ -35,6 +35,7 @@ import (
"github.com/ethereum/go-ethereum/consensus/misc/eip1559" "github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"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/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -573,7 +574,7 @@ func (c *Clique) Prepare(chain consensus.ChainHeaderReader, header *types.Header
// Finalize implements consensus.Engine. There is no post-transaction // Finalize implements consensus.Engine. There is no post-transaction
// consensus rules in clique, do nothing here. // consensus rules in clique, do nothing here.
func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
// No block rewards in PoA, so the state remains as is // No block rewards in PoA, so the state remains as is
} }

View file

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"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/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -88,7 +89,7 @@ type Engine interface {
// //
// Note: The state database might be updated to reflect any consensus rules // Note: The state database might be updated to reflect any consensus rules
// that happen at finalization (e.g. block rewards). // that happen at finalization (e.g. block rewards).
Finalize(chain ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) Finalize(chain ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body)
// FinalizeAndAssemble runs any post-transaction state modifications (e.g. block // FinalizeAndAssemble runs any post-transaction state modifications (e.g. block
// rewards or process withdrawals) and assembles the final block. // rewards or process withdrawals) and assembles the final block.

View file

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
@ -503,7 +504,7 @@ func (ethash *Ethash) Prepare(chain consensus.ChainHeaderReader, header *types.H
} }
// Finalize implements consensus.Engine, accumulating the block and uncle rewards. // Finalize implements consensus.Engine, accumulating the block and uncle rewards.
func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body) { func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state vm.StateDB, body *types.Body) {
// Accumulate any block and uncle rewards // Accumulate any block and uncle rewards
accumulateRewards(chain.Config(), state, header, body.Uncles) accumulateRewards(chain.Config(), state, header, body.Uncles)
} }
@ -566,7 +567,7 @@ func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
// accumulateRewards credits the coinbase of the given block with the mining // accumulateRewards credits the coinbase of the given block with the mining
// reward. The total reward consists of the static block reward and rewards for // reward. The total reward consists of the static block reward and rewards for
// included uncles. The coinbase of each uncle block is also rewarded. // included uncles. The coinbase of each uncle block is also rewarded.
func accumulateRewards(config *params.ChainConfig, stateDB *state.StateDB, header *types.Header, uncles []*types.Header) { func accumulateRewards(config *params.ChainConfig, stateDB vm.StateDB, header *types.Header, uncles []*types.Header) {
// Select the correct block reward based on chain progression // Select the correct block reward based on chain progression
blockReward := FrontierBlockReward blockReward := FrontierBlockReward
if config.IsByzantium(header.Number) { if config.IsByzantium(header.Number) {

View file

@ -21,11 +21,10 @@ import (
"errors" "errors"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"
) )
var ( var (
@ -74,7 +73,7 @@ func VerifyDAOHeaderExtraData(config *params.ChainConfig, header *types.Header)
// ApplyDAOHardFork modifies the state database according to the DAO hard-fork // ApplyDAOHardFork modifies the state database according to the DAO hard-fork
// rules, transferring all balances of a set of DAO accounts to a single refund // rules, transferring all balances of a set of DAO accounts to a single refund
// contract. // contract.
func ApplyDAOHardFork(statedb *state.StateDB) { func ApplyDAOHardFork(statedb vm.StateDB) {
// Retrieve the contract to refund balances into // Retrieve the contract to refund balances into
if !statedb.Exist(params.DAORefundContract) { if !statedb.Exist(params.DAORefundContract) {
statedb.CreateAccount(params.DAORefundContract) statedb.CreateAccount(params.DAORefundContract)
@ -82,7 +81,8 @@ func ApplyDAOHardFork(statedb *state.StateDB) {
// Move every DAO account and extra-balance account funds into the refund contract // Move every DAO account and extra-balance account funds into the refund contract
for _, addr := range params.DAODrainList() { for _, addr := range params.DAODrainList() {
statedb.AddBalance(params.DAORefundContract, statedb.GetBalance(addr), tracing.BalanceIncreaseDaoContract) balance := statedb.GetBalance(addr)
statedb.SetBalance(addr, new(uint256.Int), tracing.BalanceDecreaseDaoAccount) statedb.AddBalance(params.DAORefundContract, balance, tracing.BalanceIncreaseDaoContract)
statedb.SubBalance(addr, balance, tracing.BalanceDecreaseDaoAccount)
} }
} }

View file

@ -113,8 +113,12 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
} }
copy(gspec.ExtraData[32:], addr[:]) copy(gspec.ExtraData[32:], addr[:])
// chain_maker has no blockchain to retrieve the TTD from, setting to nil
// is a hack to signal it to generate pre-merge blocks
gspec.Config.TerminalTotalDifficulty = nil
td := 0 td := 0
genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil) genDb, blocks, _ := GenerateChainWithGenesis(gspec, engine, 8, nil)
for i, block := range blocks { for i, block := range blocks {
header := block.Header() header := block.Header()
if i > 0 { if i > 0 {
@ -145,7 +149,6 @@ func testHeaderVerificationForMerging(t *testing.T, isClique bool) {
} }
preBlocks = blocks preBlocks = blocks
gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td)) gspec.Config.TerminalTotalDifficulty = big.NewInt(int64(td))
t.Logf("Set ttd to %v\n", gspec.Config.TerminalTotalDifficulty)
postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) { postBlocks, _ = GenerateChain(gspec.Config, preBlocks[len(preBlocks)-1], engine, genDb, 8, func(i int, gen *BlockGen) {
gen.SetPoS() gen.SetPoS()
}) })

View file

@ -1774,7 +1774,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness
if err != nil { if err != nil {
return nil, it.index, err return nil, it.index, err
} }
statedb.SetLogger(bc.logger)
// If we are past Byzantium, enable prefetching to pull in trie node paths // If we are past Byzantium, enable prefetching to pull in trie node paths
// while processing transactions. Before Byzantium the prefetcher is mostly // while processing transactions. Before Byzantium the prefetcher is mostly

View file

@ -4092,7 +4092,6 @@ func TestEIP3651(t *testing.T) {
gspec.Config.BerlinBlock = common.Big0 gspec.Config.BerlinBlock = common.Big0
gspec.Config.LondonBlock = common.Big0 gspec.Config.LondonBlock = common.Big0
gspec.Config.TerminalTotalDifficulty = common.Big0 gspec.Config.TerminalTotalDifficulty = common.Big0
gspec.Config.TerminalTotalDifficultyPassed = true
gspec.Config.ShanghaiTime = u64(0) gspec.Config.ShanghaiTime = u64(0)
signer := types.LatestSigner(gspec.Config) signer := types.LatestSigner(gspec.Config)

View file

@ -57,7 +57,6 @@ func TestGeneratePOSChain(t *testing.T) {
db = rawdb.NewMemoryDatabase() db = rawdb.NewMemoryDatabase()
) )
config.TerminalTotalDifficultyPassed = true
config.TerminalTotalDifficulty = common.Big0 config.TerminalTotalDifficulty = common.Big0
config.ShanghaiTime = u64(0) config.ShanghaiTime = u64(0)
config.CancunTime = u64(0) config.CancunTime = u64(0)

View file

@ -378,26 +378,25 @@ func TestTimeBasedForkInGenesis(t *testing.T) {
forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes())) forkidHash = checksumToBytes(crc32.ChecksumIEEE(genesis.Hash().Bytes()))
config = func(shanghai, cancun uint64) *params.ChainConfig { config = func(shanghai, cancun uint64) *params.ChainConfig {
return &params.ChainConfig{ return &params.ChainConfig{
ChainID: big.NewInt(1337), ChainID: big.NewInt(1337),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: true, DAOForkSupport: true,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, MergeNetsplitBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0), ShanghaiTime: &shanghai,
ShanghaiTime: &shanghai, CancunTime: &cancun,
CancunTime: &cancun, Ethash: new(params.EthashConfig),
Ethash: new(params.EthashConfig),
} }
} }
) )

View file

@ -257,31 +257,30 @@ func newDbConfig(scheme string) *triedb.Config {
func TestVerkleGenesisCommit(t *testing.T) { func TestVerkleGenesisCommit(t *testing.T) {
var verkleTime uint64 = 0 var verkleTime uint64 = 0
verkleConfig := &params.ChainConfig{ verkleConfig := &params.ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: false, DAOForkSupport: false,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: nil, MergeNetsplitBlock: nil,
ShanghaiTime: &verkleTime, ShanghaiTime: &verkleTime,
CancunTime: &verkleTime, CancunTime: &verkleTime,
PragueTime: &verkleTime, PragueTime: &verkleTime,
VerkleTime: &verkleTime, VerkleTime: &verkleTime,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, Ethash: nil,
Ethash: nil, Clique: nil,
Clique: nil,
} }
genesis := &Genesis{ genesis := &Genesis{

View file

@ -23,7 +23,6 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -208,19 +207,18 @@ func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
} }
// SetState updates a value in account storage. // SetState updates a value in account storage.
func (s *stateObject) SetState(key, value common.Hash) { // It returns the previous value
func (s *stateObject) SetState(key, value common.Hash) common.Hash {
// If the new value is the same as old, don't set. Otherwise, track only the // If the new value is the same as old, don't set. Otherwise, track only the
// dirty changes, supporting reverting all of it back to no change. // dirty changes, supporting reverting all of it back to no change.
prev, origin := s.getState(key) prev, origin := s.getState(key)
if prev == value { if prev == value {
return return prev
} }
// New value is different, update and journal the change // New value is different, update and journal the change
s.db.journal.storageChange(s.address, key, prev, origin) s.db.journal.storageChange(s.address, key, prev, origin)
s.setState(key, value, origin) s.setState(key, value, origin)
if s.db.logger != nil && s.db.logger.OnStorageChange != nil { return prev
s.db.logger.OnStorageChange(s.address, key, prev, value)
}
} }
// setState updates a value in account dirty storage. The dirtiness will be // setState updates a value in account dirty storage. The dirtiness will be
@ -448,33 +446,25 @@ func (s *stateObject) commit() (*accountUpdate, *trienode.NodeSet, error) {
// AddBalance adds amount to s's balance. // AddBalance adds amount to s's balance.
// It is used to add funds to the destination account of a transfer. // It is used to add funds to the destination account of a transfer.
func (s *stateObject) AddBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { // returns the previous balance
func (s *stateObject) AddBalance(amount *uint256.Int) uint256.Int {
// EIP161: We must check emptiness for the objects such that the account // EIP161: We must check emptiness for the objects such that the account
// clearing (0,0,0 objects) can take effect. // clearing (0,0,0 objects) can take effect.
if amount.IsZero() { if amount.IsZero() {
if s.empty() { if s.empty() {
s.touch() s.touch()
} }
return return *(s.Balance())
} }
s.SetBalance(new(uint256.Int).Add(s.Balance(), amount), reason) return s.SetBalance(new(uint256.Int).Add(s.Balance(), amount))
} }
// SubBalance removes amount from s's balance. // SetBalance sets the balance for the object, and returns the previous balance.
// It is used to remove funds from the origin account of a transfer. func (s *stateObject) SetBalance(amount *uint256.Int) uint256.Int {
func (s *stateObject) SubBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) { prev := *s.data.Balance
if amount.IsZero() {
return
}
s.SetBalance(new(uint256.Int).Sub(s.Balance(), amount), reason)
}
func (s *stateObject) SetBalance(amount *uint256.Int, reason tracing.BalanceChangeReason) {
s.db.journal.balanceChange(s.address, s.data.Balance) s.db.journal.balanceChange(s.address, s.data.Balance)
if s.db.logger != nil && s.db.logger.OnBalanceChange != nil {
s.db.logger.OnBalanceChange(s.address, s.Balance().ToBig(), amount.ToBig(), reason)
}
s.setBalance(amount) s.setBalance(amount)
return prev
} }
func (s *stateObject) setBalance(amount *uint256.Int) { func (s *stateObject) setBalance(amount *uint256.Int) {
@ -547,10 +537,6 @@ func (s *stateObject) CodeSize() int {
func (s *stateObject) SetCode(codeHash common.Hash, code []byte) { func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
s.db.journal.setCode(s.address) s.db.journal.setCode(s.address)
if s.db.logger != nil && s.db.logger.OnCodeChange != nil {
// TODO remove prevcode from this callback
s.db.logger.OnCodeChange(s.address, common.BytesToHash(s.CodeHash()), nil, codeHash, code)
}
s.setCode(codeHash, code) s.setCode(codeHash, code)
} }
@ -562,9 +548,6 @@ func (s *stateObject) setCode(codeHash common.Hash, code []byte) {
func (s *stateObject) SetNonce(nonce uint64) { func (s *stateObject) SetNonce(nonce uint64) {
s.db.journal.nonceChange(s.address, s.data.Nonce) s.db.journal.nonceChange(s.address, s.data.Nonce)
if s.db.logger != nil && s.db.logger.OnNonceChange != nil {
s.db.logger.OnNonceChange(s.address, s.data.Nonce, nonce)
}
s.setNonce(nonce) s.setNonce(nonce)
} }

View file

@ -23,7 +23,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/triedb" "github.com/ethereum/go-ethereum/triedb"
@ -48,11 +47,11 @@ func TestDump(t *testing.T) {
// generate a few entries // generate a few entries
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01})) obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified) obj1.AddBalance(uint256.NewInt(22))
obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02})) obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified) obj3.SetBalance(uint256.NewInt(44))
// write some of them to the trie // write some of them to the trie
s.state.updateStateObject(obj1) s.state.updateStateObject(obj1)
@ -106,13 +105,13 @@ func TestIterativeDump(t *testing.T) {
// generate a few entries // generate a few entries
obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01})) obj1 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01}))
obj1.AddBalance(uint256.NewInt(22), tracing.BalanceChangeUnspecified) obj1.AddBalance(uint256.NewInt(22))
obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02})) obj2 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x01, 0x02}))
obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3}) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02})) obj3 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x02}))
obj3.SetBalance(uint256.NewInt(44), tracing.BalanceChangeUnspecified) obj3.SetBalance(uint256.NewInt(44))
obj4 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x00})) obj4 := s.state.getOrNewStateObject(common.BytesToAddress([]byte{0x00}))
obj4.AddBalance(uint256.NewInt(1337), tracing.BalanceChangeUnspecified) obj4.AddBalance(uint256.NewInt(1337))
// write some of them to the trie // write some of them to the trie
s.state.updateStateObject(obj1) s.state.updateStateObject(obj1)
@ -200,7 +199,7 @@ func TestCreateObjectRevert(t *testing.T) {
state.CreateAccount(addr) state.CreateAccount(addr)
so0 := state.getStateObject(addr) so0 := state.getStateObject(addr)
so0.SetBalance(uint256.NewInt(42), tracing.BalanceChangeUnspecified) so0.SetBalance(uint256.NewInt(42))
so0.SetNonce(43) so0.SetNonce(43)
so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'}) so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
state.setStateObject(so0) state.setStateObject(so0)

View file

@ -21,7 +21,6 @@ import (
"errors" "errors"
"fmt" "fmt"
"maps" "maps"
"math/big"
"slices" "slices"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -81,7 +80,6 @@ type StateDB struct {
db Database db Database
prefetcher *triePrefetcher prefetcher *triePrefetcher
trie Trie trie Trie
logger *tracing.Hooks
reader Reader reader Reader
// originalRoot is the pre-state root, before any changes were made. // originalRoot is the pre-state root, before any changes were made.
@ -189,11 +187,6 @@ func New(root common.Hash, db Database) (*StateDB, error) {
return sdb, nil return sdb, nil
} }
// SetLogger sets the logger for account update hooks.
func (s *StateDB) SetLogger(l *tracing.Hooks) {
s.logger = l
}
// StartPrefetcher initializes a new trie prefetcher to pull in nodes from the // StartPrefetcher initializes a new trie prefetcher to pull in nodes from the
// state trie concurrently while the state is mutated so that when we reach the // state trie concurrently while the state is mutated so that when we reach the
// commit phase, most of the needed data is already hot. // commit phase, most of the needed data is already hot.
@ -247,9 +240,6 @@ func (s *StateDB) AddLog(log *types.Log) {
log.TxHash = s.thash log.TxHash = s.thash
log.TxIndex = uint(s.txIndex) log.TxIndex = uint(s.txIndex)
log.Index = s.logSize log.Index = s.logSize
if s.logger != nil && s.logger.OnLog != nil {
s.logger.OnLog(log)
}
s.logs[s.thash] = append(s.logs[s.thash], log) s.logs[s.thash] = append(s.logs[s.thash], log)
s.logSize++ s.logSize++
} }
@ -409,25 +399,30 @@ func (s *StateDB) HasSelfDestructed(addr common.Address) bool {
*/ */
// AddBalance adds amount to the account associated with addr. // AddBalance adds amount to the account associated with addr.
func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { func (s *StateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
stateObject := s.getOrNewStateObject(addr) stateObject := s.getOrNewStateObject(addr)
if stateObject != nil { if stateObject == nil {
stateObject.AddBalance(amount, reason) return uint256.Int{}
} }
return stateObject.AddBalance(amount)
} }
// SubBalance subtracts amount from the account associated with addr. // SubBalance subtracts amount from the account associated with addr.
func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { func (s *StateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
stateObject := s.getOrNewStateObject(addr) stateObject := s.getOrNewStateObject(addr)
if stateObject != nil { if stateObject == nil {
stateObject.SubBalance(amount, reason) return uint256.Int{}
} }
if amount.IsZero() {
return *(stateObject.Balance())
}
return stateObject.SetBalance(new(uint256.Int).Sub(stateObject.Balance(), amount))
} }
func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) { func (s *StateDB) SetBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) {
stateObject := s.getOrNewStateObject(addr) stateObject := s.getOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetBalance(amount, reason) stateObject.SetBalance(amount)
} }
} }
@ -445,11 +440,11 @@ func (s *StateDB) SetCode(addr common.Address, code []byte) {
} }
} }
func (s *StateDB) SetState(addr common.Address, key, value common.Hash) { func (s *StateDB) SetState(addr common.Address, key, value common.Hash) common.Hash {
stateObject := s.getOrNewStateObject(addr) if stateObject := s.getOrNewStateObject(addr); stateObject != nil {
if stateObject != nil { return stateObject.SetState(key, value)
stateObject.SetState(key, value)
} }
return common.Hash{}
} }
// SetStorage replaces the entire storage for the specified account with given // SetStorage replaces the entire storage for the specified account with given
@ -477,7 +472,7 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
if obj != nil { if obj != nil {
newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code) newObj.SetCode(common.BytesToHash(obj.CodeHash()), obj.code)
newObj.SetNonce(obj.Nonce()) newObj.SetNonce(obj.Nonce())
newObj.SetBalance(obj.Balance(), tracing.BalanceChangeUnspecified) newObj.SetBalance(obj.Balance())
} }
} }
@ -486,15 +481,17 @@ func (s *StateDB) SetStorage(addr common.Address, storage map[common.Hash]common
// //
// The account's state object is still available until the state is committed, // The account's state object is still available until the state is committed,
// getStateObject will return a non-nil account after SelfDestruct. // getStateObject will return a non-nil account after SelfDestruct.
func (s *StateDB) SelfDestruct(addr common.Address) { func (s *StateDB) SelfDestruct(addr common.Address) uint256.Int {
stateObject := s.getStateObject(addr) stateObject := s.getStateObject(addr)
var prevBalance uint256.Int
if stateObject == nil { if stateObject == nil {
return return prevBalance
} }
prevBalance = *(stateObject.Balance())
// Regardless of whether it is already destructed or not, we do have to // Regardless of whether it is already destructed or not, we do have to
// journal the balance-change, if we set it to zero here. // journal the balance-change, if we set it to zero here.
if !stateObject.Balance().IsZero() { if !stateObject.Balance().IsZero() {
stateObject.SetBalance(new(uint256.Int), tracing.BalanceDecreaseSelfdestruct) stateObject.SetBalance(new(uint256.Int))
} }
// If it is already marked as self-destructed, we do not need to add it // If it is already marked as self-destructed, we do not need to add it
// for journalling a second time. // for journalling a second time.
@ -502,16 +499,18 @@ func (s *StateDB) SelfDestruct(addr common.Address) {
s.journal.destruct(addr) s.journal.destruct(addr)
stateObject.markSelfdestructed() stateObject.markSelfdestructed()
} }
return prevBalance
} }
func (s *StateDB) Selfdestruct6780(addr common.Address) { func (s *StateDB) SelfDestruct6780(addr common.Address) (uint256.Int, bool) {
stateObject := s.getStateObject(addr) stateObject := s.getStateObject(addr)
if stateObject == nil { if stateObject == nil {
return return uint256.Int{}, false
} }
if stateObject.newContract { if stateObject.newContract {
s.SelfDestruct(addr) return s.SelfDestruct(addr), true
} }
return *(stateObject.Balance()), false
} }
// SetTransientState sets transient storage for a given account. It // SetTransientState sets transient storage for a given account. It
@ -735,11 +734,6 @@ func (s *StateDB) Finalise(deleteEmptyObjects bool) {
if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) { if obj.selfDestructed || (deleteEmptyObjects && obj.empty()) {
delete(s.stateObjects, obj.address) delete(s.stateObjects, obj.address)
s.markDelete(addr) s.markDelete(addr)
// If ether was sent to account post-selfdestruct it is burnt.
if bal := obj.Balance(); s.logger != nil && s.logger.OnBalanceChange != nil && obj.selfDestructed && bal.Sign() != 0 {
s.logger.OnBalanceChange(obj.address, bal.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestructBurn)
}
// We need to maintain account deletions explicitly (will remain // We need to maintain account deletions explicitly (will remain
// set indefinitely). Note only the first occurred self-destruct // set indefinitely). Note only the first occurred self-destruct
// event is tracked. // event is tracked.

View file

@ -0,0 +1,242 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package state
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/stateless"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/trie/utils"
"github.com/holiman/uint256"
)
// hookedStateDB represents a statedb which emits calls to tracing-hooks
// on state operations.
type hookedStateDB struct {
inner *StateDB
hooks *tracing.Hooks
}
// NewHookedState wraps the given stateDb with the given hooks
func NewHookedState(stateDb *StateDB, hooks *tracing.Hooks) *hookedStateDB {
s := &hookedStateDB{stateDb, hooks}
if s.hooks == nil {
s.hooks = new(tracing.Hooks)
}
return s
}
func (s *hookedStateDB) CreateAccount(addr common.Address) {
s.inner.CreateAccount(addr)
}
func (s *hookedStateDB) CreateContract(addr common.Address) {
s.inner.CreateContract(addr)
}
func (s *hookedStateDB) GetBalance(addr common.Address) *uint256.Int {
return s.inner.GetBalance(addr)
}
func (s *hookedStateDB) GetNonce(addr common.Address) uint64 {
return s.inner.GetNonce(addr)
}
func (s *hookedStateDB) GetCodeHash(addr common.Address) common.Hash {
return s.inner.GetCodeHash(addr)
}
func (s *hookedStateDB) GetCode(addr common.Address) []byte {
return s.inner.GetCode(addr)
}
func (s *hookedStateDB) GetCodeSize(addr common.Address) int {
return s.inner.GetCodeSize(addr)
}
func (s *hookedStateDB) AddRefund(u uint64) {
s.inner.AddRefund(u)
}
func (s *hookedStateDB) SubRefund(u uint64) {
s.inner.SubRefund(u)
}
func (s *hookedStateDB) GetRefund() uint64 {
return s.inner.GetRefund()
}
func (s *hookedStateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
return s.inner.GetCommittedState(addr, hash)
}
func (s *hookedStateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
return s.inner.GetState(addr, hash)
}
func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash {
return s.inner.GetStorageRoot(addr)
}
func (s *hookedStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash {
return s.inner.GetTransientState(addr, key)
}
func (s *hookedStateDB) SetTransientState(addr common.Address, key, value common.Hash) {
s.inner.SetTransientState(addr, key, value)
}
func (s *hookedStateDB) HasSelfDestructed(addr common.Address) bool {
return s.inner.HasSelfDestructed(addr)
}
func (s *hookedStateDB) Exist(addr common.Address) bool {
return s.inner.Exist(addr)
}
func (s *hookedStateDB) Empty(addr common.Address) bool {
return s.inner.Empty(addr)
}
func (s *hookedStateDB) AddressInAccessList(addr common.Address) bool {
return s.inner.AddressInAccessList(addr)
}
func (s *hookedStateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk bool, slotOk bool) {
return s.inner.SlotInAccessList(addr, slot)
}
func (s *hookedStateDB) AddAddressToAccessList(addr common.Address) {
s.inner.AddAddressToAccessList(addr)
}
func (s *hookedStateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
s.inner.AddSlotToAccessList(addr, slot)
}
func (s *hookedStateDB) PointCache() *utils.PointCache {
return s.inner.PointCache()
}
func (s *hookedStateDB) Prepare(rules params.Rules, sender, coinbase common.Address, dest *common.Address, precompiles []common.Address, txAccesses types.AccessList) {
s.inner.Prepare(rules, sender, coinbase, dest, precompiles, txAccesses)
}
func (s *hookedStateDB) RevertToSnapshot(i int) {
s.inner.RevertToSnapshot(i)
}
func (s *hookedStateDB) Snapshot() int {
return s.inner.Snapshot()
}
func (s *hookedStateDB) AddPreimage(hash common.Hash, bytes []byte) {
s.inner.Snapshot()
}
func (s *hookedStateDB) Witness() *stateless.Witness {
return s.inner.Witness()
}
func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
prev := s.inner.SubBalance(addr, amount, reason)
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
newBalance := new(uint256.Int).Sub(&prev, amount)
s.hooks.OnBalanceChange(addr, prev.ToBig(), newBalance.ToBig(), reason)
}
return prev
}
func (s *hookedStateDB) AddBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
prev := s.inner.AddBalance(addr, amount, reason)
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
newBalance := new(uint256.Int).Add(&prev, amount)
s.hooks.OnBalanceChange(addr, prev.ToBig(), newBalance.ToBig(), reason)
}
return prev
}
func (s *hookedStateDB) SetNonce(address common.Address, nonce uint64) {
s.inner.SetNonce(address, nonce)
if s.hooks.OnNonceChange != nil {
s.hooks.OnNonceChange(address, nonce-1, nonce)
}
}
func (s *hookedStateDB) SetCode(address common.Address, code []byte) {
s.inner.SetCode(address, code)
if s.hooks.OnCodeChange != nil {
s.hooks.OnCodeChange(address, types.EmptyCodeHash, nil, crypto.Keccak256Hash(code), code)
}
}
func (s *hookedStateDB) SetState(address common.Address, key common.Hash, value common.Hash) common.Hash {
prev := s.inner.SetState(address, key, value)
if s.hooks.OnStorageChange != nil && prev != value {
s.hooks.OnStorageChange(address, key, prev, value)
}
return prev
}
func (s *hookedStateDB) SelfDestruct(address common.Address) uint256.Int {
prev := s.inner.SelfDestruct(address)
if !prev.IsZero() {
if s.hooks.OnBalanceChange != nil {
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
}
}
return prev
}
func (s *hookedStateDB) SelfDestruct6780(address common.Address) (uint256.Int, bool) {
prev, changed := s.inner.SelfDestruct6780(address)
if !prev.IsZero() && changed {
if s.hooks.OnBalanceChange != nil {
s.hooks.OnBalanceChange(address, prev.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestruct)
}
}
return prev, changed
}
func (s *hookedStateDB) AddLog(log *types.Log) {
// The inner will modify the log (add fields), so invoke that first
s.inner.AddLog(log)
if s.hooks.OnLog != nil {
s.hooks.OnLog(log)
}
}
func (s *hookedStateDB) Finalise(deleteEmptyObjects bool) {
defer s.inner.Finalise(deleteEmptyObjects)
if s.hooks.OnBalanceChange == nil {
return
}
for addr := range s.inner.journal.dirties {
obj := s.inner.stateObjects[addr]
if obj != nil && obj.selfDestructed {
// If ether was sent to account post-selfdestruct it is burnt.
if bal := obj.Balance(); bal.Sign() != 0 {
s.hooks.OnBalanceChange(addr, bal.ToBig(), new(big.Int), tracing.BalanceDecreaseSelfdestructBurn)
}
}
}
}

View file

@ -0,0 +1,130 @@
// Copyright 2024 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package state
import (
"fmt"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types"
"github.com/holiman/uint256"
)
// This method tests that the 'burn' from sending-to-selfdestructed accounts
// is accounted for.
// (There is also a higher-level test in eth/tracers: TestSupplySelfDestruct )
func TestBurn(t *testing.T) {
// Note: burn can happen even after EIP-6780, if within one single transaction,
// the following occur:
// 1. contract B creates contract A
// 2. contract A is destructed
// 3. constract B sends ether to A
var burned = new(uint256.Int)
s, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
hooked := NewHookedState(s, &tracing.Hooks{
OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
if reason == tracing.BalanceDecreaseSelfdestructBurn {
burned.Add(burned, uint256.MustFromBig(prev))
}
},
})
createAndDestroy := func(addr common.Address) {
hooked.AddBalance(addr, uint256.NewInt(100), tracing.BalanceChangeUnspecified)
hooked.CreateContract(addr)
hooked.SelfDestruct(addr)
// sanity-check that balance is now 0
if have, want := hooked.GetBalance(addr), new(uint256.Int); !have.Eq(want) {
t.Fatalf("post-destruct balance wrong: have %v want %v", have, want)
}
}
addA := common.Address{0xaa}
addB := common.Address{0xbb}
addC := common.Address{0xcc}
// Tx 1: create and destroy address A and B in one tx
createAndDestroy(addA)
createAndDestroy(addB)
hooked.AddBalance(addA, uint256.NewInt(200), tracing.BalanceChangeUnspecified)
hooked.AddBalance(addB, uint256.NewInt(200), tracing.BalanceChangeUnspecified)
hooked.Finalise(true)
// Tx 2: create and destroy address C, then commit
createAndDestroy(addC)
hooked.AddBalance(addC, uint256.NewInt(200), tracing.BalanceChangeUnspecified)
hooked.Finalise(true)
s.Commit(0, false)
if have, want := burned, uint256.NewInt(600); !have.Eq(want) {
t.Fatalf("burn-count wrong, have %v want %v", have, want)
}
}
// TestHooks is a basic sanity-check of all hooks
func TestHooks(t *testing.T) {
inner, _ := New(types.EmptyRootHash, NewDatabaseForTesting())
inner.SetTxContext(common.Hash{0x11}, 100) // For the log
var result []string
var wants = []string{
"0xaa00000000000000000000000000000000000000.balance: 0->100 (BalanceChangeUnspecified)",
"0xaa00000000000000000000000000000000000000.balance: 100->50 (BalanceChangeTransfer)",
"0xaa00000000000000000000000000000000000000.nonce: 1336->1337",
"0xaa00000000000000000000000000000000000000.code: (0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470) ->0x1325 (0xa12ae05590de0c93a00bc7ac773c2fdb621e44f814985e72194f921c0050f728)",
"0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000000 ->0x0000000000000000000000000000000000000000000000000000000000000011",
"0xaa00000000000000000000000000000000000000.storage slot 0x0000000000000000000000000000000000000000000000000000000000000001: 0x0000000000000000000000000000000000000000000000000000000000000011 ->0x0000000000000000000000000000000000000000000000000000000000000022",
"log 100",
}
emitF := func(format string, a ...any) {
result = append(result, fmt.Sprintf(format, a...))
}
sdb := NewHookedState(inner, &tracing.Hooks{
OnBalanceChange: func(addr common.Address, prev, new *big.Int, reason tracing.BalanceChangeReason) {
emitF("%v.balance: %v->%v (%v)", addr, prev, new, reason)
},
OnNonceChange: func(addr common.Address, prev, new uint64) {
emitF("%v.nonce: %v->%v", addr, prev, new)
},
OnCodeChange: func(addr common.Address, prevCodeHash common.Hash, prevCode []byte, codeHash common.Hash, code []byte) {
emitF("%v.code: %#x (%v) ->%#x (%v)", addr, prevCode, prevCodeHash, code, codeHash)
},
OnStorageChange: func(addr common.Address, slot common.Hash, prev, new common.Hash) {
emitF("%v.storage slot %v: %v ->%v", addr, slot, prev, new)
},
OnLog: func(log *types.Log) {
emitF("log %v", log.TxIndex)
},
})
sdb.AddBalance(common.Address{0xaa}, uint256.NewInt(100), tracing.BalanceChangeUnspecified)
sdb.SubBalance(common.Address{0xaa}, uint256.NewInt(50), tracing.BalanceChangeTransfer)
sdb.SetNonce(common.Address{0xaa}, 1337)
sdb.SetCode(common.Address{0xaa}, []byte{0x13, 37})
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x11"))
sdb.SetState(common.Address{0xaa}, common.HexToHash("0x01"), common.HexToHash("0x22"))
sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x01"))
sdb.SetTransientState(common.Address{0xaa}, common.HexToHash("0x02"), common.HexToHash("0x02"))
sdb.AddLog(&types.Log{
Address: common.Address{0xbb},
})
for i, want := range wants {
if have := result[i]; have != want {
t.Fatalf("error event %d, have\n%v\nwant%v\n", i, have, want)
}
}
}

View file

@ -170,7 +170,7 @@ func TestCopy(t *testing.T) {
for i := byte(0); i < 255; i++ { for i := byte(0); i < 255; i++ {
obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
obj.AddBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) obj.AddBalance(uint256.NewInt(uint64(i)))
orig.updateStateObject(obj) orig.updateStateObject(obj)
} }
orig.Finalise(false) orig.Finalise(false)
@ -187,9 +187,9 @@ func TestCopy(t *testing.T) {
copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i})) copyObj := copy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i})) ccopyObj := ccopy.getOrNewStateObject(common.BytesToAddress([]byte{i}))
origObj.AddBalance(uint256.NewInt(2*uint64(i)), tracing.BalanceChangeUnspecified) origObj.AddBalance(uint256.NewInt(2 * uint64(i)))
copyObj.AddBalance(uint256.NewInt(3*uint64(i)), tracing.BalanceChangeUnspecified) copyObj.AddBalance(uint256.NewInt(3 * uint64(i)))
ccopyObj.AddBalance(uint256.NewInt(4*uint64(i)), tracing.BalanceChangeUnspecified) ccopyObj.AddBalance(uint256.NewInt(4 * uint64(i)))
orig.updateStateObject(origObj) orig.updateStateObject(origObj)
copy.updateStateObject(copyObj) copy.updateStateObject(copyObj)
@ -236,7 +236,7 @@ func TestCopyWithDirtyJournal(t *testing.T) {
// Fill up the initial states // Fill up the initial states
for i := byte(0); i < 255; i++ { for i := byte(0); i < 255; i++ {
obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
obj.AddBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) obj.AddBalance(uint256.NewInt(uint64(i)))
obj.data.Root = common.HexToHash("0xdeadbeef") obj.data.Root = common.HexToHash("0xdeadbeef")
orig.updateStateObject(obj) orig.updateStateObject(obj)
} }
@ -246,7 +246,9 @@ func TestCopyWithDirtyJournal(t *testing.T) {
// modify all in memory without finalizing // modify all in memory without finalizing
for i := byte(0); i < 255; i++ { for i := byte(0); i < 255; i++ {
obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
obj.SubBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) amount := uint256.NewInt(uint64(i))
obj.SetBalance(new(uint256.Int).Sub(obj.Balance(), amount))
orig.updateStateObject(obj) orig.updateStateObject(obj)
} }
cpy := orig.Copy() cpy := orig.Copy()
@ -280,7 +282,7 @@ func TestCopyObjectState(t *testing.T) {
// Fill up the initial states // Fill up the initial states
for i := byte(0); i < 5; i++ { for i := byte(0); i < 5; i++ {
obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj := orig.getOrNewStateObject(common.BytesToAddress([]byte{i}))
obj.AddBalance(uint256.NewInt(uint64(i)), tracing.BalanceChangeUnspecified) obj.AddBalance(uint256.NewInt(uint64(i)))
obj.data.Root = common.HexToHash("0xdeadbeef") obj.data.Root = common.HexToHash("0xdeadbeef")
orig.updateStateObject(obj) orig.updateStateObject(obj)
} }

View file

@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/tracing"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
@ -62,7 +61,7 @@ func makeTestState(scheme string) (ethdb.Database, Database, *triedb.Database, c
obj := state.getOrNewStateObject(common.BytesToAddress([]byte{i})) obj := state.getOrNewStateObject(common.BytesToAddress([]byte{i}))
acc := &testAccount{address: common.BytesToAddress([]byte{i})} acc := &testAccount{address: common.BytesToAddress([]byte{i})}
obj.AddBalance(uint256.NewInt(uint64(11*i)), tracing.BalanceChangeUnspecified) obj.AddBalance(uint256.NewInt(uint64(11 * i)))
acc.balance = uint256.NewInt(uint64(11 * i)) acc.balance = uint256.NewInt(uint64(11 * i))
obj.SetNonce(uint64(42 * i)) obj.SetNonce(uint64(42 * i))

View file

@ -75,6 +75,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// Apply pre-execution system calls. // Apply pre-execution system calls.
context = NewEVMBlockContext(header, p.chain, nil) context = NewEVMBlockContext(header, p.chain, nil)
vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg) vmenv := vm.NewEVM(context, vm.TxContext{}, statedb, p.config, cfg)
if beaconRoot := block.BeaconRoot(); beaconRoot != nil { if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb) ProcessBeaconBlockRoot(*beaconRoot, vmenv, statedb)
@ -98,7 +99,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
receipts = append(receipts, receipt) receipts = append(receipts, receipt)
allLogs = append(allLogs, receipt.Logs...) allLogs = append(allLogs, receipt.Logs...)
} }
var tracingStateDB = vm.StateDB(statedb)
if hooks := cfg.Tracer; hooks != nil {
tracingStateDB = state.NewHookedState(statedb, hooks)
}
// Read requests if Prague is enabled. // Read requests if Prague is enabled.
var requests [][]byte var requests [][]byte
if p.config.IsPrague(block.Number(), block.Time()) { if p.config.IsPrague(block.Number(), block.Time()) {
@ -109,15 +113,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
} }
requests = append(requests, depositRequests) requests = append(requests, depositRequests)
// EIP-7002 withdrawals // EIP-7002 withdrawals
withdrawalRequests := ProcessWithdrawalQueue(vmenv, statedb) withdrawalRequests := ProcessWithdrawalQueue(vmenv, tracingStateDB)
requests = append(requests, withdrawalRequests) requests = append(requests, withdrawalRequests)
// EIP-7251 consolidations // EIP-7251 consolidations
consolidationRequests := ProcessConsolidationQueue(vmenv, statedb) consolidationRequests := ProcessConsolidationQueue(vmenv, tracingStateDB)
requests = append(requests, consolidationRequests) requests = append(requests, consolidationRequests)
} }
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards) // Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
p.chain.engine.Finalize(p.chain, header, statedb, block.Body()) p.chain.engine.Finalize(p.chain, header, tracingStateDB, block.Body())
return &ProcessResult{ return &ProcessResult{
Receipts: receipts, Receipts: receipts,
@ -131,17 +135,20 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
// and uses the input parameters for its environment similar to ApplyTransaction. However, // and uses the input parameters for its environment similar to ApplyTransaction. However,
// this method takes an already created EVM instance as input. // this method takes an already created EVM instance as input.
func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) { func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (receipt *types.Receipt, err error) {
if evm.Config.Tracer != nil && evm.Config.Tracer.OnTxStart != nil { var tracingStateDB = vm.StateDB(statedb)
evm.Config.Tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) if hooks := evm.Config.Tracer; hooks != nil {
if evm.Config.Tracer.OnTxEnd != nil { tracingStateDB = state.NewHookedState(statedb, hooks)
defer func() { if hooks.OnTxStart != nil {
evm.Config.Tracer.OnTxEnd(receipt, err) hooks.OnTxStart(evm.GetVMContext(), tx, msg.From)
}() }
if hooks.OnTxEnd != nil {
defer func() { hooks.OnTxEnd(receipt, err) }()
} }
} }
// Create a new context to be used in the EVM environment. // Create a new context to be used in the EVM environment.
txContext := NewEVMTxContext(msg) txContext := NewEVMTxContext(msg)
evm.Reset(txContext, statedb) evm.Reset(txContext, tracingStateDB)
// Apply the transaction to the current state (included in the env). // Apply the transaction to the current state (included in the env).
result, err := ApplyMessage(evm, msg, gp) result, err := ApplyMessage(evm, msg, gp)
@ -152,7 +159,7 @@ func ApplyTransactionWithEVM(msg *Message, config *params.ChainConfig, gp *GasPo
// Update the state with pending changes. // Update the state with pending changes.
var root []byte var root []byte
if config.IsByzantium(blockNumber) { if config.IsByzantium(blockNumber) {
statedb.Finalise(true) tracingStateDB.Finalise(true)
} else { } else {
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes() root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).Bytes()
} }
@ -217,7 +224,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root // ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
// contract. This method is exported to be used in tests. // contract. This method is exported to be used in tests.
func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb vm.StateDB) {
if tracer := vmenv.Config.Tracer; tracer != nil { if tracer := vmenv.Config.Tracer; tracer != nil {
if tracer.OnSystemCallStart != nil { if tracer.OnSystemCallStart != nil {
tracer.OnSystemCallStart() tracer.OnSystemCallStart()
@ -243,7 +250,7 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *stat
// ProcessParentBlockHash stores the parent block hash in the history storage contract // ProcessParentBlockHash stores the parent block hash in the history storage contract
// as per EIP-2935. // as per EIP-2935.
func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb *state.StateDB) { func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb vm.StateDB) {
if tracer := vmenv.Config.Tracer; tracer != nil { if tracer := vmenv.Config.Tracer; tracer != nil {
if tracer.OnSystemCallStart != nil { if tracer.OnSystemCallStart != nil {
tracer.OnSystemCallStart() tracer.OnSystemCallStart()
@ -269,17 +276,17 @@ func ProcessParentBlockHash(prevHash common.Hash, vmenv *vm.EVM, statedb *state.
// ProcessWithdrawalQueue calls the EIP-7002 withdrawal queue contract. // ProcessWithdrawalQueue calls the EIP-7002 withdrawal queue contract.
// It returns the opaque request data returned by the contract. // It returns the opaque request data returned by the contract.
func ProcessWithdrawalQueue(vmenv *vm.EVM, statedb *state.StateDB) []byte { func ProcessWithdrawalQueue(vmenv *vm.EVM, statedb vm.StateDB) []byte {
return processRequestsSystemCall(vmenv, statedb, 0x01, params.WithdrawalQueueAddress) return processRequestsSystemCall(vmenv, statedb, 0x01, params.WithdrawalQueueAddress)
} }
// ProcessConsolidationQueue calls the EIP-7251 consolidation queue contract. // ProcessConsolidationQueue calls the EIP-7251 consolidation queue contract.
// It returns the opaque request data returned by the contract. // It returns the opaque request data returned by the contract.
func ProcessConsolidationQueue(vmenv *vm.EVM, statedb *state.StateDB) []byte { func ProcessConsolidationQueue(vmenv *vm.EVM, statedb vm.StateDB) []byte {
return processRequestsSystemCall(vmenv, statedb, 0x02, params.ConsolidationQueueAddress) return processRequestsSystemCall(vmenv, statedb, 0x02, params.ConsolidationQueueAddress)
} }
func processRequestsSystemCall(vmenv *vm.EVM, statedb *state.StateDB, requestType byte, addr common.Address) []byte { func processRequestsSystemCall(vmenv *vm.EVM, statedb vm.StateDB, requestType byte, addr common.Address) []byte {
if tracer := vmenv.Config.Tracer; tracer != nil { if tracer := vmenv.Config.Tracer; tracer != nil {
if tracer.OnSystemCallStart != nil { if tracer.OnSystemCallStart != nil {
tracer.OnSystemCallStart() tracer.OnSystemCallStart()

View file

@ -51,23 +51,22 @@ func u64(val uint64) *uint64 { return &val }
func TestStateProcessorErrors(t *testing.T) { func TestStateProcessorErrors(t *testing.T) {
var ( var (
config = &params.ChainConfig{ config = &params.ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
Ethash: new(params.EthashConfig), Ethash: new(params.EthashConfig),
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, ShanghaiTime: new(uint64),
ShanghaiTime: new(uint64), CancunTime: new(uint64),
CancunTime: new(uint64),
} }
signer = types.LatestSigner(config) signer = types.LatestSigner(config)
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
@ -257,7 +256,7 @@ func TestStateProcessorErrors(t *testing.T) {
want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1, baseFee: 875000000", want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1, baseFee: 875000000",
}, },
} { } {
block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config, false)
_, err := blockchain.InsertChain(types.Blocks{block}) _, err := blockchain.InsertChain(types.Blocks{block})
if err == nil { if err == nil {
t.Fatal("block imported without errors") t.Fatal("block imported without errors")
@ -306,7 +305,7 @@ func TestStateProcessorErrors(t *testing.T) {
want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: transaction type not supported", want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: transaction type not supported",
}, },
} { } {
block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config) block := GenerateBadBlock(gspec.ToBlock(), ethash.NewFaker(), tt.txs, gspec.Config, true)
_, err := blockchain.InsertChain(types.Blocks{block}) _, err := blockchain.InsertChain(types.Blocks{block})
if err == nil { if err == nil {
t.Fatal("block imported without errors") t.Fatal("block imported without errors")
@ -345,7 +344,7 @@ func TestStateProcessorErrors(t *testing.T) {
want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1", want: "could not apply tx 0 [0x88626ac0d53cb65308f2416103c62bb1f18b805573d4f96a3640bbbfff13c14f]: sender not an eoa: address 0x71562b71999873DB5b286dF957af199Ec94617F7, codehash: 0x9280914443471259d4570a8661015ae4a5b80186dbc619658fb494bebc3da3d1",
}, },
} { } {
block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config) block := GenerateBadBlock(gspec.ToBlock(), beacon.New(ethash.NewFaker()), tt.txs, gspec.Config, false)
_, err := blockchain.InsertChain(types.Blocks{block}) _, err := blockchain.InsertChain(types.Blocks{block})
if err == nil { if err == nil {
t.Fatal("block imported without errors") t.Fatal("block imported without errors")
@ -361,9 +360,9 @@ func TestStateProcessorErrors(t *testing.T) {
// valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently // valid, and no proper post-state can be made. But from the perspective of the blockchain, the block is sufficiently
// valid to be considered for import: // valid to be considered for import:
// - valid pow (fake), ancestry, difficulty, gaslimit etc // - valid pow (fake), ancestry, difficulty, gaslimit etc
func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig) *types.Block { func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Transactions, config *params.ChainConfig, isPOW bool) *types.Block {
difficulty := big.NewInt(0) difficulty := big.NewInt(0)
if !config.TerminalTotalDifficultyPassed { if isPOW {
fakeChainReader := newChainMaker(nil, config, engine) fakeChainReader := newChainMaker(nil, config, engine)
difficulty = engine.CalcDifficulty(fakeChainReader, parent.Time()+10, &types.Header{ difficulty = engine.CalcDifficulty(fakeChainReader, parent.Time()+10, &types.Header{
Number: parent.Number(), Number: parent.Number(),
@ -441,25 +440,22 @@ var (
func TestProcessVerkle(t *testing.T) { func TestProcessVerkle(t *testing.T) {
var ( var (
config = &params.ChainConfig{ config = &params.ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
Ethash: new(params.EthashConfig), Ethash: new(params.EthashConfig),
ShanghaiTime: u64(0), ShanghaiTime: u64(0),
VerkleTime: u64(0), VerkleTime: u64(0),
TerminalTotalDifficulty: common.Big0, TerminalTotalDifficulty: common.Big0,
TerminalTotalDifficultyPassed: true,
// TODO uncomment when proof generation is merged
// ProofInBlocks: true,
} }
signer = types.LatestSigner(config) signer = types.LatestSigner(config)
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")

View file

@ -919,7 +919,7 @@ func opSelfdestruct6780(pc *uint64, interpreter *EVMInterpreter, scope *ScopeCon
balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address()) balance := interpreter.evm.StateDB.GetBalance(scope.Contract.Address())
interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct) interpreter.evm.StateDB.SubBalance(scope.Contract.Address(), balance, tracing.BalanceDecreaseSelfdestruct)
interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct) interpreter.evm.StateDB.AddBalance(beneficiary.Bytes20(), balance, tracing.BalanceIncreaseSelfdestruct)
interpreter.evm.StateDB.Selfdestruct6780(scope.Contract.Address()) interpreter.evm.StateDB.SelfDestruct6780(scope.Contract.Address())
if tracer := interpreter.evm.Config.Tracer; tracer != nil { if tracer := interpreter.evm.Config.Tracer; tracer != nil {
if tracer.OnEnter != nil { if tracer.OnEnter != nil {
tracer.OnEnter(interpreter.evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig()) tracer.OnEnter(interpreter.evm.depth, byte(SELFDESTRUCT), scope.Contract.Address(), beneficiary.Bytes20(), []byte{}, 0, balance.ToBig())

View file

@ -33,8 +33,8 @@ type StateDB interface {
CreateAccount(common.Address) CreateAccount(common.Address)
CreateContract(common.Address) CreateContract(common.Address)
SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) SubBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int
AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) AddBalance(common.Address, *uint256.Int, tracing.BalanceChangeReason) uint256.Int
GetBalance(common.Address) *uint256.Int GetBalance(common.Address) *uint256.Int
GetNonce(common.Address) uint64 GetNonce(common.Address) uint64
@ -51,16 +51,21 @@ type StateDB interface {
GetCommittedState(common.Address, common.Hash) common.Hash GetCommittedState(common.Address, common.Hash) common.Hash
GetState(common.Address, common.Hash) common.Hash GetState(common.Address, common.Hash) common.Hash
SetState(common.Address, common.Hash, common.Hash) SetState(common.Address, common.Hash, common.Hash) common.Hash
GetStorageRoot(addr common.Address) common.Hash GetStorageRoot(addr common.Address) common.Hash
GetTransientState(addr common.Address, key common.Hash) common.Hash GetTransientState(addr common.Address, key common.Hash) common.Hash
SetTransientState(addr common.Address, key, value common.Hash) SetTransientState(addr common.Address, key, value common.Hash)
SelfDestruct(common.Address) SelfDestruct(common.Address) uint256.Int
HasSelfDestructed(common.Address) bool HasSelfDestructed(common.Address) bool
Selfdestruct6780(common.Address) // SelfDestruct6780 is post-EIP6780 selfdestruct, which means that it's a
// send-all-to-beneficiary, unless the contract was created in this same
// transaction, in which case it will be destructed.
// This method returns the prior balance, along with a boolean which is
// true iff the object was indeed destructed.
SelfDestruct6780(common.Address) (uint256.Int, bool)
// Exist reports whether the given account exists in state. // Exist reports whether the given account exists in state.
// Notably this should also return true for self-destructed accounts. // Notably this should also return true for self-destructed accounts.
@ -90,6 +95,9 @@ type StateDB interface {
AddPreimage(common.Hash, []byte) AddPreimage(common.Hash, []byte)
Witness() *stateless.Witness Witness() *stateless.Witness
// Finalise must be invoked at the end of a transaction
Finalise(bool)
} }
// CallContext provides a basic interface for the EVM calling conventions. The EVM // CallContext provides a basic interface for the EVM calling conventions. The EVM

View file

@ -61,27 +61,26 @@ func setDefaults(cfg *Config) {
cancunTime = uint64(0) cancunTime = uint64(0)
) )
cfg.ChainConfig = &params.ChainConfig{ cfg.ChainConfig = &params.ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: new(big.Int), HomesteadBlock: new(big.Int),
DAOForkBlock: new(big.Int), DAOForkBlock: new(big.Int),
DAOForkSupport: false, DAOForkSupport: false,
EIP150Block: new(big.Int), EIP150Block: new(big.Int),
EIP155Block: new(big.Int), EIP155Block: new(big.Int),
EIP158Block: new(big.Int), EIP158Block: new(big.Int),
ByzantiumBlock: new(big.Int), ByzantiumBlock: new(big.Int),
ConstantinopleBlock: new(big.Int), ConstantinopleBlock: new(big.Int),
PetersburgBlock: new(big.Int), PetersburgBlock: new(big.Int),
IstanbulBlock: new(big.Int), IstanbulBlock: new(big.Int),
MuirGlacierBlock: new(big.Int), MuirGlacierBlock: new(big.Int),
BerlinBlock: new(big.Int), BerlinBlock: new(big.Int),
LondonBlock: new(big.Int), LondonBlock: new(big.Int),
ArrowGlacierBlock: nil, ArrowGlacierBlock: nil,
GrayGlacierBlock: nil, GrayGlacierBlock: nil,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, MergeNetsplitBlock: nil,
MergeNetsplitBlock: nil, ShanghaiTime: &shanghaiTime,
ShanghaiTime: &shanghaiTime, CancunTime: &cancunTime}
CancunTime: &cancunTime}
} }
if cfg.Difficulty == nil { if cfg.Difficulty == nil {
cfg.Difficulty = new(big.Int) cfg.Difficulty = new(big.Int)
@ -109,10 +108,7 @@ func setDefaults(cfg *Config) {
if cfg.BlobBaseFee == nil { if cfg.BlobBaseFee == nil {
cfg.BlobBaseFee = big.NewInt(params.BlobTxMinBlobGasprice) cfg.BlobBaseFee = big.NewInt(params.BlobTxMinBlobGasprice)
} }
// Merge indicators cfg.Random = &(common.Hash{})
if t := cfg.ChainConfig.ShanghaiTime; cfg.ChainConfig.TerminalTotalDifficultyPassed || (t != nil && *t == 0) {
cfg.Random = &(common.Hash{})
}
} }
// Execute executes the code using the input as call data during the execution. // Execute executes the code using the input as call data during the execution.

51
crypto/bn256/gnark/g1.go Normal file
View file

@ -0,0 +1,51 @@
package bn256
import (
"math/big"
"github.com/consensys/gnark-crypto/ecc/bn254"
)
// G1 is the affine representation of a G1 group element.
//
// Since this code is used for precompiles, using Jacobian
// points are not beneficial because there are no intermediate
// points to allow us to save on inversions.
//
// Note: We also use this struct so that we can conform to the existing API
// that the precompiles want.
type G1 struct {
inner bn254.G1Affine
}
// Add adds `a` and `b` together, storing the result in `g`
func (g *G1) Add(a, b *G1) {
g.inner.Add(&a.inner, &b.inner)
}
// ScalarMult computes the scalar multiplication between `a` and
// `scalar`, storing the result in `g`
func (g *G1) ScalarMult(a *G1, scalar *big.Int) {
g.inner.ScalarMultiplication(&a.inner, scalar)
}
// Unmarshal deserializes `buf` into `g`
//
// Note: whether the deserialization is of a compressed
// or an uncompressed point, is encoded in the bytes.
//
// For our purpose, the point will always be serialized
// as uncompressed, ie 64 bytes.
//
// This method also checks whether the point is on the
// curve and in the prime order subgroup.
func (g *G1) Unmarshal(buf []byte) (int, error) {
return g.inner.SetBytes(buf)
}
// Marshal serializes the point into a byte slice.
//
// Note: The point is serialized as uncompressed.
func (p *G1) Marshal() []byte {
return p.inner.Marshal()
}

38
crypto/bn256/gnark/g2.go Normal file
View file

@ -0,0 +1,38 @@
package bn256
import (
"github.com/consensys/gnark-crypto/ecc/bn254"
)
// G2 is the affine representation of a G2 group element.
//
// Since this code is used for precompiles, using Jacobian
// points are not beneficial because there are no intermediate
// points and G2 in particular is only used for the pairing input.
//
// Note: We also use this struct so that we can conform to the existing API
// that the precompiles want.
type G2 struct {
inner bn254.G2Affine
}
// Unmarshal deserializes `buf` into `g`
//
// Note: whether the deserialization is of a compressed
// or an uncompressed point, is encoded in the bytes.
//
// For our purpose, the point will always be serialized
// as uncompressed, ie 128 bytes.
//
// This method also checks whether the point is on the
// curve and in the prime order subgroup.
func (g *G2) Unmarshal(buf []byte) (int, error) {
return g.inner.SetBytes(buf)
}
// Marshal serializes the point into a byte slice.
//
// Note: The point is serialized as uncompressed.
func (g *G2) Marshal() []byte {
return g.inner.Marshal()
}

65
crypto/bn256/gnark/gt.go Normal file
View file

@ -0,0 +1,65 @@
package bn256
import (
"fmt"
"math/big"
"github.com/consensys/gnark-crypto/ecc/bn254"
)
// GT is the affine representation of a GT field element.
//
// Note: GT is not explicitly used in mainline code.
// It is needed for fuzzing.
type GT struct {
inner bn254.GT
}
// Pair compute the optimal Ate pairing between a G1 and
// G2 element.
//
// Note: This method is not explicitly used in mainline code.
// It is needed for fuzzing. It should also be noted,
// that the output of this function may not match other
func Pair(a_ *G1, b_ *G2) *GT {
a := a_.inner
b := b_.inner
pairingOutput, err := bn254.Pair([]bn254.G1Affine{a}, []bn254.G2Affine{b})
if err != nil {
// Since this method is only called during fuzzing, it is okay to panic here.
// We do not return an error to match the interface of the other bn256 libraries.
panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err))
}
return &GT{
inner: pairingOutput,
}
}
// Unmarshal deserializes `buf` into `g`
//
// Note: This method is not explicitly used in mainline code.
// It is needed for fuzzing.
func (g *GT) Unmarshal(buf []byte) error {
return g.inner.SetBytes(buf)
}
// Marshal serializes the point into a byte slice.
//
// Note: This method is not explicitly used in mainline code.
// It is needed for fuzzing.
func (g *GT) Marshal() []byte {
bytes := g.inner.Bytes()
return bytes[:]
}
// Exp raises `base` to the power of `exponent`
//
// Note: This method is not explicitly used in mainline code.
// It is needed for fuzzing.
func (g *GT) Exp(base GT, exponent *big.Int) *GT {
g.inner.Exp(base.inner, exponent)
return g
}

View file

@ -0,0 +1,73 @@
package bn256
import (
"github.com/consensys/gnark-crypto/ecc/bn254"
)
// Computes the following relation: ∏ᵢ e(Pᵢ, Qᵢ) =? 1
//
// To explain why gnark returns a (bool, error):
//
// - If the function `e` does not return a result then internally
// an error is returned.
// - If `e` returns a result, then error will be nil,
// but if this value is not `1` then the boolean value will be false
//
// We therefore check for an error, and return false if its non-nil and
// then return the value of the boolean if not.
func PairingCheck(a_ []*G1, b_ []*G2) bool {
a := getInnerG1s(a_)
b := getInnerG2s(b_)
// Assume that len(a) == len(b)
//
// The pairing function will return
// false, if this is not the case.
size := len(a)
// Check if input is empty -- gnark will
// return false on an empty input, however
// the ossified behavior is to return true
// on an empty input, so we add this if statement.
if size == 0 {
return true
}
ok, err := bn254.PairingCheck(a, b)
if err != nil {
return false
}
return ok
}
// getInnerG1s gets the inner gnark G1 elements.
//
// These methods are used for two reasons:
//
// - We use a new type `G1`, so we need to convert from
// []*G1 to []*bn254.G1Affine
// - The gnark API accepts slices of values and not slices of
// pointers to values, so we need to return []bn254.G1Affine
// instead of []*bn254.G1Affine.
func getInnerG1s(pointerSlice []*G1) []bn254.G1Affine {
gnarkValues := make([]bn254.G1Affine, 0, len(pointerSlice))
for _, ptr := range pointerSlice {
if ptr != nil {
gnarkValues = append(gnarkValues, ptr.inner)
}
}
return gnarkValues
}
// getInnerG2s gets the inner gnark G2 elements.
//
// The rationale for this method is the same as `getInnerG1s`.
func getInnerG2s(pointerSlice []*G2) []bn254.G2Affine {
gnarkValues := make([]bn254.G2Affine, 0, len(pointerSlice))
for _, ptr := range pointerSlice {
if ptr != nil {
gnarkValues = append(gnarkValues, ptr.inner)
}
}
return gnarkValues
}

View file

@ -66,7 +66,6 @@ func generateMergeChain(n int, merged bool) (*core.Genesis, []*types.Block) {
engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker())) engine := consensus.Engine(beaconConsensus.New(ethash.NewFaker()))
if merged { if merged {
config.TerminalTotalDifficulty = common.Big0 config.TerminalTotalDifficulty = common.Big0
config.TerminalTotalDifficultyPassed = true
engine = beaconConsensus.NewFaker() engine = beaconConsensus.NewFaker()
} }
genesis := &core.Genesis{ genesis := &core.Genesis{

View file

@ -18,7 +18,7 @@
package ethconfig package ethconfig
import ( import (
"errors" "fmt"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -162,10 +162,8 @@ type Config struct {
// Clique is allowed for now to live standalone, but ethash is forbidden and can // Clique is allowed for now to live standalone, but ethash is forbidden and can
// only exist on already merged networks. // only exist on already merged networks.
func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) { func CreateConsensusEngine(config *params.ChainConfig, db ethdb.Database) (consensus.Engine, error) {
// Geth v1.14.0 dropped support for non-merged networks in any consensus if config.TerminalTotalDifficulty == nil {
// mode. If such a network is requested, reject startup. return nil, fmt.Errorf("only PoS networks are supported, please transition old ones with Geth v1.13.x")
if !config.TerminalTotalDifficultyPassed {
return nil, errors.New("only PoS networks are supported, please transition old ones with Geth v1.13.x")
} }
// Wrap previously supported consensus engines into their post-merge counterpart // Wrap previously supported consensus engines into their post-merge counterpart
if config.Clique != nil { if config.Clique != nil {

View file

@ -75,27 +75,26 @@ func newTestBackendWithGenerator(blocks int, shanghai bool, generator func(int,
if shanghai { if shanghai {
config = &params.ChainConfig{ config = &params.ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: true, DAOForkSupport: true,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0),
ShanghaiTime: u64(0), ShanghaiTime: u64(0),
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, Ethash: new(params.EthashConfig),
Ethash: new(params.EthashConfig),
} }
engine = beacon.NewFaker() engine = beacon.NewFaker()
} }

View file

@ -1018,7 +1018,6 @@ func (api *API) traceTx(ctx context.Context, tx *types.Transaction, message *cor
} }
// The actual TxContext will be created as part of ApplyTransactionWithEVM. // The actual TxContext will be created as part of ApplyTransactionWithEVM.
vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true}) vmenv := vm.NewEVM(vmctx, vm.TxContext{GasPrice: message.GasPrice, BlobFeeCap: message.BlobGasFeeCap}, statedb, api.backend.ChainConfig(), vm.Config{Tracer: tracer.Hooks, NoBaseFee: true})
statedb.SetLogger(tracer.Hooks)
// Define a meaningful timeout of a single transaction trace // Define a meaningful timeout of a single transaction trace
if config.Timeout != nil { if config.Timeout != nil {

View file

@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"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/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@ -116,21 +117,23 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
var ( var (
signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time)) signer = types.MakeSigner(test.Genesis.Config, new(big.Int).SetUint64(uint64(test.Context.Number)), uint64(test.Context.Time))
context = test.Context.toBlockContext(test.Genesis) context = test.Context.toBlockContext(test.Genesis)
state = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme) st = tests.MakePreState(rawdb.NewMemoryDatabase(), test.Genesis.Alloc, false, rawdb.HashScheme)
) )
state.Close() st.Close()
tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config) tracer, err := tracers.DefaultDirectory.New(tracerName, new(tracers.Context), test.TracerConfig, test.Genesis.Config)
if err != nil { if err != nil {
t.Fatalf("failed to create call tracer: %v", err) t.Fatalf("failed to create call tracer: %v", err)
} }
logState := vm.StateDB(st.StateDB)
state.StateDB.SetLogger(tracer.Hooks) if tracer.Hooks != nil {
logState = state.NewHookedState(st.StateDB, tracer.Hooks)
}
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) t.Fatalf("failed to prepare transaction for tracing: %v", err)
} }
evm := vm.NewEVM(context, core.NewEVMTxContext(msg), state.StateDB, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks}) evm := vm.NewEVM(context, core.NewEVMTxContext(msg), logState, test.Genesis.Config, vm.Config{Tracer: tracer.Hooks})
tracer.OnTxStart(evm.GetVMContext(), tx, msg.From) tracer.OnTxStart(evm.GetVMContext(), tx, msg.From)
vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas())) vmRet, err := core.ApplyMessage(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
if err != nil { if err != nil {
@ -349,7 +352,7 @@ func TestInternals(t *testing.T) {
}, },
} { } {
t.Run(tc.name, func(t *testing.T) { t.Run(tc.name, func(t *testing.T) {
state := tests.MakePreState(rawdb.NewMemoryDatabase(), st := tests.MakePreState(rawdb.NewMemoryDatabase(),
types.GenesisAlloc{ types.GenesisAlloc{
to: types.Account{ to: types.Account{
Code: tc.code, Code: tc.code,
@ -358,8 +361,13 @@ func TestInternals(t *testing.T) {
Balance: big.NewInt(500000000000000), Balance: big.NewInt(500000000000000),
}, },
}, false, rawdb.HashScheme) }, false, rawdb.HashScheme)
defer state.Close() defer st.Close()
state.StateDB.SetLogger(tc.tracer.Hooks)
logState := vm.StateDB(st.StateDB)
if hooks := tc.tracer.Hooks; hooks != nil {
logState = state.NewHookedState(st.StateDB, hooks)
}
tx, err := types.SignNewTx(key, signer, &types.LegacyTx{ tx, err := types.SignNewTx(key, signer, &types.LegacyTx{
To: &to, To: &to,
Value: big.NewInt(0), Value: big.NewInt(0),
@ -373,7 +381,7 @@ func TestInternals(t *testing.T) {
Origin: origin, Origin: origin,
GasPrice: tx.GasPrice(), GasPrice: tx.GasPrice(),
} }
evm := vm.NewEVM(context, txContext, state.StateDB, config, vm.Config{Tracer: tc.tracer.Hooks}) evm := vm.NewEVM(context, txContext, logState, config, vm.Config{Tracer: tc.tracer.Hooks})
msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0)) msg, err := core.TransactionToMessage(tx, signer, big.NewInt(0))
if err != nil { if err != nil {
t.Fatalf("test %v: failed to create message: %v", tc.name, err) t.Fatalf("test %v: failed to create message: %v", tc.name, err)

View file

@ -94,7 +94,6 @@ func flatCallTracerTestRunner(tracerName string, filename string, dirPath string
return fmt.Errorf("failed to create call tracer: %v", err) return fmt.Errorf("failed to create call tracer: %v", err)
} }
state.StateDB.SetLogger(tracer.Hooks)
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil { if err != nil {
return fmt.Errorf("failed to prepare transaction for tracing: %v", err) return fmt.Errorf("failed to prepare transaction for tracing: %v", err)

View file

@ -102,7 +102,6 @@ func testPrestateDiffTracer(tracerName string, dirPath string, t *testing.T) {
t.Fatalf("failed to create call tracer: %v", err) t.Fatalf("failed to create call tracer: %v", err)
} }
state.StateDB.SetLogger(tracer.Hooks)
msg, err := core.TransactionToMessage(tx, signer, context.BaseFee) msg, err := core.TransactionToMessage(tx, signer, context.BaseFee)
if err != nil { if err != nil {
t.Fatalf("failed to prepare transaction for tracing: %v", err) t.Fatalf("failed to prepare transaction for tracing: %v", err)

View file

@ -597,6 +597,7 @@ func testSupplyTracer(t *testing.T, genesis *core.Genesis, gen func(*core.BlockG
} }
func compareAsJSON(t *testing.T, expected interface{}, actual interface{}) { func compareAsJSON(t *testing.T, expected interface{}, actual interface{}) {
t.Helper()
want, err := json.Marshal(expected) want, err := json.Marshal(expected)
if err != nil { if err != nil {
t.Fatalf("failed to marshal expected value to JSON: %v", err) t.Fatalf("failed to marshal expected value to JSON: %v", err)
@ -608,6 +609,6 @@ func compareAsJSON(t *testing.T, expected interface{}, actual interface{}) {
} }
if !bytes.Equal(want, have) { if !bytes.Equal(want, have) {
t.Fatalf("incorrect supply info: expected %s, got %s", string(want), string(have)) t.Fatalf("incorrect supply info:\nwant %s\nhave %s", string(want), string(have))
} }
} }

View file

@ -41,8 +41,7 @@
"grayGlacierBlock": 0, "grayGlacierBlock": 0,
"shanghaiTime": 0, "shanghaiTime": 0,
"cancunTime": 0, "cancunTime": 0,
"terminalTotalDifficulty": 0, "terminalTotalDifficulty": 0
"terminalTotalDifficultyPassed": true
} }
}, },
"context": { "context": {

View file

@ -61,7 +61,6 @@
"berlinBlock": 4460644, "berlinBlock": 4460644,
"londonBlock": 5062605, "londonBlock": 5062605,
"terminalTotalDifficulty": 10790000, "terminalTotalDifficulty": 10790000,
"terminalTotalDifficultyPassed": true,
"clique": { "clique": {
"period": 15, "period": 15,
"epoch": 30000 "epoch": 30000
@ -185,4 +184,4 @@
"type": "call" "type": "call"
} }
] ]
} }

View file

@ -59,7 +59,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -116,7 +116,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -60,7 +60,6 @@
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"shanghaiTime": 1681338455, "shanghaiTime": 1681338455,
"terminalTotalDifficulty": 7797655526461000, "terminalTotalDifficulty": 7797655526461000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },
@ -186,4 +185,4 @@
"value": "0x0", "value": "0x0",
"type": "CREATE" "type": "CREATE"
} }
} }

View file

@ -281,7 +281,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -149,7 +149,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -84,7 +84,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -45,7 +45,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -119,7 +119,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -57,7 +57,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -59,7 +59,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -41,8 +41,7 @@
"grayGlacierBlock": 0, "grayGlacierBlock": 0,
"shanghaiTime": 0, "shanghaiTime": 0,
"cancunTime": 0, "cancunTime": 0,
"terminalTotalDifficulty": 0, "terminalTotalDifficulty": 0
"terminalTotalDifficultyPassed": true
} }
}, },
"context": { "context": {

View file

@ -38,7 +38,6 @@
"grayGlacierBlock": 0, "grayGlacierBlock": 0,
"shanghaiTime": 0, "shanghaiTime": 0,
"terminalTotalDifficulty": 0, "terminalTotalDifficulty": 0,
"terminalTotalDifficultyPassed": true,
"isDev": true "isDev": true
} }
}, },
@ -59,4 +58,4 @@
"balance": "0x8ac7230489e80000" "balance": "0x8ac7230489e80000"
} }
} }
} }

View file

@ -49,7 +49,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -55,7 +55,6 @@
"londonBlock": 12965000, "londonBlock": 12965000,
"arrowGlacierBlock": 13773000, "arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000, "grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {} "ethash": {}
} }
}, },

View file

@ -47,6 +47,11 @@ func (c *callContext) toBlockContext(genesis *core.Genesis) vm.BlockContext {
if genesis.Config.IsLondon(context.BlockNumber) { if genesis.Config.IsLondon(context.BlockNumber) {
context.BaseFee = (*big.Int)(c.BaseFee) 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 { if genesis.ExcessBlobGas != nil && genesis.BlobGasUsed != nil {
excessBlobGas := eip4844.CalcExcessBlobGas(*genesis.ExcessBlobGas, *genesis.BlobGasUsed) excessBlobGas := eip4844.CalcExcessBlobGas(*genesis.ExcessBlobGas, *genesis.BlobGasUsed)
context.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas) context.BlobBaseFee = eip4844.CalcBlobFee(excessBlobGas)

View file

@ -49,9 +49,11 @@ type dummyStatedb struct {
state.StateDB state.StateDB
} }
func (*dummyStatedb) GetRefund() uint64 { return 1337 } func (*dummyStatedb) GetRefund() uint64 { return 1337 }
func (*dummyStatedb) GetState(_ common.Address, _ common.Hash) common.Hash { return common.Hash{} } func (*dummyStatedb) GetState(_ common.Address, _ common.Hash) common.Hash { return common.Hash{} }
func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) {} func (*dummyStatedb) SetState(_ common.Address, _ common.Hash, _ common.Hash) common.Hash {
return common.Hash{}
}
func TestStoreCapture(t *testing.T) { func TestStoreCapture(t *testing.T) {
var ( var (

View file

@ -21,6 +21,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io" "io"
"math"
"math/big" "math/big"
"net/http" "net/http"
"strings" "strings"
@ -459,13 +460,14 @@ func newGQLService(t *testing.T, stack *node.Node, shanghai bool, gspec *core.Ge
var engine consensus.Engine = ethash.NewFaker() var engine consensus.Engine = ethash.NewFaker()
if shanghai { if shanghai {
engine = beacon.NewFaker() engine = beacon.NewFaker()
chainCfg := gspec.Config gspec.Config.TerminalTotalDifficulty = common.Big0
chainCfg.TerminalTotalDifficultyPassed = true
chainCfg.TerminalTotalDifficulty = common.Big0
// GenerateChain will increment timestamps by 10. // GenerateChain will increment timestamps by 10.
// Shanghai upgrade at block 1. // Shanghai upgrade at block 1.
shanghaiTime := uint64(5) shanghaiTime := uint64(5)
chainCfg.ShanghaiTime = &shanghaiTime gspec.Config.ShanghaiTime = &shanghaiTime
} else {
// set an arbitrary large ttd as chains are required to be known to be merged
gspec.Config.TerminalTotalDifficulty = big.NewInt(math.MaxInt64)
} }
ethBackend, err := eth.New(stack, ethConf) ethBackend, err := eth.New(stack, ethConf)
if err != nil { if err != nil {

View file

@ -1209,11 +1209,16 @@ func applyMessage(ctx context.Context, b Backend, args TransactionArgs, state *s
if precompiles != nil { if precompiles != nil {
evm.SetPrecompiles(precompiles) evm.SetPrecompiles(precompiles)
} }
res, err := applyMessageWithEVM(ctx, evm, msg, timeout, gp)
return applyMessageWithEVM(ctx, evm, msg, state, timeout, gp) // If an internal state error occurred, let that have precedence. Otherwise,
// a "trie root missing" type of error will masquerade as e.g. "insufficient gas"
if err := state.Error(); err != nil {
return nil, err
}
return res, err
} }
func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, state *state.StateDB, timeout time.Duration, gp *core.GasPool) (*core.ExecutionResult, error) { func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, timeout time.Duration, gp *core.GasPool) (*core.ExecutionResult, error) {
// Wait for the context to be done and cancel the evm. Even if the // Wait for the context to be done and cancel the evm. Even if the
// EVM has finished, cancelling may be done (repeatedly) // EVM has finished, cancelling may be done (repeatedly)
go func() { go func() {
@ -1223,9 +1228,6 @@ func applyMessageWithEVM(ctx context.Context, evm *vm.EVM, msg *core.Message, st
// Execute the message. // Execute the message.
result, err := core.ApplyMessage(evm, msg, gp) result, err := core.ApplyMessage(evm, msg, gp)
if err := state.Error(); err != nil {
return nil, err
}
// If the timer caused an abort, return an appropriate error message // If the timer caused an abort, return an appropriate error message
if evm.Cancelled() { if evm.Cancelled() {

View file

@ -2192,6 +2192,7 @@ func TestSimulateV1(t *testing.T) {
t.Fatalf("failed to unmarshal result: %v", err) t.Fatalf("failed to unmarshal result: %v", err)
} }
if !reflect.DeepEqual(have, tc.want) { if !reflect.DeepEqual(have, tc.want) {
t.Log(string(resBytes))
t.Errorf("test %s, result mismatch, have\n%v\n, want\n%v\n", tc.name, have, tc.want) t.Errorf("test %s, result mismatch, have\n%v\n, want\n%v\n", tc.name, have, tc.want)
} }
}) })

View file

@ -187,7 +187,10 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
} }
evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, sim.state, sim.chainConfig, *vmConfig) evm = vm.NewEVM(blockContext, vm.TxContext{GasPrice: new(big.Int)}, sim.state, sim.chainConfig, *vmConfig)
) )
sim.state.SetLogger(tracer.Hooks()) var tracingStateDB = vm.StateDB(sim.state)
if hooks := tracer.Hooks(); hooks != nil {
tracingStateDB = state.NewHookedState(sim.state, hooks)
}
// It is possible to override precompiles with EVM bytecode, or // It is possible to override precompiles with EVM bytecode, or
// move them to another address. // move them to another address.
if precompiles != nil { if precompiles != nil {
@ -205,8 +208,8 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
tracer.reset(tx.Hash(), uint(i)) tracer.reset(tx.Hash(), uint(i))
// EoA check is always skipped, even in validation mode. // EoA check is always skipped, even in validation mode.
msg := call.ToMessage(header.BaseFee, !sim.validate, true) msg := call.ToMessage(header.BaseFee, !sim.validate, true)
evm.Reset(core.NewEVMTxContext(msg), sim.state) evm.Reset(core.NewEVMTxContext(msg), tracingStateDB)
result, err := applyMessageWithEVM(ctx, evm, msg, sim.state, timeout, sim.gp) result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp)
if err != nil { if err != nil {
txErr := txValidationError(err) txErr := txValidationError(err)
return nil, nil, txErr return nil, nil, txErr
@ -214,7 +217,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header,
// Update the state with pending changes. // Update the state with pending changes.
var root []byte var root []byte
if sim.chainConfig.IsByzantium(blockContext.BlockNumber) { if sim.chainConfig.IsByzantium(blockContext.BlockNumber) {
sim.state.Finalise(true) tracingStateDB.Finalise(true)
} else { } else {
root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes() root = sim.state.IntermediateRoot(sim.chainConfig.IsEIP158(blockContext.BlockNumber)).Bytes()
} }

View file

@ -18,6 +18,7 @@ package params
import ( import (
"fmt" "fmt"
"math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -38,249 +39,240 @@ var (
// MainnetChainConfig is the chain parameters to run a node on the main network. // MainnetChainConfig is the chain parameters to run a node on the main network.
MainnetChainConfig = &ChainConfig{ MainnetChainConfig = &ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(1_150_000), HomesteadBlock: big.NewInt(1_150_000),
DAOForkBlock: big.NewInt(1_920_000), DAOForkBlock: big.NewInt(1_920_000),
DAOForkSupport: true, DAOForkSupport: true,
EIP150Block: big.NewInt(2_463_000), EIP150Block: big.NewInt(2_463_000),
EIP155Block: big.NewInt(2_675_000), EIP155Block: big.NewInt(2_675_000),
EIP158Block: big.NewInt(2_675_000), EIP158Block: big.NewInt(2_675_000),
ByzantiumBlock: big.NewInt(4_370_000), ByzantiumBlock: big.NewInt(4_370_000),
ConstantinopleBlock: big.NewInt(7_280_000), ConstantinopleBlock: big.NewInt(7_280_000),
PetersburgBlock: big.NewInt(7_280_000), PetersburgBlock: big.NewInt(7_280_000),
IstanbulBlock: big.NewInt(9_069_000), IstanbulBlock: big.NewInt(9_069_000),
MuirGlacierBlock: big.NewInt(9_200_000), MuirGlacierBlock: big.NewInt(9_200_000),
BerlinBlock: big.NewInt(12_244_000), BerlinBlock: big.NewInt(12_244_000),
LondonBlock: big.NewInt(12_965_000), LondonBlock: big.NewInt(12_965_000),
ArrowGlacierBlock: big.NewInt(13_773_000), ArrowGlacierBlock: big.NewInt(13_773_000),
GrayGlacierBlock: big.NewInt(15_050_000), GrayGlacierBlock: big.NewInt(15_050_000),
TerminalTotalDifficulty: MainnetTerminalTotalDifficulty, // 58_750_000_000_000_000_000_000 TerminalTotalDifficulty: MainnetTerminalTotalDifficulty, // 58_750_000_000_000_000_000_000
TerminalTotalDifficultyPassed: true, ShanghaiTime: newUint64(1681338455),
ShanghaiTime: newUint64(1681338455), CancunTime: newUint64(1710338135),
CancunTime: newUint64(1710338135), DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"),
DepositContractAddress: common.HexToAddress("0x00000000219ab540356cbb839cbe05303d7705fa"), Ethash: new(EthashConfig),
Ethash: new(EthashConfig),
} }
// HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network. // HoleskyChainConfig contains the chain parameters to run a node on the Holesky test network.
HoleskyChainConfig = &ChainConfig{ HoleskyChainConfig = &ChainConfig{
ChainID: big.NewInt(17000), ChainID: big.NewInt(17000),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: true, DAOForkSupport: true,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: nil, MuirGlacierBlock: nil,
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: nil, ArrowGlacierBlock: nil,
GrayGlacierBlock: nil, GrayGlacierBlock: nil,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, MergeNetsplitBlock: nil,
MergeNetsplitBlock: nil, ShanghaiTime: newUint64(1696000704),
ShanghaiTime: newUint64(1696000704), CancunTime: newUint64(1707305664),
CancunTime: newUint64(1707305664), Ethash: new(EthashConfig),
Ethash: new(EthashConfig),
} }
// SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network. // SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
SepoliaChainConfig = &ChainConfig{ SepoliaChainConfig = &ChainConfig{
ChainID: big.NewInt(11155111), ChainID: big.NewInt(11155111),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: true, DAOForkSupport: true,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: nil, ArrowGlacierBlock: nil,
GrayGlacierBlock: nil, GrayGlacierBlock: nil,
TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000), TerminalTotalDifficulty: big.NewInt(17_000_000_000_000_000),
TerminalTotalDifficultyPassed: true, MergeNetsplitBlock: big.NewInt(1735371),
MergeNetsplitBlock: big.NewInt(1735371), ShanghaiTime: newUint64(1677557088),
ShanghaiTime: newUint64(1677557088), CancunTime: newUint64(1706655072),
CancunTime: newUint64(1706655072), Ethash: new(EthashConfig),
Ethash: new(EthashConfig),
} }
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced // AllEthashProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Ethash consensus. // and accepted by the Ethereum core developers into the Ethash consensus.
AllEthashProtocolChanges = &ChainConfig{ AllEthashProtocolChanges = &ChainConfig{
ChainID: big.NewInt(1337), ChainID: big.NewInt(1337),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: false, DAOForkSupport: false,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: nil, TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
ShanghaiTime: nil, MergeNetsplitBlock: nil,
CancunTime: nil, ShanghaiTime: nil,
PragueTime: nil, CancunTime: nil,
VerkleTime: nil, PragueTime: nil,
TerminalTotalDifficulty: nil, VerkleTime: nil,
TerminalTotalDifficultyPassed: true, Ethash: new(EthashConfig),
Ethash: new(EthashConfig), Clique: nil,
Clique: nil,
} }
AllDevChainProtocolChanges = &ChainConfig{ AllDevChainProtocolChanges = &ChainConfig{
ChainID: big.NewInt(1337), ChainID: big.NewInt(1337),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
ShanghaiTime: newUint64(0), ShanghaiTime: newUint64(0),
CancunTime: newUint64(0), CancunTime: newUint64(0),
PragueTime: newUint64(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0), PragueTime: newUint64(0),
TerminalTotalDifficultyPassed: true,
} }
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus. // and accepted by the Ethereum core developers into the Clique consensus.
AllCliqueProtocolChanges = &ChainConfig{ AllCliqueProtocolChanges = &ChainConfig{
ChainID: big.NewInt(1337), ChainID: big.NewInt(1337),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: false, DAOForkSupport: false,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: nil, ArrowGlacierBlock: nil,
GrayGlacierBlock: nil, GrayGlacierBlock: nil,
MergeNetsplitBlock: nil, MergeNetsplitBlock: nil,
ShanghaiTime: nil, ShanghaiTime: nil,
CancunTime: nil, CancunTime: nil,
PragueTime: nil, PragueTime: nil,
VerkleTime: nil, VerkleTime: nil,
TerminalTotalDifficulty: nil, TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
TerminalTotalDifficultyPassed: false, Ethash: nil,
Ethash: nil, Clique: &CliqueConfig{Period: 0, Epoch: 30000},
Clique: &CliqueConfig{Period: 0, Epoch: 30000},
} }
// TestChainConfig contains every protocol change (EIPs) introduced // TestChainConfig contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers for testing purposes. // and accepted by the Ethereum core developers for testing purposes.
TestChainConfig = &ChainConfig{ TestChainConfig = &ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: false, DAOForkSupport: false,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: nil, MergeNetsplitBlock: nil,
ShanghaiTime: nil, ShanghaiTime: nil,
CancunTime: nil, CancunTime: nil,
PragueTime: nil, PragueTime: nil,
VerkleTime: nil, VerkleTime: nil,
TerminalTotalDifficulty: nil, TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
TerminalTotalDifficultyPassed: false, Ethash: new(EthashConfig),
Ethash: new(EthashConfig), Clique: nil,
Clique: nil,
} }
// MergedTestChainConfig contains every protocol change (EIPs) introduced // MergedTestChainConfig contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers for testing purposes. // and accepted by the Ethereum core developers for testing purposes.
MergedTestChainConfig = &ChainConfig{ MergedTestChainConfig = &ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: false, DAOForkSupport: false,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0), EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0), EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0), ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0), ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0), IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0), MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0), BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0), LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0), ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0), GrayGlacierBlock: big.NewInt(0),
MergeNetsplitBlock: big.NewInt(0), MergeNetsplitBlock: big.NewInt(0),
ShanghaiTime: newUint64(0), ShanghaiTime: newUint64(0),
CancunTime: newUint64(0), CancunTime: newUint64(0),
PragueTime: newUint64(0), PragueTime: newUint64(0),
VerkleTime: nil, VerkleTime: nil,
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, Ethash: new(EthashConfig),
Ethash: new(EthashConfig), Clique: nil,
Clique: nil,
} }
// NonActivatedConfig defines the chain configuration without activating // NonActivatedConfig defines the chain configuration without activating
// any protocol change (EIPs). // any protocol change (EIPs).
NonActivatedConfig = &ChainConfig{ NonActivatedConfig = &ChainConfig{
ChainID: big.NewInt(1), ChainID: big.NewInt(1),
HomesteadBlock: nil, HomesteadBlock: nil,
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: false, DAOForkSupport: false,
EIP150Block: nil, EIP150Block: nil,
EIP155Block: nil, EIP155Block: nil,
EIP158Block: nil, EIP158Block: nil,
ByzantiumBlock: nil, ByzantiumBlock: nil,
ConstantinopleBlock: nil, ConstantinopleBlock: nil,
PetersburgBlock: nil, PetersburgBlock: nil,
IstanbulBlock: nil, IstanbulBlock: nil,
MuirGlacierBlock: nil, MuirGlacierBlock: nil,
BerlinBlock: nil, BerlinBlock: nil,
LondonBlock: nil, LondonBlock: nil,
ArrowGlacierBlock: nil, ArrowGlacierBlock: nil,
GrayGlacierBlock: nil, GrayGlacierBlock: nil,
MergeNetsplitBlock: nil, MergeNetsplitBlock: nil,
ShanghaiTime: nil, ShanghaiTime: nil,
CancunTime: nil, CancunTime: nil,
PragueTime: nil, PragueTime: nil,
VerkleTime: nil, VerkleTime: nil,
TerminalTotalDifficulty: nil, TerminalTotalDifficulty: big.NewInt(math.MaxInt64),
TerminalTotalDifficultyPassed: false, Ethash: new(EthashConfig),
Ethash: new(EthashConfig), Clique: nil,
Clique: nil,
} }
TestRules = TestChainConfig.Rules(new(big.Int), false, 0) TestRules = TestChainConfig.Rules(new(big.Int), false, 0)
) )
@ -332,13 +324,6 @@ type ChainConfig struct {
// the network that triggers the consensus upgrade. // the network that triggers the consensus upgrade.
TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"` TerminalTotalDifficulty *big.Int `json:"terminalTotalDifficulty,omitempty"`
// TerminalTotalDifficultyPassed is a flag specifying that the network already
// passed the terminal total difficulty. Its purpose is to disable legacy sync
// even without having seen the TTD locally (safer long term).
//
// TODO(karalabe): Drop this field eventually (always assuming PoS mode)
TerminalTotalDifficultyPassed bool `json:"terminalTotalDifficultyPassed,omitempty"`
DepositContractAddress common.Address `json:"depositContractAddress,omitempty"` DepositContractAddress common.Address `json:"depositContractAddress,omitempty"`
// Various consensus engines // Various consensus engines
@ -377,21 +362,9 @@ func (c *ChainConfig) Description() string {
banner += fmt.Sprintf("Chain ID: %v (%s)\n", c.ChainID, network) banner += fmt.Sprintf("Chain ID: %v (%s)\n", c.ChainID, network)
switch { switch {
case c.Ethash != nil: case c.Ethash != nil:
if c.TerminalTotalDifficulty == nil { banner += "Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work)\n"
banner += "Consensus: Ethash (proof-of-work)\n"
} else if !c.TerminalTotalDifficultyPassed {
banner += "Consensus: Beacon (proof-of-stake), merging from Ethash (proof-of-work)\n"
} else {
banner += "Consensus: Beacon (proof-of-stake), merged from Ethash (proof-of-work)\n"
}
case c.Clique != nil: case c.Clique != nil:
if c.TerminalTotalDifficulty == nil { banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n"
banner += "Consensus: Clique (proof-of-authority)\n"
} else if !c.TerminalTotalDifficultyPassed {
banner += "Consensus: Beacon (proof-of-stake), merging from Clique (proof-of-authority)\n"
} else {
banner += "Consensus: Beacon (proof-of-stake), merged from Clique (proof-of-authority)\n"
}
default: default:
banner += "Consensus: unknown\n" banner += "Consensus: unknown\n"
} }
@ -426,17 +399,12 @@ func (c *ChainConfig) Description() string {
banner += "\n" banner += "\n"
// Add a special section for the merge as it's non-obvious // Add a special section for the merge as it's non-obvious
if c.TerminalTotalDifficulty == nil { banner += "Merge configured:\n"
banner += "The Merge is not yet available for this network!\n" banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n"
banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n" banner += " - Network known to be merged\n"
} else { banner += fmt.Sprintf(" - Total terminal difficulty: %v\n", c.TerminalTotalDifficulty)
banner += "Merge configured:\n" if c.MergeNetsplitBlock != nil {
banner += " - Hard-fork specification: https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md\n" banner += fmt.Sprintf(" - Merge netsplit block: #%-8v\n", c.MergeNetsplitBlock)
banner += fmt.Sprintf(" - Network known to be merged: %v\n", c.TerminalTotalDifficultyPassed)
banner += fmt.Sprintf(" - Total terminal difficulty: %v\n", c.TerminalTotalDifficulty)
if c.MergeNetsplitBlock != nil {
banner += fmt.Sprintf(" - Merge netsplit block: #%-8v\n", c.MergeNetsplitBlock)
}
} }
banner += "\n" banner += "\n"

View file

@ -22,6 +22,7 @@ import (
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
stdmath "math"
"math/big" "math/big"
"os" "os"
"reflect" "reflect"
@ -129,6 +130,11 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t
} }
// Commit genesis state // Commit genesis state
gspec := t.genesis(config) gspec := t.genesis(config)
// if ttd is not specified, set an arbitrary huge value
if gspec.Config.TerminalTotalDifficulty == nil {
gspec.Config.TerminalTotalDifficulty = big.NewInt(stdmath.MaxInt64)
}
triedb := triedb.NewDatabase(db, tconf) triedb := triedb.NewDatabase(db, tconf)
gblock, err := gspec.Commit(db, triedb) gblock, err := gspec.Commit(db, triedb)
if err != nil { if err != nil {

View file

@ -36,22 +36,21 @@ var (
} }
ropstenChainConfig = params.ChainConfig{ ropstenChainConfig = params.ChainConfig{
ChainID: big.NewInt(3), ChainID: big.NewInt(3),
HomesteadBlock: big.NewInt(0), HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil, DAOForkBlock: nil,
DAOForkSupport: true, DAOForkSupport: true,
EIP150Block: big.NewInt(0), EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(10), EIP155Block: big.NewInt(10),
EIP158Block: big.NewInt(10), EIP158Block: big.NewInt(10),
ByzantiumBlock: big.NewInt(1_700_000), ByzantiumBlock: big.NewInt(1_700_000),
ConstantinopleBlock: big.NewInt(4_230_000), ConstantinopleBlock: big.NewInt(4_230_000),
PetersburgBlock: big.NewInt(4_939_394), PetersburgBlock: big.NewInt(4_939_394),
IstanbulBlock: big.NewInt(6_485_846), IstanbulBlock: big.NewInt(6_485_846),
MuirGlacierBlock: big.NewInt(7_117_117), MuirGlacierBlock: big.NewInt(7_117_117),
BerlinBlock: big.NewInt(9_812_189), BerlinBlock: big.NewInt(9_812_189),
LondonBlock: big.NewInt(10_499_401), LondonBlock: big.NewInt(10_499_401),
TerminalTotalDifficulty: new(big.Int).SetUint64(50_000_000_000_000_000), TerminalTotalDifficulty: new(big.Int).SetUint64(50_000_000_000_000_000),
TerminalTotalDifficultyPassed: true,
} }
) )

View file

@ -22,12 +22,12 @@ import (
"io" "io"
"math/big" "math/big"
"github.com/consensys/gnark-crypto/ecc/bn254"
cloudflare "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" cloudflare "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
gnark "github.com/ethereum/go-ethereum/crypto/bn256/gnark"
google "github.com/ethereum/go-ethereum/crypto/bn256/google" google "github.com/ethereum/go-ethereum/crypto/bn256/google"
) )
func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine) { func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *gnark.G1) {
_, xc, err := cloudflare.RandomG1(input) _, xc, err := cloudflare.RandomG1(input)
if err != nil { if err != nil {
// insufficient input // insufficient input
@ -37,14 +37,14 @@ func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine)
if _, err := xg.Unmarshal(xc.Marshal()); err != nil { if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err)) panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err))
} }
xs := new(bn254.G1Affine) xs := new(gnark.G1)
if err := xs.Unmarshal(xc.Marshal()); err != nil { if _, err := xs.Unmarshal(xc.Marshal()); err != nil {
panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err)) panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err))
} }
return xc, xg, xs return xc, xg, xs
} }
func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine) { func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *gnark.G2) {
_, xc, err := cloudflare.RandomG2(input) _, xc, err := cloudflare.RandomG2(input)
if err != nil { if err != nil {
// insufficient input // insufficient input
@ -54,14 +54,14 @@ func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine)
if _, err := xg.Unmarshal(xc.Marshal()); err != nil { if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err)) panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err))
} }
xs := new(bn254.G2Affine) xs := new(gnark.G2)
if err := xs.Unmarshal(xc.Marshal()); err != nil { if _, err := xs.Unmarshal(xc.Marshal()); err != nil {
panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err)) panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err))
} }
return xc, xg, xs return xc, xg, xs
} }
// fuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries. // fuzzAdd fuzzes bn256 addition between the Google, Cloudflare and Gnark libraries.
func fuzzAdd(data []byte) int { func fuzzAdd(data []byte) int {
input := bytes.NewReader(data) input := bytes.NewReader(data)
xc, xg, xs := getG1Points(input) xc, xg, xs := getG1Points(input)
@ -72,7 +72,7 @@ func fuzzAdd(data []byte) int {
if yc == nil { if yc == nil {
return 0 return 0
} }
// Ensure both libs can parse the second curve point // Ensure libs can parse the second curve point
// Add the two points and ensure they result in the same output // Add the two points and ensure they result in the same output
rc := new(cloudflare.G1) rc := new(cloudflare.G1)
rc.Add(xc, yc) rc.Add(xc, yc)
@ -80,9 +80,8 @@ func fuzzAdd(data []byte) int {
rg := new(google.G1) rg := new(google.G1)
rg.Add(xg, yg) rg.Add(xg, yg)
tmpX := new(bn254.G1Jac).FromAffine(xs) rs := new(gnark.G1)
tmpY := new(bn254.G1Jac).FromAffine(ys) rs.Add(xs, ys)
rs := new(bn254.G1Affine).FromJacobian(tmpX.AddAssign(tmpY))
if !bytes.Equal(rc.Marshal(), rg.Marshal()) { if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
panic("add mismatch: cloudflare/google") panic("add mismatch: cloudflare/google")
@ -94,8 +93,8 @@ func fuzzAdd(data []byte) int {
return 1 return 1
} }
// fuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare // fuzzMul fuzzes bn256 scalar multiplication between the Google, Cloudflare
// libraries. // and Gnark libraries.
func fuzzMul(data []byte) int { func fuzzMul(data []byte) int {
input := bytes.NewReader(data) input := bytes.NewReader(data)
pc, pg, ps := getG1Points(input) pc, pg, ps := getG1Points(input)
@ -122,15 +121,13 @@ func fuzzMul(data []byte) int {
rg := new(google.G1) rg := new(google.G1)
rg.ScalarMult(pg, new(big.Int).SetBytes(buf)) rg.ScalarMult(pg, new(big.Int).SetBytes(buf))
rs := new(bn254.G1Jac) rs := new(gnark.G1)
psJac := new(bn254.G1Jac).FromAffine(ps) rs.ScalarMult(ps, new(big.Int).SetBytes(buf))
rs.ScalarMultiplication(psJac, new(big.Int).SetBytes(buf))
rsAffine := new(bn254.G1Affine).FromJacobian(rs)
if !bytes.Equal(rc.Marshal(), rg.Marshal()) { if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
panic("scalar mul mismatch: cloudflare/google") panic("scalar mul mismatch: cloudflare/google")
} }
if !bytes.Equal(rc.Marshal(), rsAffine.Marshal()) { if !bytes.Equal(rc.Marshal(), rs.Marshal()) {
panic("scalar mul mismatch: cloudflare/gnark") panic("scalar mul mismatch: cloudflare/gnark")
} }
return 1 return 1
@ -150,17 +147,26 @@ func fuzzPair(data []byte) int {
// Pair the two points and ensure they result in the same output // Pair the two points and ensure they result in the same output
clPair := cloudflare.Pair(pc, tc).Marshal() clPair := cloudflare.Pair(pc, tc).Marshal()
gPair := google.Pair(pg, tg).Marshal() gPair := google.Pair(pg, tg).Marshal()
sPair := gnark.Pair(ps, ts).Marshal()
if !bytes.Equal(clPair, gPair) { if !bytes.Equal(clPair, gPair) {
panic("pairing mismatch: cloudflare/google") panic("pairing mismatch: cloudflare/google")
} }
cPair, err := bn254.Pair([]bn254.G1Affine{*ps}, []bn254.G2Affine{*ts})
if err != nil { normalizedClPair := normalizeGTToGnark(clPair).Marshal()
panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err)) if !bytes.Equal(normalizedClPair, sPair) {
panic("pairing mismatch: cloudflare/gnark")
} }
// gnark uses a different pairing algorithm which might produce return 1
// different but also correct outputs, we need to scale the output by s }
// normalizeGTToGnark scales a Cloudflare/Google GT element by `s`
// so that it can be compared with a gnark GT point.
//
// For the definition of `s` see 3.5 in https://eprint.iacr.org/2015/192.pdf
func normalizeGTToGnark(cloudflareOrGoogleGT []byte) *gnark.GT {
// Compute s = 2*u(6*u^2 + 3*u + 1)
u, _ := new(big.Int).SetString("0x44e992b44a6909f1", 0) u, _ := new(big.Int).SetString("0x44e992b44a6909f1", 0)
u_exp2 := new(big.Int).Exp(u, big.NewInt(2), nil) // u^2 u_exp2 := new(big.Int).Exp(u, big.NewInt(2), nil) // u^2
u_6_exp2 := new(big.Int).Mul(big.NewInt(6), u_exp2) // 6*u^2 u_6_exp2 := new(big.Int).Mul(big.NewInt(6), u_exp2) // 6*u^2
@ -170,14 +176,12 @@ func fuzzPair(data []byte) int {
u_2 := new(big.Int).Mul(big.NewInt(2), u) // 2*u u_2 := new(big.Int).Mul(big.NewInt(2), u) // 2*u
s := u_2.Mul(u_2, inner) // 2*u(6*u^2 + 3*u + 1) s := u_2.Mul(u_2, inner) // 2*u(6*u^2 + 3*u + 1)
gRes := new(bn254.GT) // Scale the Cloudflare/Google GT element by `s`
if err := gRes.SetBytes(clPair); err != nil { gRes := new(gnark.GT)
if err := gRes.Unmarshal(cloudflareOrGoogleGT); err != nil {
panic(err) panic(err)
} }
gRes = gRes.Exp(*gRes, s) gRes = gRes.Exp(*gRes, s)
if !bytes.Equal(cPair.Marshal(), gRes.Marshal()) {
panic("pairing mismatch: cloudflare/gnark")
}
return 1 return gRes
} }