mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 02:12:23 +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)
|
misc.ApplyDAOHardFork(statedb)
|
||||||
}
|
}
|
||||||
// Iterate over and process the individual transactions
|
// Iterate over and process the individual transactions
|
||||||
|
receipts = make([]*types.Receipt, len(block.Transactions()))
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range block.Transactions() {
|
||||||
statedb.Prepare(tx.Hash(), block.Hash(), i)
|
statedb.Prepare(tx.Hash(), block.Hash(), i)
|
||||||
receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
|
receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, 0, err
|
return nil, nil, 0, err
|
||||||
}
|
}
|
||||||
receipts = append(receipts, receipt)
|
receipts[i] = receipt
|
||||||
allLogs = append(allLogs, receipt.Logs...)
|
allLogs = append(allLogs, receipt.Logs...)
|
||||||
}
|
}
|
||||||
// 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)
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,7 @@ type (
|
||||||
// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
|
// 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) {
|
func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) {
|
||||||
if contract.CodeAddr != nil {
|
if contract.CodeAddr != nil {
|
||||||
precompiles := PrecompiledContractsHomestead
|
if p := evm.interpreter.precompiles[*contract.CodeAddr]; p != nil {
|
||||||
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
|
|
||||||
precompiles = PrecompiledContractsByzantium
|
|
||||||
}
|
|
||||||
if p := precompiles[*contract.CodeAddr]; p != nil {
|
|
||||||
return RunPrecompiledContract(p, input, contract)
|
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()
|
snapshot = evm.StateDB.Snapshot()
|
||||||
)
|
)
|
||||||
if !evm.StateDB.Exist(addr) {
|
if !evm.StateDB.Exist(addr) {
|
||||||
precompiles := PrecompiledContractsHomestead
|
if evm.interpreter.precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
|
||||||
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
|
|
||||||
precompiles = PrecompiledContractsByzantium
|
|
||||||
}
|
|
||||||
if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
|
|
||||||
// Calling a non existing account, don't do antything, but ping the tracer
|
// Calling a non existing account, don't do antything, but ping the tracer
|
||||||
if evm.vmConfig.Debug && evm.depth == 0 {
|
if evm.vmConfig.Debug && evm.depth == 0 {
|
||||||
evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value)
|
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)
|
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.
|
// 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.
|
// The contract is a scoped environment for this execution context only.
|
||||||
contract := NewContract(caller, to, value, gas)
|
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()
|
start := time.Now()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -53,6 +54,7 @@ type Interpreter struct {
|
||||||
|
|
||||||
readOnly bool // Whether to throw on stateful modifications
|
readOnly bool // Whether to throw on stateful modifications
|
||||||
returnData []byte // Last CALL's return data for subsequent reuse
|
returnData []byte // Last CALL's return data for subsequent reuse
|
||||||
|
precompiles map[common.Address]PrecompiledContract
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInterpreter returns a new instance of the Interpreter.
|
// 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{
|
return &Interpreter{
|
||||||
evm: evm,
|
evm: evm,
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
gasTable: evm.ChainConfig().GasTable(evm.BlockNumber),
|
gasTable: evm.ChainConfig().GasTable(evm.BlockNumber),
|
||||||
intPool: newIntPool(),
|
intPool: newZerosizeIntPool(),
|
||||||
|
precompiles: precompiles,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ func newIntPool() *intPool {
|
||||||
return &intPool{pool: newstack()}
|
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.
|
// 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!
|
// Note, the returned int's value is arbitrary and will not be zeroed!
|
||||||
func (p *intPool) get() *big.Int {
|
func (p *intPool) get() *big.Int {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ func newstack() *Stack {
|
||||||
return &Stack{data: make([]*big.Int, 0, 1024)}
|
return &Stack{data: make([]*big.Int, 0, 1024)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newZeroSizeStack() *Stack {
|
||||||
|
return &Stack{data: make([]*big.Int, 0)}
|
||||||
|
}
|
||||||
|
|
||||||
func (st *Stack) Data() []*big.Int {
|
func (st *Stack) Data() []*big.Int {
|
||||||
return st.data
|
return st.data
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue