-
Notifications
You must be signed in to change notification settings - Fork 174
/
events.go
98 lines (90 loc) · 5.18 KB
/
events.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
package protocol
import (
"github.com/onflow/flow-go/model/flow"
)
// Consumer defines a set of events that occur within the protocol state, that
// can be propagated to other components via an implementation of this interface.
// Collectively, these are referred to as "Protocol Events".
//
// Protocol events are delivered immediately after the database transaction
// committing the corresponding state change completes successfully.
// This means that events are delivered exactly once, while the system is running.
// Events may not be delivered during crashes and restarts, but any missed events
// are guaranteed to be reflected in the Protocol State upon restarting.
// Components consuming protocol events which cannot tolerate missed events
// must implement initialization logic which accounts for any missed events.
//
// EXAMPLE:
// Suppose block A is finalized at height 100. If the BlockFinalized(A) event is
// dropped due to a crash, then when the node restarts, the latest finalized block
// in the Protocol State is guaranteed to be A.
//
// CAUTION: Protocol event subscriber callbacks are invoked synchronously in the
// critical path of protocol state mutations. Most subscribers should immediately
// spawn a goroutine to handle the notification to avoid blocking protocol state
// progression, especially for frequent protocol events (eg. BlockFinalized).
//
// NOTE: the epoch-related callbacks are only called once the fork containing
// the relevant event has been finalized.
type Consumer interface {
// BlockFinalized is called when a block is finalized.
// Formally, this callback is informationally idempotent. I.e. the consumer
// of this callback must handle repeated calls for the same block.
BlockFinalized(block *flow.Header)
// BlockProcessable is called when a correct block is encountered that is
// ready to be processed (i.e. it is connected to the finalized chain and
// its source of randomness is available). BlockProcessable is never emitted
// for the root block, as the root block is always processable.
// Formally, this callback is informationally idempotent. I.e. the consumer
// of this callback must handle repeated calls for the same block.
// TODO trigger this on block insertion (used to be on MarkValid)
// - don't trigger for root block or below
BlockProcessable(block *flow.Header)
// EpochTransition is called when we transition to a new epoch. This is
// equivalent to the beginning of the new epoch's staking phase and the end
// of the previous epoch's epoch committed phase.
//
// The block parameter is the first block of the new epoch.
//
// NOTE: Only called once the transition has been finalized.
EpochTransition(newEpochCounter uint64, first *flow.Header)
// EpochSetupPhaseStarted is called when we begin the epoch setup phase for
// the current epoch. This is equivalent to the end of the epoch staking
// phase for the current epoch.
//
// Referencing the diagram below, the event is emitted when block c is incorporated.
// The block parameter is the first block of the epoch setup phase (block c).
//
// |<-- Epoch N ------------------------------------------------->|
// |<-- StakingPhase -->|<-- SetupPhase -->|<-- CommittedPhase -->|
// ^--- block A - this block's execution result contains an EpochSetup event
// ^--- block b - contains seal for block A
// ^--- block c - contains qc for block b, first block of Setup phase
// ^--- block d - finalizes block c, triggers EpochSetupPhaseStarted event
//
// NOTE: Only called once the phase transition has been finalized.
EpochSetupPhaseStarted(currentEpochCounter uint64, first *flow.Header)
// EpochCommittedPhaseStarted is called when we begin the epoch committed phase
// for the current epoch. This is equivalent to the end of the epoch setup
// phase for the current epoch.
//
// Referencing the diagram below, the event is emitted when block f is received.
// The block parameter is the first block of the epoch committed phase (block f).
//
// |<-- Epoch N ------------------------------------------------->|
// |<-- StakingPhase -->|<-- SetupPhase -->|<-- CommittedPhase -->|
// ^--- block D - this block's execution result contains an EpochCommit event
// ^--- block e - contains seal for block D
// ^--- block f - contains qc for block e, first block of Committed phase
// ^--- block g - finalizes block f, triggers EpochCommittedPhaseStarted event
///
//
// NOTE: Only called once the phase transition has been finalized.
EpochCommittedPhaseStarted(currentEpochCounter uint64, first *flow.Header)
// EpochEmergencyFallbackTriggered is called when epoch fallback mode (EECC) is triggered.
// Since EECC is a permanent, spork-scoped state, this event is triggered only once.
// After this event is triggered, no further epoch transitions will occur,
// no further epoch phase transitions will occur, and no further epoch-related
// related protocol events (the events defined in this interface) will be emitted.
EpochEmergencyFallbackTriggered()
}