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 }