mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 14:16:44 +00:00
core/vm: implement contract pool
This commit is contained in:
parent
0983cd789e
commit
72b800501c
6 changed files with 79 additions and 13 deletions
48
core/vm/contract_pool.go
Normal file
48
core/vm/contract_pool.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package vm
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
var contractPool = sync.Pool{
|
||||
New: func() any {
|
||||
return &Contract{}
|
||||
},
|
||||
}
|
||||
|
||||
// GetContract returns a contract from the pool or creates a new one
|
||||
func GetContract(caller common.Address, address common.Address, value *uint256.Int, gas uint64, jumpDests map[common.Hash]bitvec) *Contract {
|
||||
contract := contractPool.Get().(*Contract)
|
||||
|
||||
// Reset the contract with new values
|
||||
contract.caller = caller
|
||||
contract.address = address
|
||||
contract.jumpdests = jumpDests
|
||||
if contract.jumpdests == nil {
|
||||
// Initialize the jump analysis map if it's nil, mostly for tests
|
||||
contract.jumpdests = make(map[common.Hash]bitvec)
|
||||
}
|
||||
contract.Gas = gas
|
||||
contract.value = value
|
||||
|
||||
contract.Code = nil
|
||||
contract.CodeHash = common.Hash{}
|
||||
contract.Input = nil
|
||||
contract.IsDeployment = false
|
||||
contract.IsSystemCall = false
|
||||
|
||||
contract.analysis = nil
|
||||
|
||||
return contract
|
||||
}
|
||||
|
||||
// ReturnContract returns a contract to the pool
|
||||
func ReturnContract(contract *Contract) {
|
||||
if contract == nil {
|
||||
return
|
||||
}
|
||||
contractPool.Put(contract)
|
||||
}
|
||||
|
|
@ -238,7 +238,9 @@ func (evm *EVM) Call(caller common.Address, addr common.Address, input []byte, g
|
|||
ret, err = nil, nil // gas is unchanged
|
||||
} else {
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
contract := NewContract(caller, addr, value, gas, evm.jumpDests)
|
||||
contract := GetContract(caller, addr, value, gas, evm.jumpDests)
|
||||
defer ReturnContract(contract)
|
||||
|
||||
contract.IsSystemCall = isSystemCall(caller)
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), code)
|
||||
ret, err = evm.interpreter.Run(contract, input, false)
|
||||
|
|
@ -298,7 +300,9 @@ func (evm *EVM) CallCode(caller common.Address, addr common.Address, input []byt
|
|||
} else {
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
contract := NewContract(caller, caller, value, gas, evm.jumpDests)
|
||||
contract := GetContract(caller, caller, value, gas, evm.jumpDests)
|
||||
defer ReturnContract(contract)
|
||||
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
|
||||
ret, err = evm.interpreter.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
|
|
@ -342,7 +346,9 @@ func (evm *EVM) DelegateCall(originCaller common.Address, caller common.Address,
|
|||
// Initialise a new contract and make initialise the delegate values
|
||||
//
|
||||
// Note: The value refers to the original value from the parent call.
|
||||
contract := NewContract(originCaller, caller, value, gas, evm.jumpDests)
|
||||
contract := GetContract(originCaller, caller, value, gas, evm.jumpDests)
|
||||
defer ReturnContract(contract)
|
||||
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
|
||||
ret, err = evm.interpreter.Run(contract, input, false)
|
||||
gas = contract.Gas
|
||||
|
|
@ -393,7 +399,9 @@ func (evm *EVM) StaticCall(caller common.Address, addr common.Address, input []b
|
|||
} else {
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
contract := NewContract(caller, addr, new(uint256.Int), gas, evm.jumpDests)
|
||||
contract := GetContract(caller, addr, new(uint256.Int), gas, evm.jumpDests)
|
||||
defer ReturnContract(contract)
|
||||
|
||||
contract.SetCallCode(evm.resolveCodeHash(addr), evm.resolveCode(addr))
|
||||
|
||||
// When an error was returned by the EVM or when setting the creation code
|
||||
|
|
@ -500,7 +508,8 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
|
||||
// Initialise a new contract and set the code that is to be used by the EVM.
|
||||
// The contract is a scoped environment for this execution context only.
|
||||
contract := NewContract(caller, address, value, gas, evm.jumpDests)
|
||||
contract := GetContract(caller, address, value, gas, evm.jumpDests)
|
||||
defer ReturnContract(contract)
|
||||
|
||||
// Explicitly set the code to a null hash to prevent caching of jump analysis
|
||||
// for the initialization code.
|
||||
|
|
@ -514,7 +523,8 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui
|
|||
contract.UseGas(contract.Gas, evm.Config.Tracer, tracing.GasChangeCallFailedExecution)
|
||||
}
|
||||
}
|
||||
return ret, address, contract.Gas, err
|
||||
leftOverGas = contract.Gas
|
||||
return ret, address, leftOverGas, err
|
||||
}
|
||||
|
||||
// initNewContract runs a new contract's creation code, performs checks on the
|
||||
|
|
|
|||
|
|
@ -567,10 +567,11 @@ func TestOpTstore(t *testing.T) {
|
|||
mem = NewMemory()
|
||||
caller = common.Address{}
|
||||
to = common.Address{1}
|
||||
contract = NewContract(caller, to, new(uint256.Int), 0, nil)
|
||||
contract = GetContract(caller, to, new(uint256.Int), 0, nil)
|
||||
scopeContext = ScopeContext{mem, stack, contract}
|
||||
value = common.Hex2Bytes("abcdef00000000000000abba000000000deaf000000c0de00100000000133700")
|
||||
)
|
||||
defer ReturnContract(contract)
|
||||
|
||||
// Add a stateObject for the caller and the contract being called
|
||||
statedb.CreateAccount(caller)
|
||||
|
|
|
|||
|
|
@ -55,8 +55,10 @@ func runTrace(tracer *tracers.Tracer, vmctx *vmContext, chaincfg *params.ChainCo
|
|||
gasLimit uint64 = 31000
|
||||
startGas uint64 = 10000
|
||||
value = uint256.NewInt(0)
|
||||
contract = vm.NewContract(common.Address{}, common.Address{}, value, startGas, nil)
|
||||
contract = vm.GetContract(common.Address{}, common.Address{}, value, startGas, nil)
|
||||
)
|
||||
defer vm.ReturnContract(contract)
|
||||
|
||||
evm.SetTxContext(vmctx.txCtx)
|
||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
||||
if contractCode != nil {
|
||||
|
|
@ -183,8 +185,10 @@ func TestHaltBetweenSteps(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
scope := &vm.ScopeContext{
|
||||
Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
|
||||
Contract: vm.GetContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
|
||||
}
|
||||
defer vm.ReturnContract(scope.Contract)
|
||||
|
||||
evm := vm.NewEVM(vm.BlockContext{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, chainConfig, vm.Config{Tracer: tracer.Hooks})
|
||||
evm.SetTxContext(vm.TxContext{GasPrice: big.NewInt(1)})
|
||||
tracer.OnTxStart(evm.GetVMContext(), types.NewTx(&types.LegacyTx{}), common.Address{})
|
||||
|
|
@ -281,8 +285,9 @@ func TestEnterExit(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
scope := &vm.ScopeContext{
|
||||
Contract: vm.NewContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
|
||||
Contract: vm.GetContract(common.Address{}, common.Address{}, uint256.NewInt(0), 0, nil),
|
||||
}
|
||||
defer vm.ReturnContract(scope.Contract)
|
||||
tracer.OnEnter(1, byte(vm.CALL), scope.Contract.Caller(), scope.Contract.Address(), []byte{}, 1000, new(big.Int))
|
||||
tracer.OnExit(1, []byte{}, 400, nil, false)
|
||||
|
||||
|
|
|
|||
|
|
@ -43,8 +43,10 @@ func TestStoreCapture(t *testing.T) {
|
|||
var (
|
||||
logger = NewStructLogger(nil)
|
||||
evm = vm.NewEVM(vm.BlockContext{}, &dummyStatedb{}, params.TestChainConfig, vm.Config{Tracer: logger.Hooks()})
|
||||
contract = vm.NewContract(common.Address{}, common.Address{}, new(uint256.Int), 100000, nil)
|
||||
contract = vm.GetContract(common.Address{}, common.Address{}, new(uint256.Int), 100000, nil)
|
||||
)
|
||||
defer vm.ReturnContract(contract)
|
||||
|
||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x0, byte(vm.SSTORE)}
|
||||
var index common.Hash
|
||||
logger.OnTxStart(evm.GetVMContext(), nil, common.Address{})
|
||||
|
|
|
|||
|
|
@ -301,8 +301,8 @@ func runBenchmark(b *testing.B, t *StateTest) {
|
|||
evm.SetTxContext(txContext)
|
||||
|
||||
// Create "contract" for sender to cache code analysis.
|
||||
sender := vm.NewContract(msg.From, msg.From, nil, 0, nil)
|
||||
|
||||
sender := vm.GetContract(msg.From, msg.From, nil, 0, nil)
|
||||
defer vm.ReturnContract(sender)
|
||||
var (
|
||||
gasUsed uint64
|
||||
elapsed uint64
|
||||
|
|
|
|||
Loading…
Reference in a new issue