github.com/ava-labs/avalanchego@v1.11.11/vms/avm/txs/operation.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package txs
     5  
     6  import (
     7  	"bytes"
     8  	"errors"
     9  	"sort"
    10  
    11  	"github.com/ava-labs/avalanchego/codec"
    12  	"github.com/ava-labs/avalanchego/ids"
    13  	"github.com/ava-labs/avalanchego/utils"
    14  	"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
    15  	"github.com/ava-labs/avalanchego/vms/avm/fxs"
    16  	"github.com/ava-labs/avalanchego/vms/components/avax"
    17  	"github.com/ava-labs/avalanchego/vms/components/verify"
    18  )
    19  
    20  var (
    21  	ErrNilOperation              = errors.New("nil operation is not valid")
    22  	ErrNilFxOperation            = errors.New("nil fx operation is not valid")
    23  	ErrNotSortedAndUniqueUTXOIDs = errors.New("utxo IDs not sorted and unique")
    24  )
    25  
    26  type Operation struct {
    27  	avax.Asset `serialize:"true"`
    28  	UTXOIDs    []*avax.UTXOID  `serialize:"true"  json:"inputIDs"`
    29  	FxID       ids.ID          `serialize:"false" json:"fxID"`
    30  	Op         fxs.FxOperation `serialize:"true"  json:"operation"`
    31  }
    32  
    33  func (op *Operation) Verify() error {
    34  	switch {
    35  	case op == nil:
    36  		return ErrNilOperation
    37  	case op.Op == nil:
    38  		return ErrNilFxOperation
    39  	case !utils.IsSortedAndUnique(op.UTXOIDs):
    40  		return ErrNotSortedAndUniqueUTXOIDs
    41  	default:
    42  		return verify.All(&op.Asset, op.Op)
    43  	}
    44  }
    45  
    46  type operationAndCodec struct {
    47  	op    *Operation
    48  	codec codec.Manager
    49  }
    50  
    51  func (o *operationAndCodec) Compare(other *operationAndCodec) int {
    52  	oBytes, err := o.codec.Marshal(CodecVersion, o.op)
    53  	if err != nil {
    54  		return 0
    55  	}
    56  	otherBytes, err := o.codec.Marshal(CodecVersion, other.op)
    57  	if err != nil {
    58  		return 0
    59  	}
    60  	return bytes.Compare(oBytes, otherBytes)
    61  }
    62  
    63  func SortOperations(ops []*Operation, c codec.Manager) {
    64  	sortableOps := make([]*operationAndCodec, len(ops))
    65  	for i, op := range ops {
    66  		sortableOps[i] = &operationAndCodec{
    67  			op:    op,
    68  			codec: c,
    69  		}
    70  	}
    71  
    72  	utils.Sort(sortableOps)
    73  	for i, sortableOp := range sortableOps {
    74  		ops[i] = sortableOp.op
    75  	}
    76  }
    77  
    78  func IsSortedAndUniqueOperations(ops []*Operation, c codec.Manager) bool {
    79  	sortableOps := make([]*operationAndCodec, len(ops))
    80  	for i, op := range ops {
    81  		sortableOps[i] = &operationAndCodec{
    82  			op:    op,
    83  			codec: c,
    84  		}
    85  	}
    86  	return utils.IsSortedAndUnique(sortableOps)
    87  }
    88  
    89  type innerSortOperationsWithSigners struct {
    90  	ops     []*Operation
    91  	signers [][]*secp256k1.PrivateKey
    92  	codec   codec.Manager
    93  }
    94  
    95  func (ops *innerSortOperationsWithSigners) Less(i, j int) bool {
    96  	iOp := ops.ops[i]
    97  	jOp := ops.ops[j]
    98  
    99  	iBytes, err := ops.codec.Marshal(CodecVersion, iOp)
   100  	if err != nil {
   101  		return false
   102  	}
   103  	jBytes, err := ops.codec.Marshal(CodecVersion, jOp)
   104  	if err != nil {
   105  		return false
   106  	}
   107  	return bytes.Compare(iBytes, jBytes) == -1
   108  }
   109  
   110  func (ops *innerSortOperationsWithSigners) Len() int {
   111  	return len(ops.ops)
   112  }
   113  
   114  func (ops *innerSortOperationsWithSigners) Swap(i, j int) {
   115  	ops.ops[j], ops.ops[i] = ops.ops[i], ops.ops[j]
   116  	ops.signers[j], ops.signers[i] = ops.signers[i], ops.signers[j]
   117  }
   118  
   119  func SortOperationsWithSigners(ops []*Operation, signers [][]*secp256k1.PrivateKey, codec codec.Manager) {
   120  	sort.Sort(&innerSortOperationsWithSigners{ops: ops, signers: signers, codec: codec})
   121  }