Try   HackMD

Eth2.0 Validator API Standard

Why?

  • The main goal of this effort is to increase client diversity. UIs are very important to some users so this standard should ensure all clients have at least one.
  • The secondary goal is to offload UI work from core dev teams to other parties that can prioritize this work over Altair, the merge, etc.

WIP: This standard must be cheap to implement to be successful. Core devs are encouraged to voice concerns around complexity to ensure a timely implementation.


Minimal validator API to enable a basic validator manager workflow. Supports:

  • Import, delete keystores
  • Import, export slashing db

Does not support:

  • Metrics visualization or plotting any type of chain data. Instead, should be done with metrics tooling such as Grafana or block explorers
  • VoluntaryExit. Instead, should be done with the deposit cli tooling.
  • Backup accounts. When migrating validator clients stakers should re-generate the keystores from the mnemonic or retrieve them from a self-managed backup.
  • Displaying logs.

All routes SHOULD be disabled by default and only be enabled with a CLI flag such as --enable-validator-api.

All sensitive routes MUST be authenticated. There SHOULD exist a single password per validator client binary such that multiple users are not supported.

The validator API MUST allow to add and delete accounts but SHOULD not allow to retrieve them. Users are encouraged to use alternative locations to backup their keystores and use them to perform validator client migration.

Routes

All account and slashing protection routes MUST be authenticated with a token set by the Login route. The server MUST not rely on the UI's Javascript to add extra headers for authentication, and SHOULD use an HttpOnly cookie token for authentication.

  • Authenticated routes MUST return 401 Unauthorized if no token is found.
  • Authenticated routes MUST return 403 Forbidden if a token is found but is invalid or incorrect.

WIP: Routes prefix and versioning TBD

GET /accounts - ListAccounts

Request {
    // The maximum number of accounts to return in the response.
    // This field is optional.
    page_size: int32
    // A pagination token returned from a previous call to `ListAccounts`
    // that indicates where this listing should continue from.
    // This field is optional.
    page_token: string
}

Response {
    accounts: {
        // The validating public key.
        validating_pubkey: bytes
        // The derivation path (if present in the imported keystore).
        derivation_path: string
        // Latest slashing protection DB data item associated with this pubkey
        // Signal no slashing protection DB data with a value of TBD (0, null, "")
        slashing_protection_last_entry: string
    }[]
    // A pagination token returned from a previous call
    // that indicates from where listing should continue.
    // This field is optional
    next_page_token: string
    // Total count matching the request.
    total_size: int32
}

POST /accounts/import - ImportAccounts

Import keystores generated by the Eth2.0 deposit CLI tooling. All keystores MUST be encrypted with the same password.

Request {
    // JSON-encoded keystore files to import during wallet creation.
    keystores_imported: string[]
    // Password to unlock imported keystore files.
    keystores_password: string
}

Response {
    imported_pubkeys: bytes[]
}

POST /accounts/delete DeleteAccounts

Delete keystores for the pubkeys provided in the request. The validator client MUST stop validating with these keystores immediately and MUST return a 200 status only after confirming no more signatures can be created with those keys.

Request {
    // List of public keys to delete.
    pubkeys: bytes[];
}

Response {
    // List of public keys successfully deleted.
    deleted_pubkeys: bytes[];
}

GET /slashing_protection - ExportSlashingProtection

MUST return a file with the format defined in EIP-3076: Slashing Protection Interchange Format. If pubkeys is not specified MUST return data for all pubkeys in the local slashing protection DB.

Request {
    // List of public keys to export slashing protection DB data.
    // This field is optional
    pubkeys: bytes[];
}

Response {
    // JSON representation of the slash protection
    file: string
}

POST /slashing_protection - ImportSlashingProtection

MUST accept a file with the format defined in EIP-3076: Slashing Protection Interchange Format.

Users are encouraged to use the slashing_protection_last_entry field to confirm that they successfully added slashing protection data for their accounts.

Request {
    // JSON representation of the slash protection
    slashing_protection_json: string
}

// Response empty

GET /login - LoginStatus

Convenience method to check if user has signed up, and their token is valid.

// Request empty

Response {
    has_signed_up: bool
}

POST /login - Login

Request {
    password: string
    password_confirmation: string
}

// Response empty

MUST validate the provided passwords against a local "Record". After successful validation MUST return a Set-Cookie header

Set-Cookie: SESSION=<token>; HttpOnly; SameSite=Strict

Cookie atributes:

  • HttpOnly: MUST be included
  • SameSite: MUST be set to Strict
  • Max-Age: MAY be included
  • Secure: SHOULD not be included. Validator client servers may not have TLS/SSL certificates
  • Domain: MAY be included

POST /signup - Signup

Request {
    password: string
    password_confirmation: string
}

// Response empty

Register a new password to be used to encrypt the local wallet. The password MUST:

  • Be stored locally hashed with salt to authenticate future logins.
  • Be used to encrypt and decrypt the local representation of the imported keystores

The validator binary MUST expose a CLI argument --persist-password to enable persisting the password such that it can be restarted and perform validator duties without requiring interaction by the user.

POST /logout Logout

MUST invalidate the token set by the Login route if found in the request headers.

// Request empty
// Response empty

POST /change_password - ChangePassword

The validator client MUST re-encrypt the local representation of the keystores if applicable.

Request {
    current_password: string;
    password: string;
    password_confirmation: string;
}

// Response empty