# Ethereum validators performance
The following stats will reflect the performance of a validator from the very first moment from which keystores was uploaded to the brain, it will not be fetched its previous performance.
**Basic**
- Validator status [`/eth/v1/beacon/states/{state_id}/validators`](https://ethereum.github.io/beacon-APIs/#/Beacon/getStateValidators). See [validator status specification](https://hackmd.io/ofFJ5gOmQpu1jjHilHbdQQ)
- Validator Effectiveness (or Attestation Inclusion Delay o retrasados): the distance between the slot assigned and the slot where the attestation was finally made. Ideal is 0.
- Blocks
- Sync Committees
- Attestation Success Rate (or attestations assignment) `(%) = (Number of Successful Attestations + Number of Successful Proposals) / (Total Attestation Opportunities + Total Proposal Opportunities) * 100`:
1. **knowing the validator's assigned slot** Retrieve the Validator's Attestation Duties for a given epoch (it will be the finalized head): https://ethereum.github.io/beacon-APIs/#/Validator/getAttesterDuties. This will return the **slot**, **committee_index** and **validator_committee_index** in which the validator is expected to attest during a given epoch, it might attest within the next slots but that would mean a inclusion distance delay).
```json
{
"dependent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
"execution_optimistic": false,
"data": [
{
"pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a",
"validator_index": "1",
"committee_index": "1",
"committee_length": "1",
"committees_at_slot": "1",
"validator_committee_index": "1",
"slot": "1"
}
]
}
```
2. **Check if the Validator Submitted an Attestation** check whether the validator submitted an attestation for a given block in the slot and committee index and finally checking the bit from `aggregation_bits` with index validator_committee_index (data retrieved in previous step): https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockAttestations
```json
{
"execution_optimistic": false,
"finalized": false,
"data": [
{
"aggregation_bits": "0x01",
"signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505",
"data": {
"slot": "1",
"index": "1",
"beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2",
"source": {
"epoch": "1",
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
},
"target": {
"epoch": "1",
"root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"
}
}
}
]
}
```
- What data to save on db:
- Epoch | missed/attested | slot | Inclussion distance (how to reproduce)
- Create a database in postgresql or mongodb?
```sql
CREATE TABLE attestation_status (
validator_index BIGINT NOT NULL, -- Validator index or you can change to pubkey if preferred
epoch_slot BIGINT NOT NULL, -- The slot within the epoch
attestation_success BOOLEAN NOT NULL, -- Whether the attestation was successful or missed
PRIMARY KEY (validator_index, epoch_slot) -- Ensures uniqueness for each validator-slot pair
);
```
## Attestations summary
- An attestation is basically the sum of 3 votes: head, target & source. See more here https://ethos.dev/beacon-chain
- Seems like most used RPC endpoint to check if validator attested or not in an epoch (is online) is https://ethereum.github.io/beacon-APIs/#/Validator/getLiveness. It returns if a validator (defined by index) was seen during that epoch attesting.
- We can also know rewards/penalizations for hitting or missing an attestation at a given block https://ethereum.github.io/beacon-APIs/#/Rewards/getAttestationsRewards. Rewards/penalitzation are the sum of "head", "target" & "source" of the endpoint response. Rewards are negative if attestation was missed, possitive if attestation was correct. Note that we can also deduce if attestation was missed or hit here, aswell as validator balance
- total_rewards are positive numbers --> attestation hit
- total_rewards are negative numbers --> attestation miss. these are not rewards, but penalites.
- when the attestation hits, total_rewards will be equal to those of ideal_rewards that correspond to actual effective_balance of the validator.
More info on lighthouse discord:
from message https://discord.com/channels/605577013327167508/605577013331361793/1281537003816620062
to https://discord.com/channels/605577013327167508/605577013331361793/1281628446925258824
**Extra**
- slashing rate
- penalty rate
- block proposal success rate
- block production latency.
## Implementation
1. Brain cron task
- Will run for the current epoch finalized until:
- new epoch and no data -> write on db the reason: syncing, error, elOffline
- new epoch and data -> write on db the validator performance
- Cron timeline:
1. Get head finalized
2. Compare with epoch in db
2.1 If already in db skip
2.2 If not in db continue
2.2.1 Get validator performance
2.2.1.1 If error retry (every 1/2 min or so) -> check again epoch finalized, if it has changed save error and continue with new epoch finalized
2.2.1.2 If data -> write on db
- To track validator performance the following endpoints will be called
- https://ethereum.github.io/beacon-APIs/#/Rewards/getSyncCommitteeRewards
- Block rewards:
- https://ethereum.github.io/beacon-APIs/#/Rewards/getBlockRewards -> this endpoint not working in Lodestar
- https://ethereum.github.io/beacon-APIs/#/Beacon/getBlockV2
- https://ethereum.github.io/beacon-APIs/#/Rewards/getAttestationsRewards
- (OPTIONAL) https://ethereum.github.io/beacon-APIs/#/Validator/getLiveness
2. Postgres database
```sql
CREATE TABLE IF NOT EXISTS validator_performance (
validator_index BIGINT NOT NULL,
epoch BIGINT NOT NULL,
slot BIGINT NOT NULL,
liveness BOOLEAN NOT NULL,
block_proposal_status ENUM ('missed', 'proposed', 'unchosen') NOT NULL ,
sync_comittee_rewards BIGINT NOT NULL,
attestations_rewards JSONB NOT NULL, `{"head": "2000","target":"2000","source":"4000","inclusion_delay":"2000",}`
error TEXT,
PRIMARY KEY (validator_index, epoch)
```
3. Validator performance UI
3.1 UI in brain
3.2 Add postgres as source data in DMS https://hackmd.io/ZozDbUKmS0G0ZltntoaRmg
- Create a `postgres-targets.json` file with the specs required, see https://grafana.com/docs/grafana/latest/datasources/postgres/
```json
"user": "",
"password": ,
```
- Implement in dappmanager installer this new file
- Implement in DMS this postgres target file injection
- Grafana dashboard
## Questions
- Why does inclusion distance is defined in the beacon api standard https://ethereum.github.io/beacon-APIs/#/Rewards/getAttestationsRewards as `inclusion_delay` but none consensus client return it in the response? (Lodestar does return it but returns 0)
- Can be determined the [livness](https://ethereum.github.io/beacon-APIs/#/Validator/getLiveness) using just the [block attestation rewards](https://ethereum.github.io/beacon-APIs/#/Rewards/getAttestationsRewards)?
- Liveness true is attestation rewards positive
- Liveness false is attestation rewards negative