-
Notifications
You must be signed in to change notification settings - Fork 671
/
fx.go
110 lines (92 loc) · 2.84 KB
/
fx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package nftfx
import (
"bytes"
"errors"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/vms/components/verify"
"github.com/ava-labs/avalanchego/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")
errWrongNumberOfUTXOs = errors.New("wrong number of UTXOs for the operation")
errWrongUniqueID = errors.New("wrong unique ID provided")
errWrongBytes = errors.New("wrong bytes provided")
errCantTransfer = errors.New("cant transfer with this fx")
)
type Fx struct{ secp256k1fx.Fx }
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.CodecRegistry()
return utils.Err(
c.RegisterType(&MintOutput{}),
c.RegisterType(&TransferOutput{}),
c.RegisterType(&MintOperation{}),
c.RegisterType(&TransferOperation{}),
c.RegisterType(&Credential{}),
)
}
func (fx *Fx) VerifyOperation(txIntf, opIntf, credIntf interface{}, utxosIntf []interface{}) error {
tx, ok := txIntf.(secp256k1fx.UnsignedTx)
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
}
}
func (fx *Fx) VerifyMintOperation(tx secp256k1fx.UnsignedTx, 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)
}
}
func (fx *Fx) VerifyTransferOperation(tx secp256k1fx.UnsignedTx, 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)
}
}
func (*Fx) VerifyTransfer(_, _, _, _ interface{}) error {
return errCantTransfer
}