core/{.,state,vm},miner,ethr/tracers: implement 7709
Co-authored-by: Ignacio Hagopian <jsign.uy@gmail.com>
This commit is contained in:
parent
4d94bd83b2
commit
90e5325183
|
@ -122,6 +122,11 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
// Merge the tx-local access event into the "block-local" one, in order to collect
|
||||||
|
// all values, so that the witness can be built.
|
||||||
|
if b.statedb.GetTrie().IsVerkle() {
|
||||||
|
b.statedb.AccessEvents().Merge(evm.AccessEvents)
|
||||||
|
}
|
||||||
b.txs = append(b.txs, tx)
|
b.txs = append(b.txs, tx)
|
||||||
b.receipts = append(b.receipts, receipt)
|
b.receipts = append(b.receipts, receipt)
|
||||||
if b.header.BlobGasUsed != nil {
|
if b.header.BlobGasUsed != nil {
|
||||||
|
@ -379,7 +384,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
|
||||||
misc.ApplyDAOHardFork(statedb)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.IsPrague(b.header.Number, b.header.Time) {
|
if config.IsPrague(b.header.Number, b.header.Time) || config.IsVerkle(b.header.Number, b.header.Time) {
|
||||||
// EIP-2935
|
// EIP-2935
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
||||||
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
||||||
|
@ -487,13 +492,11 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
// Save pre state for proof generation
|
// Save pre state for proof generation
|
||||||
// preState := statedb.Copy()
|
// preState := statedb.Copy()
|
||||||
|
|
||||||
// Pre-execution system calls.
|
// EIP-2935 / 7709
|
||||||
if config.IsPrague(b.header.Number, b.header.Time) {
|
|
||||||
// EIP-2935
|
|
||||||
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
|
||||||
|
blockContext.Random = &common.Hash{} // enable post-merge instruction set
|
||||||
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
|
||||||
ProcessParentBlockHash(b.header.ParentHash, evm)
|
ProcessParentBlockHash(b.header.ParentHash, evm)
|
||||||
}
|
|
||||||
|
|
||||||
// Execute any user modifications to the block.
|
// Execute any user modifications to the block.
|
||||||
if gen != nil {
|
if gen != nil {
|
||||||
|
@ -561,7 +564,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
|
||||||
return cm.chain, cm.receipts, proofs, keyvals
|
return cm.chain, cm.receipts, proofs, keyvals
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
|
func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n int, gen func(int, *BlockGen)) (common.Hash, ethdb.Database, []*types.Block, []types.Receipts, []*verkle.VerkleProof, []verkle.StateDiff) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
|
cacheConfig := DefaultCacheConfigWithScheme(rawdb.PathScheme)
|
||||||
cacheConfig.SnapshotLimit = 0
|
cacheConfig.SnapshotLimit = 0
|
||||||
|
@ -572,7 +575,7 @@ func GenerateVerkleChainWithGenesis(genesis *Genesis, engine consensus.Engine, n
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
blocks, receipts, proofs, keyvals := GenerateVerkleChain(genesis.Config, genesisBlock, engine, db, triedb, n, gen)
|
blocks, receipts, proofs, keyvals := GenerateVerkleChain(genesis.Config, genesisBlock, engine, db, triedb, n, gen)
|
||||||
return db, blocks, receipts, proofs, keyvals
|
return genesisBlock.Hash(), db, blocks, receipts, proofs, keyvals
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
|
func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engine consensus.Engine) *types.Header {
|
||||||
|
|
|
@ -157,6 +157,10 @@ func (s *hookedStateDB) Witness() *stateless.Witness {
|
||||||
return s.inner.Witness()
|
return s.inner.Witness()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *hookedStateDB) AccessEvents() *AccessEvents {
|
||||||
|
return s.inner.AccessEvents()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
|
func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
|
||||||
prev := s.inner.SubBalance(addr, amount, reason)
|
prev := s.inner.SubBalance(addr, amount, reason)
|
||||||
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
|
if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
|
||||||
|
|
|
@ -85,7 +85,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
||||||
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
if beaconRoot := block.BeaconRoot(); beaconRoot != nil {
|
||||||
ProcessBeaconBlockRoot(*beaconRoot, evm)
|
ProcessBeaconBlockRoot(*beaconRoot, evm)
|
||||||
}
|
}
|
||||||
if p.config.IsPrague(block.Number(), block.Time()) {
|
if p.config.IsPrague(block.Number(), block.Time()) || p.config.IsVerkle(block.Number(), block.Time()) {
|
||||||
ProcessParentBlockHash(block.ParentHash(), evm)
|
ProcessParentBlockHash(block.ParentHash(), evm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +155,12 @@ func ApplyTransactionWithEVM(msg *Message, gp *GasPool, statedb *state.StateDB,
|
||||||
}
|
}
|
||||||
*usedGas += result.UsedGas
|
*usedGas += result.UsedGas
|
||||||
|
|
||||||
|
// Merge the tx-local access event into the "block-local" one, in order to collect
|
||||||
|
// all values, so that the witness can be built.
|
||||||
|
if statedb.GetTrie().IsVerkle() {
|
||||||
|
statedb.AccessEvents().Merge(evm.AccessEvents)
|
||||||
|
}
|
||||||
|
|
||||||
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), nil
|
return MakeReceipt(evm, result, statedb, blockNumber, blockHash, tx, *usedGas, root), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,12 +187,6 @@ func MakeReceipt(evm *vm.EVM, result *ExecutionResult, statedb *state.StateDB, b
|
||||||
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
|
receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge the tx-local access event into the "block-local" one, in order to collect
|
|
||||||
// all values, so that the witness can be built.
|
|
||||||
if statedb.GetTrie().IsVerkle() {
|
|
||||||
statedb.AccessEvents().Merge(evm.AccessEvents)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the receipt logs and create the bloom filter.
|
// Set the receipt logs and create the bloom filter.
|
||||||
receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash)
|
receipt.Logs = statedb.GetLogs(tx.Hash(), blockNumber.Uint64(), blockHash)
|
||||||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
||||||
|
@ -229,12 +229,12 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
|
||||||
}
|
}
|
||||||
evm.SetTxContext(NewEVMTxContext(msg))
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress)
|
evm.StateDB.AddAddressToAccessList(params.BeaconRootsAddress)
|
||||||
_, _, _ = evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
_, _, _ = evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560, true)
|
||||||
evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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/7709.
|
||||||
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
|
func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
|
||||||
if tracer := evm.Config.Tracer; tracer != nil {
|
if tracer := evm.Config.Tracer; tracer != nil {
|
||||||
onSystemCallStart(tracer, evm.GetVMContext())
|
onSystemCallStart(tracer, evm.GetVMContext())
|
||||||
|
@ -253,7 +253,13 @@ func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
|
||||||
}
|
}
|
||||||
evm.SetTxContext(NewEVMTxContext(msg))
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
evm.StateDB.AddAddressToAccessList(params.HistoryStorageAddress)
|
evm.StateDB.AddAddressToAccessList(params.HistoryStorageAddress)
|
||||||
_, _, _ = evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
_, _, err := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560, true)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if evm.StateDB.AccessEvents() != nil {
|
||||||
|
evm.StateDB.AccessEvents().Merge(evm.AccessEvents)
|
||||||
|
}
|
||||||
evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +292,7 @@ func processRequestsSystemCall(requests *[][]byte, evm *vm.EVM, requestType byte
|
||||||
}
|
}
|
||||||
evm.SetTxContext(NewEVMTxContext(msg))
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
evm.StateDB.AddAddressToAccessList(addr)
|
evm.StateDB.AddAddressToAccessList(addr)
|
||||||
ret, _, _ := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560)
|
ret, _, _ := evm.Call(vm.AccountRef(msg.From), *msg.To, msg.Data, 30_000_000, common.U2560, true)
|
||||||
evm.StateDB.Finalise(true)
|
evm.StateDB.Finalise(true)
|
||||||
if len(ret) == 0 {
|
if len(ret) == 0 {
|
||||||
return // skip empty output
|
return // skip empty output
|
||||||
|
|
|
@ -484,7 +484,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the transaction's call.
|
// Execute the transaction's call.
|
||||||
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value)
|
ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
var gasRefund uint64
|
var gasRefund uint64
|
||||||
|
|
|
@ -152,7 +152,7 @@ func TestProcessVerkle(t *testing.T) {
|
||||||
txCost1*2 + txCost2,
|
txCost1*2 + txCost2,
|
||||||
txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas,
|
txCost1*2 + txCost2 + contractCreationCost + codeWithExtCodeCopyGas,
|
||||||
}
|
}
|
||||||
_, chain, _, proofs, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
_, _, chain, _, proofs, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
|
|
||||||
// TODO need to check that the tx cost provided is the exact amount used (no remaining left-over)
|
// TODO need to check that the tx cost provided is the exact amount used (no remaining left-over)
|
||||||
|
@ -219,7 +219,7 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
// block 1 parent hash is 0x0100....
|
// block 1 parent hash is 0x0100....
|
||||||
// block 2 parent hash is 0x0200....
|
// block 2 parent hash is 0x0200....
|
||||||
// etc
|
// etc
|
||||||
checkBlockHashes := func(statedb *state.StateDB) {
|
checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) {
|
||||||
statedb.SetNonce(params.HistoryStorageAddress, 1)
|
statedb.SetNonce(params.HistoryStorageAddress, 1)
|
||||||
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
|
statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
|
||||||
// Process n blocks, from 1 .. num
|
// Process n blocks, from 1 .. num
|
||||||
|
@ -227,20 +227,24 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
for i := 1; i <= num; i++ {
|
for i := 1; i <= num; i++ {
|
||||||
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
|
||||||
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
|
vmContext := NewEVMBlockContext(header, nil, new(common.Address))
|
||||||
evm := vm.NewEVM(vmContext, statedb, params.MergedTestChainConfig, vm.Config{})
|
chainConfig := params.MergedTestChainConfig
|
||||||
|
if isVerkle {
|
||||||
|
chainConfig = testVerkleChainConfig
|
||||||
|
}
|
||||||
|
evm := vm.NewEVM(vmContext, statedb, chainConfig, vm.Config{})
|
||||||
ProcessParentBlockHash(header.ParentHash, evm)
|
ProcessParentBlockHash(header.ParentHash, evm)
|
||||||
}
|
}
|
||||||
// Read block hashes for block 0 .. num-1
|
// Read block hashes for block 0 .. num-1
|
||||||
for i := 0; i < num; i++ {
|
for i := 0; i < num; i++ {
|
||||||
have, want := getContractStoredBlockHash(statedb, uint64(i)), common.Hash{byte(i + 1)}
|
have, want := getContractStoredBlockHash(statedb, uint64(i), isVerkle), common.Hash{byte(i + 1)}
|
||||||
if have != want {
|
if have != want {
|
||||||
t.Errorf("block %d, have parent hash %v, want %v", i, have, want)
|
t.Errorf("block %d, verkle=%v, have parent hash %v, want %v", i, isVerkle, have, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Run("MPT", func(t *testing.T) {
|
t.Run("MPT", func(t *testing.T) {
|
||||||
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
|
||||||
checkBlockHashes(statedb)
|
checkBlockHashes(statedb, false)
|
||||||
})
|
})
|
||||||
t.Run("Verkle", func(t *testing.T) {
|
t.Run("Verkle", func(t *testing.T) {
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
@ -248,15 +252,18 @@ func TestProcessParentBlockHash(t *testing.T) {
|
||||||
cacheConfig.SnapshotLimit = 0
|
cacheConfig.SnapshotLimit = 0
|
||||||
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
|
||||||
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
|
statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
|
||||||
checkBlockHashes(statedb)
|
checkBlockHashes(statedb, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number'
|
// getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number'
|
||||||
func getContractStoredBlockHash(statedb *state.StateDB, number uint64) common.Hash {
|
func getContractStoredBlockHash(statedb *state.StateDB, number uint64, isVerkle bool) common.Hash {
|
||||||
ringIndex := number % params.HistoryServeWindow
|
ringIndex := number % params.HistoryServeWindow
|
||||||
var key common.Hash
|
var key common.Hash
|
||||||
binary.BigEndian.PutUint64(key[24:], ringIndex)
|
binary.BigEndian.PutUint64(key[24:], ringIndex)
|
||||||
|
if isVerkle {
|
||||||
|
return statedb.GetState(params.HistoryStorageAddress, key)
|
||||||
|
}
|
||||||
return statedb.GetState(params.HistoryStorageAddress, key)
|
return statedb.GetState(params.HistoryStorageAddress, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +286,7 @@ func TestProcessVerkleInvalidContractCreation(t *testing.T) {
|
||||||
//
|
//
|
||||||
// - The second block contains a single failing contract creation transaction,
|
// - The second block contains a single failing contract creation transaction,
|
||||||
// that fails right off the bat.
|
// that fails right off the bat.
|
||||||
_, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
genesisH, _, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -364,8 +371,9 @@ func TestProcessVerkleInvalidContractCreation(t *testing.T) {
|
||||||
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
||||||
t.Fatalf("nil new value in BLOCKHASH contract insert")
|
t.Fatalf("nil new value in BLOCKHASH contract insert")
|
||||||
}
|
}
|
||||||
if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() {
|
if *stemStateDiff.SuffixDiffs[0].NewValue != genesisH {
|
||||||
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, chain[0].Hash())
|
// je sais pas pourquoi, le hash storé est faux. On dirait le empty code hash mais c'est un hasard
|
||||||
|
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, genesisH)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// For all other entries present in the witness, check that nothing beyond
|
// For all other entries present in the witness, check that nothing beyond
|
||||||
|
@ -393,8 +401,8 @@ func TestProcessVerkleInvalidContractCreation(t *testing.T) {
|
||||||
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
||||||
t.Fatalf("missing post state value for BLOCKHASH contract at block #2")
|
t.Fatalf("missing post state value for BLOCKHASH contract at block #2")
|
||||||
}
|
}
|
||||||
if *stemStateDiff.SuffixDiffs[0].NewValue != common.HexToHash("0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54") {
|
if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() {
|
||||||
t.Fatalf("invalid post state value for BLOCKHASH contract at block #2: 0788c2c0f23aa07eb8bf76fe6c1ca9064a4821c1fd0af803913da488a58dba54 != %x", (*stemStateDiff.SuffixDiffs[0].NewValue)[:])
|
t.Fatalf("invalid post state value for BLOCKHASH contract at block #2: %x != %x", chain[0].Hash(), (*stemStateDiff.SuffixDiffs[0].NewValue)[:])
|
||||||
}
|
}
|
||||||
} else if suffixDiff.Suffix > 4 {
|
} else if suffixDiff.Suffix > 4 {
|
||||||
t.Fatalf("invalid suffix diff found for %x in block #2: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
|
t.Fatalf("invalid suffix diff found for %x in block #2: %d\n", stemStateDiff.Stem, suffixDiff.Suffix)
|
||||||
|
@ -440,7 +448,7 @@ func TestProcessVerkleContractWithEmptyCode(t *testing.T) {
|
||||||
config.ChainID.SetUint64(69421)
|
config.ChainID.SetUint64(69421)
|
||||||
gspec := verkleTestGenesis(&config)
|
gspec := verkleTestGenesis(&config)
|
||||||
|
|
||||||
_, chain, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
genesisH, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
var tx types.Transaction
|
var tx types.Transaction
|
||||||
// a transaction that does some PUSH1n but returns a 0-sized contract
|
// a transaction that does some PUSH1n but returns a 0-sized contract
|
||||||
|
@ -472,8 +480,8 @@ func TestProcessVerkleContractWithEmptyCode(t *testing.T) {
|
||||||
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
if stemStateDiff.SuffixDiffs[0].NewValue == nil {
|
||||||
t.Fatalf("nil new value in BLOCKHASH contract insert")
|
t.Fatalf("nil new value in BLOCKHASH contract insert")
|
||||||
}
|
}
|
||||||
if *stemStateDiff.SuffixDiffs[0].NewValue != chain[0].Hash() {
|
if *stemStateDiff.SuffixDiffs[0].NewValue != genesisH {
|
||||||
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, chain[0].Hash())
|
t.Fatalf("invalid BLOCKHASH value: %x != %x", *stemStateDiff.SuffixDiffs[0].NewValue, genesisH)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
|
for _, suffixDiff := range stemStateDiff.SuffixDiffs {
|
||||||
|
@ -532,7 +540,7 @@ func TestProcessVerkleExtCodeHashOpcode(t *testing.T) {
|
||||||
}
|
}
|
||||||
extCodeHashContractAddr := crypto.CreateAddress(deployer, 1)
|
extCodeHashContractAddr := crypto.CreateAddress(deployer, 1)
|
||||||
|
|
||||||
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -605,7 +613,7 @@ func TestProcessVerkleBalanceOpcode(t *testing.T) {
|
||||||
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
account2 = common.HexToAddress("0x6177843db3138ae69679A54b95cf345ED759450d")
|
||||||
gspec = verkleTestGenesis(&config)
|
gspec = verkleTestGenesis(&config)
|
||||||
)
|
)
|
||||||
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
txData := slices.Concat(
|
txData := slices.Concat(
|
||||||
[]byte{byte(vm.PUSH20)},
|
[]byte{byte(vm.PUSH20)},
|
||||||
|
@ -686,7 +694,7 @@ func TestProcessVerkleSelfDestructInSeparateTx(t *testing.T) {
|
||||||
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
|
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
|
||||||
contract := crypto.CreateAddress(deployer, 0)
|
contract := crypto.CreateAddress(deployer, 0)
|
||||||
|
|
||||||
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
|
@ -794,7 +802,7 @@ func TestProcessVerkleSelfDestructInSameTx(t *testing.T) {
|
||||||
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
|
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
|
||||||
contract := crypto.CreateAddress(deployer, 0)
|
contract := crypto.CreateAddress(deployer, 0)
|
||||||
|
|
||||||
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
|
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
|
||||||
Value: big.NewInt(42),
|
Value: big.NewInt(42),
|
||||||
|
@ -897,7 +905,7 @@ func TestProcessVerkleSelfDestructInSeparateTxWithSelfBeneficiary(t *testing.T)
|
||||||
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
|
deployer := crypto.PubkeyToAddress(testKey.PublicKey)
|
||||||
contract := crypto.CreateAddress(deployer, 0)
|
contract := crypto.CreateAddress(deployer, 0)
|
||||||
|
|
||||||
_, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
_, _, _, _, _, statediffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 2, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
// Create self-destruct contract, sending 42 wei.
|
// Create self-destruct contract, sending 42 wei.
|
||||||
|
@ -977,7 +985,7 @@ func TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiary(t *testing.T) {
|
||||||
|
|
||||||
selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)}
|
selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)}
|
||||||
|
|
||||||
_, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
_, _, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
|
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
|
||||||
Value: big.NewInt(42),
|
Value: big.NewInt(42),
|
||||||
|
@ -1043,7 +1051,7 @@ func TestProcessVerkleSelfDestructInSameTxWithSelfBeneficiaryAndPrefundedAccount
|
||||||
|
|
||||||
selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)}
|
selfDestructContract := []byte{byte(vm.ADDRESS), byte(vm.SELFDESTRUCT)}
|
||||||
|
|
||||||
_, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
_, _, _, _, _, stateDiffs := GenerateVerkleChainWithGenesis(gspec, beacon.New(ethash.NewFaker()), 1, func(i int, gen *BlockGen) {
|
||||||
gen.SetPoS()
|
gen.SetPoS()
|
||||||
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
|
tx, _ := types.SignNewTx(testKey, signer, &types.LegacyTx{Nonce: 0,
|
||||||
Value: big.NewInt(42),
|
Value: big.NewInt(42),
|
||||||
|
|
|
@ -59,6 +59,7 @@ type Contract struct {
|
||||||
|
|
||||||
// is the execution frame represented by this object a contract deployment
|
// is the execution frame represented by this object a contract deployment
|
||||||
IsDeployment bool
|
IsDeployment bool
|
||||||
|
IsSystemCall bool
|
||||||
|
|
||||||
Gas uint64
|
Gas uint64
|
||||||
value *uint256.Int
|
value *uint256.Int
|
||||||
|
|
|
@ -345,11 +345,13 @@ func opExtCodeCopyEIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeC
|
||||||
self: AccountRef(addr),
|
self: AccountRef(addr),
|
||||||
}
|
}
|
||||||
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64())
|
paddedCodeCopy, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(code, uint64CodeOffset, length.Uint64())
|
||||||
|
if !contract.IsSystemCall {
|
||||||
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
|
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(addr, copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
|
||||||
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
||||||
scope.Contract.Gas = 0
|
scope.Contract.Gas = 0
|
||||||
return nil, ErrOutOfGas
|
return nil, ErrOutOfGas
|
||||||
}
|
}
|
||||||
|
}
|
||||||
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), paddedCodeCopy)
|
scope.Memory.Set(memOffset.Uint64(), length.Uint64(), paddedCodeCopy)
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -367,7 +369,7 @@ func opPush1EIP4762(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
||||||
if *pc < codeLen {
|
if *pc < codeLen {
|
||||||
scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))
|
scope.Stack.push(integer.SetUint64(uint64(scope.Contract.Code[*pc])))
|
||||||
|
|
||||||
if !scope.Contract.IsDeployment && *pc%31 == 0 {
|
if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall && *pc%31 == 0 {
|
||||||
// touch next chunk if PUSH1 is at the boundary. if so, *pc has
|
// touch next chunk if PUSH1 is at the boundary. if so, *pc has
|
||||||
// advanced past this boundary.
|
// advanced past this boundary.
|
||||||
contractAddr := scope.Contract.Address()
|
contractAddr := scope.Contract.Address()
|
||||||
|
@ -397,7 +399,7 @@ func makePushEIP4762(size uint64, pushByteSize int) executionFunc {
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
|
|
||||||
if !scope.Contract.IsDeployment {
|
if !scope.Contract.IsDeployment && !scope.Contract.IsSystemCall {
|
||||||
contractAddr := scope.Contract.Address()
|
contractAddr := scope.Contract.Address()
|
||||||
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false)
|
statelessGas := interpreter.evm.AccessEvents.CodeChunksRangeGas(contractAddr, uint64(start), uint64(pushByteSize), uint64(len(scope.Contract.Code)), false)
|
||||||
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
if !scope.Contract.UseGas(statelessGas, interpreter.evm.Config.Tracer, tracing.GasChangeUnspecified) {
|
||||||
|
|
|
@ -174,7 +174,7 @@ func (evm *EVM) Interpreter() *EVMInterpreter {
|
||||||
// parameters. It also handles any necessary value transfer required and takes
|
// parameters. It also handles any necessary value transfer required and takes
|
||||||
// the necessary steps to create accounts and reverses the state in case of an
|
// the necessary steps to create accounts and reverses the state in case of an
|
||||||
// execution error or failed value transfer.
|
// execution error or failed value transfer.
|
||||||
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int) (ret []byte, leftOverGas uint64, err error) {
|
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *uint256.Int, isSyscall bool) (ret []byte, leftOverGas uint64, err error) {
|
||||||
// Capture the tracer start/end events in debug mode
|
// Capture the tracer start/end events in debug mode
|
||||||
if evm.Config.Tracer != nil {
|
if evm.Config.Tracer != nil {
|
||||||
evm.captureBegin(evm.depth, CALL, caller.Address(), addr, input, gas, value.ToBig())
|
evm.captureBegin(evm.depth, CALL, caller.Address(), addr, input, gas, value.ToBig())
|
||||||
|
@ -194,7 +194,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||||
p, isPrecompile := evm.precompile(addr)
|
p, isPrecompile := evm.precompile(addr)
|
||||||
|
|
||||||
if !evm.StateDB.Exist(addr) {
|
if !evm.StateDB.Exist(addr) {
|
||||||
if !isPrecompile && evm.chainRules.IsEIP4762 {
|
if !isPrecompile && evm.chainRules.IsEIP4762 && !isSyscall {
|
||||||
// add proof of absence to witness
|
// add proof of absence to witness
|
||||||
wgas := evm.AccessEvents.AddAccount(addr, false)
|
wgas := evm.AccessEvents.AddAccount(addr, false)
|
||||||
if gas < wgas {
|
if gas < wgas {
|
||||||
|
@ -225,8 +225,9 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
||||||
// If the account has no code, we can abort here
|
// If the account has no code, we can abort here
|
||||||
// The depth-check is already done, and precompiles handled above
|
// The depth-check is already done, and precompiles handled above
|
||||||
contract := NewContract(caller, AccountRef(addrCopy), value, gas)
|
contract := NewContract(caller, AccountRef(addrCopy), value, gas)
|
||||||
|
contract.IsSystemCall = isSyscall
|
||||||
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), code)
|
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), code)
|
||||||
ret, err = evm.interpreter.Run(contract, input, false)
|
ret, err = evm.interpreter.Run(contract, input, false, isSyscall)
|
||||||
gas = contract.Gas
|
gas = contract.Gas
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,7 +287,7 @@ func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte,
|
||||||
// The contract is a scoped environment for this execution context only.
|
// The contract is a scoped environment for this execution context only.
|
||||||
contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
|
contract := NewContract(caller, AccountRef(caller.Address()), value, gas)
|
||||||
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy))
|
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy))
|
||||||
ret, err = evm.interpreter.Run(contract, input, false)
|
ret, err = evm.interpreter.Run(contract, input, false, false)
|
||||||
gas = contract.Gas
|
gas = contract.Gas
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -333,7 +334,7 @@ func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []by
|
||||||
// Initialise a new contract and make initialise the delegate values
|
// Initialise a new contract and make initialise the delegate values
|
||||||
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
|
contract := NewContract(caller, AccountRef(caller.Address()), nil, gas).AsDelegate()
|
||||||
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy))
|
contract.SetCallCode(&addrCopy, evm.resolveCodeHash(addrCopy), evm.resolveCode(addrCopy))
|
||||||
ret, err = evm.interpreter.Run(contract, input, false)
|
ret, err = evm.interpreter.Run(contract, input, false, false)
|
||||||
gas = contract.Gas
|
gas = contract.Gas
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -391,7 +392,7 @@ func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte
|
||||||
// When an error was returned by the EVM or when setting the creation code
|
// When an error was returned by the EVM or when setting the creation code
|
||||||
// above we revert to the snapshot and consume any gas remaining. Additionally
|
// above we revert to the snapshot and consume any gas remaining. Additionally
|
||||||
// when we're in Homestead this also counts for code storage gas errors.
|
// when we're in Homestead this also counts for code storage gas errors.
|
||||||
ret, err = evm.interpreter.Run(contract, input, true)
|
ret, err = evm.interpreter.Run(contract, input, true, false)
|
||||||
gas = contract.Gas
|
gas = contract.Gas
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -521,7 +522,7 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||||
// initNewContract runs a new contract's creation code, performs checks on the
|
// initNewContract runs a new contract's creation code, performs checks on the
|
||||||
// resulting code that is to be deployed, and consumes necessary gas.
|
// resulting code that is to be deployed, and consumes necessary gas.
|
||||||
func (evm *EVM) initNewContract(contract *Contract, address common.Address, value *uint256.Int) ([]byte, error) {
|
func (evm *EVM) initNewContract(contract *Contract, address common.Address, value *uint256.Int) ([]byte, error) {
|
||||||
ret, err := evm.interpreter.Run(contract, nil, false)
|
ret, err := evm.interpreter.Run(contract, nil, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ret, err
|
return ret, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -394,7 +394,7 @@ func gasCall(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize
|
||||||
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
||||||
return 0, ErrGasUintOverflow
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
if evm.chainRules.IsEIP4762 {
|
if evm.chainRules.IsEIP4762 && !contract.IsSystemCall {
|
||||||
if transfersValue {
|
if transfersValue {
|
||||||
gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address))
|
gas, overflow = math.SafeAdd(gas, evm.AccessEvents.ValueTransferGas(contract.Address(), address))
|
||||||
if overflow {
|
if overflow {
|
||||||
|
@ -428,7 +428,7 @@ func gasCallCode(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memory
|
||||||
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
if gas, overflow = math.SafeAdd(gas, memoryGas); overflow {
|
||||||
return 0, ErrGasUintOverflow
|
return 0, ErrGasUintOverflow
|
||||||
}
|
}
|
||||||
if evm.chainRules.IsEIP4762 {
|
if evm.chainRules.IsEIP4762 && !contract.IsSystemCall {
|
||||||
address := common.Address(stack.Back(1).Bytes20())
|
address := common.Address(stack.Back(1).Bytes20())
|
||||||
transfersValue := !stack.Back(2).IsZero()
|
transfersValue := !stack.Back(2).IsZero()
|
||||||
if transfersValue {
|
if transfersValue {
|
||||||
|
|
|
@ -97,7 +97,7 @@ func TestEIP2200(t *testing.T) {
|
||||||
}
|
}
|
||||||
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
|
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, Config{ExtraEips: []int{2200}})
|
||||||
|
|
||||||
_, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int))
|
_, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, tt.gaspool, new(uint256.Int), false)
|
||||||
if !errors.Is(err, tt.failure) {
|
if !errors.Is(err, tt.failure) {
|
||||||
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
|
t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ func TestCreateGas(t *testing.T) {
|
||||||
|
|
||||||
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config)
|
evm := NewEVM(vmctx, statedb, params.AllEthashProtocolChanges, config)
|
||||||
var startGas = uint64(testGas)
|
var startGas = uint64(testGas)
|
||||||
ret, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int))
|
ret, gas, err := evm.Call(AccountRef(common.Address{}), address, nil, startGas, new(uint256.Int), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -752,7 +752,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
|
||||||
if !value.IsZero() {
|
if !value.IsZero() {
|
||||||
gas += params.CallStipend
|
gas += params.CallStipend
|
||||||
}
|
}
|
||||||
ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, &value)
|
ret, returnGas, err := interpreter.evm.Call(scope.Contract, toAddr, args, gas, &value, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
temp.Clear()
|
temp.Clear()
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"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/stateless"
|
"github.com/ethereum/go-ethereum/core/stateless"
|
||||||
"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"
|
||||||
|
@ -98,6 +99,8 @@ type StateDB interface {
|
||||||
|
|
||||||
Witness() *stateless.Witness
|
Witness() *stateless.Witness
|
||||||
|
|
||||||
|
AccessEvents() *state.AccessEvents
|
||||||
|
|
||||||
// Finalise must be invoked at the end of a transaction
|
// Finalise must be invoked at the end of a transaction
|
||||||
Finalise(bool)
|
Finalise(bool)
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ func NewEVMInterpreter(evm *EVM) *EVMInterpreter {
|
||||||
// It's important to note that any errors returned by the interpreter should be
|
// It's important to note that any errors returned by the interpreter should be
|
||||||
// considered a revert-and-consume-all-gas operation except for
|
// considered a revert-and-consume-all-gas operation except for
|
||||||
// ErrExecutionReverted which means revert-and-keep-gas-left.
|
// ErrExecutionReverted which means revert-and-keep-gas-left.
|
||||||
func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) {
|
func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly, isSyscall bool) (ret []byte, err error) {
|
||||||
// Increment the call depth which is restricted to 1024
|
// Increment the call depth which is restricted to 1024
|
||||||
in.evm.depth++
|
in.evm.depth++
|
||||||
defer func() { in.evm.depth-- }()
|
defer func() { in.evm.depth-- }()
|
||||||
|
@ -233,7 +233,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||||
logged, pcCopy, gasCopy = false, pc, contract.Gas
|
logged, pcCopy, gasCopy = false, pc, contract.Gas
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.evm.chainRules.IsEIP4762 && !contract.IsDeployment {
|
if in.evm.chainRules.IsEIP4762 && !contract.IsDeployment && !isSyscall {
|
||||||
// if the PC ends up in a new "chunk" of verkleized code, charge the
|
// if the PC ends up in a new "chunk" of verkleized code, charge the
|
||||||
// associated costs.
|
// associated costs.
|
||||||
contractAddr := contract.Address()
|
contractAddr := contract.Address()
|
||||||
|
|
|
@ -53,7 +53,7 @@ func TestLoopInterrupt(t *testing.T) {
|
||||||
timeout := make(chan bool)
|
timeout := make(chan bool)
|
||||||
|
|
||||||
go func(evm *EVM) {
|
go func(evm *EVM) {
|
||||||
_, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int))
|
_, _, err := evm.Call(AccountRef(common.Address{}), address, nil, math.MaxUint64, new(uint256.Int), false)
|
||||||
errChannel <- err
|
errChannel <- err
|
||||||
}(evm)
|
}(evm)
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,9 @@ func gasSLoad4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memor
|
||||||
}
|
}
|
||||||
|
|
||||||
func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasBalance4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
if contract.IsSystemCall {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
address := stack.peek().Bytes20()
|
address := stack.peek().Bytes20()
|
||||||
gas := evm.AccessEvents.BasicDataGas(address, false)
|
gas := evm.AccessEvents.BasicDataGas(address, false)
|
||||||
if gas == 0 {
|
if gas == 0 {
|
||||||
|
@ -54,6 +57,9 @@ func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
|
||||||
if _, isPrecompile := evm.precompile(address); isPrecompile {
|
if _, isPrecompile := evm.precompile(address); isPrecompile {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
if contract.IsSystemCall {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
gas := evm.AccessEvents.BasicDataGas(address, false)
|
gas := evm.AccessEvents.BasicDataGas(address, false)
|
||||||
if gas == 0 {
|
if gas == 0 {
|
||||||
gas = params.WarmStorageReadCostEIP2929
|
gas = params.WarmStorageReadCostEIP2929
|
||||||
|
@ -62,6 +68,9 @@ func gasExtCodeSize4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
|
||||||
}
|
}
|
||||||
|
|
||||||
func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
func gasExtCodeHash4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory, memorySize uint64) (uint64, error) {
|
||||||
|
if contract.IsSystemCall {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
address := stack.peek().Bytes20()
|
address := stack.peek().Bytes20()
|
||||||
if _, isPrecompile := evm.precompile(address); isPrecompile {
|
if _, isPrecompile := evm.precompile(address); isPrecompile {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
|
@ -79,6 +88,9 @@ func makeCallVariantGasEIP4762(oldCalculator gasFunc) gasFunc {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
if contract.IsSystemCall {
|
||||||
|
return gas, nil
|
||||||
|
}
|
||||||
if _, isPrecompile := evm.precompile(contract.Address()); isPrecompile {
|
if _, isPrecompile := evm.precompile(contract.Address()); isPrecompile {
|
||||||
return gas, nil
|
return gas, nil
|
||||||
}
|
}
|
||||||
|
@ -102,6 +114,9 @@ func gasSelfdestructEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Mem
|
||||||
if _, isPrecompile := evm.precompile(beneficiaryAddr); isPrecompile {
|
if _, isPrecompile := evm.precompile(beneficiaryAddr); isPrecompile {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
if contract.IsSystemCall {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
contractAddr := contract.Address()
|
contractAddr := contract.Address()
|
||||||
statelessGas := evm.AccessEvents.BasicDataGas(contractAddr, false)
|
statelessGas := evm.AccessEvents.BasicDataGas(contractAddr, false)
|
||||||
if contractAddr != beneficiaryAddr {
|
if contractAddr != beneficiaryAddr {
|
||||||
|
@ -131,7 +146,7 @@ func gasCodeCopyEip4762(evm *EVM, contract *Contract, stack *Stack, mem *Memory,
|
||||||
uint64CodeOffset = gomath.MaxUint64
|
uint64CodeOffset = gomath.MaxUint64
|
||||||
}
|
}
|
||||||
_, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(contract.Code, uint64CodeOffset, length.Uint64())
|
_, copyOffset, nonPaddedCopyLength := getDataAndAdjustedBounds(contract.Code, uint64CodeOffset, length.Uint64())
|
||||||
if !contract.IsDeployment {
|
if !contract.IsDeployment && !contract.IsSystemCall {
|
||||||
gas += evm.AccessEvents.CodeChunksRangeGas(contract.Address(), copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
|
gas += evm.AccessEvents.CodeChunksRangeGas(contract.Address(), copyOffset, nonPaddedCopyLength, uint64(len(contract.Code)), false)
|
||||||
}
|
}
|
||||||
return gas, nil
|
return gas, nil
|
||||||
|
@ -143,6 +158,9 @@ func gasExtCodeCopyEIP4762(evm *EVM, contract *Contract, stack *Stack, mem *Memo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
if contract.IsSystemCall {
|
||||||
|
return gas, nil
|
||||||
|
}
|
||||||
addr := common.Address(stack.peek().Bytes20())
|
addr := common.Address(stack.peek().Bytes20())
|
||||||
wgas := evm.AccessEvents.BasicDataGas(addr, false)
|
wgas := evm.AccessEvents.BasicDataGas(addr, false)
|
||||||
if wgas == 0 {
|
if wgas == 0 {
|
||||||
|
|
|
@ -148,6 +148,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
|
||||||
input,
|
input,
|
||||||
cfg.GasLimit,
|
cfg.GasLimit,
|
||||||
uint256.MustFromBig(cfg.Value),
|
uint256.MustFromBig(cfg.Value),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil {
|
if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil {
|
||||||
cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err)
|
cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err)
|
||||||
|
@ -219,6 +220,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er
|
||||||
input,
|
input,
|
||||||
cfg.GasLimit,
|
cfg.GasLimit,
|
||||||
uint256.MustFromBig(cfg.Value),
|
uint256.MustFromBig(cfg.Value),
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil {
|
if cfg.EVMConfig.Tracer != nil && cfg.EVMConfig.Tracer.OnTxEnd != nil {
|
||||||
cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err)
|
cfg.EVMConfig.Tracer.OnTxEnd(&types.Receipt{GasUsed: cfg.GasLimit - leftOverGas}, err)
|
||||||
|
|
|
@ -78,7 +78,7 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
|
||||||
|
|
||||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit, GasPrice: vmctx.txCtx.GasPrice}), contract.Caller())
|
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{Gas: gasLimit, GasPrice: vmctx.txCtx.GasPrice}), contract.Caller())
|
||||||
tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
|
tracer.OnEnter(0, byte(vm.CALL), contract.Caller(), contract.Address(), []byte{}, startGas, value.ToBig())
|
||||||
ret, err := evm.Interpreter().Run(contract, []byte{}, false)
|
ret, err := evm.Interpreter().Run(contract, []byte{}, false, false)
|
||||||
tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
|
tracer.OnExit(0, ret, startGas-contract.Gas, err, true)
|
||||||
// Rest gas assumes no refund
|
// Rest gas assumes no refund
|
||||||
tracer.OnTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
|
tracer.OnTxEnd(&types.Receipt{GasUsed: gasLimit - contract.Gas}, nil)
|
||||||
|
|
|
@ -64,7 +64,7 @@ func TestStoreCapture(t *testing.T) {
|
||||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
||||||
var index common.Hash
|
var index common.Hash
|
||||||
logger.OnTxStart(evm.GetVMContext(), nil, common.Address{})
|
logger.OnTxStart(evm.GetVMContext(), nil, common.Address{})
|
||||||
_, err := evm.Interpreter().Run(contract, []byte{}, false)
|
_, err := evm.Interpreter().Run(contract, []byte{}, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -322,7 +322,7 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
// Execute the message.
|
// Execute the message.
|
||||||
_, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value))
|
_, leftOverGas, err := evm.Call(sender, *msg.To, msg.Data, msg.GasLimit, uint256.MustFromBig(msg.Value), false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Error(err)
|
b.Error(err)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue