-
Notifications
You must be signed in to change notification settings - Fork 669
/
tx_semantic_verify.go
126 lines (105 loc) · 3 KB
/
tx_semantic_verify.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package avm
import (
"github.com/ava-labs/avalanchego/vms/avm/txs"
"github.com/ava-labs/avalanchego/vms/components/avax"
"github.com/ava-labs/avalanchego/vms/components/verify"
)
var _ txs.Visitor = (*txSemanticVerify)(nil)
// SemanticVerify that this transaction is well-formed.
type txSemanticVerify struct {
tx *txs.Tx
vm *VM
}
func (t *txSemanticVerify) BaseTx(tx *txs.BaseTx) error {
for i, in := range tx.Ins {
// Note: Verification of the length of [t.tx.Creds] happens during
// syntactic verification, which happens before semantic verification.
cred := t.tx.Creds[i].Verifiable
if err := t.vm.verifyTransfer(t.tx.Unsigned, in, cred); err != nil {
return err
}
}
for _, out := range tx.Outs {
fxIndex, err := t.vm.getFx(out.Out)
if err != nil {
return err
}
if assetID := out.AssetID(); !t.vm.verifyFxUsage(fxIndex, assetID) {
return errIncompatibleFx
}
}
return nil
}
func (t *txSemanticVerify) ImportTx(tx *txs.ImportTx) error {
if err := t.BaseTx(&tx.BaseTx); err != nil {
return err
}
if !t.vm.bootstrapped {
return nil
}
if err := verify.SameSubnet(t.vm.ctx, tx.SourceChain); err != nil {
return err
}
utxoIDs := make([][]byte, len(tx.ImportedIns))
for i, in := range tx.ImportedIns {
inputID := in.UTXOID.InputID()
utxoIDs[i] = inputID[:]
}
allUTXOBytes, err := t.vm.ctx.SharedMemory.Get(tx.SourceChain, utxoIDs)
if err != nil {
return err
}
codec := t.vm.parser.Codec()
offset := tx.BaseTx.NumCredentials()
for i, in := range tx.ImportedIns {
utxo := avax.UTXO{}
if _, err := codec.Unmarshal(allUTXOBytes[i], &utxo); err != nil {
return err
}
// Note: Verification of the length of [t.tx.Creds] happens during
// syntactic verification, which happens before semantic verification.
cred := t.tx.Creds[i+offset].Verifiable
if err := t.vm.verifyTransferOfUTXO(tx, in, cred, &utxo); err != nil {
return err
}
}
return nil
}
func (t *txSemanticVerify) ExportTx(tx *txs.ExportTx) error {
if t.vm.bootstrapped {
if err := verify.SameSubnet(t.vm.ctx, tx.DestinationChain); err != nil {
return err
}
}
for _, out := range tx.ExportedOuts {
fxIndex, err := t.vm.getFx(out.Out)
if err != nil {
return err
}
assetID := out.AssetID()
if !t.vm.verifyFxUsage(fxIndex, assetID) {
return errIncompatibleFx
}
}
return t.BaseTx(&tx.BaseTx)
}
func (t *txSemanticVerify) OperationTx(tx *txs.OperationTx) error {
if err := t.BaseTx(&tx.BaseTx); err != nil {
return err
}
offset := tx.BaseTx.NumCredentials()
for i, op := range tx.Ops {
// Note: Verification of the length of [t.tx.Creds] happens during
// syntactic verification, which happens before semantic verification.
cred := t.tx.Creds[i+offset].Verifiable
if err := t.vm.verifyOperation(tx, op, cred); err != nil {
return err
}
}
return nil
}
func (t *txSemanticVerify) CreateAssetTx(tx *txs.CreateAssetTx) error {
return t.BaseTx((&tx.BaseTx))
}