Skip to content

Commit ca29d1f

Browse files
authored
Merge pull request #6431 from oasisprotocol/peternose/trivial/move-vrf-entropy
go/consensus/cometbft/apps/scheduler: Refactor code
2 parents 05e0dbd + 804799f commit ca29d1f

4 files changed

Lines changed: 86 additions & 89 deletions

File tree

.changelog/6431.trivial.md

Whitespace-only changes.

go/consensus/cometbft/apps/scheduler/scheduler.go

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,23 @@ func (app *Application) maybeElect(ctx *api.Context) error {
114114

115115
// shouldElect determines whether elections should be performed.
116116
func (app *Application) shouldElect(ctx *api.Context) (*electionDecision, error) {
117+
// The 0th epoch will not have suitable entropy for elections, nor
118+
// will it have useful node registrations.
119+
baseEpoch, err := app.state.GetBaseEpoch()
120+
if err != nil {
121+
return nil, fmt.Errorf("cometbft/scheduler: couldn't get base epoch: %w", err)
122+
}
123+
124+
epochChanged, epoch := app.state.EpochChanged(ctx)
125+
if epoch == baseEpoch {
126+
ctx.Logger().Info("system in bootstrap period, skipping election",
127+
"epoch", epoch,
128+
)
129+
return &electionDecision{}, nil
130+
}
131+
117132
// Check if epoch has changed.
118133
// TODO: We'll later have this for each type of committee.
119-
epochChanged, epoch := app.state.EpochChanged(ctx)
120134
if epochChanged {
121135
// For elections on epoch changes, distribute rewards.
122136
return &electionDecision{
@@ -149,20 +163,6 @@ func (app *Application) elect(ctx *api.Context, epoch beacon.EpochTime, reward b
149163
return fmt.Errorf("cometbft/scheduler: before schedule notification failed: %w", err)
150164
}
151165

152-
// The 0th epoch will not have suitable entropy for elections, nor
153-
// will it have useful node registrations.
154-
baseEpoch, err := app.state.GetBaseEpoch()
155-
if err != nil {
156-
return fmt.Errorf("cometbft/scheduler: couldn't get base epoch: %w", err)
157-
}
158-
159-
if epoch == baseEpoch {
160-
ctx.Logger().Info("system in bootstrap period, skipping election",
161-
"epoch", epoch,
162-
)
163-
return nil
164-
}
165-
166166
state := schedulerState.NewMutableState(ctx.State())
167167
schedulerParameters, err := state.ConsensusParameters(ctx)
168168
if err != nil {
@@ -177,6 +177,20 @@ func (app *Application) elect(ctx *api.Context, epoch beacon.EpochTime, reward b
177177
if err != nil {
178178
return fmt.Errorf("cometbft/scheduler: couldn't get beacon parameters: %w", err)
179179
}
180+
entropy, err := beaconState.Beacon(ctx)
181+
if err != nil {
182+
return fmt.Errorf("cometbft/scheduler: couldn't get beacon: %w", err)
183+
}
184+
185+
var vrf *beacon.PrevVRFState
186+
if beaconParameters.Backend == beacon.BackendVRF {
187+
vrfState, err := beaconState.VRFState(ctx)
188+
if err != nil {
189+
return fmt.Errorf("cometbft/scheduler: failed to query VRF state: %w", err)
190+
}
191+
vrf = vrfState.PrevState
192+
}
193+
180194
// If weak alphas are allowed then skip the eligibility check as
181195
// well because the byzantine node and associated tests are extremely
182196
// fragile, and breaks in hard-to-debug ways if timekeeping isn't
@@ -231,12 +245,13 @@ func (app *Application) elect(ctx *api.Context, epoch beacon.EpochTime, reward b
231245
validatorEntities, err := electValidators(
232246
ctx,
233247
epoch,
234-
beaconState,
235248
beaconParameters,
236249
stakeAcc,
237250
rewardableEntities,
238251
nodes,
239252
schedulerParameters,
253+
entropy,
254+
vrf,
240255
)
241256
if err != nil {
242257
// It is unclear what the behavior should be if the validator
@@ -255,13 +270,14 @@ func (app *Application) elect(ctx *api.Context, epoch beacon.EpochTime, reward b
255270
ctx,
256271
epoch,
257272
schedulerParameters,
258-
beaconState,
259273
beaconParameters,
260274
registryParameters,
261275
stakeAcc,
262276
rewardableEntities,
263277
validatorEntities,
264278
committeeNodes,
279+
entropy,
280+
vrf,
265281
isFeatureVersion242,
266282
); err != nil {
267283
return fmt.Errorf("cometbft/scheduler: couldn't elect committees: %w", err)
@@ -301,39 +317,49 @@ func (app *Application) ExecuteTx(*api.Context, *transaction.Transaction) error
301317
func (app *Application) EndBlock(ctx *api.Context) (types.ResponseEndBlock, error) {
302318
var resp types.ResponseEndBlock
303319

320+
validatorUpdates, err := updateValidators(ctx, resp)
321+
if err != nil {
322+
return resp, err
323+
}
324+
325+
resp.ValidatorUpdates = validatorUpdates
326+
327+
return resp, nil
328+
}
329+
330+
func updateValidators(ctx *api.Context, resp types.ResponseEndBlock) ([]types.ValidatorUpdate, error) {
304331
state := schedulerState.NewMutableState(ctx.State())
305332
pendingValidators, err := state.PendingValidators(ctx)
306333
if err != nil {
307-
return resp, fmt.Errorf("cometbft/scheduler: failed to query pending validators: %w", err)
334+
return nil, fmt.Errorf("cometbft/scheduler: failed to query pending validators: %w", err)
308335
}
309336
if pendingValidators == nil {
310337
// No validator updates to apply.
311-
return resp, nil
338+
return nil, nil
312339
}
313340

314341
currentValidators, err := state.CurrentValidators(ctx)
315342
if err != nil {
316-
return resp, fmt.Errorf("cometbft/scheduler: failed to query current validators: %w", err)
343+
return nil, fmt.Errorf("cometbft/scheduler: failed to query current validators: %w", err)
317344
}
318345

319346
// Clear out the pending validator update.
320347
if err = state.PutPendingValidators(ctx, nil); err != nil {
321-
return resp, fmt.Errorf("cometbft/scheduler: failed to clear validators: %w", err)
348+
return nil, fmt.Errorf("cometbft/scheduler: failed to clear validators: %w", err)
322349
}
323350

324351
// CometBFT expects a vector of ValidatorUpdate that expresses
325352
// the difference between the current validator set (tracked manually
326353
// from InitChain), and the new validator set, which is a huge pain
327354
// in the ass.
328355

329-
resp.ValidatorUpdates = diffValidators(ctx.Logger(), currentValidators, pendingValidators)
356+
validatorUpdates := diffValidators(ctx.Logger(), currentValidators, pendingValidators)
330357

331358
// Stash the updated validator set.
332359
if err = state.PutCurrentValidators(ctx, pendingValidators); err != nil {
333-
return resp, fmt.Errorf("cometbft/scheduler: failed to set validators: %w", err)
360+
return nil, fmt.Errorf("cometbft/scheduler: failed to set validators: %w", err)
334361
}
335-
336-
return resp, nil
362+
return validatorUpdates, nil
337363
}
338364

339365
func diffValidators(logger *logging.Logger, current, pending map[signature.PublicKey]*scheduler.Validator) []types.ValidatorUpdate {
@@ -433,13 +459,14 @@ func (app *Application) electCommittees(
433459
ctx *api.Context,
434460
epoch beacon.EpochTime,
435461
schedulerParameters *scheduler.ConsensusParameters,
436-
beaconState *beaconState.MutableState,
437462
beaconParameters *beacon.ConsensusParameters,
438463
registryParameters *registry.ConsensusParameters,
439464
stakeAcc *stakingState.StakeAccumulatorCache,
440465
rewardableEntities map[staking.Address]struct{},
441466
validatorEntities map[staking.Address]struct{},
442467
nodes []*nodeWithStatus,
468+
entropy []byte,
469+
vrf *beacon.PrevVRFState,
443470
isFeatureVersion242 bool,
444471
) error {
445472
runtimes, err := fetchRuntimes(ctx)
@@ -457,7 +484,6 @@ func (app *Application) electCommittees(
457484
ctx,
458485
epoch,
459486
schedulerParameters,
460-
beaconState,
461487
beaconParameters,
462488
registryParameters,
463489
stakeAcc,
@@ -466,6 +492,8 @@ func (app *Application) electCommittees(
466492
runtime,
467493
nodes,
468494
kind,
495+
entropy,
496+
vrf,
469497
isFeatureVersion242,
470498
); err != nil {
471499
return err
@@ -481,12 +509,13 @@ func (app *Application) electCommittees(
481509
func electValidators(
482510
ctx *api.Context,
483511
epoch beacon.EpochTime,
484-
beaconState *beaconState.MutableState,
485512
beaconParameters *beacon.ConsensusParameters,
486513
stakeAcc *stakingState.StakeAccumulatorCache,
487514
rewardableEntities map[staking.Address]struct{},
488515
nodes []*node.Node,
489516
schedulerParameters *scheduler.ConsensusParameters,
517+
entropy []byte,
518+
vrf *beacon.PrevVRFState,
490519
) (map[staking.Address]struct{}, error) {
491520
// Filter nodes based on eligibility and minimum required entity stake.
492521
var validators []*node.Node
@@ -509,17 +538,13 @@ func electValidators(
509538

510539
// Sort all of the entities that are actually running eligible validator
511540
// nodes by descending stake.
512-
weakEntropy, err := beaconState.Beacon(ctx)
513-
if err != nil {
514-
return nil, fmt.Errorf("cometbft/scheduler: couldn't get beacon: %w", err)
515-
}
516-
sortedEntities, err := stakingAddressMapToSliceByStake(entities, stakeAcc, weakEntropy, schedulerParameters)
541+
sortedEntities, err := stakingAddressMapToSliceByStake(entities, stakeAcc, entropy, schedulerParameters)
517542
if err != nil {
518543
return nil, err
519544
}
520545

521546
// Shuffle validator nodes.
522-
shuffledNodes, err := shuffleValidators(ctx, epoch, schedulerParameters, beaconState, beaconParameters, validators)
547+
shuffledNodes, err := shuffleValidators(ctx, epoch, schedulerParameters, beaconParameters, validators, entropy, vrf)
523548
if err != nil {
524549
return nil, err
525550
}

go/consensus/cometbft/apps/scheduler/scheduler_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,11 +804,13 @@ func TestElectCommittee(t *testing.T) {
804804

805805
rewardableEntities := make(map[staking.Address]struct{})
806806

807+
entropy, err := beaconState.Beacon(ctx)
808+
require.NoError(err, "Beacon")
809+
807810
err = electCommittee(
808811
ctx,
809812
epoch,
810813
schedulerParameters,
811-
beaconState,
812814
beaconParameters,
813815
registryParameters,
814816
stakeAcc,
@@ -817,6 +819,8 @@ func TestElectCommittee(t *testing.T) {
817819
&tc.rt,
818820
nodes,
819821
tc.kind,
822+
entropy,
823+
nil,
820824
true,
821825
)
822826
require.NoError(err, "committee election should not fail")

0 commit comments

Comments
 (0)