mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
core/vm: precompiles into interpreter, 0-size alloc intpool,prealloc receipts
This commit is contained in:
parent
40a2c52397
commit
f26087d3a6
5 changed files with 39 additions and 18 deletions
|
|
@ -66,13 +66,14 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
|
|||
misc.ApplyDAOHardFork(statedb)
|
||||
}
|
||||
// Iterate over and process the individual transactions
|
||||
receipts = make([]*types.Receipt, len(block.Transactions()))
|
||||
for i, tx := range block.Transactions() {
|
||||
statedb.Prepare(tx.Hash(), block.Hash(), i)
|
||||
receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
|
||||
if err != nil {
|
||||
return nil, nil, 0, err
|
||||
}
|
||||
receipts = append(receipts, receipt)
|
||||
receipts[i] = receipt
|
||||
allLogs = append(allLogs, receipt.Logs...)
|
||||
}
|
||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||
|
|
|
|||
|
|
@ -41,11 +41,7 @@ type (
|
|||
// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
|
||||
func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) {
|
||||
if contract.CodeAddr != nil {
|
||||
precompiles := PrecompiledContractsHomestead
|
||||
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
|
||||
precompiles = PrecompiledContractsByzantium
|
||||
}
|
||||
if p := precompiles[*contract.CodeAddr]; p != nil {
|
||||
if p := evm.interpreter.precompiles[*contract.CodeAddr]; p != nil {
|
||||
return RunPrecompiledContract(p, input, contract)
|
||||
}
|
||||
}
|
||||
|
|
@ -155,11 +151,8 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
snapshot = evm.StateDB.Snapshot()
|
||||
)
|
||||
if !evm.StateDB.Exist(addr) {
|
||||
precompiles := PrecompiledContractsHomestead
|
||||
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
|
||||
precompiles = PrecompiledContractsByzantium
|
||||
}
|
||||
if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
|
||||
if evm.interpreter.precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
|
||||
|
||||
// Calling a non existing account, don't do antything, but ping the tracer
|
||||
if evm.vmConfig.Debug && evm.depth == 0 {
|
||||
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
|
||||
|
|
@ -171,10 +164,21 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
|
|||
}
|
||||
evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
|
||||
|
||||
code := evm.StateDB.GetCode(addr)
|
||||
codeHash := evm.StateDB.GetCodeHash(addr)
|
||||
_, isPrecompile := evm.interpreter.precompiles[addr]
|
||||
|
||||
if !isPrecompile && len(code) == 0 {
|
||||
// Shortcut execution if there is no code,
|
||||
// but make sure to set returndata to nil
|
||||
evm.interpreter.returnData = nil
|
||||
return nil, gas, nil
|
||||
}
|
||||
|
||||
// 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, to, value, gas)
|
||||
contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
|
||||
contract.SetCallCode(&addr, codeHash, code)
|
||||
|
||||
start := time.Now()
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"fmt"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
|
@ -51,8 +52,9 @@ type Interpreter struct {
|
|||
gasTable params.GasTable
|
||||
intPool *intPool
|
||||
|
||||
readOnly bool // Whether to throw on stateful modifications
|
||||
returnData []byte // Last CALL's return data for subsequent reuse
|
||||
readOnly bool // Whether to throw on stateful modifications
|
||||
returnData []byte // Last CALL's return data for subsequent reuse
|
||||
precompiles map[common.Address]PrecompiledContract
|
||||
}
|
||||
|
||||
// NewInterpreter returns a new instance of the Interpreter.
|
||||
|
|
@ -73,11 +75,17 @@ func NewInterpreter(evm *EVM, cfg Config) *Interpreter {
|
|||
}
|
||||
}
|
||||
|
||||
precompiles := PrecompiledContractsHomestead
|
||||
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
|
||||
precompiles = PrecompiledContractsByzantium
|
||||
}
|
||||
|
||||
return &Interpreter{
|
||||
evm: evm,
|
||||
cfg: cfg,
|
||||
gasTable: evm.ChainConfig().GasTable(evm.BlockNumber),
|
||||
intPool: newIntPool(),
|
||||
evm: evm,
|
||||
cfg: cfg,
|
||||
gasTable: evm.ChainConfig().GasTable(evm.BlockNumber),
|
||||
intPool: newZerosizeIntPool(),
|
||||
precompiles: precompiles,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ func newIntPool() *intPool {
|
|||
return &intPool{pool: newstack()}
|
||||
}
|
||||
|
||||
func newZerosizeIntPool() *intPool {
|
||||
return &intPool{pool: newZeroSizeStack()}
|
||||
}
|
||||
|
||||
// get retrieves a big int from the pool, allocating one if the pool is empty.
|
||||
// Note, the returned int's value is arbitrary and will not be zeroed!
|
||||
func (p *intPool) get() *big.Int {
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ func newstack() *Stack {
|
|||
return &Stack{data: make([]*big.Int, 0, 1024)}
|
||||
}
|
||||
|
||||
func newZeroSizeStack() *Stack {
|
||||
return &Stack{data: make([]*big.Int, 0)}
|
||||
}
|
||||
|
||||
func (st *Stack) Data() []*big.Int {
|
||||
return st.data
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue