Validators

Validators are an essential part of the Heimdall. Heimdall has an option to change validators at the end of each block. It is called EndBlocker That's part of Cosmos-SDK: https://docs.cosmos.network/master/building-modules/beginblock-endblock.html

Heimdall uses following structure for the validator:

// Validator for Heimdall
type Validator struct {
ID ValidatorID `json:"ID"`
StartEpoch uint64 `json:"startEpoch"`
EndEpoch uint64 `json:"endEpoch"`
VotingPower int64 `json:"power"`
PubKey PubKey `json:"pubKey"`
Signer HeimdallAddress `json:"signer"`
LastUpdated string `json:"last_updated"`
ProposerPriority int64 `json:"accum"`
}
// ValidatorID validator ID and helper functions
type ValidatorID uint64

Here StartEpoch and EndEpoch are checkpoint numbers in between validator will be active as a validator. In EndBlocker for the app, Heimdall gets all active validators and updates the current validator set in the state.

In the end, it returns validator updates for the Tendermint.

Source: https://github.com/maticnetwork/heimdall/blob/develop/app/app.go#L500-L542

...
// --- Start update to new validators
currentValidatorSet := app.StakingKeeper.GetValidatorSet(ctx)
allValidators := app.StakingKeeper.GetAllValidators(ctx)
ackCount := app.CheckpointKeeper.GetACKCount(ctx)
// get validator updates
setUpdates := helper.GetUpdatedValidators(
&currentValidatorSet, // pointer to current validator set -- UpdateValidators will modify it
allValidators, // All validators
ackCount, // ack count
)
if len(setUpdates) > 0 {
// create new validator set
if err := currentValidatorSet.UpdateWithChangeSet(setUpdates); err != nil {
// return with nothing
logger.Error("Unable to update current validator set", "Error", err)
return abci.ResponseEndBlock{}
}
// increment proposer priority
currentValidatorSet.IncrementProposerPriority(1)
// save set in store
if err := app.StakingKeeper.UpdateValidatorSetInStore(ctx, currentValidatorSet); err != nil {
// return with nothing
logger.Error("Unable to update current validator set in state", "Error", err)
return abci.ResponseEndBlock{}
}
// convert updates from map to array
for _, v := range setUpdates {
tmValUpdates = append(tmValUpdates, abci.ValidatorUpdate{
Power: int64(v.VotingPower),
PubKey: v.PubKey.ABCIPubKey(),
})
}
}
...
// send validator updates to peppermint
return abci.ResponseEndBlock{
ValidatorUpdates: tmValUpdates,
}