Implement VC API (#1657)

## Issue Addressed

NA

## Proposed Changes

- Implements a HTTP API for the validator client.
- Creates EIP-2335 keystores with an empty `description` field, instead of a missing `description` field. Adds option to set name.
- Be more graceful with setups without any validators (yet)
    - Remove an error log when there are no validators.
    - Create the `validator` dir if it doesn't exist.
- Allow building a `ValidatorDir` without a withdrawal keystore (required for the API method where we only post a voting keystore).
- Add optional `description` field to `validator_definitions.yml`

## TODO

- [x] Signature header, as per https://github.com/sigp/lighthouse/issues/1269#issuecomment-649879855
- [x] Return validator descriptions
- [x] Return deposit data
- [x] Respect the mnemonic offset
- [x] Check that mnemonic can derive returned keys
- [x] Be strict about non-localhost
- [x] Allow graceful start without any validators (+ create validator dir)
- [x] Docs final pass
- [x] Swap to EIP-2335 description field. 
- [x] Fix Zerioze TODO in VC api types.
- [x] Zeroize secp256k1 key

## Endpoints

- [x] `GET /lighthouse/version`
- [x] `GET /lighthouse/health`
- [x] `GET /lighthouse/validators` 
- [x] `POST /lighthouse/validators/hd`
- [x] `POST /lighthouse/validators/keystore`
- [x] `PATCH /lighthouse/validators/:validator_pubkey`
- [ ] ~~`POST /lighthouse/validators/:validator_pubkey/exit/:epoch`~~ Future works


## Additional Info

TBC
This commit is contained in:
Paul Hauner
2020-10-02 09:42:19 +00:00
parent 1d278aaa83
commit 6ea3bc5e52
43 changed files with 2882 additions and 172 deletions

View File

@@ -19,6 +19,9 @@
* [/lighthouse](./api-lighthouse.md)
* [Validator Inclusion APIs](./validator-inclusion.md)
* [Validator Client API](./api-vc.md)
* [Endpoints](./api-vc-endpoints.md)
* [Authorization Header](./api-vc-auth-header.md)
* [Signature Header](./api-vc-sig-header.md)
* [Prometheus Metrics](./advanced_metrics.md)
* [Advanced Usage](./advanced.md)
* [Database Configuration](./advanced_database.md)

View File

@@ -0,0 +1,55 @@
# Validator Client API: Authorization Header
## Overview
The validator client HTTP server requires that all requests have the following
HTTP header:
- Name: `Authorization`
- Value: `Basic <api-token>`
Where `<api-token>` is a string that can be obtained from the validator client
host. Here is an example `Authorization` header:
```
Authorization Basic api-token-0x03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123
```
## Obtaining the API token
The API token can be obtained via two methods:
### Method 1: Reading from a file
The API token is stored as a file in the `validators` directory. For most users
this is `~/.lighthouse/{testnet}/validators/api-token.txt`. Here's an
example using the `cat` command to print the token to the terminal, but any
text editor will suffice:
```
$ cat api-token.txt
api-token-0x03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123
```
### Method 2: Reading from logs
When starting the validator client it will output a log message containing an
`api-token` field:
```
Sep 28 19:17:52.615 INFO HTTP API started api_token: api-token-0x03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123, listen_address: 127.0.0.1:5062
```
## Example
Here is an example `curl` command using the API token in the `Authorization` header:
```bash
curl localhost:5062/lighthouse/version -H "Authorization: Basic api-token-0x03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123"
```
The server should respond with its version:
```json
{"data":{"version":"Lighthouse/v0.2.11-fc0654fbe+/x86_64-linux"}}
```

View File

@@ -0,0 +1,363 @@
# Validator Client API: Endpoints
## Endpoints
HTTP Path | Description |
| --- | -- |
[`GET /lighthouse/version`](#get-lighthouseversion) | Get the Lighthouse software version
[`GET /lighthouse/health`](#get-lighthousehealth) | Get information about the host machine
[`GET /lighthouse/spec`](#get-lighthousespec) | Get the Eth2 specification used by the validator
[`GET /lighthouse/validators`](#get-lighthousevalidators) | List all validators
[`GET /lighthouse/validators/:voting_pubkey`](#get-lighthousevalidatorsvoting_pubkey) | Get a specific validator
[`PATCH /lighthouse/validators/:voting_pubkey`](#patch-lighthousevalidatorsvoting_pubkey) | Update a specific validator
[`POST /lighthouse/validators`](#post-lighthousevalidators) | Create a new validator and mnemonic.
[`POST /lighthouse/validators/mnemonic`](#post-lighthousevalidatorsmnemonic) | Create a new validator from an existing mnemonic.
## `GET /lighthouse/version`
Returns the software version and `git` commit hash for the Lighthouse binary.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/version`
Method | GET
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200
### Example Response Body
```json
{
"data": {
"version": "Lighthouse/v0.2.11-fc0654fbe+/x86_64-linux"
}
}
```
## `GET /lighthouse/health`
Returns information regarding the health of the host machine.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/health`
Method | GET
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200
*Note: this endpoint is presently only available on Linux.*
### Example Response Body
```json
{
"data": {
"pid": 1476293,
"pid_num_threads": 19,
"pid_mem_resident_set_size": 4009984,
"pid_mem_virtual_memory_size": 1306775552,
"sys_virt_mem_total": 33596100608,
"sys_virt_mem_available": 23073017856,
"sys_virt_mem_used": 9346957312,
"sys_virt_mem_free": 22410510336,
"sys_virt_mem_percent": 31.322334,
"sys_loadavg_1": 0.98,
"sys_loadavg_5": 0.98,
"sys_loadavg_15": 1.01
}
}
```
## `GET /lighthouse/spec`
Returns the Eth2 specification loaded for this validator.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/spec`
Method | GET
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200
### Example Response Body
```json
{
"data": {
"CONFIG_NAME": "mainnet",
"MAX_COMMITTEES_PER_SLOT": "64",
"TARGET_COMMITTEE_SIZE": "128",
"MIN_PER_EPOCH_CHURN_LIMIT": "4",
"CHURN_LIMIT_QUOTIENT": "65536",
"SHUFFLE_ROUND_COUNT": "90",
"MIN_GENESIS_ACTIVE_VALIDATOR_COUNT": "1024",
"MIN_GENESIS_TIME": "1601380800",
"GENESIS_DELAY": "172800",
"MIN_DEPOSIT_AMOUNT": "1000000000",
"MAX_EFFECTIVE_BALANCE": "32000000000",
"EJECTION_BALANCE": "16000000000",
"EFFECTIVE_BALANCE_INCREMENT": "1000000000",
"HYSTERESIS_QUOTIENT": "4",
"HYSTERESIS_DOWNWARD_MULTIPLIER": "1",
"HYSTERESIS_UPWARD_MULTIPLIER": "5",
"PROPORTIONAL_SLASHING_MULTIPLIER": "3",
"GENESIS_FORK_VERSION": "0x00000002",
"BLS_WITHDRAWAL_PREFIX": "0x00",
"SECONDS_PER_SLOT": "12",
"MIN_ATTESTATION_INCLUSION_DELAY": "1",
"MIN_SEED_LOOKAHEAD": "1",
"MAX_SEED_LOOKAHEAD": "4",
"MIN_EPOCHS_TO_INACTIVITY_PENALTY": "4",
"MIN_VALIDATOR_WITHDRAWABILITY_DELAY": "256",
"SHARD_COMMITTEE_PERIOD": "256",
"BASE_REWARD_FACTOR": "64",
"WHISTLEBLOWER_REWARD_QUOTIENT": "512",
"PROPOSER_REWARD_QUOTIENT": "8",
"INACTIVITY_PENALTY_QUOTIENT": "16777216",
"MIN_SLASHING_PENALTY_QUOTIENT": "32",
"SAFE_SLOTS_TO_UPDATE_JUSTIFIED": "8",
"DOMAIN_BEACON_PROPOSER": "0x00000000",
"DOMAIN_BEACON_ATTESTER": "0x01000000",
"DOMAIN_RANDAO": "0x02000000",
"DOMAIN_DEPOSIT": "0x03000000",
"DOMAIN_VOLUNTARY_EXIT": "0x04000000",
"DOMAIN_SELECTION_PROOF": "0x05000000",
"DOMAIN_AGGREGATE_AND_PROOF": "0x06000000",
"MAX_VALIDATORS_PER_COMMITTEE": "2048",
"SLOTS_PER_EPOCH": "32",
"EPOCHS_PER_ETH1_VOTING_PERIOD": "32",
"SLOTS_PER_HISTORICAL_ROOT": "8192",
"EPOCHS_PER_HISTORICAL_VECTOR": "65536",
"EPOCHS_PER_SLASHINGS_VECTOR": "8192",
"HISTORICAL_ROOTS_LIMIT": "16777216",
"VALIDATOR_REGISTRY_LIMIT": "1099511627776",
"MAX_PROPOSER_SLASHINGS": "16",
"MAX_ATTESTER_SLASHINGS": "2",
"MAX_ATTESTATIONS": "128",
"MAX_DEPOSITS": "16",
"MAX_VOLUNTARY_EXITS": "16",
"ETH1_FOLLOW_DISTANCE": "1024",
"TARGET_AGGREGATORS_PER_COMMITTEE": "16",
"RANDOM_SUBNETS_PER_VALIDATOR": "1",
"EPOCHS_PER_RANDOM_SUBNET_SUBSCRIPTION": "256",
"SECONDS_PER_ETH1_BLOCK": "14",
"DEPOSIT_CONTRACT_ADDRESS": "0x48b597f4b53c21b48ad95c7256b49d1779bd5890"
}
}
```
## `GET /lighthouse/validators`
Lists all validators managed by this validator client.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/validators`
Method | GET
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200
### Example Response Body
```json
{
"data": [
{
"enabled": true,
"voting_pubkey": "0xb0148e6348264131bf47bcd1829590e870c836dc893050fd0dadc7a28949f9d0a72f2805d027521b45441101f0cc1cde"
},
{
"enabled": true,
"voting_pubkey": "0xb0441246ed813af54c0a11efd53019f63dd454a1fa2a9939ce3c228419fbe113fb02b443ceeb38736ef97877eb88d43a"
},
{
"enabled": true,
"voting_pubkey": "0xad77e388d745f24e13890353031dd8137432ee4225752642aad0a2ab003c86620357d91973b6675932ff51f817088f38"
}
]
}
```
## `GET /lighthouse/validators/:voting_pubkey`
Get a validator by their `voting_pubkey`.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/validators/:voting_pubkey`
Method | GET
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200, 400
### Example Path
```
localhost:5062/lighthouse/validators/0xb0148e6348264131bf47bcd1829590e870c836dc893050fd0dadc7a28949f9d0a72f2805d027521b45441101f0cc1cde
```
### Example Response Body
```json
{
"data": {
"enabled": true,
"voting_pubkey": "0xb0148e6348264131bf47bcd1829590e870c836dc893050fd0dadc7a28949f9d0a72f2805d027521b45441101f0cc1cde"
}
}
```
## `PATCH /lighthouse/validators/:voting_pubkey`
Update some values for the validator with `voting_pubkey`.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/validators/:voting_pubkey`
Method | PATCH
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200, 400
### Example Path
```
localhost:5062/lighthouse/validators/0xb0148e6348264131bf47bcd1829590e870c836dc893050fd0dadc7a28949f9d0a72f2805d027521b45441101f0cc1cde
```
### Example Request Body
```json
{
"enabled": false
}
```
### Example Response Body
```json
null
```
## `POST /lighthouse/validators/`
Create any number of new validators, all of which will share a common mnemonic
generated by the server.
A BIP-39 mnemonic will be randomly generated and returned with the response.
This mnemonic can be used to recover all keys returned in the response.
Validators are generated from the mnemonic according to
[EIP-2334](https://eips.ethereum.org/EIPS/eip-2334), starting at index `0`.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/validators`
Method | POST
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200
### Example Request Body
```json
[
{
"enable": true,
"description": "validator_one",
"deposit_gwei": "32000000000"
},
{
"enable": false,
"description": "validator two",
"deposit_gwei": "34000000000"
}
]
```
### Example Response Body
```json
{
"data": {
"mnemonic": "marine orchard scout label trim only narrow taste art belt betray soda deal diagram glare hero scare shadow ramp blur junior behave resource tourist",
"validators": [
{
"enabled": true,
"description": "validator_one",
"voting_pubkey": "0x8ffbc881fb60841a4546b4b385ec5e9b5090fd1c4395e568d98b74b94b41a912c6101113da39d43c101369eeb9b48e50",
"eth1_deposit_tx_data": "0x22895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001206c68675776d418bfd63468789e7c68a6788c4dd45a3a911fe3d642668220bbf200000000000000000000000000000000000000000000000000000000000000308ffbc881fb60841a4546b4b385ec5e9b5090fd1c4395e568d98b74b94b41a912c6101113da39d43c101369eeb9b48e5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000cf8b3abbf0ecd91f3b0affcc3a11e9c5f8066efb8982d354ee9a812219b17000000000000000000000000000000000000000000000000000000000000000608fbe2cc0e17a98d4a58bd7a65f0475a58850d3c048da7b718f8809d8943fee1dbd5677c04b5fa08a9c44d271d009edcd15caa56387dc217159b300aad66c2cf8040696d383d0bff37b2892a7fe9ba78b2220158f3dc1b9cd6357bdcaee3eb9f2",
"deposit_gwei": "32000000000"
},
{
"enabled": false,
"description": "validator two",
"voting_pubkey": "0xa9fadd620dc68e9fe0d6e1a69f6c54a0271ad65ab5a509e645e45c6e60ff8f4fc538f301781193a08b55821444801502",
"eth1_deposit_tx_data": "0x22895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120b1911954c1b8d23233e0e2bf8c4878c8f56d25a4f790ec09a94520ec88af30490000000000000000000000000000000000000000000000000000000000000030a9fadd620dc68e9fe0d6e1a69f6c54a0271ad65ab5a509e645e45c6e60ff8f4fc538f301781193a08b5582144480150200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000a96df8b95c3ba749265e48a101f2ed974fffd7487487ed55f8dded99b617ad000000000000000000000000000000000000000000000000000000000000006090421299179824950e2f5a592ab1fdefe5349faea1e8126146a006b64777b74cce3cfc5b39d35b370e8f844e99c2dc1b19a1ebd38c7605f28e9c4540aea48f0bc48e853ae5f477fa81a9fc599d1732968c772730e1e47aaf5c5117bd045b788e",
"deposit_gwei": "34000000000"
}
]
}
}
```
## `POST /lighthouse/validators/mnemonic`
Create any number of new validators, all of which will share a common mnemonic.
The supplied BIP-39 mnemonic will be used to generate the validator keys
according to [EIP-2334](https://eips.ethereum.org/EIPS/eip-2334), starting at
the supplied `key_derivation_path_offset`. For example, if
`key_derivation_path_offset = 42`, then the first validator voting key will be
generated with the path `m/12381/3600/i/42`.
### HTTP Specification
| Property | Specification |
| --- |--- |
Path | `/lighthouse/validators/mnemonic`
Method | POST
Required Headers | [`Authorization`](./api-vc-auth-header.md)
Typical Responses | 200
### Example Request Body
```json
{
"mnemonic": "theme onion deal plastic claim silver fancy youth lock ordinary hotel elegant balance ridge web skill burger survey demand distance legal fish salad cloth",
"key_derivation_path_offset": 0,
"validators": [
{
"enable": true,
"description": "validator_one",
"deposit_gwei": "32000000000"
}
]
}
```
### Example Response Body
```json
{
"data": [
{
"enabled": true,
"description": "validator_one",
"voting_pubkey": "0xa062f95fee747144d5e511940624bc6546509eeaeae9383257a9c43e7ddc58c17c2bab4ae62053122184c381b90db380",
"eth1_deposit_tx_data": "0x22895118000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120a57324d95ae9c7abfb5cc9bd4db253ed0605dc8a19f84810bcf3f3874d0e703a0000000000000000000000000000000000000000000000000000000000000030a062f95fee747144d5e511940624bc6546509eeaeae9383257a9c43e7ddc58c17c2bab4ae62053122184c381b90db3800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200046e4199f18102b5d4e8842d0eeafaa1268ee2c21340c63f9c2cd5b03ff19320000000000000000000000000000000000000000000000000000000000000060b2a897b4ba4f3910e9090abc4c22f81f13e8923ea61c0043506950b6ae174aa643540554037b465670d28fa7b7d716a301e9b172297122acc56be1131621c072f7c0a73ea7b8c5a90ecd5da06d79d90afaea17cdeeef8ed323912c70ad62c04b",
"deposit_gwei": "32000000000"
}
]
}
```

View File

@@ -0,0 +1,108 @@
# Validator Client API: Signature Header
## Overview
The validator client HTTP server adds the following header to all responses:
- Name: `Signature`
- Value: a secp256k1 signature across the SHA256 of the response body.
Example `Signature` header:
```
Signature: 0x304402205b114366444112580bf455d919401e9c869f5af067cd496016ab70d428b5a99d0220067aede1eb5819eecfd5dd7a2b57c5ac2b98f25a7be214b05684b04523aef873
```
## Verifying the Signature
Below is a browser-ready example of signature verification.
### HTML
```html
<script src="https://rawgit.com/emn178/js-sha256/master/src/sha256.js" type="text/javascript"></script>
<script src="https://rawgit.com/indutny/elliptic/master/dist/elliptic.min.js" type="text/javascript"></script>
```
### Javascript
```javascript
// Helper function to turn a hex-string into bytes.
function hexStringToByte(str) {
if (!str) {
return new Uint8Array();
}
var a = [];
for (var i = 0, len = str.length; i < len; i+=2) {
a.push(parseInt(str.substr(i,2),16));
}
return new Uint8Array(a);
}
// This example uses the secp256k1 curve from the "elliptic" library:
//
// https://github.com/indutny/elliptic
var ec = new elliptic.ec('secp256k1');
// The public key is contained in the API token:
//
// Authorization: Basic api-token-0x03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123
var pk_bytes = hexStringToByte('03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123');
// The signature is in the `Signature` header of the response:
//
// Signature: 0x304402205b114366444112580bf455d919401e9c869f5af067cd496016ab70d428b5a99d0220067aede1eb5819eecfd5dd7a2b57c5ac2b98f25a7be214b05684b04523aef873
var sig_bytes = hexStringToByte('304402205b114366444112580bf455d919401e9c869f5af067cd496016ab70d428b5a99d0220067aede1eb5819eecfd5dd7a2b57c5ac2b98f25a7be214b05684b04523aef873');
// The HTTP response body.
var response_body = "{\"data\":{\"version\":\"Lighthouse/v0.2.11-fc0654fbe+/x86_64-linux\"}}";
// The HTTP response body is hashed (SHA256) to determine the 32-byte message.
let hash = sha256.create();
hash.update(response_body);
let message = hash.array();
// The 32-byte message hash, the signature and the public key are verified.
if (ec.verify(message, sig_bytes, pk_bytes)) {
console.log("The signature is valid")
} else {
console.log("The signature is invalid")
}
```
*This example is also available as a [JSFiddle](https://jsfiddle.net/wnqd74Lz/).*
## Example
The previous Javascript example was written using the output from the following
`curl` command:
```bash
curl -v localhost:5062/lighthouse/version -H "Authorization: Basic api-token-0x03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123"
```
```
* Trying ::1:5062...
* connect to ::1 port 5062 failed: Connection refused
* Trying 127.0.0.1:5062...
* Connected to localhost (127.0.0.1) port 5062 (#0)
> GET /lighthouse/version HTTP/1.1
> Host: localhost:5062
> User-Agent: curl/7.72.0
> Accept: */*
> Authorization: Basic api-token-0x03eace4c98e8f77477bb99efb74f9af10d800bd3318f92c33b719a4644254d4123
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< content-type: application/json
< signature: 0x304402205b114366444112580bf455d919401e9c869f5af067cd496016ab70d428b5a99d0220067aede1eb5819eecfd5dd7a2b57c5ac2b98f25a7be214b05684b04523aef873
< server: Lighthouse/v0.2.11-fc0654fbe+/x86_64-linux
< access-control-allow-origin:
< content-length: 65
< date: Tue, 29 Sep 2020 04:23:46 GMT
<
* Connection #0 to host localhost left intact
{"data":{"version":"Lighthouse/v0.2.11-fc0654fbe+/x86_64-linux"}}
```

View File

@@ -1,3 +1,38 @@
# Validator Client API
The validator client API is planned for release in late September 2020.
Lighthouse implements a HTTP/JSON API for the validator client. Since there is
no Eth2 standard validator client API, Lighthouse has defined its own.
A full list of endpoints can be found in [Endpoints](./api-vc-endpoints.md).
> Note: All requests to the HTTP server must supply an
> [`Authorization`](./api-vc-auth-header.md) header. All responses contain a
> [`Signature`](./api-vc-sig-header.md) header for optional verification.
## Starting the server
A Lighthouse validator client can be configured to expose a HTTP server by supplying the `--http` flag. The default listen address is `127.0.0.1:5062`.
The following CLI flags control the HTTP server:
- `--http`: enable the HTTP server (required even if the following flags are
provided).
- `--http-port`: specify the listen port of the server.
- `--http-allow-origin`: specify the value of the `Access-Control-Allow-Origin`
header. The default is to not supply a header.
## Security
The validator client HTTP is **not encrypted** (i.e., it is **not HTTPS**). For
this reason, it will only listen on `127.0.0.1`.
It is unsafe to expose the validator client to the public Internet without
additional transport layer security (e.g., HTTPS via nginx, SSH tunnels, etc.).
### CLI Example
Start the validator client with the HTTP server listening on [http://localhost:5062](http://localhost:5062):
```bash
lighthouse vc --http
```