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 }