github.com/MetalBlockchain/metalgo@v1.11.9/vms/nftfx/fx.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package nftfx
     5  
     6  import (
     7  	"bytes"
     8  	"errors"
     9  
    10  	"github.com/MetalBlockchain/metalgo/vms/components/verify"
    11  	"github.com/MetalBlockchain/metalgo/vms/secp256k1fx"
    12  )
    13  
    14  var (
    15  	errWrongTxType         = errors.New("wrong tx type")
    16  	errWrongUTXOType       = errors.New("wrong utxo type")
    17  	errWrongOperationType  = errors.New("wrong operation type")
    18  	errWrongCredentialType = errors.New("wrong credential type")
    19  	errWrongNumberOfUTXOs  = errors.New("wrong number of UTXOs for the operation")
    20  	errWrongUniqueID       = errors.New("wrong unique ID provided")
    21  	errWrongBytes          = errors.New("wrong bytes provided")
    22  	errCantTransfer        = errors.New("cant transfer with this fx")
    23  )
    24  
    25  type Fx struct{ secp256k1fx.Fx }
    26  
    27  func (fx *Fx) Initialize(vmIntf interface{}) error {
    28  	if err := fx.InitializeVM(vmIntf); err != nil {
    29  		return err
    30  	}
    31  
    32  	log := fx.VM.Logger()
    33  	log.Debug("initializing nft fx")
    34  
    35  	c := fx.VM.CodecRegistry()
    36  	return errors.Join(
    37  		c.RegisterType(&MintOutput{}),
    38  		c.RegisterType(&TransferOutput{}),
    39  		c.RegisterType(&MintOperation{}),
    40  		c.RegisterType(&TransferOperation{}),
    41  		c.RegisterType(&Credential{}),
    42  	)
    43  }
    44  
    45  func (fx *Fx) VerifyOperation(txIntf, opIntf, credIntf interface{}, utxosIntf []interface{}) error {
    46  	tx, ok := txIntf.(secp256k1fx.UnsignedTx)
    47  	switch {
    48  	case !ok:
    49  		return errWrongTxType
    50  	case len(utxosIntf) != 1:
    51  		return errWrongNumberOfUTXOs
    52  	}
    53  
    54  	cred, ok := credIntf.(*Credential)
    55  	if !ok {
    56  		return errWrongCredentialType
    57  	}
    58  
    59  	switch op := opIntf.(type) {
    60  	case *MintOperation:
    61  		return fx.VerifyMintOperation(tx, op, cred, utxosIntf[0])
    62  	case *TransferOperation:
    63  		return fx.VerifyTransferOperation(tx, op, cred, utxosIntf[0])
    64  	default:
    65  		return errWrongOperationType
    66  	}
    67  }
    68  
    69  func (fx *Fx) VerifyMintOperation(tx secp256k1fx.UnsignedTx, op *MintOperation, cred *Credential, utxoIntf interface{}) error {
    70  	out, ok := utxoIntf.(*MintOutput)
    71  	if !ok {
    72  		return errWrongUTXOType
    73  	}
    74  
    75  	if err := verify.All(op, cred, out); err != nil {
    76  		return err
    77  	}
    78  
    79  	switch {
    80  	case out.GroupID != op.GroupID:
    81  		return errWrongUniqueID
    82  	default:
    83  		return fx.Fx.VerifyCredentials(tx, &op.MintInput, &cred.Credential, &out.OutputOwners)
    84  	}
    85  }
    86  
    87  func (fx *Fx) VerifyTransferOperation(tx secp256k1fx.UnsignedTx, op *TransferOperation, cred *Credential, utxoIntf interface{}) error {
    88  	out, ok := utxoIntf.(*TransferOutput)
    89  	if !ok {
    90  		return errWrongUTXOType
    91  	}
    92  
    93  	if err := verify.All(op, cred, out); err != nil {
    94  		return err
    95  	}
    96  
    97  	switch {
    98  	case out.GroupID != op.Output.GroupID:
    99  		return errWrongUniqueID
   100  	case !bytes.Equal(out.Payload, op.Output.Payload):
   101  		return errWrongBytes
   102  	default:
   103  		return fx.VerifyCredentials(tx, &op.Input, &cred.Credential, &out.OutputOwners)
   104  	}
   105  }
   106  
   107  func (*Fx) VerifyTransfer(_, _, _, _ interface{}) error {
   108  	return errCantTransfer
   109  }