mirror of https://github.com/poanetwork/gecko.git
119 lines
3.0 KiB
Go
119 lines
3.0 KiB
Go
package nftfx
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
|
|
"github.com/ava-labs/gecko/utils/wrappers"
|
|
"github.com/ava-labs/gecko/vms/components/verify"
|
|
"github.com/ava-labs/gecko/vms/secp256k1fx"
|
|
)
|
|
|
|
var (
|
|
errWrongTxType = errors.New("wrong tx type")
|
|
errWrongUTXOType = errors.New("wrong utxo type")
|
|
errWrongOperationType = errors.New("wrong operation type")
|
|
errWrongCredentialType = errors.New("wrong credential type")
|
|
|
|
errNoUTXOs = errors.New("an operation must consume at least one UTXO")
|
|
errWrongNumberOfUTXOs = errors.New("wrong number of UTXOs for the operation")
|
|
errWrongNumberOfCreds = errors.New("wrong number of credentials for the operation")
|
|
|
|
errWrongUniqueID = errors.New("wrong unique ID provided")
|
|
errWrongBytes = errors.New("wrong bytes provided")
|
|
|
|
errCantTransfer = errors.New("cant transfer with this fx")
|
|
)
|
|
|
|
// Fx ...
|
|
type Fx struct{ secp256k1fx.Fx }
|
|
|
|
// Initialize ...
|
|
func (fx *Fx) Initialize(vmIntf interface{}) error {
|
|
if err := fx.InitializeVM(vmIntf); err != nil {
|
|
return err
|
|
}
|
|
|
|
log := fx.VM.Logger()
|
|
log.Debug("Initializing nft fx")
|
|
|
|
c := fx.VM.Codec()
|
|
errs := wrappers.Errs{}
|
|
errs.Add(
|
|
c.RegisterType(&MintOutput{}),
|
|
c.RegisterType(&TransferOutput{}),
|
|
c.RegisterType(&MintOperation{}),
|
|
c.RegisterType(&TransferOperation{}),
|
|
c.RegisterType(&Credential{}),
|
|
)
|
|
return errs.Err
|
|
}
|
|
|
|
// VerifyOperation ...
|
|
func (fx *Fx) VerifyOperation(txIntf, opIntf, credIntf interface{}, utxosIntf []interface{}) error {
|
|
tx, ok := txIntf.(secp256k1fx.Tx)
|
|
switch {
|
|
case !ok:
|
|
return errWrongTxType
|
|
case len(utxosIntf) != 1:
|
|
return errWrongNumberOfUTXOs
|
|
}
|
|
|
|
cred, ok := credIntf.(*Credential)
|
|
if !ok {
|
|
return errWrongCredentialType
|
|
}
|
|
|
|
switch op := opIntf.(type) {
|
|
case *MintOperation:
|
|
return fx.VerifyMintOperation(tx, op, cred, utxosIntf[0])
|
|
case *TransferOperation:
|
|
return fx.VerifyTransferOperation(tx, op, cred, utxosIntf[0])
|
|
default:
|
|
return errWrongOperationType
|
|
}
|
|
}
|
|
|
|
// VerifyMintOperation ...
|
|
func (fx *Fx) VerifyMintOperation(tx secp256k1fx.Tx, op *MintOperation, cred *Credential, utxoIntf interface{}) error {
|
|
out, ok := utxoIntf.(*MintOutput)
|
|
if !ok {
|
|
return errWrongUTXOType
|
|
}
|
|
|
|
if err := verify.All(op, cred, out); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch {
|
|
case out.GroupID != op.GroupID:
|
|
return errWrongUniqueID
|
|
default:
|
|
return fx.Fx.VerifyCredentials(tx, &op.MintInput, &cred.Credential, &out.OutputOwners)
|
|
}
|
|
}
|
|
|
|
// VerifyTransferOperation ...
|
|
func (fx *Fx) VerifyTransferOperation(tx secp256k1fx.Tx, op *TransferOperation, cred *Credential, utxoIntf interface{}) error {
|
|
out, ok := utxoIntf.(*TransferOutput)
|
|
if !ok {
|
|
return errWrongUTXOType
|
|
}
|
|
|
|
if err := verify.All(op, cred, out); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch {
|
|
case out.GroupID != op.Output.GroupID:
|
|
return errWrongUniqueID
|
|
case !bytes.Equal(out.Payload, op.Output.Payload):
|
|
return errWrongBytes
|
|
default:
|
|
return fx.VerifyCredentials(tx, &op.Input, &cred.Credential, &out.OutputOwners)
|
|
}
|
|
}
|
|
|
|
// VerifyTransfer ...
|
|
func (fx *Fx) VerifyTransfer(_, _, _, _ interface{}) error { return errCantTransfer }
|