From 5652e25d5853d124621909b11a1d932a97d0d050 Mon Sep 17 00:00:00 2001 From: D13ce Date: Thu, 19 Oct 2023 09:26:09 +0200 Subject: [PATCH 1/7] (BIDS-2567) Improve error handling and remove out-commented code --- handlers/validator.go | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/handlers/validator.go b/handlers/validator.go index 2ac6bc8568..e5cd1e1ac9 100644 --- a/handlers/validator.go +++ b/handlers/validator.go @@ -52,7 +52,6 @@ func Validator(w http.ResponseWriter, r *http.Request) { currency := GetCurrency(r) - //start := time.Now() timings := struct { Start time.Time BasicInfo time.Duration @@ -131,6 +130,12 @@ func Validator(w http.ResponseWriter, r *http.Request) { } index, err = db.GetValidatorIndex(pubKey) if err != nil { + if err != sql.ErrNoRows { + logger.Errorf("error retrieving index for validator pubkey %v: %v", pubKey, err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + // the validator might only have a public key but no index yet var name string err := db.ReaderDb.Get(&name, `SELECT name FROM validator_names WHERE publickey = $1`, pubKey) @@ -255,14 +260,9 @@ func Validator(w http.ResponseWriter, r *http.Request) { } } - // GetAvgOptimalInclusionDistance(index) - SetPageDataTitle(data, fmt.Sprintf("Validator %v", index)) data.Meta.Path = fmt.Sprintf("/validator/%v", index) - // logger.Infof("retrieving data, elapsed: %v", time.Since(start)) - // start = time.Now() - // we use MAX(validatorindex)+1 instead of COUNT(*) for querying the rank_count for performance-reasons err = db.ReaderDb.Get(&validatorPageData, ` SELECT @@ -606,7 +606,6 @@ func Validator(w http.ResponseWriter, r *http.Request) { // add attestationStats that are not yet in validator_stats lookback := int64(lastFinalizedEpoch - (lastStatsDay+1)*utils.EpochsPerDay()) if lookback > 0 { - // logger.Infof("retrieving attestations not yet in stats, lookback is %v", lookback) missedAttestations, err := db.BigtableClient.GetValidatorMissedAttestationHistory([]uint64{index}, lastFinalizedEpoch-uint64(lookback), lastFinalizedEpoch) if err != nil { return fmt.Errorf("error retrieving validator attestations not in stats from bigtable: %w", err) @@ -826,7 +825,6 @@ func Validator(w http.ResponseWriter, r *http.Request) { return } - // validatorPageData.IncomeToday.Total = float64(validatorPageData.IncomeToday.Cl) + price.GetPrice(utils.Config.Frontend.ElCurrency, utils.Config.Frontend.ClCurrency)*float64(validatorPageData.IncomeToday.El) validatorPageData.FutureDutiesEpoch = protomath.MaxU64(futureProposalEpoch, futureSyncDutyEpoch) data.Data = validatorPageData @@ -1389,9 +1387,7 @@ func ValidatorSlashings(w http.ResponseWriter, r *http.Request) { } } -/* -Function checks if the generated ECDSA signature has correct lentgth and if needed sets recovery byte to 0 or 1 -*/ +// Function checks if the generated ECDSA signature has correct lentgth and if needed sets recovery byte to 0 or 1 func sanitizeSignature(sig string) ([]byte, error) { sig = strings.Replace(sig, "0x", "", -1) decodedSig, _ := hex.DecodeString(sig) @@ -1404,11 +1400,11 @@ func sanitizeSignature(sig string) ([]byte, error) { return []byte(decodedSig), nil } -/* -Function tries to find the substring. -If successful it turns string into []byte value and returns it -If it fails, it will try to decode `msg`value from Hexadecimal to string and retry search again -*/ +// Function tries to find the substring. +// +// If successful it turns string into []byte value and returns it +// +// If it fails, it will try to decode `msg`value from Hexadecimal to string and retry search again func sanitizeMessage(msg string) ([]byte, error) { subString := "beaconcha.in" @@ -1872,10 +1868,6 @@ func ValidatorStatsTable(w http.ResponseWriter, r *http.Request) { return } - // if validatorStatsTablePageData.Rows[len(validatorStatsTablePageData.Rows)-1].Day == -1 { - // validatorStatsTablePageData.Rows = validatorStatsTablePageData.Rows[:len(validatorStatsTablePageData.Rows)-1] - // } - data.Data = validatorStatsTablePageData if handleTemplateError(w, r, "validator.go", "ValidatorStatsTable", "", validatorStatsTableTemplate.ExecuteTemplate(w, "layout", data)) != nil { return // an error has occurred and was processed @@ -1917,7 +1909,6 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { if length > 100 { length = 100 } - // descOrdering := q.Get("order[0][dir]") == "desc" // retrieve all sync periods for this validator var syncPeriods []uint64 = []uint64{} @@ -1951,7 +1942,6 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { firstSlot := firstEpoch * utils.Config.Chain.ClConfig.SlotsPerEpoch lastSlot := (lastEpoch+1)*utils.Config.Chain.ClConfig.SlotsPerEpoch - 1 - // logger.Infof("processing sync period %v epoch (%v/%v) slots (%v/%v)", period, firstEpoch, lastEpoch, firstSlot, lastSlot) for slot := lastSlot; slot >= firstSlot && (slot <= lastSlot /* guards against underflows */); slot-- { if slot > latestProposedSlot || utils.EpochOfSlot(slot) < utils.Config.Chain.ClConfig.AltairForkEpoch { continue @@ -1972,7 +1962,6 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { endSlot := slots[endIndex] startSlot := slots[startIndex] - // logger.Infof("retrieving sync duty history for validator %v and slots %v-%v (%v-%v)", validatorIndex, startSlot, endSlot, startIndex, endIndex) syncDuties, err := db.BigtableClient.GetValidatorSyncDutiesHistory([]uint64{validatorIndex}, startSlot, endSlot) if err != nil { From f11769bc30a2f86956f48357f7bc67d12285773c Mon Sep 17 00:00:00 2001 From: D13ce Date: Thu, 19 Oct 2023 11:14:10 +0200 Subject: [PATCH 2/7] (BIDS-2567) Improve and unify error logs in validator.go --- handlers/validator.go | 238 +++++++++++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 82 deletions(-) diff --git a/handlers/validator.go b/handlers/validator.go index e5cd1e1ac9..f88517f59d 100644 --- a/handlers/validator.go +++ b/handlers/validator.go @@ -5,7 +5,6 @@ import ( "database/sql" "encoding/hex" "encoding/json" - "errors" "eth2-exporter/db" "eth2-exporter/services" "eth2-exporter/templates" @@ -72,6 +71,8 @@ func Validator(w http.ResponseWriter, r *http.Request) { var index uint64 var err error + errFields := map[string]interface{}{ + "route": r.URL.String()} latestEpoch := services.LatestEpoch() latestProposedSlot := services.LatestProposedSlot() @@ -116,7 +117,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { validatorPageData.FlashMessage, err = utils.GetFlash(w, r, validatorEditFlash) if err != nil { - logger.Errorf("error retrieving flashes for validator %v: %v", vars["index"], err) + utils.LogError(err, "error getting flash message", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -128,10 +129,11 @@ func Validator(w http.ResponseWriter, r *http.Request) { validatorNotFound(data, w, r, vars, "") return } + errFields["pubKey"] = pubKey index, err = db.GetValidatorIndex(pubKey) if err != nil { if err != sql.ErrNoRows { - logger.Errorf("error retrieving index for validator pubkey %v: %v", pubKey, err) + utils.LogError(err, "error getting index for validator based on pubkey", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -140,7 +142,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { var name string err := db.ReaderDb.Get(&name, `SELECT name FROM validator_names WHERE publickey = $1`, pubKey) if err != nil && err != sql.ErrNoRows { - logger.Errorf("error getting validator-name from db for pubKey %v: %v", pubKey, err) + utils.LogError(err, "error getting validator-name from db for pubKey", 0, errFields) validatorNotFound(data, w, r, vars, "") return // err == sql.ErrNoRows -> unnamed @@ -151,7 +153,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { var pool string err = db.ReaderDb.Get(&pool, `SELECT pool FROM validator_pool WHERE publickey = $1`, pubKey) if err != nil && err != sql.ErrNoRows { - logger.Errorf("error getting validator-pool from db for pubKey %v: %v", pubKey, err) + utils.LogError(err, "error getting validator-pool from db for pubkey", 0, errFields) validatorNotFound(data, w, r, vars, "") return // err == sql.ErrNoRows -> (no pool set) @@ -164,7 +166,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { } deposits, err := db.GetValidatorDeposits(pubKey) if err != nil { - logger.Errorf("error getting validator-deposits from db: %v", err) + utils.LogError(err, "error getting validator-deposits from db for pubkey", 0, errFields) } validatorPageData.DepositsCount = uint64(len(deposits.Eth1Deposits)) validatorPageData.ShowMultipleWithdrawalCredentialsWarning = hasMultipleWithdrawalCredentials(deposits) @@ -213,7 +215,8 @@ func Validator(w http.ResponseWriter, r *http.Request) { } watchlist, err := db.GetTaggedValidators(filter) if err != nil { - logger.Errorf("error getting tagged validators from db: %v", err) + errFields["userID"] = data.User.UserID + utils.LogError(err, "error getting tagged validators from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -260,6 +263,8 @@ func Validator(w http.ResponseWriter, r *http.Request) { } } + errFields["index"] = index + SetPageDataTitle(data, fmt.Sprintf("Validator %v", index)) data.Meta.Path = fmt.Sprintf("/validator/%v", index) @@ -292,14 +297,14 @@ func Validator(w http.ResponseWriter, r *http.Request) { validatorNotFound(data, w, r, vars, "") return } else if err != nil { - logger.Errorf("error getting validator for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error getting validator page data info from db", 0, errFields) validatorNotFound(data, w, r, vars, "") return } lastAttestationSlots, err := db.BigtableClient.GetLastAttestationSlots([]uint64{index}) if err != nil { - logger.WithError(err).WithField("route", r.URL.String()).Errorf("error retrieving validator last attestation slot data") + utils.LogError(err, "error getting last attestation slots from bigtable", 0, errFields) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -403,7 +408,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { }() earnings, balances, err := GetValidatorEarnings([]uint64{index}, currency) if err != nil { - return fmt.Errorf("error retrieving validator earnings: %w", err) + return fmt.Errorf("error getting validator earnings: %w", err) } validatorPageData.Income = earnings @@ -581,7 +586,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { // Check if the latest epoch still needs to be attested (scheduled) and if so do not count it attestationData, err := db.BigtableClient.GetValidatorAttestationHistory([]uint64{index}, validatorPageData.Epoch, validatorPageData.Epoch) if err != nil { - return fmt.Errorf("error retrieving validator attestations data for epoch [%v] and validator index [%v]: %w", validatorPageData.Epoch, index, err) + return fmt.Errorf("error getting validator attestations data for epoch [%v]: %w", validatorPageData.Epoch, err) } if len(attestationData[index]) > 0 && attestationData[index][0].Status == 0 { @@ -599,7 +604,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { if err == sql.ErrNoRows { logger.Warningf("no entry in validator_stats for validator index %v while lastStatsDay = %v", index, lastStatsDay) } else if err != nil { - return fmt.Errorf("error retrieving validator attestationStats for index %v while lastStatsDay = %v: %w", index, lastStatsDay, err) + return fmt.Errorf("error getting validator attestationStats while lastStatsDay = %v: %w", lastStatsDay, err) } } @@ -608,7 +613,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { if lookback > 0 { missedAttestations, err := db.BigtableClient.GetValidatorMissedAttestationHistory([]uint64{index}, lastFinalizedEpoch-uint64(lookback), lastFinalizedEpoch) if err != nil { - return fmt.Errorf("error retrieving validator attestations not in stats from bigtable: %w", err) + return fmt.Errorf("error getting validator attestations not in stats from bigtable: %w", err) } attestationStats.MissedAttestations += uint64(len(missedAttestations[index])) } @@ -645,7 +650,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { LIMIT 1`, index) if err != nil { - return fmt.Errorf("error retrieving validator slashing info: %w", err) + return fmt.Errorf("error getting validator slashing info: %w", err) } validatorPageData.SlashedBy = slashingInfo.Slasher validatorPageData.SlashedAt = slashingInfo.Slot @@ -654,7 +659,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { err = db.ReaderDb.Get(&validatorPageData.SlashingsCount, `SELECT COALESCE(SUM(attesterslashingscount) + SUM(proposerslashingscount), 0) FROM blocks WHERE blocks.proposer = $1 AND blocks.status = '1'`, index) if err != nil { - return fmt.Errorf("error retrieving slashings-count: %w", err) + return fmt.Errorf("error getting slashings-count: %w", err) } return nil }) @@ -662,10 +667,10 @@ func Validator(w http.ResponseWriter, r *http.Request) { g.Go(func() error { eff, err := db.BigtableClient.GetValidatorEffectiveness([]uint64{index}, validatorPageData.Epoch-1) if err != nil { - return fmt.Errorf("error retrieving validator effectiveness: %w", err) + return fmt.Errorf("error getting validator effectiveness: %w", err) } if len(eff) > 1 { - return fmt.Errorf("error retrieving validator effectiveness: invalid length %v", len(eff)) + return fmt.Errorf("error getting validator effectiveness: invalid length %v", len(eff)) } else if len(eff) == 0 { validatorPageData.AttestationInclusionEffectiveness = 0 } else { @@ -719,7 +724,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { FROM validator_stats WHERE validatorindex = $1`, index) if err != nil { - return fmt.Errorf("error retrieving validator syncStats: %w", err) + return fmt.Errorf("error getting validator syncStats: %w", err) } } @@ -733,7 +738,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { if lastSyncPeriod.LastEpoch > lastExportedEpoch { res, err := db.BigtableClient.GetValidatorSyncDutiesHistory([]uint64{index}, (lastExportedEpoch+1)*utils.Config.Chain.ClConfig.SlotsPerEpoch, latestProposedSlot) if err != nil { - return fmt.Errorf("error retrieving validator sync participations data from bigtable: %w", err) + return fmt.Errorf("error getting validator sync participations data from bigtable: %w", err) } syncStatsBt := utils.AddSyncStats([]uint64{index}, res, nil) // if last sync period is the current one, add remaining scheduled slots @@ -760,7 +765,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { maxPeriod := allSyncPeriods[0].Period expectedSyncCount, err := getExpectedSyncCommitteeSlots([]uint64{index}, lastFinalizedEpoch) if err != nil { - return fmt.Errorf("error retrieving expected sync committee slots: %w", err) + return fmt.Errorf("error getting expected sync committee slots: %w", err) } if expectedSyncCount != 0 { validatorPageData.SyncLuck = float64(validatorPageData.ParticipatedSyncCountSlots+validatorPageData.MissedSyncCountSlots) / float64(expectedSyncCount) @@ -820,7 +825,7 @@ func Validator(w http.ResponseWriter, r *http.Request) { err = g.Wait() if err != nil { - utils.LogError(err, "error retrieving validator data", 0) + utils.LogError(err, "error getting validator data", 0) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -886,16 +891,20 @@ func ValidatorDeposits(w http.ResponseWriter, r *http.Request) { return } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "pubkey": pubkey} + deposits, err := db.GetValidatorDeposits(pubkey) if err != nil { - logger.Errorf("error getting validator-deposits for %v: %v", vars["pubkey"], err) + utils.LogError(err, "error getting validator-deposits from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } err = json.NewEncoder(w).Encode(deposits) if err != nil { - logger.Errorf("error encoding validator-deposits for %v: %v", vars["pubkey"], err) + utils.LogError(err, "error encoding validator-deposits", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -917,9 +926,14 @@ func ValidatorAttestationInclusionEffectiveness(w http.ResponseWriter, r *http.R epoch = epoch - 1 } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "index": index, + "epoch": epoch} + eff, err := db.BigtableClient.GetValidatorEffectiveness([]uint64{index}, epoch) if err != nil { - logger.Errorf("error retrieving validator effectiveness: %v", err) + utils.LogError(err, "error getting validator effectiveness from bigtable", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -928,21 +942,22 @@ func ValidatorAttestationInclusionEffectiveness(w http.ResponseWriter, r *http.R Effectiveness float64 `json:"effectiveness"` } + errFields["effectiveness length"] = len(eff) if len(eff) > 1 { - logger.Errorf("error retrieving validator effectiveness: invalid length %v", len(eff)) + utils.LogError(err, "error getting validator effectiveness because of invalid length", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } else if len(eff) == 0 { err = json.NewEncoder(w).Encode(resp{Effectiveness: 0}) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } } else { err = json.NewEncoder(w).Encode(resp{Effectiveness: eff[0].AttestationEfficiency}) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -986,11 +1001,18 @@ func ValidatorProposedBlocks(w http.ResponseWriter, r *http.Request) { length = 100 } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "index": index, + "draw": draw, + "start": start, + "length": length} + var totalCount uint64 err = db.ReaderDb.Get(&totalCount, "SELECT COUNT(*) FROM blocks WHERE proposer = $1", index) if err != nil { - logger.Errorf("error retrieving proposed blocks count: %v", err) + utils.LogError(err, "error getting proposed blocks count from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1035,7 +1057,7 @@ func ValidatorProposedBlocks(w http.ResponseWriter, r *http.Request) { LIMIT $2 OFFSET $3`, index, length, start) if err != nil { - logger.Errorf("error retrieving proposed blocks data: %v", err) + utils.LogError(err, "error getting proposed blocks data from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1065,7 +1087,7 @@ func ValidatorProposedBlocks(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1098,6 +1120,12 @@ func ValidatorAttestations(w http.ResponseWriter, r *http.Request) { return } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "index": index, + "draw": draw, + "start": start} + length := 10 epoch := services.LatestEpoch() @@ -1109,7 +1137,7 @@ func ValidatorAttestations(w http.ResponseWriter, r *http.Request) { err = db.ReaderDb.Get(&ae, "SELECT activationepoch, exitepoch FROM validators WHERE validatorindex = $1", index) if err != nil { - logger.Errorf("error retrieving attestations count: %v", err) + utils.LogError(err, "error getting attestations count from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1139,7 +1167,9 @@ func ValidatorAttestations(w http.ResponseWriter, r *http.Request) { attestationData, err := db.BigtableClient.GetValidatorAttestationHistory([]uint64{index}, uint64(startEpoch), uint64(endEpoch)) if err != nil { - logger.Errorf("error retrieving bigtable validator attestations data: %v", err) + errFields["startEpoch"] = startEpoch + errFields["endEpoch"] = endEpoch + utils.LogError(err, "error getting validator attestations data from bigtable", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1171,7 +1201,7 @@ func ValidatorAttestations(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1223,18 +1253,27 @@ func ValidatorWithdrawals(w http.ResponseWriter, r *http.Request) { orderDir = "desc" } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "index": index, + "draw": draw, + "start": start, + "orderColumn": orderColumn, + "orderBy": orderBy, + "orderDir": orderDir} + length := uint64(10) withdrawalCount, err := db.GetTotalWithdrawalsCount([]uint64{index}) if err != nil { - logger.Errorf("error retrieving validator withdrawals count: %v", err) + utils.LogError(err, "error getting validator withdrawals count from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } withdrawals, err := db.GetValidatorWithdrawals(index, length, start, orderBy, orderDir) if err != nil { - logger.Errorf("error retrieving validator withdrawals: %v", err) + utils.LogError(err, "error getting validator withdrawals from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1260,7 +1299,7 @@ func ValidatorWithdrawals(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1287,6 +1326,11 @@ func ValidatorSlashings(w http.ResponseWriter, r *http.Request) { return } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "index": index, + "draw": draw} + var totalCount uint64 err = db.ReaderDb.Get(&totalCount, ` SELECT @@ -1299,7 +1343,7 @@ func ValidatorSlashings(w http.ResponseWriter, r *http.Request) { INNER JOIN blocks d ON d.slot = c.block_slot AND d.proposer = $1 )`, index) if err != nil { - logger.Errorf("error retrieving totalCount of validator-slashings: %v", err) + utils.LogError(err, "error getting totalCount of validator-slashings from db", 0, errFields) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } @@ -1317,7 +1361,7 @@ func ValidatorSlashings(w http.ResponseWriter, r *http.Request) { WHERE attestation1_indices IS NOT NULL AND attestation2_indices IS NOT NULL`, index) if err != nil { - logger.Errorf("error retrieving validator attestations data: %v", err) + utils.LogError(err, "error getting validator attestations data from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1328,7 +1372,7 @@ func ValidatorSlashings(w http.ResponseWriter, r *http.Request) { FROM blocks_proposerslashings INNER JOIN blocks ON blocks.proposer = $1 AND blocks_proposerslashings.block_slot = blocks.slot`, index) if err != nil { - logger.Errorf("error retrieving block proposer slashings data: %v", err) + utils.LogError(err, "error getting validator proposer slashings data from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1381,7 +1425,7 @@ func ValidatorSlashings(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1392,7 +1436,7 @@ func sanitizeSignature(sig string) ([]byte, error) { sig = strings.Replace(sig, "0x", "", -1) decodedSig, _ := hex.DecodeString(sig) if len(decodedSig) != 65 { - return nil, errors.New("signature is less then 65 bytes") + return nil, fmt.Errorf("signature is less than 65 bytes (len = %v)", len(decodedSig)) } if decodedSig[crypto.RecoveryIDOffset] == 27 || decodedSig[crypto.RecoveryIDOffset] == 28 { decodedSig[crypto.RecoveryIDOffset] -= 27 @@ -1417,8 +1461,7 @@ func sanitizeMessage(msg string) ([]byte, error) { if strings.Contains(decodedString, subString) { return []byte(decodedString), nil } - return nil, errors.New("beachoncha.in was not found") - + return nil, fmt.Errorf("%v was not found", subString) } } @@ -1481,10 +1524,17 @@ func SaveValidatorName(w http.ResponseWriter, r *http.Request) { recoveredAddress := crypto.PubkeyToAddress(*recoveredPubkey) + errFields := map[string]interface{}{ + "route": r.URL.String(), + "pubkey": pubkey, + "name": name, + "applyNameToAll": applyNameToAll, + "recoveredAddress": recoveredAddress} + var depositedAddress string deposits, err := db.GetValidatorDeposits(pubkeyDecoded) if err != nil { - logger.Errorf("error getting validator-deposits from db for signature verification: %v", err) + utils.LogError(err, "error getting validator-deposits from db for signature verification", 0, errFields) utils.SetFlash(w, r, validatorEditFlash, "Error: the provided signature is invalid") http.Redirect(w, r, "/validator/"+pubkey, http.StatusMovedPermanently) } @@ -1503,7 +1553,7 @@ func SaveValidatorName(w http.ResponseWriter, r *http.Request) { FROM (SELECT DISTINCT publickey FROM eth1_deposits WHERE from_address = $2 AND valid_signature) a ON CONFLICT (publickey) DO UPDATE SET name = excluded.name`, name, recoveredAddress.Bytes()) if err != nil { - logger.Errorf("error saving validator name (apply to all): %x: %v: %v", pubkeyDecoded, name, err) + utils.LogError(err, "error saving validator name", 0, errFields) utils.SetFlash(w, r, validatorEditFlash, "Error: Db error while updating validator names") http.Redirect(w, r, "/validator/"+pubkey, http.StatusMovedPermanently) return @@ -1518,7 +1568,7 @@ func SaveValidatorName(w http.ResponseWriter, r *http.Request) { VALUES($2, $1) ON CONFLICT (publickey) DO UPDATE SET name = excluded.name`, name, pubkeyDecoded) if err != nil { - logger.Errorf("error saving validator name: %x: %v: %v", pubkeyDecoded, name, err) + utils.LogError(err, "error saving validator name", 0, errFields) utils.SetFlash(w, r, validatorEditFlash, "Error: Db error while updating validator name") http.Redirect(w, r, "/validator/"+pubkey, http.StatusMovedPermanently) return @@ -1565,13 +1615,19 @@ func ValidatorHistory(w http.ResponseWriter, r *http.Request) { return } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "index": index, + "draw": draw, + "start": start} + var activationAndExitEpoch = struct { ActivationEpoch uint64 `db:"activationepoch"` ExitEpoch uint64 `db:"exitepoch"` }{} err = db.ReaderDb.Get(&activationAndExitEpoch, "SELECT activationepoch, exitepoch FROM validators WHERE validatorindex = $1", index) if err != nil { - logger.Errorf("error retrieving activationAndExitEpoch for validator-history: %v", err) + utils.LogError(err, "error getting activationAndExitEpoch for validator-history from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1616,7 +1672,7 @@ func ValidatorHistory(w http.ResponseWriter, r *http.Request) { OR orphaned_blocks > 0 );`, index) if err != nil { - logger.Errorf("error retrieving lastActionDay for validator-history: %v", err) + utils.LogError(err, "error getting lastActionDay for validator-history from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1716,7 +1772,7 @@ func ValidatorHistory(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1730,7 +1786,7 @@ func getWithdrawalAndIncome(index uint64, startEpoch uint64, endEpoch uint64) (m var err error withdrawals, err = db.GetValidatorsWithdrawalsByEpoch([]uint64{index}, startEpoch, endEpoch) if err != nil { - logger.Errorf("error retrieving validator withdrawals by epoch: %v", err) + logger.Errorf("error getting validator withdrawals by epoch: %v", err) return err } return nil @@ -1741,7 +1797,7 @@ func getWithdrawalAndIncome(index uint64, startEpoch uint64, endEpoch uint64) (m var err error incomeDetails, err = db.BigtableClient.GetValidatorIncomeDetailsHistory([]uint64{index}, startEpoch, endEpoch) if err != nil { - logger.Errorf("error retrieving validator income details history from bigtable: %v", err) + logger.Errorf("error getting validator income details history from bigtable: %v", err) return err } return nil @@ -1801,19 +1857,23 @@ func ValidatorStatsTable(w http.ResponseWriter, r *http.Request) { var index uint64 var err error + errFields := map[string]interface{}{ + "route": r.URL.String()} + data := InitPageData(w, r, "validators", "/validators", "", templateFiles) // Request came with a hash if utils.IsHash(vars["index"]) { pubKey, err := hex.DecodeString(strings.TrimPrefix(vars["index"], "0x")) if err != nil { - logger.Errorf("error parsing validator public key %v: %v", vars["index"], err) + utils.LogError(err, "error decoding validator index", 0, errFields) validatorNotFound(data, w, r, vars, "/stats") return } index, err = db.GetValidatorIndex(pubKey) if err != nil { - logger.Warnf("error parsing validator pubkey: %v", err) + errFields["pubkey"] = pubKey + utils.LogError(err, "error getting validator index from db", 0, errFields) validatorNotFound(data, w, r, vars, "/stats") return } @@ -1828,6 +1888,8 @@ func ValidatorStatsTable(w http.ResponseWriter, r *http.Request) { } } + errFields["index"] = index + SetPageDataTitle(data, fmt.Sprintf("Validator %v Daily Statistics", index)) data.Meta.Path = fmt.Sprintf("/validator/%v/stats", index) @@ -1838,32 +1900,34 @@ func ValidatorStatsTable(w http.ResponseWriter, r *http.Request) { err = db.ReaderDb.Select(&validatorStatsTablePageData.Rows, ` SELECT - validatorindex, - day, - start_balance, - end_balance, - min_balance, - max_balance, - start_effective_balance, - end_effective_balance, - min_effective_balance, - max_effective_balance, - COALESCE(missed_attestations, 0) AS missed_attestations, - COALESCE(proposed_blocks, 0) AS proposed_blocks, - COALESCE(missed_blocks, 0) AS missed_blocks, - COALESCE(orphaned_blocks, 0) AS orphaned_blocks, - COALESCE(attester_slashings, 0) AS attester_slashings, - COALESCE(proposer_slashings, 0) AS proposer_slashings, - COALESCE(deposits, 0) AS deposits, - COALESCE(deposits_amount, 0) AS deposits_amount, - COALESCE(participated_sync, 0) AS participated_sync, - COALESCE(missed_sync, 0) AS missed_sync, - COALESCE(orphaned_sync, 0) AS orphaned_sync, - COALESCE(cl_rewards_gwei, 0) AS cl_rewards_gwei - FROM validator_stats WHERE validatorindex = $1 ORDER BY day DESC`, index) + validatorindex, + day, + start_balance, + end_balance, + min_balance, + max_balance, + start_effective_balance, + end_effective_balance, + min_effective_balance, + max_effective_balance, + COALESCE(missed_attestations, 0) AS missed_attestations, + COALESCE(proposed_blocks, 0) AS proposed_blocks, + COALESCE(missed_blocks, 0) AS missed_blocks, + COALESCE(orphaned_blocks, 0) AS orphaned_blocks, + COALESCE(attester_slashings, 0) AS attester_slashings, + COALESCE(proposer_slashings, 0) AS proposer_slashings, + COALESCE(deposits, 0) AS deposits, + COALESCE(deposits_amount, 0) AS deposits_amount, + COALESCE(participated_sync, 0) AS participated_sync, + COALESCE(missed_sync, 0) AS missed_sync, + COALESCE(orphaned_sync, 0) AS orphaned_sync, + COALESCE(cl_rewards_gwei, 0) AS cl_rewards_gwei + FROM validator_stats + WHERE validatorindex = $1 + ORDER BY day DESC`, index) if err != nil { - logger.Errorf("error retrieving validator stats history: %v", err) + utils.LogError(err, "error getting validator stats history from db", 0, errFields) validatorNotFound(data, w, r, vars, "/stats") return } @@ -1910,6 +1974,13 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { length = 100 } + errFields := map[string]interface{}{ + "route": r.URL.String(), + "index": validatorIndex, + "draw": draw, + "start": start, + "length": length} + // retrieve all sync periods for this validator var syncPeriods []uint64 = []uint64{} @@ -1919,7 +1990,7 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { WHERE validatorindex = $1 ORDER BY period desc`, validatorIndex) if err != nil { - logger.WithError(err).Errorf("error getting sync tab count data of sync-assignments") + utils.LogError(err, "error getting sync tab count data of sync-assignments from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1964,8 +2035,11 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { syncDuties, err := db.BigtableClient.GetValidatorSyncDutiesHistory([]uint64{validatorIndex}, startSlot, endSlot) + errFields["startSlot"] = startSlot + errFields["endSlot"] = endSlot + if err != nil { - utils.LogError(fmt.Errorf("error retrieving validator [%v] sync duty data from bigtable for slots [%v-%v]: %w", validatorIndex, startSlot, endSlot, err), "", 0) + utils.LogError(err, "error getting validator sync duties data from bigtable", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1975,7 +2049,7 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { participations, err := db.GetSyncParticipationBySlotRange(startSlot, endSlot) if err != nil { - utils.LogError(fmt.Errorf("error retrieving validator [%v] sync participation data from bigtable for slots [%v-%v]: %w", validatorIndex, startSlot, endSlot, err), "", 0) + utils.LogError(err, "error getting validator sync participation data from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -1983,7 +2057,7 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { missedSlots := []uint64{} err = db.ReaderDb.Select(&missedSlots, `SELECT slot FROM blocks WHERE slot = ANY($1) AND status = '2'`, slotsRange) if err != nil { - logger.WithError(err).Errorf("error getting missed slots data") + utils.LogError(err, "error getting missed slots data from db", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } @@ -2040,7 +2114,7 @@ func ValidatorSync(w http.ResponseWriter, r *http.Request) { err = json.NewEncoder(w).Encode(data) if err != nil { - logger.Errorf("error enconding json response for %v route: %v", r.URL.String(), err) + utils.LogError(err, "error encoding json response", 0, errFields) http.Error(w, "Internal server error", http.StatusInternalServerError) return } From 3efb360dfaa1384ee9c5d98a83519175c77c310a Mon Sep 17 00:00:00 2001 From: D13ce Date: Thu, 19 Oct 2023 11:14:55 +0200 Subject: [PATCH 3/7] (BIDS-2567) Hide stats button for deposited/pending validators --- templates/validator/heading.html | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/templates/validator/heading.html b/templates/validator/heading.html index d591307ba6..82d5811880 100644 --- a/templates/validator/heading.html +++ b/templates/validator/heading.html @@ -36,11 +36,13 @@

{{ end }} - - - - - + {{ if (and (ne .Status "deposited") (ne .Status "deposited_invalid") (ne .Status "pending")) }} + + + + + + {{ end }}