-
Notifications
You must be signed in to change notification settings - Fork 662
/
engine.go
493 lines (450 loc) · 19 KB
/
engine.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
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
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
// Copyright (C) 2019-2022, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package common
import (
"time"
"github.com/ava-labs/avalanchego/api/health"
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow"
"github.com/ava-labs/avalanchego/snow/validators"
)
// Engine describes the standard interface of a consensus engine
type Engine interface {
Handler
// Return the context of the chain this engine is working on
Context() *snow.ConsensusContext
// Start engine operations from given request ID
Start(startReqID uint32) error
// Returns nil if the engine is healthy.
// Periodically called and reported through the health API
health.Checker
// GetVM returns this engine's VM
GetVM() VM
}
type Handler interface {
AllGetsServer
StateSummaryFrontierHandler
AcceptedStateSummaryHandler
AcceptedFrontierHandler
AcceptedHandler
AncestorsHandler
PutHandler
QueryHandler
ChitsHandler
AppHandler
InternalHandler
}
type AllGetsServer interface {
GetStateSummaryFrontierHandler
GetAcceptedStateSummaryHandler
GetAcceptedFrontierHandler
GetAcceptedHandler
GetAncestorsHandler
GetHandler
}
// GetStateSummaryFrontierHandler defines how a consensus engine reacts to a get
// state summary frontier message from another validator. Functions only return
// fatal errors.
type GetStateSummaryFrontierHandler interface {
// Notify this engine of a request for the frontier of state summaries.
//
// The accepted frontier is the last state summary available locally.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID.
//
// This engine should respond with an StateSummaryFrontier message with the
// same requestID, and the engine's current state summary frontier.
GetStateSummaryFrontier(validatorID ids.NodeID, requestID uint32) error
}
// StateSummaryFrontierHandler defines how a consensus engine reacts to a state
// summary frontier message from other validators. Functions only return fatal
// errors.
type StateSummaryFrontierHandler interface {
// Notify this engine of a state summary frontier.
//
// This function can be called by any validator. It is not safe to assume
// this message is in response to a GetStateSummaryFrontier message, is
// utilizing a unique requestID, or that the summary bytes are from a valid
// state summary.
StateSummaryFrontier(validatorID ids.NodeID, requestID uint32, summary []byte) error
// Notify this engine that a get state summary frontier request it issued
// has failed.
//
// This function will be called if the engine sent a GetStateSummaryFrontier
// message that is not anticipated to be responded to. This could be because
// the recipient of the message is unknown or if the message request has
// timed out.
//
// The validatorID, and requestID, are assumed to be the same as those sent
// in the GetStateSummaryFrontier message.
GetStateSummaryFrontierFailed(validatorID ids.NodeID, requestID uint32) error
}
// GetAcceptedStateSummaryHandler defines how a consensus engine reacts to a get
// accepted state summary message from another validator. Functions only return
// fatal errors.
type GetAcceptedStateSummaryHandler interface {
// Notify this engine of a request to return state summary IDs referenced by
// the provided keys.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID. However, the validatorID is
// assumed to be authenticated.
//
// This engine should respond with an AcceptedStateSummary message with the
// same requestID, and the subset of the state summaries that this node has
// locally available.
GetAcceptedStateSummary(validatorID ids.NodeID, requestID uint32, keys []uint64) error
}
// AcceptedStateSummaryHandler defines how a consensus engine reacts to an
// accepted state summary message from another validator. Functions only return
// fatal errors.
type AcceptedStateSummaryHandler interface {
// Notify this engine of a set of state summaries.
//
// This function can be called by any validator. It is not safe to assume
// this message is in response to a GetAcceptedStateSummary message,
// is utilizing a unique requestID, or that the summaryIDs are a subset of the
// state summaries requested by key from a GetAcceptedStateSummary message.
AcceptedStateSummary(validatorID ids.NodeID, requestID uint32, summaryIDs []ids.ID) error
// Notify this engine that a get accepted state summary request it issued has
// failed.
//
// This function will be called if the engine sent a GetAcceptedStateSummary
// message that is not anticipated to be responded to. This could be because
// the recipient of the message is unknown or if the message request has
// timed out.
//
// The validatorID, and requestID, are assumed to be the same as those sent
// in the GetAcceptedStateSummary message.
GetAcceptedStateSummaryFailed(validatorID ids.NodeID, requestID uint32) error
}
// GetAcceptedFrontierHandler defines how a consensus engine reacts to a get
// accepted frontier message from another validator. Functions only return fatal
// errors.
type GetAcceptedFrontierHandler interface {
// Notify this engine of a request for the accepted frontier of vertices.
//
// The accepted frontier is the set of accepted vertices that do not have
// any accepted descendants.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID.
//
// This engine should respond with an AcceptedFrontier message with the same
// requestID, and the engine's current accepted frontier.
GetAcceptedFrontier(validatorID ids.NodeID, requestID uint32) error
}
// AcceptedFrontierHandler defines how a consensus engine reacts to accepted
// frontier messages from other validators. Functions only return fatal errors.
type AcceptedFrontierHandler interface {
// Notify this engine of an accepted frontier.
//
// This function can be called by any validator. It is not safe to assume
// this message is in response to a GetAcceptedFrontier message, is
// utilizing a unique requestID, or that the containerIDs from a valid
// frontier.
AcceptedFrontier(
validatorID ids.NodeID,
requestID uint32,
containerIDs []ids.ID,
) error
// Notify this engine that a get accepted frontier request it issued has
// failed.
//
// This function will be called if the engine sent a GetAcceptedFrontier
// message that is not anticipated to be responded to. This could be because
// the recipient of the message is unknown or if the message request has
// timed out.
//
// The validatorID, and requestID, are assumed to be the same as those sent
// in the GetAcceptedFrontier message.
GetAcceptedFrontierFailed(validatorID ids.NodeID, requestID uint32) error
}
// GetAcceptedHandler defines how a consensus engine reacts to a get accepted
// message from another validator. Functions only return fatal errors.
type GetAcceptedHandler interface {
// Notify this engine of a request to filter non-accepted vertices.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID. However, the validatorID is
// assumed to be authenticated.
//
// This engine should respond with an Accepted message with the same
// requestID, and the subset of the containerIDs that this node has decided
// are accepted.
GetAccepted(
validatorID ids.NodeID,
requestID uint32,
containerIDs []ids.ID,
) error
}
// AcceptedHandler defines how a consensus engine reacts to accepted messages
// from other validators. Functions only return fatal
// errors.
type AcceptedHandler interface {
// Notify this engine of a set of accepted vertices.
//
// This function can be called by any validator. It is not safe to assume
// this message is in response to a GetAccepted message, is utilizing a
// unique requestID, or that the containerIDs are a subset of the
// containerIDs from a GetAccepted message.
Accepted(
validatorID ids.NodeID,
requestID uint32,
containerIDs []ids.ID,
) error
// Notify this engine that a get accepted request it issued has failed.
//
// This function will be called if the engine sent a GetAccepted message
// that is not anticipated to be responded to. This could be because the
// recipient of the message is unknown or if the message request has timed
// out.
//
// The validatorID, and requestID, are assumed to be the same as those sent
// in the GetAccepted message.
GetAcceptedFailed(validatorID ids.NodeID, requestID uint32) error
}
// GetAncestorsHandler defines how a consensus engine reacts to a get ancestors
// message from another validator. Functions only return fatal errors.
type GetAncestorsHandler interface {
// Notify this engine of a request for a container and its ancestors.
//
// The request is from validator [validatorID]. The requested container is
// [containerID].
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID. It is also not safe to
// assume the requested containerID exists.
//
// This engine should respond with an Ancestors message with the same
// requestID, which contains [containerID] as well as its ancestors. See
// Ancestors's documentation.
//
// If this engine doesn't have some ancestors, it should reply with its best
// effort attempt at getting them. If this engine doesn't have [containerID]
// it can ignore this message.
GetAncestors(validatorID ids.NodeID, requestID uint32, containerID ids.ID) error
}
// AncestorsHandler defines how a consensus engine reacts to bootstrapping
// retrieval messages from other validators. Functions only return fatal errors.
type AncestorsHandler interface {
// Notify this engine of multiple containers.
//
// Each element of [containers] is the byte representation of a container.
//
// This should only be called during bootstrapping, in response to a
// GetAncestors message to [validatorID] with request ID [requestID].
//
// This call should contain the container requested in that message, along
// with ancestors. The containers should be in BFS order (ie the first
// container must be the container requested in the GetAncestors message and
// further back ancestors are later in [containers]
//
// It is not safe to assume this message is in response to a GetAncestor
// message, that this message has a unique requestID or that any of the
// containers in [containers] are valid.
Ancestors(
validatorID ids.NodeID,
requestID uint32,
containers [][]byte,
) error
// Notify this engine that a GetAncestors request it issued has failed.
//
// This function will be called if the engine sent a GetAncestors message
// that is not anticipated to be responded to. This could be because the
// recipient of the message is unknown or if the message request has timed
// out.
//
// The validatorID and requestID are assumed to be the same as those sent in
// the GetAncestors message.
GetAncestorsFailed(validatorID ids.NodeID, requestID uint32) error
}
// GetHandler defines how a consensus engine reacts to get message from another
// validator. Functions only return fatal errors.
type GetHandler interface {
// Notify this engine of a request for a container.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID. It is also not safe to
// assume the requested containerID exists.
//
// There should never be a situation where a virtuous node sends a Get
// request to another virtuous node that does not have the requested
// container.
//
// This engine should respond with a Put message with the same requestID if
// the container was locally available. Otherwise, the message can be safely
// dropped.
Get(validatorID ids.NodeID, requestID uint32, containerID ids.ID) error
}
// PutHandler defines how a consensus engine reacts to put messages from other
// validators. Functions only return fatal errors.
type PutHandler interface {
// Notify this engine of a container.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID.
Put(
validatorID ids.NodeID,
requestID uint32,
container []byte,
) error
// Notify this engine that a get request it issued has failed.
//
// This function will be called if the engine sent a Get message that is not
// anticipated to be responded to. This could be because the recipient of
// the message is unknown or if the message request has timed out.
//
// The validatorID and requestID are assumed to be the same as those sent in
// the Get message.
GetFailed(validatorID ids.NodeID, requestID uint32) error
}
// QueryHandler defines how a consensus engine reacts to query messages from
// other validators. Functions only return fatal errors.
type QueryHandler interface {
// Notify this engine of a request for our preferences.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID. However, the validatorID is
// assumed to be authenticated.
//
// If the container or its ancestry is incomplete, this engine is expected
// to request the missing containers from the validator. Once the ancestry
// is complete, this engine should send this validator the current
// preferences in a Chits message. The Chits message should have the same
// requestID that was passed in here.
PullQuery(
validatorID ids.NodeID,
requestID uint32,
containerID ids.ID,
) error
// Notify this engine of a request for our preferences.
//
// This function can be called by any validator. It is not safe to assume
// this message is utilizing a unique requestID.
//
// This function is meant to behave the same way as PullQuery, except the
// container is optimistically provided to potentially remove the need for
// a series of Get/Put messages.
//
// If the ancestry of the container is incomplete, this engine is expected
// to request the ancestry from the validator. Once the ancestry is
// complete, this engine should send this validator the current preferences
// in a Chits message. The Chits message should have the same requestID that
// was passed in here.
PushQuery(
validatorID ids.NodeID,
requestID uint32,
container []byte,
) error
}
// ChitsHandler defines how a consensus engine reacts to query response messages
// from other validators. Functions only return fatal errors.
type ChitsHandler interface {
// Notify this engine of the specified validators preferences.
//
// This function can be called by any validator. It is not safe to assume
// this message is in response to a PullQuery or a PushQuery message.
// However, the validatorID is assumed to be authenticated.
Chits(validatorID ids.NodeID, requestID uint32, containerIDs []ids.ID) error
// Notify this engine of the specified validators preferences.
//
// This function can be called by any validator. It is not safe to assume
// this message is in response to a PullQuery or a PushQuery message.
// However, the validatorID is assumed to be authenticated.
//
// The new ChitsV2 could be sent from a node that implements "ChitsV2"
// sender with linearized DAG, while the older nodes may not have
// implemented such, thus fallback.
ChitsV2(validatorID ids.NodeID, requestID uint32, containerIDs []ids.ID, containerID ids.ID) error
// Notify this engine that a query it issued has failed.
//
// This function will be called if the engine sent a PullQuery or PushQuery
// message that is not anticipated to be responded to. This could be because
// the recipient of the message is unknown or if the message request has
// timed out.
//
// The validatorID and the requestID are assumed to be the same as those
// sent in the Query message.
QueryFailed(validatorID ids.NodeID, requestID uint32) error
}
// AppHandler defines how a consensus engine reacts to app specific messages.
// Functions only return fatal errors.
type AppHandler interface {
// Notify this engine of a request for data from [nodeID].
//
// The meaning of [request], and what should be sent in response to it, is
// application (VM) specific.
//
// It is not guaranteed that:
// * [request] is well-formed/valid.
//
// This node should typically send an AppResponse to [nodeID] in response to
// a valid message using the same request ID before the deadline. However,
// the VM may arbitrarily choose to not send a response to this request.
AppRequest(nodeID ids.NodeID, requestID uint32, deadline time.Time, request []byte) error
// Notify this engine that an AppRequest message it sent to [nodeID] with
// request ID [requestID] failed.
//
// This may be because the request timed out or because the message couldn't
// be sent to [nodeID].
//
// It is guaranteed that:
// * This engine sent a request to [nodeID] with ID [requestID].
// * AppRequestFailed([nodeID], [requestID]) has not already been called.
// * AppResponse([nodeID], [requestID]) has not already been called.
AppRequestFailed(nodeID ids.NodeID, requestID uint32) error
// Notify this engine of a response to the AppRequest message it sent to
// [nodeID] with request ID [requestID].
//
// The meaning of [response] is application (VM) specifc.
//
// It is guaranteed that:
// * This engine sent a request to [nodeID] with ID [requestID].
// * AppRequestFailed([nodeID], [requestID]) has not already been called.
// * AppResponse([nodeID], [requestID]) has not already been called.
//
// It is not guaranteed that:
// * [response] contains the expected response
// * [response] is well-formed/valid.
//
// If [response] is invalid or not the expected response, the VM chooses how
// to react. For example, the VM may send another AppRequest, or it may give
// up trying to get the requested information.
AppResponse(nodeID ids.NodeID, requestID uint32, response []byte) error
// Notify this engine of a gossip message from [nodeID].
//
// The meaning of [msg] is application (VM) specific, and the VM defines how
// to react to this message.
//
// This message is not expected in response to any event, and it does not
// need to be responded to.
//
// A node may gossip the same message multiple times. That is,
// AppGossip([nodeID], [msg]) may be called multiple times.
AppGossip(nodeID ids.NodeID, msg []byte) error
}
// InternalHandler defines how this consensus engine reacts to messages from
// other components of this validator. Functions only return fatal errors if
// they occur.
type InternalHandler interface {
// Notify this engine of peer changes.
validators.Connector
// Notify this engine that a registered timeout has fired.
Timeout() error
// Gossip to the network a container on the accepted frontier
Gossip() error
// Halt this engine.
//
// This function will be called before the environment starts exiting. This
// function is slightly special, in that it does not expect the chain's
// context lock to be held before calling this function.
Halt()
// Shutdown this engine.
//
// This function will be called when the environment is exiting.
Shutdown() error
// Notify this engine of a message from the virtual machine.
Notify(Message) error
}