-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconfig.go
More file actions
250 lines (208 loc) · 6.21 KB
/
config.go
File metadata and controls
250 lines (208 loc) · 6.21 KB
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
package hotstuff2
import (
"fmt"
"time"
"go.uber.org/zap"
)
// Config holds the configuration for a HotStuff2 consensus instance.
type Config[H Hash] struct {
// MyIndex is the validator index of this node.
MyIndex uint16
// Validators is the set of all validators in the network.
Validators ValidatorSet
// PrivateKey is the private key for signing messages.
PrivateKey PrivateKey
// Storage provides persistent storage for blocks and consensus state.
Storage Storage[H]
// Network provides message broadcasting and delivery.
Network Network[H]
// Executor handles block execution and validation.
Executor Executor[H]
// Timer provides timeout management for the pacemaker.
Timer Timer
// Pacemaker configures the timing behavior (timeouts, block time, backoff).
// If nil, DefaultPacemakerConfig() is used.
Pacemaker *PacemakerConfig
// Logger for structured logging.
Logger *zap.Logger
// CryptoScheme specifies which signature scheme to use ("ed25519" or "bls").
CryptoScheme string
// EnableVerification enables runtime TLA+ model twins verification.
EnableVerification bool
}
// ConfigOption is a functional option for configuring HotStuff2.
type ConfigOption[H Hash] func(*Config[H]) error
// NewConfig creates a new Config with the given options.
func NewConfig[H Hash](opts ...ConfigOption[H]) (*Config[H], error) {
cfg := &Config[H]{
Logger: zap.NewNop(), // Default: no-op logger
CryptoScheme: CryptoSchemeEd25519, // Default: Ed25519
EnableVerification: false, // Default: no verification
}
for _, opt := range opts {
if err := opt(cfg); err != nil {
return nil, err
}
}
// Validate required fields
if err := cfg.validate(); err != nil {
return nil, fmt.Errorf("invalid config: %w", err)
}
return cfg, nil
}
// validate checks that all required configuration fields are set.
func (c *Config[H]) validate() error {
if c.Validators == nil {
return wrapConfig("validators is required")
}
if c.PrivateKey == nil {
return wrapConfig("private key is required")
}
if c.Storage == nil {
return wrapConfig("storage is required")
}
if c.Network == nil {
return wrapConfig("network is required")
}
if c.Executor == nil {
return wrapConfig("executor is required")
}
if c.Timer == nil {
return wrapConfig("timer is required")
}
if !c.Validators.Contains(c.MyIndex) {
return wrapConfigf("validator index %d not in validator set", c.MyIndex)
}
if c.CryptoScheme != CryptoSchemeEd25519 && c.CryptoScheme != CryptoSchemeBLS {
return wrapConfigf("unsupported crypto scheme: %s", c.CryptoScheme)
}
// Validate Byzantine fault tolerance: n >= 3f + 1
n := c.Validators.Count()
f := c.Validators.F()
if n < 3*f+1 {
return wrapConfigf("insufficient validators: n=%d, f=%d (need n >= 3f+1)", n, f)
}
return nil
}
// WithMyIndex sets the validator index for this node.
func WithMyIndex[H Hash](index uint16) ConfigOption[H] {
return func(c *Config[H]) error {
c.MyIndex = index
return nil
}
}
// WithValidators sets the validator set.
func WithValidators[H Hash](validators ValidatorSet) ConfigOption[H] {
return func(c *Config[H]) error {
if validators == nil {
return fmt.Errorf("validators cannot be nil")
}
c.Validators = validators
return nil
}
}
// WithPrivateKey sets the private key for signing.
func WithPrivateKey[H Hash](key PrivateKey) ConfigOption[H] {
return func(c *Config[H]) error {
if key == nil {
return fmt.Errorf("private key cannot be nil")
}
c.PrivateKey = key
return nil
}
}
// WithStorage sets the storage backend.
func WithStorage[H Hash](storage Storage[H]) ConfigOption[H] {
return func(c *Config[H]) error {
if storage == nil {
return fmt.Errorf("storage cannot be nil")
}
c.Storage = storage
return nil
}
}
// WithNetwork sets the network layer.
func WithNetwork[H Hash](network Network[H]) ConfigOption[H] {
return func(c *Config[H]) error {
if network == nil {
return fmt.Errorf("network cannot be nil")
}
c.Network = network
return nil
}
}
// WithExecutor sets the block executor.
func WithExecutor[H Hash](executor Executor[H]) ConfigOption[H] {
return func(c *Config[H]) error {
if executor == nil {
return fmt.Errorf("executor cannot be nil")
}
c.Executor = executor
return nil
}
}
// WithTimer sets the timer implementation.
func WithTimer[H Hash](timer Timer) ConfigOption[H] {
return func(c *Config[H]) error {
if timer == nil {
return fmt.Errorf("timer cannot be nil")
}
c.Timer = timer
return nil
}
}
// WithLogger sets the logger.
func WithLogger[H Hash](logger *zap.Logger) ConfigOption[H] {
return func(c *Config[H]) error {
if logger == nil {
return fmt.Errorf("logger cannot be nil")
}
c.Logger = logger
return nil
}
}
// WithCryptoScheme sets the signature scheme ("ed25519" or "bls").
func WithCryptoScheme[H Hash](scheme string) ConfigOption[H] {
return func(c *Config[H]) error {
if scheme != CryptoSchemeEd25519 && scheme != CryptoSchemeBLS {
return fmt.Errorf("unsupported crypto scheme: %s", scheme)
}
c.CryptoScheme = scheme
return nil
}
}
// WithVerification enables or disables runtime TLA+ verification.
func WithVerification[H Hash](enabled bool) ConfigOption[H] {
return func(c *Config[H]) error {
c.EnableVerification = enabled
return nil
}
}
// WithPacemaker sets the pacemaker configuration.
// Use this to configure target block time, timeouts, and backoff behavior.
func WithPacemaker[H Hash](config PacemakerConfig) ConfigOption[H] {
return func(c *Config[H]) error {
if err := config.Validate(); err != nil {
return err
}
c.Pacemaker = &config
return nil
}
}
// WithTargetBlockTime is a convenience method to configure pacemaker for a
// specific target block time. This sets up appropriate timeouts for production use.
func WithTargetBlockTime[H Hash](blockTime time.Duration) ConfigOption[H] {
return func(c *Config[H]) error {
config := ProductionPacemakerConfig(blockTime)
c.Pacemaker = &config
return nil
}
}
// Quorum returns the quorum size (2f+1).
func (c *Config[H]) Quorum() int {
return 2*c.Validators.F() + 1
}
// IsLeader returns true if this node is the leader for the given view.
func (c *Config[H]) IsLeader(view uint32) bool {
return c.Validators.GetLeader(view) == c.MyIndex
}