github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/vm/stackitem/item.go (about)

     1  package stackitem
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"math"
    10  	"math/big"
    11  	"reflect"
    12  	"unicode/utf8"
    13  
    14  	"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
    15  	"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
    16  	"github.com/nspcc-dev/neo-go/pkg/util"
    17  )
    18  
    19  const (
    20  	// MaxBigIntegerSizeBits is the maximum size of a BigInt item in bits.
    21  	MaxBigIntegerSizeBits = 32 * 8
    22  	// MaxSize is the maximum item size allowed in the VM.
    23  	MaxSize = math.MaxUint16 * 2
    24  	// MaxComparableNumOfItems is the maximum number of items that can be compared for structs.
    25  	MaxComparableNumOfItems = MaxDeserialized
    26  	// MaxClonableNumOfItems is the maximum number of items that can be cloned in structs.
    27  	MaxClonableNumOfItems = MaxDeserialized
    28  	// MaxByteArrayComparableSize is the maximum allowed length of a ByteArray for Equals method.
    29  	// It is set to be the maximum uint16 value + 1.
    30  	MaxByteArrayComparableSize = math.MaxUint16 + 1
    31  	// MaxKeySize is the maximum size of a map key.
    32  	MaxKeySize = 64
    33  )
    34  
    35  // Item represents the "real" value that is pushed on the stack.
    36  type Item interface {
    37  	fmt.Stringer
    38  	Value() any
    39  	// Dup duplicates current Item.
    40  	Dup() Item
    41  	// TryBool converts Item to a boolean value.
    42  	TryBool() (bool, error)
    43  	// TryBytes converts Item to a byte slice. If the underlying type is a
    44  	// byte slice, it's returned as is without copying.
    45  	TryBytes() ([]byte, error)
    46  	// TryInteger converts Item to an integer.
    47  	TryInteger() (*big.Int, error)
    48  	// Equals checks if 2 StackItems are equal.
    49  	Equals(s Item) bool
    50  	// Type returns stack item type.
    51  	Type() Type
    52  	// Convert converts Item to another type.
    53  	Convert(Type) (Item, error)
    54  }
    55  
    56  // Convertible is something that can be converted to/from Item.
    57  type Convertible interface {
    58  	ToStackItem() (Item, error)
    59  	FromStackItem(Item) error
    60  }
    61  
    62  // Equatable describes a special value of Interop that can be compared with
    63  // value of some other Interop that implements Equatable.
    64  type Equatable interface {
    65  	// Equals checks if two objects are equal.
    66  	Equals(other Equatable) bool
    67  }
    68  
    69  var (
    70  	// ErrInvalidConversion is returned upon an attempt to make an incorrect
    71  	// conversion between item types.
    72  	ErrInvalidConversion = errors.New("invalid conversion")
    73  
    74  	// ErrTooBig is returned when an item exceeds some size constraints, like
    75  	// the maximum allowed integer value of the number of elements in an array. It
    76  	// can also be returned by serialization functions if the resulting
    77  	// value exceeds MaxSize.
    78  	ErrTooBig = errors.New("too big")
    79  	// ErrReadOnly is returned on attempt to modify immutable stack item.
    80  	ErrReadOnly = errors.New("item is read-only")
    81  
    82  	errTooBigComparable = fmt.Errorf("%w: uncomparable", ErrTooBig)
    83  	errTooBigInteger    = fmt.Errorf("%w: integer", ErrTooBig)
    84  	errTooBigKey        = fmt.Errorf("%w: map key", ErrTooBig)
    85  	errTooBigSize       = fmt.Errorf("%w: size", ErrTooBig)
    86  	errTooBigElements   = fmt.Errorf("%w: many elements", ErrTooBig)
    87  )
    88  
    89  // mkInvConversion creates a conversion error with additional metadata (from and
    90  // to types).
    91  func mkInvConversion(from Item, to Type) error {
    92  	return fmt.Errorf("%w: %s/%s", ErrInvalidConversion, from, to)
    93  }
    94  
    95  // Make tries to make an appropriate stack item from the provided value.
    96  // It will panic if it's not possible.
    97  func Make(v any) Item {
    98  	switch val := v.(type) {
    99  	case int:
   100  		return (*BigInteger)(big.NewInt(int64(val)))
   101  	case int64:
   102  		return (*BigInteger)(big.NewInt(val))
   103  	case uint8:
   104  		return (*BigInteger)(big.NewInt(int64(val)))
   105  	case uint16:
   106  		return (*BigInteger)(big.NewInt(int64(val)))
   107  	case uint32:
   108  		return (*BigInteger)(big.NewInt(int64(val)))
   109  	case uint64:
   110  		return (*BigInteger)(new(big.Int).SetUint64(val))
   111  	case []byte:
   112  		return NewByteArray(val)
   113  	case string:
   114  		return NewByteArray([]byte(val))
   115  	case bool:
   116  		return Bool(val)
   117  	case []Item:
   118  		return &Array{
   119  			value: val,
   120  		}
   121  	case *big.Int:
   122  		return NewBigInteger(val)
   123  	case Item:
   124  		return val
   125  	case []int:
   126  		var a []Item
   127  		for _, i := range val {
   128  			a = append(a, Make(i))
   129  		}
   130  		return Make(a)
   131  	case []any:
   132  		res := make([]Item, len(val))
   133  		for i := range val {
   134  			res[i] = Make(val[i])
   135  		}
   136  		return Make(res)
   137  	case util.Uint160:
   138  		return Make(val.BytesBE())
   139  	case util.Uint256:
   140  		return Make(val.BytesBE())
   141  	case *util.Uint160:
   142  		if val == nil {
   143  			return Null{}
   144  		}
   145  		return Make(*val)
   146  	case *util.Uint256:
   147  		if val == nil {
   148  			return Null{}
   149  		}
   150  		return Make(*val)
   151  	case nil:
   152  		return Null{}
   153  	default:
   154  		i64T := reflect.TypeOf(int64(0))
   155  		if reflect.TypeOf(val).ConvertibleTo(i64T) {
   156  			i64Val := reflect.ValueOf(val).Convert(i64T).Interface()
   157  			return Make(i64Val)
   158  		}
   159  		panic(
   160  			fmt.Sprintf(
   161  				"invalid stack item type: %v (%v)",
   162  				val,
   163  				reflect.TypeOf(val),
   164  			),
   165  		)
   166  	}
   167  }
   168  
   169  // ToString converts an Item to a string if it is a valid UTF-8.
   170  func ToString(item Item) (string, error) {
   171  	bs, err := item.TryBytes()
   172  	if err != nil {
   173  		return "", err
   174  	}
   175  	if !utf8.Valid(bs) {
   176  		return "", fmt.Errorf("%w: not UTF-8", ErrInvalidValue)
   177  	}
   178  	return string(bs), nil
   179  }
   180  
   181  // convertPrimitive converts a primitive item to the specified type.
   182  func convertPrimitive(item Item, typ Type) (Item, error) {
   183  	if item.Type() == typ {
   184  		return item, nil
   185  	}
   186  	switch typ {
   187  	case IntegerT:
   188  		bi, err := item.TryInteger()
   189  		if err != nil {
   190  			return nil, err
   191  		}
   192  		return NewBigInteger(bi), nil
   193  	case ByteArrayT, BufferT:
   194  		b, err := item.TryBytes()
   195  		if err != nil {
   196  			return nil, err
   197  		}
   198  		if typ == BufferT {
   199  			return NewBuffer(bytes.Clone(b)), nil
   200  		}
   201  		// ByteArray can't really be changed, so it's OK to reuse `b`.
   202  		return NewByteArray(b), nil
   203  	case BooleanT:
   204  		b, err := item.TryBool()
   205  		if err != nil {
   206  			return nil, err
   207  		}
   208  		return NewBool(b), nil
   209  	default:
   210  		return nil, mkInvConversion(item, typ)
   211  	}
   212  }
   213  
   214  // Struct represents a struct on the stack.
   215  type Struct struct {
   216  	value []Item
   217  	rc
   218  	ro
   219  }
   220  
   221  // NewStruct returns a new Struct object.
   222  func NewStruct(items []Item) *Struct {
   223  	return &Struct{
   224  		value: items,
   225  	}
   226  }
   227  
   228  // Value implements the Item interface.
   229  func (i *Struct) Value() any {
   230  	return i.value
   231  }
   232  
   233  // Remove removes the element at `pos` index from the Struct value.
   234  // It will panic if a bad index given.
   235  func (i *Struct) Remove(pos int) {
   236  	if i.IsReadOnly() {
   237  		panic(ErrReadOnly)
   238  	}
   239  	i.value = append(i.value[:pos], i.value[pos+1:]...)
   240  }
   241  
   242  // Append adds an Item to the end of the Struct value.
   243  func (i *Struct) Append(item Item) {
   244  	if i.IsReadOnly() {
   245  		panic(ErrReadOnly)
   246  	}
   247  	i.value = append(i.value, item)
   248  }
   249  
   250  // Clear removes all elements from the Struct item value.
   251  func (i *Struct) Clear() {
   252  	if i.IsReadOnly() {
   253  		panic(ErrReadOnly)
   254  	}
   255  	i.value = i.value[:0]
   256  }
   257  
   258  // Len returns the length of the Struct value.
   259  func (i *Struct) Len() int {
   260  	return len(i.value)
   261  }
   262  
   263  // String implements the Item interface.
   264  func (i *Struct) String() string {
   265  	return "Struct"
   266  }
   267  
   268  // Dup implements the Item interface.
   269  func (i *Struct) Dup() Item {
   270  	// it's a reference type, so no copying here.
   271  	return i
   272  }
   273  
   274  // TryBool implements the Item interface.
   275  func (i *Struct) TryBool() (bool, error) { return true, nil }
   276  
   277  // TryBytes implements the Item interface.
   278  func (i *Struct) TryBytes() ([]byte, error) {
   279  	return nil, mkInvConversion(i, ByteArrayT)
   280  }
   281  
   282  // TryInteger implements the Item interface.
   283  func (i *Struct) TryInteger() (*big.Int, error) {
   284  	return nil, mkInvConversion(i, IntegerT)
   285  }
   286  
   287  // Equals implements the Item interface.
   288  func (i *Struct) Equals(s Item) bool {
   289  	if s == nil {
   290  		return false
   291  	}
   292  	val, ok := s.(*Struct)
   293  	if !ok {
   294  		return false
   295  	}
   296  	var limit = MaxComparableNumOfItems - 1 // 1 for current element.
   297  	return i.equalStruct(val, &limit)
   298  }
   299  
   300  func (i *Struct) equalStruct(s *Struct, limit *int) bool {
   301  	if i == s {
   302  		return true
   303  	} else if len(i.value) != len(s.value) {
   304  		return false
   305  	}
   306  	var maxComparableSize = MaxByteArrayComparableSize
   307  	for j := range i.value {
   308  		*limit--
   309  		if *limit == 0 {
   310  			panic(errTooBigElements)
   311  		}
   312  		arr, ok := i.value[j].(*ByteArray)
   313  		if ok {
   314  			if !arr.equalsLimited(s.value[j], &maxComparableSize) {
   315  				return false
   316  			}
   317  		} else {
   318  			if maxComparableSize == 0 {
   319  				panic(errTooBigComparable)
   320  			}
   321  			maxComparableSize--
   322  			sa, oka := i.value[j].(*Struct)
   323  			sb, okb := s.value[j].(*Struct)
   324  			if oka && okb {
   325  				if !sa.equalStruct(sb, limit) {
   326  					return false
   327  				}
   328  			} else if !i.value[j].Equals(s.value[j]) {
   329  				return false
   330  			}
   331  		}
   332  	}
   333  	return true
   334  }
   335  
   336  // Type implements the Item interface.
   337  func (i *Struct) Type() Type { return StructT }
   338  
   339  // Convert implements the Item interface.
   340  func (i *Struct) Convert(typ Type) (Item, error) {
   341  	switch typ {
   342  	case StructT:
   343  		return i, nil
   344  	case ArrayT:
   345  		arr := make([]Item, len(i.value))
   346  		copy(arr, i.value)
   347  		return NewArray(arr), nil
   348  	case BooleanT:
   349  		return NewBool(true), nil
   350  	default:
   351  		return nil, mkInvConversion(i, typ)
   352  	}
   353  }
   354  
   355  // Clone returns a Struct with all Struct fields copied by the value.
   356  // Array fields are still copied by reference.
   357  func (i *Struct) Clone() (*Struct, error) {
   358  	var limit = MaxClonableNumOfItems - 1 // For this struct itself.
   359  	return i.clone(&limit)
   360  }
   361  
   362  func (i *Struct) clone(limit *int) (*Struct, error) {
   363  	ret := &Struct{value: make([]Item, len(i.value))}
   364  	for j := range i.value {
   365  		*limit--
   366  		if *limit < 0 {
   367  			return nil, ErrTooBig
   368  		}
   369  		switch t := i.value[j].(type) {
   370  		case *Struct:
   371  			var err error
   372  
   373  			ret.value[j], err = t.clone(limit)
   374  			if err != nil {
   375  				return nil, err
   376  			}
   377  		default:
   378  			ret.value[j] = t
   379  		}
   380  	}
   381  	return ret, nil
   382  }
   383  
   384  // Null represents null on the stack.
   385  type Null struct{}
   386  
   387  // String implements the Item interface.
   388  func (i Null) String() string {
   389  	return "Null"
   390  }
   391  
   392  // Value implements the Item interface.
   393  func (i Null) Value() any {
   394  	return nil
   395  }
   396  
   397  // Dup implements the Item interface.
   398  // There is no need to perform a real copy here
   399  // since Null has no internal state.
   400  func (i Null) Dup() Item {
   401  	return i
   402  }
   403  
   404  // TryBool implements the Item interface.
   405  func (i Null) TryBool() (bool, error) { return false, nil }
   406  
   407  // TryBytes implements the Item interface.
   408  func (i Null) TryBytes() ([]byte, error) {
   409  	return nil, mkInvConversion(i, ByteArrayT)
   410  }
   411  
   412  // TryInteger implements the Item interface.
   413  func (i Null) TryInteger() (*big.Int, error) {
   414  	return nil, mkInvConversion(i, IntegerT)
   415  }
   416  
   417  // Equals implements the Item interface.
   418  func (i Null) Equals(s Item) bool {
   419  	_, ok := s.(Null)
   420  	return ok
   421  }
   422  
   423  // Type implements the Item interface.
   424  func (i Null) Type() Type { return AnyT }
   425  
   426  // Convert implements the Item interface.
   427  func (i Null) Convert(typ Type) (Item, error) {
   428  	if typ == AnyT || !typ.IsValid() {
   429  		return nil, mkInvConversion(i, typ)
   430  	}
   431  	return i, nil
   432  }
   433  
   434  // BigInteger represents a big integer on the stack.
   435  type BigInteger big.Int
   436  
   437  // NewBigInteger returns an new BigInteger object.
   438  func NewBigInteger(value *big.Int) *BigInteger {
   439  	if err := CheckIntegerSize(value); err != nil {
   440  		panic(err)
   441  	}
   442  	return (*BigInteger)(value)
   443  }
   444  
   445  // CheckIntegerSize checks that the value size doesn't exceed the VM limit for Interer.
   446  func CheckIntegerSize(value *big.Int) error {
   447  	// There are 2 cases when `BitLen` differs from the actual size:
   448  	// 1. Positive integer with the highest bit on byte boundary = 1.
   449  	// 2. Negative integer with the highest bit on byte boundary = 1
   450  	//    minus some value. (-0x80 -> 0x80, -0x7F -> 0x81, -0x81 -> 0x7FFF).
   451  	sz := value.BitLen()
   452  	// This check is not required, just an optimization for the common case.
   453  	if sz < MaxBigIntegerSizeBits {
   454  		return nil
   455  	}
   456  	if sz > MaxBigIntegerSizeBits {
   457  		return errTooBigInteger
   458  	}
   459  	if value.Sign() == 1 || value.TrailingZeroBits() != MaxBigIntegerSizeBits-1 {
   460  		return errTooBigInteger
   461  	}
   462  	return nil
   463  }
   464  
   465  // Big casts i to the big.Int type.
   466  func (i *BigInteger) Big() *big.Int {
   467  	return (*big.Int)(i)
   468  }
   469  
   470  // Bytes converts i to a slice of bytes.
   471  func (i *BigInteger) Bytes() []byte {
   472  	return bigint.ToBytes(i.Big())
   473  }
   474  
   475  // TryBool implements the Item interface.
   476  func (i *BigInteger) TryBool() (bool, error) {
   477  	return i.Big().Sign() != 0, nil
   478  }
   479  
   480  // TryBytes implements the Item interface.
   481  func (i *BigInteger) TryBytes() ([]byte, error) {
   482  	return i.Bytes(), nil
   483  }
   484  
   485  // TryInteger implements the Item interface.
   486  func (i *BigInteger) TryInteger() (*big.Int, error) {
   487  	return i.Big(), nil
   488  }
   489  
   490  // Equals implements the Item interface.
   491  func (i *BigInteger) Equals(s Item) bool {
   492  	if i == s {
   493  		return true
   494  	} else if s == nil {
   495  		return false
   496  	}
   497  	val, ok := s.(*BigInteger)
   498  	return ok && i.Big().Cmp(val.Big()) == 0
   499  }
   500  
   501  // Value implements the Item interface.
   502  func (i *BigInteger) Value() any {
   503  	return i.Big()
   504  }
   505  
   506  func (i *BigInteger) String() string {
   507  	return "BigInteger"
   508  }
   509  
   510  // Dup implements the Item interface.
   511  func (i *BigInteger) Dup() Item {
   512  	n := new(big.Int)
   513  	return (*BigInteger)(n.Set(i.Big()))
   514  }
   515  
   516  // Type implements the Item interface.
   517  func (i *BigInteger) Type() Type { return IntegerT }
   518  
   519  // Convert implements the Item interface.
   520  func (i *BigInteger) Convert(typ Type) (Item, error) {
   521  	return convertPrimitive(i, typ)
   522  }
   523  
   524  // MarshalJSON implements the json.Marshaler interface.
   525  func (i *BigInteger) MarshalJSON() ([]byte, error) {
   526  	return json.Marshal(i.Big())
   527  }
   528  
   529  // Bool represents a boolean Item.
   530  type Bool bool
   531  
   532  // NewBool returns an new Bool object.
   533  func NewBool(val bool) Bool {
   534  	return Bool(val)
   535  }
   536  
   537  // Value implements the Item interface.
   538  func (i Bool) Value() any {
   539  	return bool(i)
   540  }
   541  
   542  // MarshalJSON implements the json.Marshaler interface.
   543  func (i Bool) MarshalJSON() ([]byte, error) {
   544  	return json.Marshal(bool(i))
   545  }
   546  
   547  func (i Bool) String() string {
   548  	return "Boolean"
   549  }
   550  
   551  // Dup implements the Item interface.
   552  func (i Bool) Dup() Item {
   553  	return i
   554  }
   555  
   556  // TryBool implements the Item interface.
   557  func (i Bool) TryBool() (bool, error) { return bool(i), nil }
   558  
   559  // Bytes converts Bool to bytes.
   560  func (i Bool) Bytes() []byte {
   561  	if i {
   562  		return []byte{1}
   563  	}
   564  	return []byte{0}
   565  }
   566  
   567  // TryBytes implements the Item interface.
   568  func (i Bool) TryBytes() ([]byte, error) {
   569  	return i.Bytes(), nil
   570  }
   571  
   572  // TryInteger implements the Item interface.
   573  func (i Bool) TryInteger() (*big.Int, error) {
   574  	if i {
   575  		return big.NewInt(1), nil
   576  	}
   577  	return big.NewInt(0), nil
   578  }
   579  
   580  // Equals implements the Item interface.
   581  func (i Bool) Equals(s Item) bool {
   582  	if i == s {
   583  		return true
   584  	} else if s == nil {
   585  		return false
   586  	}
   587  	val, ok := s.(Bool)
   588  	return ok && i == val
   589  }
   590  
   591  // Type implements the Item interface.
   592  func (i Bool) Type() Type { return BooleanT }
   593  
   594  // Convert implements the Item interface.
   595  func (i Bool) Convert(typ Type) (Item, error) {
   596  	return convertPrimitive(i, typ)
   597  }
   598  
   599  // ByteArray represents a byte array on the stack.
   600  type ByteArray []byte
   601  
   602  // NewByteArray returns an new ByteArray object.
   603  func NewByteArray(b []byte) *ByteArray {
   604  	return (*ByteArray)(&b)
   605  }
   606  
   607  // Value implements the Item interface.
   608  func (i *ByteArray) Value() any {
   609  	return []byte(*i)
   610  }
   611  
   612  // MarshalJSON implements the json.Marshaler interface.
   613  func (i *ByteArray) MarshalJSON() ([]byte, error) {
   614  	return json.Marshal(hex.EncodeToString(*i))
   615  }
   616  
   617  func (i *ByteArray) String() string {
   618  	return "ByteString"
   619  }
   620  
   621  // TryBool implements the Item interface.
   622  func (i *ByteArray) TryBool() (bool, error) {
   623  	if len(*i) > MaxBigIntegerSizeBits/8 {
   624  		return false, errTooBigInteger
   625  	}
   626  	for _, b := range *i {
   627  		if b != 0 {
   628  			return true, nil
   629  		}
   630  	}
   631  	return false, nil
   632  }
   633  
   634  // TryBytes implements the Item interface.
   635  func (i ByteArray) TryBytes() ([]byte, error) {
   636  	return i, nil
   637  }
   638  
   639  // TryInteger implements the Item interface.
   640  func (i ByteArray) TryInteger() (*big.Int, error) {
   641  	if len(i) > MaxBigIntegerSizeBits/8 {
   642  		return nil, errTooBigInteger
   643  	}
   644  	return bigint.FromBytes(i), nil
   645  }
   646  
   647  // Equals implements the Item interface.
   648  func (i *ByteArray) Equals(s Item) bool {
   649  	var limit = MaxByteArrayComparableSize
   650  	return i.equalsLimited(s, &limit)
   651  }
   652  
   653  // equalsLimited compares ByteArray with provided stackitem using the limit.
   654  func (i *ByteArray) equalsLimited(s Item, limit *int) bool {
   655  	if i == nil {
   656  		return s == nil
   657  	}
   658  	lCurr := len(*i)
   659  	if lCurr > *limit || *limit == 0 {
   660  		panic(errTooBigComparable)
   661  	}
   662  
   663  	var comparedSize = 1
   664  	defer func() { *limit -= comparedSize }()
   665  
   666  	if s == nil {
   667  		return false
   668  	}
   669  	val, ok := s.(*ByteArray)
   670  	if !ok {
   671  		return false
   672  	}
   673  	comparedSize = lCurr
   674  	lOther := len(*val)
   675  	if lOther > comparedSize {
   676  		comparedSize = lOther
   677  	}
   678  	if i == val {
   679  		return true
   680  	}
   681  	if lOther > *limit {
   682  		panic(errTooBigComparable)
   683  	}
   684  	return bytes.Equal(*i, *val)
   685  }
   686  
   687  // Dup implements the Item interface.
   688  func (i *ByteArray) Dup() Item {
   689  	ba := bytes.Clone(*i)
   690  	return (*ByteArray)(&ba)
   691  }
   692  
   693  // Type implements the Item interface.
   694  func (i *ByteArray) Type() Type { return ByteArrayT }
   695  
   696  // Convert implements the Item interface.
   697  func (i *ByteArray) Convert(typ Type) (Item, error) {
   698  	return convertPrimitive(i, typ)
   699  }
   700  
   701  // Array represents a new Array object.
   702  type Array struct {
   703  	value []Item
   704  	rc
   705  	ro
   706  }
   707  
   708  // NewArray returns a new Array object.
   709  func NewArray(items []Item) *Array {
   710  	return &Array{
   711  		value: items,
   712  	}
   713  }
   714  
   715  // Value implements the Item interface.
   716  func (i *Array) Value() any {
   717  	return i.value
   718  }
   719  
   720  // Remove removes the element at `pos` index from Array value.
   721  // It will panics on bad index.
   722  func (i *Array) Remove(pos int) {
   723  	if i.IsReadOnly() {
   724  		panic(ErrReadOnly)
   725  	}
   726  	i.value = append(i.value[:pos], i.value[pos+1:]...)
   727  }
   728  
   729  // Append adds an Item to the end of the Array value.
   730  func (i *Array) Append(item Item) {
   731  	if i.IsReadOnly() {
   732  		panic(ErrReadOnly)
   733  	}
   734  	i.value = append(i.value, item)
   735  }
   736  
   737  // Clear removes all elements from the Array item value.
   738  func (i *Array) Clear() {
   739  	if i.IsReadOnly() {
   740  		panic(ErrReadOnly)
   741  	}
   742  	i.value = i.value[:0]
   743  }
   744  
   745  // Len returns length of Array value.
   746  func (i *Array) Len() int {
   747  	return len(i.value)
   748  }
   749  
   750  // MarshalJSON implements the json.Marshaler interface.
   751  func (i *Array) MarshalJSON() ([]byte, error) {
   752  	return json.Marshal(i.value)
   753  }
   754  
   755  func (i *Array) String() string {
   756  	return "Array"
   757  }
   758  
   759  // TryBool implements the Item interface.
   760  func (i *Array) TryBool() (bool, error) { return true, nil }
   761  
   762  // TryBytes implements the Item interface.
   763  func (i *Array) TryBytes() ([]byte, error) {
   764  	return nil, mkInvConversion(i, ByteArrayT)
   765  }
   766  
   767  // TryInteger implements the Item interface.
   768  func (i *Array) TryInteger() (*big.Int, error) {
   769  	return nil, mkInvConversion(i, IntegerT)
   770  }
   771  
   772  // Equals implements the Item interface.
   773  func (i *Array) Equals(s Item) bool {
   774  	return i == s
   775  }
   776  
   777  // Dup implements the Item interface.
   778  func (i *Array) Dup() Item {
   779  	// reference type
   780  	return i
   781  }
   782  
   783  // Type implements the Item interface.
   784  func (i *Array) Type() Type { return ArrayT }
   785  
   786  // Convert implements the Item interface.
   787  func (i *Array) Convert(typ Type) (Item, error) {
   788  	switch typ {
   789  	case ArrayT:
   790  		return i, nil
   791  	case StructT:
   792  		arr := make([]Item, len(i.value))
   793  		copy(arr, i.value)
   794  		return NewStruct(arr), nil
   795  	case BooleanT:
   796  		return NewBool(true), nil
   797  	default:
   798  		return nil, mkInvConversion(i, typ)
   799  	}
   800  }
   801  
   802  // MapElement is a key-value pair of StackItems.
   803  type MapElement struct {
   804  	Key   Item
   805  	Value Item
   806  }
   807  
   808  // Map represents a Map object. It's ordered, so we use slice representation,
   809  // which should be fine for maps with less than 32 or so elements. Given that
   810  // our VM has quite low limit of overall stack items, it should be good enough,
   811  // but it can be extended with a real map for fast random access in the future
   812  // if needed.
   813  type Map struct {
   814  	value []MapElement
   815  	rc
   816  	ro
   817  }
   818  
   819  // NewMap returns a new Map object.
   820  func NewMap() *Map {
   821  	return &Map{
   822  		value: make([]MapElement, 0),
   823  	}
   824  }
   825  
   826  // NewMapWithValue returns a new Map object filled with the specified value.
   827  func NewMapWithValue(value []MapElement) *Map {
   828  	if value != nil {
   829  		return &Map{
   830  			value: value,
   831  		}
   832  	}
   833  	return NewMap()
   834  }
   835  
   836  // Value implements the Item interface.
   837  func (i *Map) Value() any {
   838  	return i.value
   839  }
   840  
   841  // Clear removes all elements from the Map item value.
   842  func (i *Map) Clear() {
   843  	if i.IsReadOnly() {
   844  		panic(ErrReadOnly)
   845  	}
   846  	i.value = i.value[:0]
   847  }
   848  
   849  // Len returns the length of the Map value.
   850  func (i *Map) Len() int {
   851  	return len(i.value)
   852  }
   853  
   854  // TryBool implements the Item interface.
   855  func (i *Map) TryBool() (bool, error) { return true, nil }
   856  
   857  // TryBytes implements the Item interface.
   858  func (i *Map) TryBytes() ([]byte, error) {
   859  	return nil, mkInvConversion(i, ByteArrayT)
   860  }
   861  
   862  // TryInteger implements the Item interface.
   863  func (i *Map) TryInteger() (*big.Int, error) {
   864  	return nil, mkInvConversion(i, IntegerT)
   865  }
   866  
   867  // Equals implements the Item interface.
   868  func (i *Map) Equals(s Item) bool {
   869  	return i == s
   870  }
   871  
   872  func (i *Map) String() string {
   873  	return "Map"
   874  }
   875  
   876  // Index returns an index of the key in map.
   877  func (i *Map) Index(key Item) int {
   878  	for k := range i.value {
   879  		if i.value[k].Key.Equals(key) {
   880  			return k
   881  		}
   882  	}
   883  	return -1
   884  }
   885  
   886  // Has checks if the map has the specified key.
   887  func (i *Map) Has(key Item) bool {
   888  	return i.Index(key) >= 0
   889  }
   890  
   891  // Dup implements the Item interface.
   892  func (i *Map) Dup() Item {
   893  	// reference type
   894  	return i
   895  }
   896  
   897  // Type implements the Item interface.
   898  func (i *Map) Type() Type { return MapT }
   899  
   900  // Convert implements the Item interface.
   901  func (i *Map) Convert(typ Type) (Item, error) {
   902  	switch typ {
   903  	case MapT:
   904  		return i, nil
   905  	case BooleanT:
   906  		return NewBool(true), nil
   907  	default:
   908  		return nil, mkInvConversion(i, typ)
   909  	}
   910  }
   911  
   912  // Add adds a key-value pair to the map.
   913  func (i *Map) Add(key, value Item) {
   914  	if err := IsValidMapKey(key); err != nil {
   915  		panic(err)
   916  	}
   917  	if i.IsReadOnly() {
   918  		panic(ErrReadOnly)
   919  	}
   920  	index := i.Index(key)
   921  	if index >= 0 {
   922  		i.value[index].Value = value
   923  	} else {
   924  		i.value = append(i.value, MapElement{key, value})
   925  	}
   926  }
   927  
   928  // Drop removes the given index from the map (no bounds check done here).
   929  func (i *Map) Drop(index int) {
   930  	if i.IsReadOnly() {
   931  		panic(ErrReadOnly)
   932  	}
   933  	copy(i.value[index:], i.value[index+1:])
   934  	i.value = i.value[:len(i.value)-1]
   935  }
   936  
   937  // IsValidMapKey checks whether it's possible to use the given Item as a Map
   938  // key.
   939  func IsValidMapKey(key Item) error {
   940  	switch key.(type) {
   941  	case Bool, *BigInteger:
   942  		return nil
   943  	case *ByteArray:
   944  		size := len(key.Value().([]byte))
   945  		if size > MaxKeySize {
   946  			return errTooBigKey
   947  		}
   948  		return nil
   949  	default:
   950  		return fmt.Errorf("%w: %s map key", ErrInvalidType, key.Type())
   951  	}
   952  }
   953  
   954  // Interop represents interop data on the stack.
   955  type Interop struct {
   956  	value any
   957  }
   958  
   959  // NewInterop returns a new Interop object.
   960  func NewInterop(value any) *Interop {
   961  	return &Interop{
   962  		value: value,
   963  	}
   964  }
   965  
   966  // Value implements the Item interface.
   967  func (i *Interop) Value() any {
   968  	return i.value
   969  }
   970  
   971  // String implements stringer interface.
   972  func (i *Interop) String() string {
   973  	return "InteropInterface"
   974  }
   975  
   976  // Dup implements the Item interface.
   977  func (i *Interop) Dup() Item {
   978  	// reference type
   979  	return i
   980  }
   981  
   982  // TryBool implements the Item interface.
   983  func (i *Interop) TryBool() (bool, error) { return true, nil }
   984  
   985  // TryBytes implements the Item interface.
   986  func (i *Interop) TryBytes() ([]byte, error) {
   987  	return nil, mkInvConversion(i, ByteArrayT)
   988  }
   989  
   990  // TryInteger implements the Item interface.
   991  func (i *Interop) TryInteger() (*big.Int, error) {
   992  	return nil, mkInvConversion(i, IntegerT)
   993  }
   994  
   995  // Equals implements the Item interface.
   996  func (i *Interop) Equals(s Item) bool {
   997  	if i == s {
   998  		return true
   999  	} else if s == nil {
  1000  		return false
  1001  	}
  1002  	val, ok := s.(*Interop)
  1003  	if !ok {
  1004  		return false
  1005  	}
  1006  	a, okA := i.value.(Equatable)
  1007  	b, okB := val.value.(Equatable)
  1008  	return (okA && okB && a.Equals(b)) || (!okA && !okB && i.value == val.value)
  1009  }
  1010  
  1011  // Type implements the Item interface.
  1012  func (i *Interop) Type() Type { return InteropT }
  1013  
  1014  // Convert implements the Item interface.
  1015  func (i *Interop) Convert(typ Type) (Item, error) {
  1016  	switch typ {
  1017  	case InteropT:
  1018  		return i, nil
  1019  	case BooleanT:
  1020  		return NewBool(true), nil
  1021  	default:
  1022  		return nil, mkInvConversion(i, typ)
  1023  	}
  1024  }
  1025  
  1026  // MarshalJSON implements the json.Marshaler interface.
  1027  func (i *Interop) MarshalJSON() ([]byte, error) {
  1028  	return json.Marshal(i.value)
  1029  }
  1030  
  1031  // Pointer represents a VM-level instruction pointer.
  1032  type Pointer struct {
  1033  	pos    int
  1034  	script []byte
  1035  	hash   util.Uint160
  1036  }
  1037  
  1038  // NewPointer returns a new pointer on the specified position.
  1039  func NewPointer(pos int, script []byte) *Pointer {
  1040  	return &Pointer{
  1041  		pos:    pos,
  1042  		script: script,
  1043  		hash:   hash.Hash160(script),
  1044  	}
  1045  }
  1046  
  1047  // NewPointerWithHash returns a new pointer on the specified position of the
  1048  // specified script. It differs from NewPointer in that the script hash is being
  1049  // passed explicitly to save on hash calculation. This hash is then being used
  1050  // for pointer comparisons.
  1051  func NewPointerWithHash(pos int, script []byte, h util.Uint160) *Pointer {
  1052  	return &Pointer{
  1053  		pos:    pos,
  1054  		script: script,
  1055  		hash:   h,
  1056  	}
  1057  }
  1058  
  1059  // String implements the Item interface.
  1060  func (p *Pointer) String() string {
  1061  	return "Pointer"
  1062  }
  1063  
  1064  // Value implements the Item interface.
  1065  func (p *Pointer) Value() any {
  1066  	return p.pos
  1067  }
  1068  
  1069  // Dup implements the Item interface.
  1070  func (p *Pointer) Dup() Item {
  1071  	return &Pointer{
  1072  		pos:    p.pos,
  1073  		script: p.script,
  1074  		hash:   p.hash,
  1075  	}
  1076  }
  1077  
  1078  // TryBool implements the Item interface.
  1079  func (p *Pointer) TryBool() (bool, error) {
  1080  	return true, nil
  1081  }
  1082  
  1083  // TryBytes implements the Item interface.
  1084  func (p *Pointer) TryBytes() ([]byte, error) {
  1085  	return nil, mkInvConversion(p, ByteArrayT)
  1086  }
  1087  
  1088  // TryInteger implements the Item interface.
  1089  func (p *Pointer) TryInteger() (*big.Int, error) {
  1090  	return nil, mkInvConversion(p, IntegerT)
  1091  }
  1092  
  1093  // Equals implements the Item interface.
  1094  func (p *Pointer) Equals(s Item) bool {
  1095  	if p == s {
  1096  		return true
  1097  	}
  1098  	ptr, ok := s.(*Pointer)
  1099  	return ok && p.pos == ptr.pos && p.hash == ptr.hash
  1100  }
  1101  
  1102  // Type implements the Item interface.
  1103  func (p *Pointer) Type() Type {
  1104  	return PointerT
  1105  }
  1106  
  1107  // Convert implements the Item interface.
  1108  func (p *Pointer) Convert(typ Type) (Item, error) {
  1109  	switch typ {
  1110  	case PointerT:
  1111  		return p, nil
  1112  	case BooleanT:
  1113  		return NewBool(true), nil
  1114  	default:
  1115  		return nil, mkInvConversion(p, typ)
  1116  	}
  1117  }
  1118  
  1119  // ScriptHash returns the pointer item hash.
  1120  func (p *Pointer) ScriptHash() util.Uint160 {
  1121  	return p.hash
  1122  }
  1123  
  1124  // Position returns the pointer item position.
  1125  func (p *Pointer) Position() int {
  1126  	return p.pos
  1127  }
  1128  
  1129  // Buffer represents represents a Buffer stack item.
  1130  type Buffer []byte
  1131  
  1132  // NewBuffer returns a new Buffer object.
  1133  func NewBuffer(b []byte) *Buffer {
  1134  	return (*Buffer)(&b)
  1135  }
  1136  
  1137  // Value implements the Item interface.
  1138  func (i *Buffer) Value() any {
  1139  	return []byte(*i)
  1140  }
  1141  
  1142  // String implements the fmt.Stringer interface.
  1143  func (i *Buffer) String() string {
  1144  	return "Buffer"
  1145  }
  1146  
  1147  // TryBool implements the Item interface.
  1148  func (i *Buffer) TryBool() (bool, error) {
  1149  	return true, nil
  1150  }
  1151  
  1152  // TryBytes implements the Item interface.
  1153  func (i *Buffer) TryBytes() ([]byte, error) {
  1154  	return *i, nil
  1155  }
  1156  
  1157  // TryInteger implements the Item interface.
  1158  func (i *Buffer) TryInteger() (*big.Int, error) {
  1159  	return nil, mkInvConversion(i, IntegerT)
  1160  }
  1161  
  1162  // Equals implements the Item interface.
  1163  func (i *Buffer) Equals(s Item) bool {
  1164  	return i == s
  1165  }
  1166  
  1167  // Dup implements the Item interface.
  1168  func (i *Buffer) Dup() Item {
  1169  	return i
  1170  }
  1171  
  1172  // MarshalJSON implements the json.Marshaler interface.
  1173  func (i *Buffer) MarshalJSON() ([]byte, error) {
  1174  	return json.Marshal(hex.EncodeToString(*i))
  1175  }
  1176  
  1177  // Type implements the Item interface.
  1178  func (i *Buffer) Type() Type { return BufferT }
  1179  
  1180  // Convert implements the Item interface.
  1181  func (i *Buffer) Convert(typ Type) (Item, error) {
  1182  	switch typ {
  1183  	case BooleanT:
  1184  		return NewBool(true), nil
  1185  	case BufferT:
  1186  		return i, nil
  1187  	case ByteArrayT:
  1188  		return NewByteArray(bytes.Clone(*i)), nil
  1189  	case IntegerT:
  1190  		if len(*i) > MaxBigIntegerSizeBits/8 {
  1191  			return nil, errTooBigInteger
  1192  		}
  1193  		return NewBigInteger(bigint.FromBytes(*i)), nil
  1194  	default:
  1195  		return nil, mkInvConversion(i, typ)
  1196  	}
  1197  }
  1198  
  1199  // Len returns the length of the Buffer value.
  1200  func (i *Buffer) Len() int {
  1201  	return len(*i)
  1202  }
  1203  
  1204  // DeepCopy returns a new deep copy of the provided item.
  1205  // Values of Interop items are not deeply copied.
  1206  // It does preserve duplicates only for non-primitive types.
  1207  func DeepCopy(item Item, asImmutable bool) Item {
  1208  	seen := make(map[Item]Item, typicalNumOfItems)
  1209  	return deepCopy(item, seen, asImmutable)
  1210  }
  1211  
  1212  func deepCopy(item Item, seen map[Item]Item, asImmutable bool) Item {
  1213  	if it := seen[item]; it != nil {
  1214  		return it
  1215  	}
  1216  	switch it := item.(type) {
  1217  	case Null:
  1218  		return Null{}
  1219  	case *Array:
  1220  		arr := NewArray(make([]Item, len(it.value)))
  1221  		seen[item] = arr
  1222  		for i := range it.value {
  1223  			arr.value[i] = deepCopy(it.value[i], seen, asImmutable)
  1224  		}
  1225  		arr.MarkAsReadOnly()
  1226  		return arr
  1227  	case *Struct:
  1228  		arr := NewStruct(make([]Item, len(it.value)))
  1229  		seen[item] = arr
  1230  		for i := range it.value {
  1231  			arr.value[i] = deepCopy(it.value[i], seen, asImmutable)
  1232  		}
  1233  		arr.MarkAsReadOnly()
  1234  		return arr
  1235  	case *Map:
  1236  		m := NewMap()
  1237  		seen[item] = m
  1238  		for i := range it.value {
  1239  			key := deepCopy(it.value[i].Key, seen,
  1240  				false) // Key is always primitive and not a Buffer.
  1241  			value := deepCopy(it.value[i].Value, seen, asImmutable)
  1242  			m.Add(key, value)
  1243  		}
  1244  		m.MarkAsReadOnly()
  1245  		return m
  1246  	case *BigInteger:
  1247  		bi := new(big.Int).Set(it.Big())
  1248  		return (*BigInteger)(bi)
  1249  	case *ByteArray:
  1250  		return NewByteArray(bytes.Clone(*it))
  1251  	case *Buffer:
  1252  		if asImmutable {
  1253  			return NewByteArray(bytes.Clone(*it))
  1254  		}
  1255  		return NewBuffer(bytes.Clone(*it))
  1256  	case Bool:
  1257  		return it
  1258  	case *Pointer:
  1259  		return NewPointerWithHash(it.pos, it.script, it.hash)
  1260  	case *Interop:
  1261  		return NewInterop(it.value)
  1262  	default:
  1263  		return nil
  1264  	}
  1265  }