@@ -2,6 +2,7 @@ package vm_test
22
33import (
44 "fmt"
5+ "math/big"
56 "testing"
67
78 "github.com/ethereum/go-ethereum/core/vm"
@@ -15,9 +16,14 @@ import (
1516
1617type vmHooksStub struct {
1718 replacement * vm.JumpTable
19+ overridden bool
1820}
1921
22+ var _ vm.Hooks = (* vmHooksStub )(nil )
23+
24+ // OverrideJumpTable overrides all non-nil operations from s.replacement .
2025func (s * vmHooksStub ) OverrideJumpTable (_ params.Rules , jt * vm.JumpTable ) * vm.JumpTable {
26+ s .overridden = true
2127 for op , instr := range s .replacement {
2228 if instr != nil {
2329 fmt .Println (op , instr )
@@ -28,22 +34,30 @@ func (s *vmHooksStub) OverrideJumpTable(_ params.Rules, jt *vm.JumpTable) *vm.Ju
2834}
2935
3036func TestOverrideJumpTable (t * testing.T ) {
37+ override := new (bool )
3138 hooks := & hookstest.Stub {
32- OverrideJumpTableFlag : true ,
39+ OverrideJumpTableFn : func () bool {
40+ return * override
41+ },
3342 }
3443 hooks .Register (t )
3544
36- var called bool
37- const opcode = 1
45+ const (
46+ opcode = 1
47+ gasLimit uint64 = 1e6
48+ )
49+ rng := ethtest .NewPseudoRand (142857 )
50+ gasCost := 1 + rng .Uint64n (gasLimit )
51+ executed := false
3852
3953 vmHooks := & vmHooksStub {
4054 replacement : & vm.JumpTable {
4155 opcode : vm .NewOperation (
4256 func (pc * uint64 , interpreter * vm.EVMInterpreter , callContext * vm.ScopeContext ) ([]byte , error ) {
43- called = true
57+ executed = true
4458 return nil , nil
4559 },
46- 10 , nil ,
60+ gasCost , nil ,
4761 0 , 0 ,
4862 func (s * vm.Stack ) (size uint64 , overflow bool ) {
4963 return 0 , false
@@ -53,14 +67,34 @@ func TestOverrideJumpTable(t *testing.T) {
5367 }
5468 vm .RegisterHooks (vmHooks )
5569
56- state , evm := ethtest .NewZeroEVM (t )
70+ t .Run ("LookupInstructionSet" , func (t * testing.T ) {
71+ _ , evm := ethtest .NewZeroEVM (t )
72+ rules := evm .ChainConfig ().Rules (big .NewInt (0 ), false , 0 )
5773
58- rng := ethtest .NewPseudoRand (142857 )
59- contract := rng .Address ()
60- state .CreateAccount (contract )
61- state .SetCode (contract , []byte {opcode })
74+ for _ , b := range []bool {false , true } {
75+ vmHooks .overridden = false
76+
77+ * override = b
78+ _ , err := vm .LookupInstructionSet (rules )
79+ require .NoError (t , err )
80+ require .Equal (t , b , vmHooks .overridden , "vm.Hooks.OverrideJumpTable() called i.f.f. params.RulesHooks.OverrideJumpTable() returns true" )
81+ }
82+ })
83+
84+ t .Run ("EVMInterpreter" , func (t * testing.T ) {
85+ // We don't need to test the non-override case in EVMInterpreter because
86+ // that uses code shared with LookupInstructionSet. Here we only care
87+ // that the op gets executed as expected.
88+ * override = true
89+ state , evm := ethtest .NewZeroEVM (t )
90+
91+ contract := rng .Address ()
92+ state .CreateAccount (contract )
93+ state .SetCode (contract , []byte {opcode })
6294
63- _ , _ , err := evm .Call (vm .AccountRef (rng .Address ()), contract , []byte {}, 1e6 , uint256 .NewInt (0 ))
64- require .NoError (t , err )
65- assert .True (t , called )
95+ _ , gasRemaining , err := evm .Call (vm .AccountRef (rng .Address ()), contract , []byte {}, gasLimit , uint256 .NewInt (0 ))
96+ require .NoError (t , err , "evm.Call([contract with overridden opcode])" )
97+ assert .True (t , executed , "executionFunc was called" )
98+ assert .Equal (t , gasLimit - gasCost , gasRemaining , "gas remaining" )
99+ })
66100}
0 commit comments