@@ -23,12 +23,22 @@ const (
23
23
24
24
func candidateAction (ctx context.Context ) {
25
25
now := time .Now ()
26
+
26
27
currentAPI := deps .NodeBridge .APIProvider ().APIForTime (now )
27
28
currentSlot := currentAPI .TimeProvider ().SlotFromTime (now )
28
29
30
+ if ! deps .NodeBridge .NodeStatus ().GetIsBootstrapped () {
31
+ Component .LogDebugf ("not issuing candidacy announcement for account %s in slot %d because node is not bootstrapped yet." , validatorAccount .ID (), currentSlot )
32
+
33
+ // If a node is not bootstrapped, then retry until it is bootstrapped.
34
+ executor .ExecuteAt (CandidateTask , func () { candidateAction (ctx ) }, now .Add (ParamsValidator .CandidacyRetryInterval ))
35
+
36
+ return
37
+ }
38
+
29
39
isCandidate , err := readIsCandidate (ctx , validatorAccount .ID (), currentSlot )
30
40
if err != nil {
31
- Component .LogWarnf ("error while checking if account is already a candidate: %s" , err .Error ())
41
+ Component .LogWarnf ("error while checking if account %s is already a candidate: %s" , validatorAccount . ID () , err .Error ())
32
42
33
43
// If there is an error, then retry registering as a candidate, except if the context was canceled.
34
44
if ! ierrors .Is (err , context .Canceled ) {
@@ -39,7 +49,8 @@ func candidateAction(ctx context.Context) {
39
49
}
40
50
41
51
if isCandidate {
42
- Component .LogDebugf ("not issuing candidacy announcement block as account %s is already registered as candidate in epoch %d" , validatorAccount .ID (), currentAPI .TimeProvider ().EpochFromSlot (currentSlot ))
52
+ Component .LogDebugf ("not issuing candidacy announcement for account %s in slot %d as it is already registered as candidate in epoch %d" , validatorAccount .ID (), currentSlot , currentAPI .TimeProvider ().EpochFromSlot (currentSlot ))
53
+
43
54
// If an account is a registered candidate, then try to register as a candidate in the next epoch.
44
55
executor .ExecuteAt (CandidateTask , func () { candidateAction (ctx ) }, currentAPI .TimeProvider ().SlotStartTime (currentAPI .TimeProvider ().EpochStart (currentAPI .TimeProvider ().EpochFromSlot (currentSlot )+ 1 )))
45
56
@@ -49,41 +60,47 @@ func candidateAction(ctx context.Context) {
49
60
epochEndSlot := currentAPI .TimeProvider ().EpochEnd (currentAPI .TimeProvider ().EpochFromSlot (currentSlot ))
50
61
if currentSlot + currentAPI .ProtocolParameters ().EpochNearingThreshold () > epochEndSlot {
51
62
Component .LogDebugf ("not issuing candidacy announcement for account %s as block's slot would be issued in (%d) is past the Epoch Nearing Threshold (%d) of epoch %d" , validatorAccount .ID (), currentSlot , epochEndSlot - currentAPI .ProtocolParameters ().EpochNearingThreshold (), currentAPI .TimeProvider ().EpochFromSlot (currentSlot ))
63
+
52
64
// If it's too late to register as a candidate, then try to register in the next epoch.
53
65
executor .ExecuteAt (CandidateTask , func () { candidateAction (ctx ) }, currentAPI .TimeProvider ().SlotStartTime (currentAPI .TimeProvider ().EpochStart (currentAPI .TimeProvider ().EpochFromSlot (currentSlot )+ 1 )))
54
66
55
67
return
56
68
}
57
69
58
70
// Schedule next committeeMemberAction regardless of the result below.
59
- // If a node is not bootstrapped, then retry until it is bootstrapped.
60
71
// The candidacy block might be issued and fail to be accepted in the node for various reasons,
61
72
// so we should stop issuing candidacy blocks only when the account is successfully registered as a candidate.
62
73
// For this reason,
63
74
// retry interval parameter should be bigger than the fishing threshold to avoid issuing redundant candidacy blocks.
64
75
executor .ExecuteAt (CandidateTask , func () { candidateAction (ctx ) }, now .Add (ParamsValidator .CandidacyRetryInterval ))
65
76
66
- if ! deps .NodeBridge .NodeStatus ().GetIsBootstrapped () {
67
- Component .LogDebug ("not issuing candidate block because node is not bootstrapped yet." )
68
-
69
- return
70
- }
71
-
72
77
if err = issueCandidateBlock (ctx , now , currentAPI ); err != nil {
73
- Component .LogWarnf ("error while trying to issue candidacy announcement: %s" , err .Error ())
78
+ Component .LogWarnf ("error while trying to issue candidacy announcement for account %s in slot %d : %s" , validatorAccount . ID (), currentSlot , err .Error ())
74
79
}
75
80
}
76
81
77
82
func committeeMemberAction (ctx context.Context ) {
78
83
now := time .Now ()
84
+
79
85
currentAPI := deps .NodeBridge .APIProvider ().APIForTime (now )
80
86
currentSlot := currentAPI .TimeProvider ().SlotFromTime (now )
81
87
currentEpoch := currentAPI .TimeProvider ().EpochFromSlot (currentSlot )
82
- slotDurationMillis := int64 ( currentAPI . ProtocolParameters (). SlotDurationInSeconds ()) * 1000
88
+
83
89
// Calculate the broadcast interval in milliseconds.
90
+ slotDurationMillis := int64 (currentAPI .ProtocolParameters ().SlotDurationInSeconds ()) * 1000
84
91
broadcastIntervalMillis := slotDurationMillis / int64 (currentAPI .ProtocolParameters ().ValidationBlocksPerSlot ())
85
92
committeeBroadcastInterval := time .Duration (broadcastIntervalMillis * int64 (time .Millisecond ))
86
93
94
+ // If we are not bootstrapped and we are _not_ ignoring such condition, we return.
95
+ if ! deps .NodeBridge .NodeStatus ().GetIsBootstrapped () && ! ParamsValidator .IgnoreBootstrapped {
96
+ Component .LogDebugf ("not issuing validation block for account %s because node is not bootstrapped yet." , validatorAccount .ID ())
97
+
98
+ // If a node is not bootstrapped, then retry until it is bootstrapped.
99
+ executor .ExecuteAt (CommitteeTask , func () { committeeMemberAction (ctx ) }, now .Add (committeeBroadcastInterval ))
100
+
101
+ return
102
+ }
103
+
87
104
// If we are bootstrapped let's check if we are part of the committee.
88
105
if deps .NodeBridge .NodeStatus ().GetIsBootstrapped () {
89
106
isCommitteeMember , err := readIsCommitteeMember (ctx , validatorAccount .ID (), currentSlot )
@@ -99,44 +116,37 @@ func committeeMemberAction(ctx context.Context) {
99
116
}
100
117
101
118
if ! isCommitteeMember {
102
- Component .LogDebug ("account %s is not a committee member in epoch %d" , currentEpoch )
119
+ Component .LogDebugf ("account %s is not a committee member in epoch %d" , validatorAccount . ID () , currentEpoch )
103
120
executor .ExecuteAt (CommitteeTask , func () { committeeMemberAction (ctx ) }, currentAPI .TimeProvider ().SlotStartTime (currentAPI .TimeProvider ().EpochStart (currentEpoch + 1 )))
104
121
105
122
return
106
123
}
107
124
}
108
125
109
- // Schedule next committeeMemberAction regardless of whether the node is bootstrapped or validation block is issued
126
+ // Schedule next committeeMemberAction regardless of whether the validation block is issued or not
110
127
// as it must be issued as part of validator's responsibility.
111
128
executor .ExecuteAt (CommitteeTask , func () { committeeMemberAction (ctx ) }, now .Add (committeeBroadcastInterval ))
112
129
113
- // If we are not bootstrapped and we are _not_ ignoring such condition, we return.
114
- if ! deps .NodeBridge .NodeStatus ().GetIsBootstrapped () && ! ParamsValidator .IgnoreBootstrapped {
115
- Component .LogDebug ("not issuing validation block because node is not bootstrapped yet." )
116
-
117
- return
118
- }
119
-
120
130
// If we are either bootstrapped (and we are part of the committee) or we are ignoring being bootstrapped we issue
121
131
// a validation block, reviving the chain if necessary.
122
132
if err := issueValidationBlock (ctx , now , currentAPI , committeeBroadcastInterval ); err != nil {
123
- Component .LogWarnf ("error while trying to issue validation block: %s" , err .Error ())
133
+ Component .LogWarnf ("error while trying to issue validation block for account %s : %s" , validatorAccount . ID () , err .Error ())
124
134
}
125
135
}
126
136
127
137
func issueCandidateBlock (ctx context.Context , blockIssuingTime time.Time , currentAPI iotago.API ) error {
128
- blockSlot := currentAPI .TimeProvider ().SlotFromTime (blockIssuingTime )
129
-
130
138
issuanceBlockHeaderResponse , err := blockIssuance (ctx , iotago .BasicBlockMaxParents )
131
139
if err != nil {
132
- return ierrors .Wrapf (err , "failed to get blockIssuance" )
140
+ return ierrors .Wrap (err , "failed to get blockIssuance" )
133
141
}
134
142
135
143
latestParentBlockIssuingTime := issuanceBlockHeaderResponse .LatestParentBlockIssuingTime .Add (time .Nanosecond )
136
144
if blockIssuingTime .Before (latestParentBlockIssuingTime ) {
137
145
blockIssuingTime = latestParentBlockIssuingTime
138
146
}
139
147
148
+ blockSlot := currentAPI .TimeProvider ().SlotFromTime (blockIssuingTime )
149
+
140
150
addressableCommitment , err := getAddressableCommitment (ctx , blockSlot )
141
151
if err != nil {
142
152
return ierrors .Wrap (err , "error getting commitment" )
@@ -185,12 +195,12 @@ func issueCandidateBlock(ctx context.Context, blockIssuingTime time.Time, curren
185
195
func issueValidationBlock (ctx context.Context , blockIssuingTime time.Time , currentAPI iotago.API , committeeBroadcastInterval time.Duration ) error {
186
196
protocolParametersHash , err := currentAPI .ProtocolParameters ().Hash ()
187
197
if err != nil {
188
- return ierrors .Wrapf (err , "failed to get protocol parameters hash" )
198
+ return ierrors .Wrap (err , "failed to get protocol parameters hash" )
189
199
}
190
200
191
201
issuanceBlockHeaderResponse , err := blockIssuance (ctx , iotago .ValidationBlockMaxParents )
192
202
if err != nil {
193
- return ierrors .Wrapf (err , "failed to get blockIssuance" )
203
+ return ierrors .Wrap (err , "failed to get blockIssuance" )
194
204
}
195
205
196
206
latestParentBlockIssuingTime := issuanceBlockHeaderResponse .LatestParentBlockIssuingTime .Add (time .Nanosecond )
@@ -208,15 +218,15 @@ func issueValidationBlock(ctx context.Context, blockIssuingTime time.Time, curre
208
218
// to allow the validator to issue validation blocks.
209
219
commitment , parentID , reviveChainErr := reviveChain (ctx , blockIssuingTime )
210
220
if reviveChainErr != nil {
211
- return ierrors .Wrapf (err , "error reviving chain" )
221
+ return ierrors .Wrap (err , "error reviving chain" )
212
222
}
213
223
214
224
addressableCommitment = commitment
215
225
issuanceBlockHeaderResponse .StrongParents = []iotago.BlockID {parentID }
216
226
issuanceBlockHeaderResponse .WeakParents = []iotago.BlockID {}
217
227
issuanceBlockHeaderResponse .ShallowLikeParents = []iotago.BlockID {}
218
228
} else if err != nil {
219
- return ierrors .Wrapf (err , "error getting commitment" )
229
+ return ierrors .Wrap (err , "error getting commitment" )
220
230
}
221
231
222
232
// create the validation block here using the validation block builder from iota.go
@@ -232,12 +242,12 @@ func issueValidationBlock(ctx context.Context, blockIssuingTime time.Time, curre
232
242
Sign (validatorAccount .ID (), validatorAccount .PrivateKey ()).
233
243
Build ()
234
244
if err != nil {
235
- return ierrors .Wrapf (err , "error creating validation block" )
245
+ return ierrors .Wrap (err , "error creating validation block" )
236
246
}
237
247
238
248
blockID , err := submitBlock (ctx , validationBlock )
239
249
if err != nil {
240
- return ierrors .Wrapf (err , "error issuing validation block" )
250
+ return ierrors .Wrap (err , "error issuing validation block" )
241
251
}
242
252
243
253
Component .LogDebugf ("issued validation block: %s - commitment %s %d - latest finalized slot %d - broadcast interval %v" , blockID , validationBlock .Header .SlotCommitmentID , validationBlock .Header .SlotCommitmentID .Slot (), validationBlock .Header .LatestFinalizedSlot , committeeBroadcastInterval .Truncate (time .Millisecond ))
0 commit comments