github.com/mavryk-network/mvgo@v1.19.9/micheline/primitives.go (about) 1 // Copyright (c) 2020-2024 Blockwatch Data Inc. 2 // Author: alex@blockwatch.cc 3 4 // Michelson type spec 5 // see http://protocol.mavryk.org/whitedoc/michelson.html#full-grammar 6 // 7 // PACK prefixes with 0x05! 8 // So that when contracts checking signatures (multisigs etc) do the current 9 // best practice, PACK; ...; CHECK_SIGNATURE, the 0x05 byte distinguishes the 10 // message from blocks, endorsements, transactions, or tezos-signer authorization 11 // requests (0x01-0x04) 12 13 package micheline 14 15 import ( 16 "bytes" 17 "crypto/sha256" 18 "encoding/binary" 19 "encoding/hex" 20 "encoding/json" 21 "errors" 22 "fmt" 23 "io" 24 "math/big" 25 "strconv" 26 "strings" 27 "time" 28 29 "github.com/mavryk-network/mvgo/mavryk" 30 ) 31 32 var ( 33 InvalidPrim = Prim{} 34 EmptyPrim = Prim{Type: PrimNullary, OpCode: 255} 35 36 PrimSkip = errors.New("skip branch") 37 ErrTypeMismatch = errors.New("type mismatch") 38 ) 39 40 type PrimType byte 41 42 const ( 43 PrimInt PrimType = iota // 00 {name: 'int'} 44 PrimString // 01 {name: 'string'} 45 PrimSequence // 02 [] 46 PrimNullary // 03 {name: 'prim', len: 0, annots: false}, 47 PrimNullaryAnno // 04 {name: 'prim', len: 0, annots: true}, 48 PrimUnary // 05 {name: 'prim', len: 1, annots: false}, 49 PrimUnaryAnno // 06 {name: 'prim', len: 1, annots: true}, 50 PrimBinary // 07 {name: 'prim', len: 2, annots: false}, 51 PrimBinaryAnno // 08 {name: 'prim', len: 2, annots: true}, 52 PrimVariadicAnno // 09 {name: 'prim', len: n, annots: true}, 53 PrimBytes // 0A {name: 'bytes' } 54 ) 55 56 func (t PrimType) TypeCode() OpCode { 57 switch t { 58 case PrimInt: 59 return T_INT 60 case PrimString: 61 return T_STRING 62 default: 63 return T_BYTES 64 } 65 } 66 67 func (t PrimType) IsValid() bool { 68 return t <= PrimBytes 69 } 70 71 func ParsePrimType(val string) (PrimType, error) { 72 switch val { 73 case INT: 74 return PrimInt, nil 75 case STRING: 76 return PrimString, nil 77 case BYTES: 78 return PrimBytes, nil 79 default: 80 return 0, fmt.Errorf("micheline: invalid prim type '%s'", val) 81 } 82 } 83 84 // non-normative strings, use for debugging only 85 func (t PrimType) String() string { 86 switch t { 87 case PrimInt: 88 return INT 89 case PrimString: 90 return STRING 91 case PrimSequence: 92 return "sequence" 93 case PrimNullary: 94 return "prim" 95 case PrimNullaryAnno: 96 return "prim+" 97 case PrimUnary: 98 return "unary" 99 case PrimUnaryAnno: 100 return "unary+" 101 case PrimBinary: 102 return "binary" 103 case PrimBinaryAnno: 104 return "binary+" 105 case PrimVariadicAnno: 106 return "variadic" 107 case PrimBytes: 108 return BYTES 109 default: 110 return "invalid" 111 } 112 } 113 114 func (t PrimType) MarshalText() ([]byte, error) { 115 return []byte(t.String()), nil 116 } 117 118 type PrimList []Prim 119 120 func (l PrimList) Last() Prim { 121 n := len(l) 122 if n == 0 { 123 return InvalidPrim 124 } 125 return l[n-1] 126 } 127 128 type Prim struct { 129 Type PrimType // primitive type 130 OpCode OpCode // primitive opcode (invalid on sequences, strings, bytes, int) 131 Args PrimList // optional arguments 132 Anno []string // optional type annotations 133 Int *big.Int // optional data 134 String string // optional data 135 Bytes []byte // optional data 136 WasPacked bool // true when content was unpacked (and no type info is available) 137 Path []int // optional path to this prim (use to track type structure) 138 } 139 140 func (p Prim) IsValid() bool { 141 return p.Type.IsValid() && (p.Type > 0 || p.Int != nil) 142 } 143 144 func (p Prim) IsEmpty() bool { 145 return p.Type == PrimNullary && p.OpCode == 255 146 } 147 148 func (p Prim) Size() int { 149 sz := szPrim + len(p.String) + len(p.Bytes) 150 if p.Int != nil { 151 sz += len(p.Int.Bytes()) 152 } 153 for _, v := range p.Anno { 154 sz += len(v) 155 } 156 for _, v := range p.Args { 157 sz += v.Size() 158 } 159 return sz 160 } 161 162 func (p Prim) Hash64() uint64 { 163 var buf []byte 164 if p.IsValid() { 165 buf, _ = p.MarshalBinary() 166 } 167 h := sha256.Sum256(buf) 168 return binary.BigEndian.Uint64(h[:8]) 169 } 170 171 func (p Prim) Clone() Prim { 172 clone := Prim{ 173 Type: p.Type, 174 OpCode: p.OpCode, 175 String: p.String, 176 WasPacked: p.WasPacked, 177 } 178 if p.Args != nil { 179 clone.Args = make([]Prim, len(p.Args)) 180 for i, arg := range p.Args { 181 clone.Args[i] = arg.Clone() 182 } 183 } 184 if p.Anno != nil { 185 clone.Anno = make([]string, len(p.Anno)) 186 copy(clone.Anno, p.Anno) 187 } 188 if p.Int != nil { 189 clone.Int = big.NewInt(0) 190 clone.Int.Set(p.Int) 191 } 192 if p.Bytes != nil { 193 clone.Bytes = make([]byte, len(p.Bytes)) 194 copy(clone.Bytes, p.Bytes) 195 } 196 return clone 197 } 198 199 func (p Prim) CloneNoAnnots() Prim { 200 typ := p.Type 201 switch typ { 202 case PrimNullaryAnno, PrimUnaryAnno, PrimBinaryAnno: 203 typ-- 204 } 205 clone := Prim{ 206 Type: typ, 207 OpCode: p.OpCode, 208 String: p.String, 209 WasPacked: p.WasPacked, 210 } 211 if p.Args != nil { 212 clone.Args = make([]Prim, len(p.Args)) 213 for i, arg := range p.Args { 214 clone.Args[i] = arg.CloneNoAnnots() 215 } 216 } 217 if p.Int != nil { 218 clone.Int = big.NewInt(0) 219 clone.Int.Set(p.Int) 220 } 221 if p.Bytes != nil { 222 clone.Bytes = make([]byte, len(p.Bytes)) 223 copy(clone.Bytes, p.Bytes) 224 } 225 return clone 226 } 227 228 func (p Prim) IsEqual(p2 Prim) bool { 229 return IsEqualPrim(p, p2, false) 230 } 231 232 func (p Prim) IsEqualWithAnno(p2 Prim) bool { 233 return IsEqualPrim(p, p2, true) 234 } 235 236 func (p Prim) Compare(p2 Prim) int { 237 if p.Type != p2.Type { 238 return 0 239 } 240 switch p.Type { 241 case PrimString: 242 return strings.Compare(p.String, p2.String) 243 case PrimBytes: 244 return bytes.Compare(p.Bytes, p2.Bytes) 245 case PrimInt: 246 return p.Int.Cmp(p2.Int) 247 default: 248 return 0 249 } 250 } 251 252 func IsEqualPrim(p1, p2 Prim, withAnno bool) bool { 253 if p1.OpCode != p2.OpCode { 254 return false 255 } 256 257 t1, t2 := p1.Type, p2.Type 258 if !withAnno { 259 switch t1 { 260 case PrimNullaryAnno, PrimUnaryAnno, PrimBinaryAnno: 261 t1-- 262 } 263 switch t2 { 264 case PrimNullaryAnno, PrimUnaryAnno, PrimBinaryAnno: 265 t2-- 266 } 267 } 268 if t1 != t2 { 269 return false 270 } 271 272 if len(p1.Args) != len(p2.Args) { 273 return false 274 } 275 276 if withAnno { 277 if len(p1.Anno) != len(p2.Anno) { 278 return false 279 } 280 for i := range p1.Anno { 281 l1, l2 := len(p1.Anno[i]), len(p2.Anno[i]) 282 if l1 != l2 { 283 return false 284 } 285 if l1 > 0 && l2 > 0 && p1.Anno[i][1:] != p2.Anno[i][1:] { 286 return false 287 } 288 } 289 } 290 291 if p1.String != p2.String { 292 return false 293 } 294 if (p1.Int == nil) != (p2.Int == nil) { 295 return false 296 } 297 if p1.Int != nil { 298 if p1.Int.Cmp(p2.Int) != 0 { 299 return false 300 } 301 } 302 if (p1.Bytes == nil) != (p2.Bytes == nil) { 303 return false 304 } 305 if p1.Bytes != nil { 306 if !bytes.Equal(p1.Bytes, p2.Bytes) { 307 return false 308 } 309 } 310 311 for i := range p1.Args { 312 if !IsEqualPrim(p1.Args[i], p2.Args[i], withAnno) { 313 return false 314 } 315 } 316 317 return true 318 } 319 320 // PrimWalkerFunc is the callback function signature used while 321 // traversing a prim tree in read-only mode. 322 type PrimWalkerFunc func(p Prim) error 323 324 // Walk traverses the prim tree in pre-order in read-only mode, forwarding 325 // value copies to the callback. 326 func (p Prim) Walk(f PrimWalkerFunc) error { 327 if err := f(p); err != nil { 328 if err == PrimSkip { 329 return nil 330 } 331 return err 332 } 333 for _, v := range p.Args { 334 if err := v.Walk(f); err != nil { 335 return err 336 } 337 } 338 return nil 339 } 340 341 // PrimWalkerFunc is the callback function signature used while 342 // traversing a prim tree. The callback may change the contents of 343 // the visited node, including altering nested child nodes and annotations. 344 type PrimVisitorFunc func(p *Prim) error 345 346 // Visit traverses the prim tree in pre-order and allows the callback to 347 // alter the contents of a visited node. 348 func (p *Prim) Visit(f PrimVisitorFunc) error { 349 if err := f(p); err != nil { 350 if err == PrimSkip { 351 return nil 352 } 353 return err 354 } 355 for i := range p.Args { 356 if err := p.Args[i].Visit(f); err != nil { 357 return err 358 } 359 } 360 return nil 361 } 362 363 // returns true when the prim can be expressed as a single value 364 // key/value pairs (ie. prims with annots) do not fit into this category 365 // used when mapping complex big map values to JSON objects 366 func (p Prim) IsScalar() bool { 367 switch p.Type { 368 case PrimInt, PrimString, PrimBytes, PrimNullary: 369 return true 370 case PrimSequence: 371 return len(p.Args) == 1 && !p.HasAnno() 372 case PrimNullaryAnno, PrimUnaryAnno, PrimBinaryAnno, PrimVariadicAnno: 373 return false 374 case PrimUnary: 375 switch p.OpCode { 376 case D_LEFT, D_RIGHT, D_SOME: 377 return p.Args[0].IsScalar() 378 } 379 return false 380 case PrimBinary: 381 switch p.OpCode { 382 case T_OPTION, T_OR: 383 return p.Args[0].IsScalar() 384 } 385 return false 386 } 387 return false 388 } 389 390 func (p Prim) IsSequence() bool { 391 return p.Type == PrimSequence 392 } 393 394 func (p Prim) IsInstruction() bool { 395 return p.OpCode.TypeCode() == T_LAMBDA 396 } 397 398 func (p Prim) IsTicket() bool { 399 return p.OpCode == T_TICKET 400 } 401 402 func (p Prim) IsSet() bool { 403 return p.OpCode == T_SET 404 } 405 406 func (p Prim) IsList() bool { 407 return p.OpCode == T_LIST 408 } 409 410 func (p Prim) IsMap() bool { 411 return p.OpCode == T_MAP 412 } 413 414 func (p Prim) IsLambda() bool { 415 return p.OpCode == T_LAMBDA 416 } 417 418 func (p Prim) IsElt() bool { 419 return p.OpCode == D_ELT 420 } 421 422 func (p Prim) IsConstant() bool { 423 return p.OpCode == H_CONSTANT 424 } 425 426 func (p Prim) IsPair() bool { 427 switch p.OpCode { 428 case T_PAIR, D_PAIR: 429 return true 430 } 431 return false 432 } 433 434 func (p Prim) IsNil() bool { 435 switch p.OpCode { 436 case D_UNIT, D_NONE: 437 return true 438 } 439 return false 440 } 441 442 func (p Prim) IsEmptyBigmap() bool { 443 return p.OpCode == I_EMPTY_BIG_MAP 444 } 445 446 func (p Prim) IsScalarType() bool { 447 switch p.OpCode { 448 case T_BOOL, 449 T_CONTRACT, 450 T_INT, 451 T_KEY, 452 T_KEY_HASH, 453 T_NAT, 454 T_SIGNATURE, 455 T_STRING, 456 T_BYTES, 457 T_MUMAV, 458 T_TIMESTAMP, 459 T_UNIT, 460 T_OPERATION, 461 T_ADDRESS, 462 T_CHAIN_ID, 463 T_NEVER, 464 T_BLS12_381_G1, 465 T_BLS12_381_G2, 466 T_BLS12_381_FR, 467 T_SAPLING_STATE, 468 T_SAPLING_TRANSACTION: 469 return true 470 default: 471 return false 472 } 473 } 474 475 func (p Prim) IsContainerType() bool { 476 switch p.OpCode { 477 case T_MAP, T_LIST, T_SET, T_LAMBDA: 478 return true 479 default: 480 return false 481 } 482 } 483 484 // Detects whether a primitive contains a regular pair or any form 485 // of container type. Pairs can be unfolded into flat sequences. 486 func (p Prim) CanUnfold(typ Type) bool { 487 // regular pairs (works for type and value trees) 488 if p.IsPair() { 489 return true 490 } 491 492 // Note: due to Tezos encoding issues, comb pairs in block receipts 493 // are naked sequences (they lack an enclosing pair wrapper), this means 494 // we have to distinquish them from other container types who also use 495 // a sequence as container, such as lists, sets, maps, lambdas 496 if p.IsContainerType() || typ.IsContainerType() { 497 return false 498 } 499 500 // When multiple optimized combs (i.e. naked sequences) are nested 501 // it is sometimes not possible to track the correct type in the 502 // type tree. Hence we revert to a heuristic that checks if the 503 // current primitive looks like a container type by checking its 504 // contents 505 if p.IsSequence() && !p.LooksLikeContainer() && !p.LooksLikeCode() { 506 return true 507 } 508 509 return false 510 } 511 512 // Checks if a Prim looks like an optimized (i.e. flat) comb sequence. 513 func (p Prim) IsConvertedComb() bool { 514 if !p.IsSequence() { 515 return false 516 } 517 for _, v := range p.Args { 518 if v.IsPair() { 519 return false 520 } 521 } 522 return len(p.Args) > 0 523 } 524 525 // Checks if a Prim looks like a container type. This is necessary to 526 // distinguish optimized comb pairs from other container types. 527 func (p Prim) LooksLikeContainer() bool { 528 // must be a sequence 529 if !p.IsSequence() { 530 return false 531 } 532 533 // empty container 534 if len(p.Args) == 0 { 535 return true 536 } 537 538 // contains Elt's 539 if p.Args[0].IsElt() && p.Args[len(p.Args)-1].IsElt() { 540 return true 541 } 542 543 // contains a single scalar 544 if len(p.Args) == 1 { 545 switch p.Args[0].Type { 546 case PrimInt, PrimString, PrimBytes, PrimNullary: 547 return true 548 } 549 } 550 551 // contains similar records 552 if p.HasSimilarChildTypes() { 553 return true 554 } 555 556 return false 557 } 558 559 // Checks if all children have the same type by generating a type tree from 560 // values. Can be used to identfy containers based on the existence of similar 561 // records. 562 // 563 // Works for simple and nested primitives but may mis-detect ambiguous 564 // simple types like PrimInt (used for int, nat, timestamp, mumav), or PrimString 565 // resp. PrimBytes. May also misdetect when optional types like T_OR, T_OPTION are 566 // used and their values are nil since we cannot detect embedded type here. 567 func (p Prim) HasSimilarChildTypes() bool { 568 if len(p.Args) == 0 { 569 return true 570 } 571 oc := p.Args[0].OpCode.TypeCode() 572 firstType := p.Args[0].BuildType() 573 for _, v := range p.Args[1:] { 574 var isSame bool 575 switch v.OpCode { 576 case D_SOME, D_NONE, D_FALSE, D_TRUE, D_LEFT, D_RIGHT: 577 isSame = oc == v.OpCode.TypeCode() 578 default: 579 isSame = firstType.IsSimilar(v.BuildType()) 580 } 581 if !isSame { 582 return false 583 } 584 } 585 return true 586 } 587 588 func (p Prim) LooksLikeMap() bool { 589 // must be a sequence 590 if !p.IsSequence() || len(p.Args) == 0 { 591 return false 592 } 593 594 // contents must be Elt 595 return p.Args[0].IsElt() && p.Args[len(p.Args)-1].IsElt() 596 } 597 598 func (p Prim) LooksLikeSet() bool { 599 // must be a sequence 600 if !p.IsSequence() || len(p.Args) == 0 { 601 return false 602 } 603 604 // contains similar records 605 if !p.HasSimilarChildTypes() { 606 return false 607 } 608 609 return true 610 } 611 612 // Checks if a Prim looks like a lambda type. 613 func (p Prim) LooksLikeCode() bool { 614 if p.OpCode == T_LAMBDA || p.IsInstruction() { 615 return true 616 } 617 618 if p.Type != PrimSequence || len(p.Args) == 0 { 619 return false 620 } 621 622 // first prim contains instruction ocpode 623 if p.Args[0].IsInstruction() { 624 return true 625 } 626 627 return false 628 } 629 630 // Converts a pair tree into a flat sequence. While Michelson 631 // optimized comb pairs are only used for right-side combs, this 632 // function applies to all pairs. It makes use of the type definition 633 // to identify which contained type is a regular pair, an already 634 // unfolded pair sequence or anther container type. 635 // 636 // - Works both on value trees and type trees. 637 // - When called on already converted comb sequences this function is a noop. 638 func (p Prim) UnfoldPair(typ Type) []Prim { 639 flat := make([]Prim, 0) 640 for i, v := range p.Args { 641 t := Type{} 642 if len(typ.Args) > i { 643 t = Type{typ.Args[i]} 644 } 645 if !v.WasPacked && v.CanUnfold(t) && !t.HasAnno() { 646 flat = append(flat, v.Args...) 647 } else { 648 flat = append(flat, v) 649 } 650 } 651 return flat 652 } 653 654 func (p Prim) UnfoldPairRecursive(typ Type) []Prim { 655 flat := make([]Prim, 0) 656 for i, v := range p.Args { 657 t := Type{} 658 if len(typ.Args) > i { 659 t = Type{typ.Args[i]} 660 } 661 if !v.WasPacked && v.CanUnfold(t) && !t.HasAnno() { 662 flat = append(flat, v.UnfoldPairRecursive(t)...) 663 } else { 664 flat = append(flat, v) 665 } 666 } 667 return flat 668 } 669 670 // Turns a pair sequence into a right-hand pair tree 671 func (p Prim) FoldPair() Prim { 672 if !p.IsSequence() || len(p.Args) < 2 { 673 return p 674 } 675 switch len(p.Args) { 676 case 2: 677 return NewPair(p.Args[0], p.Args[1]) 678 default: 679 return NewPair(p.Args[0], NewSeq(p.Args[1:]...).FoldPair()) 680 } 681 } 682 683 // Checks if a primitve contains a packed value such as a byte sequence 684 // generated with PACK (starting with 0x05), an address or ascii/utf string. 685 func (p Prim) IsPacked() bool { 686 return p.Type == PrimBytes && 687 (isPackedBytes(p.Bytes) || mavryk.IsAddressBytes(p.Bytes) || isASCIIBytes(p.Bytes)) 688 } 689 690 // Packs produces a packed serialization for of a primitive's contents that 691 // is prefixed with a 0x5 byte. 692 func (p Prim) Pack() []byte { 693 buf := bytes.NewBuffer(nil) 694 buf.WriteByte(0x5) 695 _ = p.EncodeBuffer(buf) 696 return buf.Bytes() 697 } 698 699 // Unpacks all primitive contents that looks like packed and returns a new primitive 700 // tree. 701 func (p Prim) Unpack() (pp Prim, err error) { 702 if !p.IsPacked() { 703 return p, fmt.Errorf("prim is not packed") 704 } 705 defer func() { 706 if e := recover(); e != nil { 707 pp = p 708 err = fmt.Errorf("prim is not packed") 709 } 710 }() 711 pp = Prim{WasPacked: true} 712 switch { 713 case isPackedBytes(p.Bytes): 714 if err := pp.UnmarshalBinary(p.Bytes[1:]); err != nil { 715 return p, err 716 } 717 if pp.IsPackedAny() { 718 if up, err := pp.UnpackAll(); err == nil { 719 pp = up 720 } 721 } 722 case mavryk.IsAddressBytes(p.Bytes): 723 a := mavryk.Address{} 724 if err := a.Decode(p.Bytes); err != nil { 725 return p, err 726 } 727 pp.Type = PrimString 728 pp.String = a.String() 729 case isASCII(string(p.Bytes)): 730 pp.Type = PrimString 731 pp.String = string(p.Bytes) 732 default: 733 pp = p 734 } 735 return pp, nil 736 } 737 738 func (p Prim) IsPackedAny() bool { 739 if p.IsPacked() { 740 return true 741 } 742 for _, v := range p.Args { 743 if v.IsPackedAny() { 744 return true 745 } 746 } 747 return false 748 } 749 750 func (p Prim) UnpackAll() (Prim, error) { 751 if p.IsPacked() { 752 return p.Unpack() 753 } 754 if p.LooksLikeCode() { 755 return p, nil 756 } 757 pp := p 758 pp.Args = make([]Prim, len(p.Args)) 759 for i, v := range p.Args { 760 if v.IsPackedAny() { 761 if up, err := v.UnpackAll(); err == nil { 762 pp.Args[i] = up 763 } 764 continue 765 } 766 pp.Args[i] = v 767 } 768 return pp, nil 769 } 770 771 // UnpackAsciiString converts ASCII strings inside byte prims. 772 func (p Prim) UnpackAsciiString() Prim { 773 if p.Bytes != nil { 774 if s := string(p.Bytes); isASCII(s) { 775 return Prim{ 776 Type: PrimString, 777 String: s, 778 } 779 } 780 } 781 return p 782 } 783 784 // UnpackAllAsciiStrings recursively converts all ASCII strings inside byte prims. 785 func (p Prim) UnpackAllAsciiStrings() Prim { 786 if len(p.Args) == 0 { 787 return p.UnpackAsciiString() 788 } 789 up := p 790 up.Args = make([]Prim, len(p.Args)) 791 for i, v := range p.Args { 792 up.Args[i] = v.UnpackAllAsciiStrings() 793 } 794 return up 795 } 796 797 // Returns a typed/decoded value from an encoded primitive. 798 func (p Prim) Value(as OpCode) interface{} { 799 var warn bool 800 switch p.Type { 801 case PrimInt: 802 switch as { 803 case T_TIMESTAMP: 804 tm := time.Unix(p.Int.Int64(), 0).UTC() 805 if y := tm.Year(); y < 0 || y >= 10000 { 806 return p.Int.Text(10) 807 } 808 return tm 809 default: 810 var z mavryk.Z 811 z.SetBig(p.Int) 812 return z 813 } 814 815 case PrimString: 816 switch as { 817 case T_TIMESTAMP: 818 if t, err := time.Parse(time.RFC3339, p.String); err == nil { 819 return t 820 } 821 return p.String 822 823 case T_KEY_HASH, T_ADDRESS, T_CONTRACT: 824 a, err := mavryk.ParseAddress(p.String) 825 if err == nil { 826 return a 827 } 828 829 case T_KEY: 830 k, err := mavryk.ParseKey(p.String) 831 if err == nil { 832 return k 833 } 834 835 case T_SIGNATURE: 836 s, err := mavryk.ParseSignature(p.String) 837 if err == nil { 838 return s 839 } 840 841 case T_CHAIN_ID: 842 id, err := mavryk.ParseChainIdHash(p.String) 843 if err == nil { 844 return id 845 } 846 847 default: 848 return p.String 849 } 850 return p.String 851 852 case PrimBytes: 853 switch as { 854 case T_KEY_HASH, T_ADDRESS, T_CONTRACT: 855 a := mavryk.Address{} 856 if err := a.Decode(p.Bytes); err == nil { 857 return a 858 } 859 case T_TX_ROLLUP_L2_ADDRESS: 860 return mavryk.NewAddress(mavryk.AddressTypeBls12_381, p.Bytes) 861 862 case T_KEY: 863 k := mavryk.Key{} 864 if err := k.UnmarshalBinary(p.Bytes); err == nil { 865 return k 866 } 867 868 case T_SIGNATURE: 869 s := mavryk.Signature{} 870 if err := s.UnmarshalBinary(p.Bytes); err == nil { 871 return s 872 } 873 874 case T_CHAIN_ID: 875 if len(p.Bytes) == mavryk.HashTypeChainId.Len { 876 return mavryk.NewChainIdHash(p.Bytes) 877 } 878 879 default: 880 // as hex, fallthrough 881 // case T_BYTES: 882 // case T_BLS12_381_G1, T_BLS12_381_G2, T_BLS12_381_FR: 883 // case T_SAPLING_STATE: 884 // case T_LAMBDA: 885 // case T_LIST, T_MAP, T_BIG_MAP, T_SET: 886 // case T_OPTION, T_OR, T_PAIR, T_UNIT: 887 // case T_OPERATION: 888 } 889 890 return hex.EncodeToString(p.Bytes) 891 892 case PrimUnary, PrimUnaryAnno: 893 switch as { 894 case T_OR: 895 switch p.OpCode { 896 case D_LEFT: 897 return p.Args[0].Value(as) 898 case D_RIGHT: 899 if len(p.Args) > 1 { 900 return p.Args[1].Value(as) 901 } else { 902 return p.Args[0].Value(as) 903 } 904 } 905 case T_OPTION: 906 switch p.OpCode { 907 case D_NONE: 908 return nil 909 case D_SOME: 910 return p.Args[0].Value(as) 911 } 912 default: 913 warn = true 914 } 915 916 case PrimNullary, PrimNullaryAnno: 917 switch p.OpCode { 918 case D_FALSE: 919 return false 920 case D_TRUE: 921 return true 922 case D_UNIT, D_NONE: 923 return nil 924 default: 925 return p.OpCode.String() 926 } 927 928 case PrimBinary, PrimBinaryAnno: 929 switch p.OpCode { 930 case D_PAIR, T_PAIR: 931 // FIXME: requires value tree decoration (types in opcodes) 932 // mangle pair contents into string, used when rendering complex keys 933 left := p.Args[0].Value(p.Args[0].OpCode) 934 if _, ok := left.(fmt.Stringer); !ok { 935 if _, ok := left.(string); !ok { 936 left = p.Args[0].OpCode.String() 937 } 938 } 939 right := p.Args[1].Value(p.Args[1].OpCode) 940 if _, ok := right.(fmt.Stringer); !ok { 941 if _, ok := right.(string); !ok { 942 right = p.Args[1].OpCode.String() 943 } 944 } 945 return fmt.Sprintf("%s,%s", left, right) 946 } 947 948 case PrimSequence: 949 switch p.OpCode { 950 case D_PAIR, T_PAIR: 951 // FIXME: requires value tree decoration (types in opcodes) 952 var b strings.Builder 953 for i, v := range p.Args { 954 if i > 0 { 955 b.WriteByte(',') 956 } 957 val := v.Value(v.OpCode) 958 if stringer, ok := val.(fmt.Stringer); !ok { 959 if str, ok := val.(string); !ok { 960 b.WriteString(v.OpCode.String()) 961 } else { 962 b.WriteString(str) 963 } 964 } else { 965 b.WriteString(stringer.String()) 966 } 967 } 968 return b.String() 969 970 default: 971 switch as { 972 case T_UNIT, T_LAMBDA, T_LIST, T_MAP, T_BIG_MAP, T_SET, T_SAPLING_STATE: 973 return p 974 default: 975 warn = true 976 } 977 } 978 979 default: 980 switch as { 981 case T_BOOL: 982 if p.OpCode == D_TRUE { 983 return true 984 } else if p.OpCode == D_FALSE { 985 return false 986 } 987 case T_LAMBDA: 988 return p.OpCode.String() 989 case T_BYTES: 990 return hex.EncodeToString(p.Bytes) 991 default: 992 warn = true 993 } 994 } 995 996 if warn && !p.WasPacked { 997 log.Warnf("Rendering prim type %s as %s: not implemented (%s)", p.Type, as, p.Dump()) 998 } 999 1000 return p 1001 } 1002 1003 func (p Prim) MarshalYAML() (any, error) { 1004 buf, err := p.MarshalJSON() 1005 if err != nil { 1006 return nil, err 1007 } 1008 return string(buf), nil 1009 } 1010 1011 func (p Prim) MarshalJSON() ([]byte, error) { 1012 buf := bytes.NewBuffer(make([]byte, 0, 4096)) 1013 p.EncodeJSON(buf) 1014 return buf.Bytes(), nil 1015 } 1016 1017 func (p Prim) EncodeJSON(buf *bytes.Buffer) { 1018 if !p.IsValid() { 1019 buf.WriteString("{}") 1020 return 1021 } 1022 switch p.Type { 1023 case PrimSequence: 1024 buf.WriteByte('[') 1025 for i, v := range p.Args { 1026 if i > 0 { 1027 buf.WriteByte(',') 1028 } 1029 v.EncodeJSON(buf) 1030 } 1031 buf.WriteByte(']') 1032 1033 case PrimInt: 1034 buf.WriteString(`{"int":"`) 1035 buf.WriteString(p.Int.Text(10)) 1036 buf.WriteString(`"}`) 1037 1038 case PrimString: 1039 buf.WriteString(`{"string":`) 1040 buf.WriteString(strconv.Quote(p.String)) 1041 buf.WriteByte('}') 1042 1043 case PrimBytes: 1044 buf.WriteString(`{"bytes":"`) 1045 buf.WriteString(hex.EncodeToString(p.Bytes)) 1046 buf.WriteString(`"}`) 1047 1048 default: 1049 buf.WriteString(`{"prim":"`) 1050 buf.WriteString(p.OpCode.String()) 1051 buf.WriteByte('"') 1052 if len(p.Anno) > 0 && len(p.Anno[0]) > 0 { 1053 buf.WriteString(`,"annots":[`) 1054 for i, v := range p.Anno { 1055 if i > 0 { 1056 buf.WriteByte(',') 1057 } 1058 buf.WriteString(strconv.Quote(v)) 1059 } 1060 buf.WriteByte(']') 1061 } 1062 if len(p.Args) > 0 { 1063 buf.WriteString(`,"args":[`) 1064 for i, v := range p.Args { 1065 if i > 0 { 1066 buf.WriteByte(',') 1067 } 1068 v.EncodeJSON(buf) 1069 } 1070 buf.WriteByte(']') 1071 } 1072 buf.WriteByte('}') 1073 } 1074 } 1075 1076 func (p Prim) ToBytes() []byte { 1077 buf, _ := p.MarshalBinary() 1078 return buf 1079 } 1080 1081 func (p Prim) MarshalBinary() ([]byte, error) { 1082 if !p.IsValid() { 1083 return nil, nil 1084 } 1085 buf := bytes.NewBuffer(nil) 1086 if err := p.EncodeBuffer(buf); err != nil { 1087 return nil, err 1088 } 1089 return buf.Bytes(), nil 1090 } 1091 1092 func (p Prim) EncodeBuffer(buf *bytes.Buffer) error { 1093 buf.WriteByte(byte(p.Type)) 1094 switch p.Type { 1095 case PrimInt: 1096 var z mavryk.Z 1097 z.SetBig(p.Int) 1098 if err := z.EncodeBuffer(buf); err != nil { 1099 return err 1100 } 1101 1102 case PrimString: 1103 binary.Write(buf, binary.BigEndian, uint32(len(p.String))) 1104 buf.WriteString(p.String) 1105 1106 case PrimSequence: 1107 seq := bytes.NewBuffer(nil) 1108 binary.Write(seq, binary.BigEndian, uint32(0)) 1109 for _, v := range p.Args { 1110 if err := v.EncodeBuffer(seq); err != nil { 1111 return err 1112 } 1113 } 1114 res := seq.Bytes() 1115 binary.BigEndian.PutUint32(res, uint32(len(res)-4)) 1116 buf.Write(res) 1117 1118 case PrimNullary: 1119 buf.WriteByte(byte(p.OpCode)) 1120 1121 case PrimNullaryAnno: 1122 buf.WriteByte(byte(p.OpCode)) 1123 anno := strings.Join(p.Anno, " ") 1124 binary.Write(buf, binary.BigEndian, uint32(len(anno))) 1125 buf.WriteString(anno) 1126 1127 case PrimUnary: 1128 buf.WriteByte(byte(p.OpCode)) 1129 for _, v := range p.Args { 1130 if err := v.EncodeBuffer(buf); err != nil { 1131 return err 1132 } 1133 } 1134 1135 case PrimUnaryAnno: 1136 buf.WriteByte(byte(p.OpCode)) 1137 for _, v := range p.Args { 1138 if err := v.EncodeBuffer(buf); err != nil { 1139 return err 1140 } 1141 } 1142 anno := strings.Join(p.Anno, " ") 1143 binary.Write(buf, binary.BigEndian, uint32(len(anno))) 1144 buf.WriteString(anno) 1145 1146 case PrimBinary: 1147 buf.WriteByte(byte(p.OpCode)) 1148 for _, v := range p.Args { 1149 if err := v.EncodeBuffer(buf); err != nil { 1150 return err 1151 } 1152 } 1153 1154 case PrimBinaryAnno: 1155 buf.WriteByte(byte(p.OpCode)) 1156 for _, v := range p.Args { 1157 if err := v.EncodeBuffer(buf); err != nil { 1158 return err 1159 } 1160 } 1161 anno := strings.Join(p.Anno, " ") 1162 binary.Write(buf, binary.BigEndian, uint32(len(anno))) 1163 buf.WriteString(anno) 1164 1165 case PrimVariadicAnno: 1166 buf.WriteByte(byte(p.OpCode)) 1167 1168 seq := bytes.NewBuffer(nil) 1169 binary.Write(seq, binary.BigEndian, uint32(0)) 1170 for _, v := range p.Args { 1171 if err := v.EncodeBuffer(seq); err != nil { 1172 return err 1173 } 1174 } 1175 res := seq.Bytes() 1176 binary.BigEndian.PutUint32(res, uint32(len(res)-4)) 1177 buf.Write(res) 1178 1179 anno := strings.Join(p.Anno, " ") 1180 binary.Write(buf, binary.BigEndian, uint32(len(anno))) 1181 buf.WriteString(anno) 1182 1183 case PrimBytes: 1184 binary.Write(buf, binary.BigEndian, uint32(len(p.Bytes))) 1185 buf.Write(p.Bytes) 1186 } 1187 1188 return nil 1189 } 1190 1191 func (p *Prim) UnmarshalJSON(data []byte) error { 1192 if len(data) == 0 { 1193 return nil 1194 } 1195 var val any 1196 if err := json.Unmarshal(data, &val); err != nil { 1197 return err 1198 } 1199 switch v := val.(type) { 1200 case []any: 1201 return p.UnpackSequence(v) 1202 case map[string]any: 1203 return p.UnpackPrimitive(v) 1204 default: 1205 return nil 1206 } 1207 } 1208 1209 func (p *Prim) UnpackJSON(val any) error { 1210 switch t := val.(type) { 1211 case map[string]any: 1212 return p.UnpackPrimitive(t) 1213 case []any: 1214 return p.UnpackSequence(t) 1215 default: 1216 return fmt.Errorf("micheline: unexpected json type %T", val) 1217 } 1218 } 1219 1220 func (p *Prim) UnpackSequence(val []any) error { 1221 p.Type = PrimSequence 1222 p.Args = make([]Prim, len(val)) 1223 for i, v := range val { 1224 if err := p.Args[i].UnpackJSON(v); err != nil { 1225 return err 1226 } 1227 } 1228 return nil 1229 } 1230 1231 func (p *Prim) UnpackPrimitive(val map[string]any) error { 1232 for n, v := range val { 1233 switch n { 1234 case PRIM: 1235 str, ok := v.(string) 1236 if !ok { 1237 return fmt.Errorf("micheline: invalid prim value type %T %v", v, v) 1238 } 1239 oc, err := ParseOpCode(str) 1240 if err != nil { 1241 return err 1242 } 1243 p.OpCode = oc 1244 p.Type = PrimNullary 1245 case INT: 1246 str, ok := v.(string) 1247 if !ok { 1248 return fmt.Errorf("micheline: invalid int value type %T %v", v, v) 1249 } 1250 i := big.NewInt(0) 1251 i.SetString(str, 0) 1252 p.Int = i 1253 p.Type = PrimInt 1254 case STRING: 1255 str, ok := v.(string) 1256 if !ok { 1257 return fmt.Errorf("micheline: invalid string value type %T %v", v, v) 1258 } 1259 p.String = str 1260 p.Type = PrimString 1261 case BYTES: 1262 str, ok := v.(string) 1263 if !ok { 1264 return fmt.Errorf("micheline: invalid bytes value type %T %v", v, v) 1265 } 1266 b, err := hex.DecodeString(str) 1267 if err != nil { 1268 return err 1269 } 1270 p.Bytes = b 1271 p.Type = PrimBytes 1272 case ANNOTS: 1273 slist, ok := v.([]any) 1274 if !ok { 1275 return fmt.Errorf("micheline: invalid annots value type %T %v", v, v) 1276 } 1277 for _, s := range slist { 1278 p.Anno = append(p.Anno, s.(string)) 1279 } 1280 } 1281 } 1282 1283 // update type when annots are present, but no more args are defined 1284 if len(p.Anno) > 0 && p.Type == PrimNullary { 1285 p.Type = PrimNullaryAnno 1286 } 1287 1288 // process args separately and detect type based on number of args 1289 if a, ok := val[ARGS]; ok { 1290 args, ok := a.([]any) 1291 if !ok { 1292 return fmt.Errorf("micheline: invalid args value type %T %v", a, a) 1293 } 1294 1295 switch len(args) { 1296 case 0: 1297 p.Type = PrimNullary 1298 case 1: 1299 if len(p.Anno) > 0 { 1300 p.Type = PrimUnaryAnno 1301 } else { 1302 p.Type = PrimUnary 1303 } 1304 case 2: 1305 if len(p.Anno) > 0 { 1306 p.Type = PrimBinaryAnno 1307 } else { 1308 p.Type = PrimBinary 1309 } 1310 default: 1311 p.Type = PrimVariadicAnno 1312 } 1313 1314 // every arg is handled as embedded primitive 1315 p.Args = make([]Prim, len(args)) 1316 for i, v := range args { 1317 if err := p.Args[i].UnpackJSON(v); err != nil { 1318 return err 1319 } 1320 } 1321 } 1322 return nil 1323 } 1324 1325 func (p *Prim) UnmarshalBinary(data []byte) error { 1326 return p.DecodeBuffer(bytes.NewBuffer(data)) 1327 } 1328 1329 func (p *Prim) DecodeBuffer(buf *bytes.Buffer) error { 1330 b := buf.Next(1) 1331 if len(b) == 0 { 1332 return io.ErrShortBuffer 1333 } 1334 tag := PrimType(b[0]) 1335 switch tag { 1336 case PrimInt: 1337 // data is a zarith number 1338 var z mavryk.Z 1339 if err := z.DecodeBuffer(buf); err != nil { 1340 return err 1341 } 1342 p.Int = z.Big() 1343 1344 case PrimString: 1345 // cross-check content size 1346 size := int(binary.BigEndian.Uint32(buf.Next(4))) 1347 if buf.Len() < size { 1348 return io.ErrShortBuffer 1349 } 1350 p.String = string(buf.Next(size)) 1351 1352 case PrimSequence: 1353 // cross-check content size 1354 size := int(binary.BigEndian.Uint32(buf.Next(4))) 1355 if buf.Len() < size { 1356 return io.ErrShortBuffer 1357 } 1358 // extract sub-buffer 1359 seq := bytes.NewBuffer(buf.Next(size)) 1360 // decode contained primitives 1361 p.Args = make([]Prim, 0) 1362 for seq.Len() > 0 { 1363 prim := Prim{} 1364 if err := prim.DecodeBuffer(seq); err != nil { 1365 return err 1366 } 1367 p.Args = append(p.Args, prim) 1368 } 1369 1370 case PrimNullary: 1371 // opcode only 1372 b := buf.Next(1) 1373 if len(b) == 0 { 1374 return io.ErrShortBuffer 1375 } 1376 p.OpCode = OpCode(b[0]) 1377 1378 case PrimNullaryAnno: 1379 // opcode with annotations 1380 b := buf.Next(1) 1381 if len(b) == 0 { 1382 return io.ErrShortBuffer 1383 } 1384 p.OpCode = OpCode(b[0]) 1385 1386 // annotation array byte size 1387 size := int(binary.BigEndian.Uint32(buf.Next(4))) 1388 if buf.Len() < size { 1389 return io.ErrShortBuffer 1390 } 1391 anno := buf.Next(size) 1392 p.Anno = strings.Split(string(anno), " ") 1393 1394 case PrimUnary: 1395 // opcode with single argument 1396 b := buf.Next(1) 1397 if len(b) == 0 { 1398 return io.ErrShortBuffer 1399 } 1400 p.OpCode = OpCode(b[0]) 1401 1402 // argument 1403 prim := Prim{} 1404 if err := prim.DecodeBuffer(buf); err != nil { 1405 return err 1406 } 1407 p.Args = append(p.Args, prim) 1408 1409 case PrimUnaryAnno: 1410 // opcode with single argument and annotations 1411 b := buf.Next(1) 1412 if len(b) == 0 { 1413 return io.ErrShortBuffer 1414 } 1415 p.OpCode = OpCode(b[0]) 1416 1417 // argument 1418 prim := Prim{} 1419 if err := prim.DecodeBuffer(buf); err != nil { 1420 return err 1421 } 1422 p.Args = append(p.Args, prim) 1423 1424 // annotation array byte size 1425 size := int(binary.BigEndian.Uint32(buf.Next(4))) 1426 if buf.Len() < size { 1427 return io.ErrShortBuffer 1428 } 1429 anno := buf.Next(size) 1430 p.Anno = strings.Split(string(anno), " ") 1431 1432 case PrimBinary: 1433 // opcode with two arguments 1434 b := buf.Next(1) 1435 if len(b) == 0 { 1436 return io.ErrShortBuffer 1437 } 1438 p.OpCode = OpCode(b[0]) 1439 1440 // 2 arguments 1441 for i := 0; i < 2; i++ { 1442 prim := Prim{} 1443 if err := prim.DecodeBuffer(buf); err != nil { 1444 return err 1445 } 1446 p.Args = append(p.Args, prim) 1447 } 1448 1449 case PrimBinaryAnno: 1450 // opcode with two arguments and annotations 1451 b := buf.Next(1) 1452 if len(b) == 0 { 1453 return io.ErrShortBuffer 1454 } 1455 p.OpCode = OpCode(b[0]) 1456 1457 // 2 arguments 1458 for i := 0; i < 2; i++ { 1459 prim := Prim{} 1460 if err := prim.DecodeBuffer(buf); err != nil { 1461 return err 1462 } 1463 p.Args = append(p.Args, prim) 1464 } 1465 1466 // annotation array byte size 1467 size := int(binary.BigEndian.Uint32(buf.Next(4))) 1468 if buf.Len() < size { 1469 return io.ErrShortBuffer 1470 } 1471 anno := buf.Next(size) 1472 p.Anno = strings.Split(string(anno), " ") 1473 1474 case PrimVariadicAnno: 1475 // opcode with N arguments and optional annotations 1476 b := buf.Next(1) 1477 if len(b) == 0 { 1478 return io.ErrShortBuffer 1479 } 1480 p.OpCode = OpCode(b[0]) 1481 1482 // argument array byte size 1483 size := int(binary.BigEndian.Uint32(buf.Next(4))) 1484 1485 // extract sub-buffer 1486 seq := bytes.NewBuffer(buf.Next(size)) 1487 1488 // decode contained primitives 1489 for seq.Len() > 0 { 1490 prim := Prim{} 1491 if err := prim.DecodeBuffer(seq); err != nil { 1492 return err 1493 } 1494 p.Args = append(p.Args, prim) 1495 } 1496 // annotation array byte size 1497 if buf.Len() < 4 { 1498 return io.ErrShortBuffer 1499 } 1500 size = int(binary.BigEndian.Uint32(buf.Next(4))) 1501 if buf.Len() < size { 1502 return io.ErrShortBuffer 1503 } 1504 anno := buf.Next(size) 1505 p.Anno = strings.Split(string(anno), " ") 1506 1507 case PrimBytes: 1508 // cross-check content size 1509 size := int(binary.BigEndian.Uint32(buf.Next(4))) 1510 if buf.Len() < size { 1511 return io.ErrShortBuffer 1512 } 1513 p.Bytes = buf.Next(size) 1514 1515 default: 1516 return fmt.Errorf("micheline: unknown primitive type 0x%x", byte(tag)) 1517 } 1518 p.Type = tag 1519 return nil 1520 } 1521 1522 func (p Prim) FindOpCodes(typ OpCode) ([]Prim, bool) { 1523 if p.OpCode == typ { 1524 return []Prim{p}, true 1525 } 1526 found := make([]Prim, 0) 1527 for i := range p.Args { 1528 x, ok := p.Args[i].FindOpCodes(typ) 1529 if ok { 1530 found = append(found, x...) 1531 } 1532 } 1533 return found, len(found) > 0 1534 } 1535 1536 func (p Prim) ContainsOpCode(typ OpCode) bool { 1537 if p.OpCode == typ { 1538 return true 1539 } 1540 for i := range p.Args { 1541 if p.Args[i].ContainsOpCode(typ) { 1542 return true 1543 } 1544 } 1545 return false 1546 } 1547 1548 func (p Prim) FindLabels(label string) ([]Prim, bool) { 1549 if p.MatchesAnno(label) { 1550 return []Prim{p}, true 1551 } 1552 found := make([]Prim, 0) 1553 for i := range p.Args { 1554 x, ok := p.Args[i].FindLabels(label) 1555 if ok { 1556 found = append(found, x...) 1557 } 1558 } 1559 return found, len(found) > 0 1560 } 1561 1562 func (p Prim) FindBigmapByName(name string) (Prim, bool) { 1563 if p.OpCode == T_BIG_MAP && p.MatchesAnno(name) { 1564 return p, true 1565 } 1566 for i := range p.Args { 1567 if pp, found := p.Args[i].FindBigmapByName(name); found { 1568 return pp, found 1569 } 1570 } 1571 return Prim{}, false 1572 }