Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Update non-matching validators [DEV-4671] (#142) #143

Merged
merged 4 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,18 @@ jobs:
contents: read
security-events: write

steps:
steps:
- name: Setup CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: 'go'
queries: security-and-quality
- uses: actions/setup-go@v4

- uses: actions/setup-go@v5
with:
go-version: 1.20
go-version: 1.22

- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required to fetch version

Expand All @@ -42,4 +42,4 @@ jobs:
make build

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
33 changes: 32 additions & 1 deletion database/staking_validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/forbole/callisto/v4/types"
"github.com/lib/pq"

dbtypes "github.com/forbole/callisto/v4/database/types"

Expand Down Expand Up @@ -420,7 +421,7 @@ func (db *Db) SaveValidatorsStatuses(statuses []types.ValidatorStatus) error {
}

validatorStmt = validatorStmt[:len(validatorStmt)-1]
validatorStmt += "ON CONFLICT DO NOTHING"
validatorStmt += " ON CONFLICT DO NOTHING"
_, err := db.SQL.Exec(validatorStmt, valParams...)
if err != nil {
return fmt.Errorf("error while storing validators: %s", err)
Expand All @@ -441,6 +442,36 @@ WHERE validator_status.height <= excluded.height`
return nil
}

// GetAllValidatorsWithStatus returns the list of validators having the given status.
func (db *Db) GetAllValidatorsWithStatus(status int) ([]string, error) {
query := `SELECT validator_address FROM validator_status WHERE status = $1`
rows, err := db.SQL.Query(query, status)
if err != nil {
return nil, err
}
defer rows.Close()

var addresses []string
for rows.Next() {
var address string
if err := rows.Scan(&address); err != nil {
return nil, err
}
addresses = append(addresses, address)
}
return addresses, nil
}

// UpdateValidators updates the given status of the validators having the given addresses
func (db *Db) UpdateValidators(addresses []string, status int, height int64) error {
query := `
UPDATE validator_status
SET status = $1, jailed = true
WHERE validator_address = ANY($3) AND height <= $2`
_, err := db.SQL.Exec(query, status, height, pq.Array(addresses))
return err
}

// saveDoubleSignVote saves the given vote inside the database, returning the row id
func (db *Db) saveDoubleSignVote(vote types.DoubleSignVote) (int64, error) {
stmt := `
Expand Down
40 changes: 40 additions & 0 deletions modules/staking/utils_validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ func (m *Module) UpdateValidatorStatuses() error {
return fmt.Errorf("error while updating validators status and voting power: %s", err)
}

// update non-matching validators statuses to Unbonded
err = m.updateNonMatchingValidatorStatuses(block.Height, validators, int(stakingtypes.Unbonded))
if err != nil {
return fmt.Errorf("error while updating non-matching validators status: %s", err)
}
// get all active proposals IDs from db
ids, err := m.db.GetOpenProposalsIds(block.BlockTimestamp)
if err != nil {
Expand Down Expand Up @@ -321,6 +326,41 @@ func (m *Module) updateValidatorStatusAndVP(height int64, validators []stakingty
return nil
}

func (m *Module) updateNonMatchingValidatorStatuses(height int64, validators []stakingtypes.Validator, defaultStatus int) error {
// Create a map of validator consensus addresses from the input list
validatorSet := make(map[string]bool, len(validators))
for _, validator := range validators {
consAddr, err := validator.GetConsAddr()
if err != nil {
return fmt.Errorf("error getting consensus address: %w", err)
}
validatorSet[consAddr.String()] = true
}
// Fetch all validators in the database that have status == Bonded
dbValidators, err := m.db.GetAllValidatorsWithStatus(int(stakingtypes.Bonded))
if err != nil {
return fmt.Errorf("error fetching validators with status != 1: %w", err)
}
// Identify non-matching validators
nonMatchingValidators := []string{}
for _, dbValidator := range dbValidators {
if _, exists := validatorSet[dbValidator]; !exists {
nonMatchingValidators = append(nonMatchingValidators, dbValidator)
}
}

// Update the status of non-matching validators
if len(nonMatchingValidators) > 0 {
err := m.db.UpdateValidators(nonMatchingValidators, defaultStatus, height)
if err != nil {
return fmt.Errorf("error updating non-matching validators: %w", err)
}
log.Debug().Int("count", len(nonMatchingValidators)).Msg("Updated non-matching validator statuses")
}

return nil
}

func (m *Module) GetValidatorsVotingPowers(height int64, vals *tmctypes.ResultValidators) ([]types.ValidatorVotingPower, error) {
stakingVals, _, err := m.getValidators(height)
if err != nil {
Expand Down
Loading