github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/interop/runtime/engine_test.go (about) 1 package runtime 2 3 import ( 4 "encoding/json" 5 "math/big" 6 "math/rand" 7 "testing" 8 9 "github.com/nspcc-dev/neo-go/internal/random" 10 "github.com/nspcc-dev/neo-go/pkg/core/block" 11 "github.com/nspcc-dev/neo-go/pkg/core/interop" 12 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 13 "github.com/nspcc-dev/neo-go/pkg/crypto/hash" 14 "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" 15 "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" 16 "github.com/nspcc-dev/neo-go/pkg/util" 17 "github.com/nspcc-dev/neo-go/pkg/vm" 18 "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" 19 "github.com/stretchr/testify/require" 20 "go.uber.org/zap" 21 "go.uber.org/zap/zapcore" 22 "go.uber.org/zap/zaptest" 23 ) 24 25 func checkStack(t *testing.T, v *vm.VM, args ...any) { 26 require.Equal(t, len(args), v.Estack().Len()) 27 for i := range args { 28 require.Equal(t, stackitem.Make(args[i]), v.Estack().Pop().Item(), "%d", i) 29 } 30 } 31 32 func TestGetTrigger(t *testing.T) { 33 triggers := []trigger.Type{trigger.Application, trigger.Verification} 34 for _, tr := range triggers { 35 ic := &interop.Context{Trigger: tr, VM: vm.New()} 36 require.NoError(t, GetTrigger(ic)) 37 checkStack(t, ic.VM, int64(tr)) 38 } 39 } 40 41 func TestPlatform(t *testing.T) { 42 ic := &interop.Context{VM: vm.New()} 43 require.NoError(t, Platform(ic)) 44 checkStack(t, ic.VM, "NEO") 45 } 46 47 func TestGetTime(t *testing.T) { 48 b := block.New(false) 49 b.Timestamp = rand.Uint64() 50 ic := &interop.Context{VM: vm.New(), Block: b} 51 require.NoError(t, GetTime(ic)) 52 checkStack(t, ic.VM, new(big.Int).SetUint64(b.Timestamp)) 53 } 54 55 func TestGetScriptHash(t *testing.T) { 56 scripts := []struct { 57 s []byte 58 h util.Uint160 59 }{ 60 {[]byte{1, 2, 3, 4}, hash.Hash160([]byte{1, 2, 3, 4})}, 61 {[]byte{1, 2, 3}, util.Uint160{4, 8, 15, 16}}, 62 {[]byte{1, 2}, hash.Hash160([]byte{1, 2})}, 63 {[]byte{1}, hash.Hash160([]byte{1})}, 64 } 65 66 ic := &interop.Context{VM: vm.New()} 67 ic.VM.LoadScriptWithFlags(scripts[0].s, callflag.All) 68 require.NoError(t, GetEntryScriptHash(ic)) 69 checkStack(t, ic.VM, scripts[0].h.BytesBE()) 70 require.NoError(t, GetCallingScriptHash(ic)) 71 checkStack(t, ic.VM, util.Uint160{}.BytesBE()) 72 require.NoError(t, GetExecutingScriptHash(ic)) 73 checkStack(t, ic.VM, scripts[0].h.BytesBE()) 74 75 ic.VM.LoadScriptWithHash(scripts[1].s, scripts[1].h, callflag.All) 76 require.NoError(t, GetEntryScriptHash(ic)) 77 checkStack(t, ic.VM, scripts[0].h.BytesBE()) 78 require.NoError(t, GetCallingScriptHash(ic)) 79 checkStack(t, ic.VM, scripts[0].h.BytesBE()) 80 require.NoError(t, GetExecutingScriptHash(ic)) 81 checkStack(t, ic.VM, scripts[1].h.BytesBE()) 82 83 ic.VM.LoadScript(scripts[2].s) 84 require.NoError(t, GetEntryScriptHash(ic)) 85 checkStack(t, ic.VM, scripts[0].h.BytesBE()) 86 require.NoError(t, GetCallingScriptHash(ic)) 87 checkStack(t, ic.VM, scripts[1].h.BytesBE()) 88 require.NoError(t, GetExecutingScriptHash(ic)) 89 checkStack(t, ic.VM, scripts[2].h.BytesBE()) 90 91 ic.VM.LoadScript(scripts[3].s) 92 require.NoError(t, GetEntryScriptHash(ic)) 93 checkStack(t, ic.VM, scripts[0].h.BytesBE()) 94 require.NoError(t, GetCallingScriptHash(ic)) 95 checkStack(t, ic.VM, scripts[2].h.BytesBE()) 96 require.NoError(t, GetExecutingScriptHash(ic)) 97 checkStack(t, ic.VM, scripts[3].h.BytesBE()) 98 } 99 100 func TestLog(t *testing.T) { 101 newL := func(l zapcore.Level) (*zap.Logger, *zaptest.Buffer) { 102 enc := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()) 103 w := &zaptest.Buffer{} 104 zc := zapcore.NewCore(enc, w, l) 105 return zap.New(zc, zap.ErrorOutput(w)), w 106 } 107 h := random.Uint160() 108 109 t.Run("big message", func(t *testing.T) { 110 ic := &interop.Context{Log: zap.NewNop(), VM: vm.New()} 111 ic.VM.LoadScriptWithHash([]byte{1}, h, callflag.All) 112 ic.VM.Estack().PushVal(string(make([]byte, MaxNotificationSize+1))) 113 require.Error(t, Log(ic)) 114 }) 115 116 t.Run("good", func(t *testing.T) { 117 log, buf := newL(zapcore.InfoLevel) 118 ic := &interop.Context{Log: log, VM: vm.New()} 119 ic.VM.LoadScriptWithHash([]byte{1}, h, callflag.All) 120 ic.VM.Estack().PushVal("hello") 121 require.NoError(t, Log(ic)) 122 123 ls := buf.Lines() 124 require.Equal(t, 1, len(ls)) 125 126 var logMsg map[string]any 127 require.NoError(t, json.Unmarshal([]byte(ls[0]), &logMsg)) 128 require.Equal(t, "info", logMsg["level"]) 129 require.Equal(t, "hello", logMsg["msg"]) 130 require.Equal(t, h.StringLE(), logMsg["script"]) 131 }) 132 } 133 134 func TestCurrentSigners(t *testing.T) { 135 t.Run("container is block", func(t *testing.T) { 136 b := block.New(false) 137 ic := &interop.Context{VM: vm.New(), Container: b} 138 require.NoError(t, CurrentSigners(ic)) 139 checkStack(t, ic.VM, stackitem.Null{}) 140 }) 141 142 t.Run("container is transaction", func(t *testing.T) { 143 tx := &transaction.Transaction{ 144 Signers: []transaction.Signer{ 145 { 146 Account: util.Uint160{1}, 147 Scopes: transaction.None, 148 }, 149 { 150 Account: util.Uint160{2}, 151 Scopes: transaction.CalledByEntry, 152 }, 153 }, 154 } 155 ic := &interop.Context{VM: vm.New(), Container: tx} 156 require.NoError(t, CurrentSigners(ic)) 157 checkStack(t, ic.VM, stackitem.NewArray([]stackitem.Item{ 158 stackitem.NewArray([]stackitem.Item{ 159 stackitem.NewByteArray(util.Uint160{1}.BytesBE()), 160 stackitem.NewBigInteger(big.NewInt(int64(transaction.None))), 161 stackitem.NewArray([]stackitem.Item{}), 162 stackitem.NewArray([]stackitem.Item{}), 163 stackitem.NewArray([]stackitem.Item{}), 164 }), 165 stackitem.NewArray([]stackitem.Item{ 166 stackitem.NewByteArray(util.Uint160{2}.BytesBE()), 167 stackitem.NewBigInteger(big.NewInt(int64(transaction.CalledByEntry))), 168 stackitem.NewArray([]stackitem.Item{}), 169 stackitem.NewArray([]stackitem.Item{}), 170 stackitem.NewArray([]stackitem.Item{}), 171 }), 172 })) 173 }) 174 }