github.com/MetalBlockchain/metalgo@v1.11.9/vms/propertyfx/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 propertyfx
     5  
     6  import (
     7  	"errors"
     8  
     9  	"github.com/MetalBlockchain/metalgo/vms/components/verify"
    10  	"github.com/MetalBlockchain/metalgo/vms/secp256k1fx"
    11  )
    12  
    13  var (
    14  	errWrongTxType         = errors.New("wrong tx type")
    15  	errWrongUTXOType       = errors.New("wrong utxo type")
    16  	errWrongOperationType  = errors.New("wrong operation type")
    17  	errWrongCredentialType = errors.New("wrong credential type")
    18  	errWrongNumberOfUTXOs  = errors.New("wrong number of UTXOs for the operation")
    19  	errWrongMintOutput     = errors.New("wrong mint output provided")
    20  	errCantTransfer        = errors.New("cant transfer with this fx")
    21  )
    22  
    23  type Fx struct{ secp256k1fx.Fx }
    24  
    25  func (fx *Fx) Initialize(vmIntf interface{}) error {
    26  	if err := fx.InitializeVM(vmIntf); err != nil {
    27  		return err
    28  	}
    29  
    30  	log := fx.VM.Logger()
    31  	log.Debug("initializing nft fx")
    32  
    33  	c := fx.VM.CodecRegistry()
    34  	return errors.Join(
    35  		c.RegisterType(&MintOutput{}),
    36  		c.RegisterType(&OwnedOutput{}),
    37  		c.RegisterType(&MintOperation{}),
    38  		c.RegisterType(&BurnOperation{}),
    39  		c.RegisterType(&Credential{}),
    40  	)
    41  }
    42  
    43  func (fx *Fx) VerifyOperation(txIntf, opIntf, credIntf interface{}, utxosIntf []interface{}) error {
    44  	tx, ok := txIntf.(secp256k1fx.UnsignedTx)
    45  	switch {
    46  	case !ok:
    47  		return errWrongTxType
    48  	case len(utxosIntf) != 1:
    49  		return errWrongNumberOfUTXOs
    50  	}
    51  
    52  	cred, ok := credIntf.(*Credential)
    53  	if !ok {
    54  		return errWrongCredentialType
    55  	}
    56  
    57  	switch op := opIntf.(type) {
    58  	case *MintOperation:
    59  		return fx.VerifyMintOperation(tx, op, cred, utxosIntf[0])
    60  	case *BurnOperation:
    61  		return fx.VerifyTransferOperation(tx, op, cred, utxosIntf[0])
    62  	default:
    63  		return errWrongOperationType
    64  	}
    65  }
    66  
    67  func (fx *Fx) VerifyMintOperation(tx secp256k1fx.UnsignedTx, op *MintOperation, cred *Credential, utxoIntf interface{}) error {
    68  	out, ok := utxoIntf.(*MintOutput)
    69  	if !ok {
    70  		return errWrongUTXOType
    71  	}
    72  
    73  	if err := verify.All(op, cred, out); err != nil {
    74  		return err
    75  	}
    76  
    77  	switch {
    78  	case !out.OutputOwners.Equals(&op.MintOutput.OutputOwners):
    79  		return errWrongMintOutput
    80  	default:
    81  		return fx.Fx.VerifyCredentials(tx, &op.MintInput, &cred.Credential, &out.OutputOwners)
    82  	}
    83  }
    84  
    85  func (fx *Fx) VerifyTransferOperation(tx secp256k1fx.UnsignedTx, op *BurnOperation, cred *Credential, utxoIntf interface{}) error {
    86  	out, ok := utxoIntf.(*OwnedOutput)
    87  	if !ok {
    88  		return errWrongUTXOType
    89  	}
    90  
    91  	if err := verify.All(op, cred, out); err != nil {
    92  		return err
    93  	}
    94  
    95  	return fx.VerifyCredentials(tx, &op.Input, &cred.Credential, &out.OutputOwners)
    96  }
    97  
    98  func (*Fx) VerifyTransfer(_, _, _, _ interface{}) error {
    99  	return errCantTransfer
   100  }