|
|
@@ -868,6 +868,37 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+type ChainContextBackend interface {
|
|
|
+ Engine() consensus.Engine
|
|
|
+ HeaderByNumber(context.Context, rpc.BlockNumber) (*types.Header, error)
|
|
|
+}
|
|
|
+
|
|
|
+// ChainContext is an implementation of core.ChainContext. It's main use-case
|
|
|
+// is instantiating a vm.BlockContext without having access to the BlockChain object.
|
|
|
+type ChainContext struct {
|
|
|
+ b ChainContextBackend
|
|
|
+ ctx context.Context
|
|
|
+}
|
|
|
+
|
|
|
+// NewChainContext creates a new ChainContext object.
|
|
|
+func NewChainContext(ctx context.Context, backend ChainContextBackend) *ChainContext {
|
|
|
+ return &ChainContext{ctx: ctx, b: backend}
|
|
|
+}
|
|
|
+
|
|
|
+func (context *ChainContext) Engine() consensus.Engine {
|
|
|
+ return context.b.Engine()
|
|
|
+}
|
|
|
+
|
|
|
+func (context *ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
|
|
|
+ // This method is called to get the hash for a block number when executing the BLOCKHASH
|
|
|
+ // opcode. Hence no need to search for non-canonical blocks.
|
|
|
+ header, err := context.b.HeaderByNumber(context.ctx, rpc.BlockNumber(number))
|
|
|
+ if err != nil || header.Hash() != hash {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ return header
|
|
|
+}
|
|
|
+
|
|
|
func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, vmCfg vm.Config, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
|
|
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
|
|
|
|
|
@@ -889,10 +920,13 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
|
|
|
// Make sure the context is cancelled when the call has completed
|
|
|
// this makes sure resources are cleaned up.
|
|
|
defer cancel()
|
|
|
+ return doCall(ctx, b, args, state, header, timeout, new(core.GasPool).AddGas(globalGasCap), nil)
|
|
|
+}
|
|
|
|
|
|
+func doCall(ctx context.Context, b Backend, args CallArgs, state *state.StateDB, header *types.Header, timeout time.Duration, gp *core.GasPool, blockContext *vm.BlockContext) (*core.ExecutionResult, error) {
|
|
|
// Get a new instance of the EVM.
|
|
|
- msg := args.ToMessage(globalGasCap)
|
|
|
- evm, vmError, err := b.GetEVM(ctx, msg, state, header, nil, nil)
|
|
|
+ msg := args.ToMessage(gp.Gas())
|
|
|
+ evm, vmError, err := b.GetEVM(ctx, msg, state, header, nil, blockContext)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
@@ -904,7 +938,7 @@ func DoCall(ctx context.Context, b Backend, args CallArgs, blockNrOrHash rpc.Blo
|
|
|
})
|
|
|
|
|
|
// Execute the message.
|
|
|
- gp := new(core.GasPool).AddGas(math.MaxUint64)
|
|
|
+ //gp := new(core.GasPool).AddGas(math.MaxUint64)
|
|
|
result, err := core.ApplyMessage(evm, msg, gp)
|
|
|
if err := vmError(); err != nil {
|
|
|
return nil, err
|