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  }