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  }