-
Notifications
You must be signed in to change notification settings - Fork 672
/
stateless_vertex.go
147 lines (123 loc) · 3.6 KB
/
stateless_vertex.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
141
142
143
144
145
146
147
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package vertex
import (
"errors"
"fmt"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/vms/components/verify"
)
const (
// maxNumParents is the max number of parents a vertex may have
maxNumParents = 128
// maxTxsPerVtx is the max number of transactions a vertex may have
maxTxsPerVtx = 128
)
var (
errBadVersion = errors.New("invalid version")
errBadEpoch = errors.New("invalid epoch")
errTooManyParentIDs = fmt.Errorf("vertex contains more than %d parentIDs", maxNumParents)
errNoOperations = errors.New("vertex contains no operations")
errTooManyTxs = fmt.Errorf("vertex contains more than %d transactions", maxTxsPerVtx)
errInvalidParents = errors.New("vertex contains non-sorted or duplicated parentIDs")
errInvalidTxs = errors.New("vertex contains non-sorted or duplicated transactions")
_ StatelessVertex = statelessVertex{}
)
type StatelessVertex interface {
verify.Verifiable
ID() ids.ID
Bytes() []byte
Version() uint16
ChainID() ids.ID
StopVertex() bool
Height() uint64
Epoch() uint32
ParentIDs() []ids.ID
Txs() [][]byte
}
type statelessVertex struct {
// This wrapper exists so that the function calls aren't ambiguous
innerStatelessVertex
// cache the ID of this vertex
id ids.ID
// cache the binary format of this vertex
bytes []byte
}
func (v statelessVertex) ID() ids.ID {
return v.id
}
func (v statelessVertex) Bytes() []byte {
return v.bytes
}
func (v statelessVertex) Version() uint16 {
return v.innerStatelessVertex.Version
}
func (v statelessVertex) ChainID() ids.ID {
return v.innerStatelessVertex.ChainID
}
func (v statelessVertex) StopVertex() bool {
return v.innerStatelessVertex.Version == CodecVersionWithStopVtx
}
func (v statelessVertex) Height() uint64 {
return v.innerStatelessVertex.Height
}
func (v statelessVertex) Epoch() uint32 {
return v.innerStatelessVertex.Epoch
}
func (v statelessVertex) ParentIDs() []ids.ID {
return v.innerStatelessVertex.ParentIDs
}
func (v statelessVertex) Txs() [][]byte {
return v.innerStatelessVertex.Txs
}
type innerStatelessVertex struct {
Version uint16 `json:"version"`
ChainID ids.ID `json:"chainID" serializeV0:"true" serializeV1:"true"`
Height uint64 `json:"height" serializeV0:"true" serializeV1:"true"`
Epoch uint32 `json:"epoch" serializeV0:"true"`
ParentIDs []ids.ID `json:"parentIDs" serializeV0:"true" serializeV1:"true"`
Txs [][]byte `json:"txs" serializeV0:"true"`
}
func (v innerStatelessVertex) Verify() error {
if v.Version == CodecVersionWithStopVtx {
return v.verifyStopVertex()
}
return v.verify()
}
func (v innerStatelessVertex) verify() error {
switch {
case v.Version != CodecVersion:
return errBadVersion
case v.Epoch != 0:
return errBadEpoch
case len(v.ParentIDs) > maxNumParents:
return errTooManyParentIDs
case len(v.Txs) == 0:
return errNoOperations
case len(v.Txs) > maxTxsPerVtx:
return errTooManyTxs
case !utils.IsSortedAndUnique(v.ParentIDs):
return errInvalidParents
case !utils.IsSortedAndUniqueByHash(v.Txs):
return errInvalidTxs
default:
return nil
}
}
func (v innerStatelessVertex) verifyStopVertex() error {
switch {
case v.Version != CodecVersionWithStopVtx:
return errBadVersion
case v.Epoch != 0:
return errBadEpoch
case len(v.ParentIDs) > maxNumParents:
return errTooManyParentIDs
case len(v.Txs) != 0:
return errTooManyTxs
case !utils.IsSortedAndUnique(v.ParentIDs):
return errInvalidParents
default:
return nil
}
}