-
Notifications
You must be signed in to change notification settings - Fork 669
/
create_asset_tx.go
140 lines (123 loc) · 3.93 KB
/
create_asset_tx.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package avm
import (
"errors"
"fmt"
"strings"
"unicode"
"github.com/ava-labs/avalanchego/codec"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow"
"github.com/ava-labs/avalanchego/vms/components/avax"
)
const (
minNameLen = 1
maxNameLen = 128
minSymbolLen = 1
maxSymbolLen = 4
maxDenomination = 32
)
var (
errInitialStatesNotSortedUnique = errors.New("initial states not sorted and unique")
errNameTooShort = fmt.Errorf("name is too short, minimum size is %d", minNameLen)
errNameTooLong = fmt.Errorf("name is too long, maximum size is %d", maxNameLen)
errSymbolTooShort = fmt.Errorf("symbol is too short, minimum size is %d", minSymbolLen)
errSymbolTooLong = fmt.Errorf("symbol is too long, maximum size is %d", maxSymbolLen)
errNoFxs = errors.New("assets must support at least one Fx")
errIllegalNameCharacter = errors.New("asset's name must be made up of only letters and numbers")
errIllegalSymbolCharacter = errors.New("asset's symbol must be all upper case letters")
errUnexpectedWhitespace = errors.New("unexpected whitespace provided")
errDenominationTooLarge = errors.New("denomination is too large")
_ UnsignedTx = &CreateAssetTx{}
)
// CreateAssetTx is a transaction that creates a new asset.
type CreateAssetTx struct {
BaseTx `serialize:"true"`
Name string `serialize:"true" json:"name"`
Symbol string `serialize:"true" json:"symbol"`
Denomination byte `serialize:"true" json:"denomination"`
States []*InitialState `serialize:"true" json:"initialStates"`
}
func (t *CreateAssetTx) Init(vm *VM) error {
for _, state := range t.States {
fx := vm.fxs[state.FxIndex]
state.FxID = fx.ID
state.InitCtx(vm.ctx)
}
return t.BaseTx.Init(vm)
}
// InitialStates track which virtual machines, and the initial state of these
// machines, this asset uses. The returned array should not be modified.
func (t *CreateAssetTx) InitialStates() []*InitialState { return t.States }
// UTXOs returns the UTXOs transaction is producing.
func (t *CreateAssetTx) UTXOs() []*avax.UTXO {
txID := t.ID()
utxos := t.BaseTx.UTXOs()
for _, state := range t.States {
for _, out := range state.Outs {
utxos = append(utxos, &avax.UTXO{
UTXOID: avax.UTXOID{
TxID: txID,
OutputIndex: uint32(len(utxos)),
},
Asset: avax.Asset{
ID: txID,
},
Out: out,
})
}
}
return utxos
}
// SyntacticVerify that this transaction is well-formed.
func (t *CreateAssetTx) SyntacticVerify(
ctx *snow.Context,
c codec.Manager,
txFeeAssetID ids.ID,
_ uint64,
txFee uint64,
numFxs int,
) error {
switch {
case t == nil:
return errNilTx
case len(t.Name) < minNameLen:
return errNameTooShort
case len(t.Name) > maxNameLen:
return errNameTooLong
case len(t.Symbol) < minSymbolLen:
return errSymbolTooShort
case len(t.Symbol) > maxSymbolLen:
return errSymbolTooLong
case len(t.States) == 0:
return errNoFxs
case t.Denomination > maxDenomination:
return errDenominationTooLarge
case strings.TrimSpace(t.Name) != t.Name:
return errUnexpectedWhitespace
}
for _, r := range t.Name {
if r > unicode.MaxASCII || !(unicode.IsLetter(r) || unicode.IsNumber(r) || r == ' ') {
return errIllegalNameCharacter
}
}
for _, r := range t.Symbol {
if r > unicode.MaxASCII || !unicode.IsUpper(r) {
return errIllegalSymbolCharacter
}
}
if err := t.BaseTx.SyntacticVerify(ctx, c, txFeeAssetID, txFee, txFee, numFxs); err != nil {
return err
}
for _, state := range t.States {
if err := state.Verify(c, numFxs); err != nil {
return err
}
}
if !isSortedAndUniqueInitialStates(t.States) {
return errInitialStatesNotSortedUnique
}
return nil
}
func (t *CreateAssetTx) Sort() { sortInitialStates(t.States) }