From 84eaf5187c25d90ecbe394525affc2e9a7836b9c Mon Sep 17 00:00:00 2001 From: minh-bq <97180373+minh-bq@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:21:07 +0700 Subject: [PATCH] core/state: add hook to precompiled contract and create (#382) * core/state: add evm hooks for precompile and create These hooks are added to help resolve some issues on testnet. * core/blockchain: add evm hook to blockchain object --- core/blockchain.go | 13 +++++++++++-- core/state_processor.go | 5 +++++ core/vm/evm.go | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 088dd5e447..5335158c59 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -225,6 +225,7 @@ type BlockChain struct { shouldPreserve func(*types.Block) bool // Function used to determine whether should preserve the given block. shouldStoreInternalTxs bool enableAdditionalChainEvent bool + evmHook vm.EVMHook } // NewBlockChain returns a fully initialised block chain using information @@ -427,6 +428,14 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par return bc, nil } +func (bc *BlockChain) SetHook(evmHook vm.EVMHook) { + bc.evmHook = evmHook +} + +func (bc *BlockChain) GetHook() vm.EVMHook { + return bc.evmHook +} + func (bc *BlockChain) loadLatestDirtyAccounts() { dirtyStateAccounts := rawdb.ReadDirtyAccounts(bc.db) for _, data := range dirtyStateAccounts { @@ -1515,9 +1524,9 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. if status == CanonStatTy { if bc.enableAdditionalChainEvent { - bc.sendNewBlockEvent(block, receipts, true, true) + bc.sendNewBlockEvent(block, receipts, true, true) } else { - bc.sendNewBlockEvent(block, receipts, false, false) + bc.sendNewBlockEvent(block, receipts, false, false) } if len(logs) > 0 { bc.logsFeed.Send(logs) diff --git a/core/state_processor.go b/core/state_processor.go index 3aa8edbfc3..5465ee293d 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -27,6 +27,7 @@ import ( "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/log" "github.com/ethereum/go-ethereum/params" ) @@ -74,6 +75,10 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg blockContext := NewEVMBlockContext(header, p.bc, nil, publishEvents...) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, p.config, cfg) + if evmHook := p.bc.GetHook(); evmHook != nil { + log.Debug("set hook function for testnet") + vmenv.SetHook(evmHook) + } txNum := len(block.Transactions()) commonTxs := make([]*types.Transaction, 0, txNum) diff --git a/core/vm/evm.go b/core/vm/evm.go index 3d4d312c08..ae7074e68f 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -57,6 +57,12 @@ type ( ) func (evm *EVM) precompile(caller ContractRef, addr common.Address) (PrecompiledContract, bool) { + if evm.evmHook != nil { + mustReturn, contract, isPrecompile := evm.evmHook.PrecompileHook(evm, addr) + if mustReturn { + return contract, isPrecompile + } + } if c := evm.ChainConfig().BlacklistContractAddress; evm.chainRules.IsOdysseusFork && evm.StateDB.Blacklisted(c, &addr) { return &blacklistedAddress{}, true } @@ -161,6 +167,13 @@ type EVM struct { // available gas is calculated in gasCall* according to the 63/64 rule and later // applied in opCall*. callGasTemp uint64 + + evmHook EVMHook +} + +type EVMHook interface { + PrecompileHook(*EVM, common.Address) (bool, PrecompiledContract, bool) + CreateHook(*EVM, uint64, common.Address) (bool, []byte, common.Address, uint64, error) } // NewEVM returns a new EVM. The returned EVM is not thread safe and should @@ -500,6 +513,14 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, } } } + + if evm.evmHook != nil { + mustReturn, ret, address, gas, err := evm.evmHook.CreateHook(evm, gas, caller.Address()) + if mustReturn { + return ret, address, gas, err + } + } + // Handle latest hardfork firstly. if evm.chainRules.IsAntenna { if !evm.StateDB.ValidDeployerV2(caller.Address(), evm.Context.Time, evm.ChainConfig().WhiteListDeployerContractV2Address) { @@ -668,3 +689,7 @@ func (evm *EVM) PublishEvent( ) } } + +func (evm *EVM) SetHook(evmHook EVMHook) { + evm.evmHook = evmHook +}