Compare commits

...

31 Commits

Author SHA1 Message Date
Jim McDonald
09105549b1 Tidy up block info output 2020-05-12 12:45:57 +01:00
Jim McDonald
364c764de2 Update README with basedir parameter 2020-05-12 12:32:43 +01:00
Jim McDonald
3f1fe30959 Add basedir option for the filesystem wallet store.
Fixes #4
2020-05-12 12:30:16 +01:00
Jim McDonald
aae360ccb8 Fetch genesis validators root from chain 2020-05-10 08:40:43 +01:00
Jim McDonald
32a3e4649d Update signing docs 2020-05-07 18:39:08 +01:00
Jim McDonald
dd3bd121fe Update wallet create docs 2020-05-07 18:33:15 +01:00
Jim McDonald
edf84f47ba Allow creation of HD wallets from seed phrase 2020-05-06 16:09:16 +01:00
Jim McDonald
320c5ee9ab Allow creation of HD wallets from seed phrase 2020-05-06 16:08:42 +01:00
Jim McDonald
36a1674549 Clarify that exit tx not sent when invalid 2020-05-03 12:58:42 +01:00
Jim McDonald
693b2a6961 Allow use of pubkey 2020-05-01 15:35:57 +01:00
Jim McDonald
e5481f9074 Bump version 2020-04-28 17:45:09 +01:00
Jim McDonald
c89712699c Update dependencies 2020-04-28 17:44:48 +01:00
Jim McDonald
7130855b73 Update dependencies 2020-04-28 17:15:11 +01:00
Jim McDonald
d505966a42 Clearer messages 2020-04-27 12:51:54 +01:00
Jim McDonald
732c07238a Merge branch 'master' of github.com:wealdtech/ethdo 2020-04-26 08:51:09 +01:00
Jim McDonald
b843d0077e Update documentation 2020-04-26 08:45:49 +01:00
Jim McDonald
f11cf0cbf5 Merge pull request #3 from superphiz/patch-1
extraneous letter
2020-04-25 23:00:22 +01:00
superphiz
ea43e71e60 extraneous letter 2020-04-25 11:51:29 -05:00
Jim McDonald
71b01ee2aa Merge branch 'master' of github.com:wealdtech/ethdo 2020-04-25 17:18:21 +01:00
Jim McDonald
de349f5691 Documentation tidy-ups 2020-04-25 17:18:06 +01:00
Jim McDonald
b1d2e94854 Merge pull request #2 from superphiz/patch-2
removed extraneous backtick
2020-04-25 07:26:38 +01:00
Jim McDonald
2293079861 Merge pull request #1 from superphiz/patch-1
typo in "accounts"
2020-04-25 07:26:14 +01:00
superphiz
69867ba21c removed extraneous backtick 2020-04-24 20:42:47 -05:00
superphiz
f72af8247a typo in "accounts" 2020-04-24 20:39:10 -05:00
Jim McDonald
9ca4406a80 Updates for validator exit 2020-04-23 09:56:04 +01:00
Jim McDonald
1ad82adf80 Tidy up chain info output 2020-04-21 14:48:31 +01:00
Jim McDonald
11eb440df2 Update README with wallet locations 2020-04-19 11:44:01 +01:00
Jim McDonald
e2192f6992 Version deposit data for additional security 2020-04-17 18:53:31 +01:00
Jim McDonald
864aa24484 Update docs 2020-04-16 08:43:51 +01:00
Jim McDonald
9f8d7c3f7b Update Prysm docs 2020-04-16 08:03:07 +01:00
Jim McDonald
4f643ad952 Add documentation for prysm 2020-04-16 07:55:02 +01:00
24 changed files with 1394 additions and 446 deletions

233
README.md
View File

@@ -17,24 +17,33 @@ A command-line tool for managing common tasks in Ethereum 2.
## Install
`ethdo` is a standard Go program which can be installed with:
```sh
GO111MODULE=on go get github.com/wealdtech/ethdo
```
Note that `ethdo` requires at least version 1.13 of go to operate. The version of go can be found with `go version`.
If this does not work please see the [troubleshooting](https://github.com/wealdtech/ethdo/blob/master/docs/troubleshooting.md) page.
## Usage
ethdo contains a large number of features that are useful for day-to-day interactions with the Ethereum 2 blockchain.
### Wallets and accounts
ethdo uses the [go-eth2-wallet](https://github.com/wealdtech/go-eth2-wallet) system to provide unified access to different wallet types.
ethdo uses the [go-eth2-wallet](https://github.com/wealdtech/go-eth2-wallet) system to provide unified access to different wallet types. When on the filesystem the locations of the created wallets and accounts are:
- for Linux: $HOME/.config/ethereum2/wallets
- for OSX: $HOME/Library/Application Support/ethereum2/wallets
- for Windows: %APPDATA%\ethereum2\wallets
If using the filesystem store, the additional parameter `basedir` can be supplied to change this location.
All ethdo comands take the following parameters:
- `store`: the name of the storage system for wallets. This can be one of "filesystem" or "s3", and defaults to "filesystem"
- `store`: the name of the storage system for wallets. This can be one of "filesystem" (for local storage of the wallet) or "s3" (for remote storage of the wallet on [Amazon's S3](https://aws.amazon.com/s3/) storage system), and defaults to "filesystem"
- `storepassphrase`: the passphrase for the store. If this is empty the store is unencrypted
- `walletpassphrase`: the passphrase for the wallet. This is required for some wallet-centric operations such as creating new accounts
- `accountpassphrase`: the passphrase for the account. This is required for some account-centric operations such as signing data
@@ -72,223 +81,13 @@ If set, the `--debug` argument will output additional information about the oper
Commands will have an exit status of 0 on success and 1 on failure. The specific definition of success is specified in the help for each command.
### `wallet` commands
# Commands
#### `accounts`
Command information, along with sample outputs and optional arguments, is available in [the usage section](https://github.com/wealdtech/ethdo/blob/master/docs/usage.md).
`ethdo wallet accouts` lists the accounts within a wallet.
# HOWTO
```sh
$ ethdo wallet accounts --wallet="Personal wallet"
Auctions
Operations
Spending
```
With the `--verbose` flag this will provide the public key of the accounts.
```sh
$ ethdo wallet accounts --wallet="Personal wallet" --verbose
Auctions: 0x812f340269c315c1d882ae7c13cdaddf862dbdbd482b1836798b2070160dd1e194088cc6f39347782028d1e56bd18674
Operations: 0x8e2f9e8cc29658ff37ecc30e95a0807579b224586c185d128cb7a7490784c1ad9b0ab93dbe604ab075b40079931e6670
Spending: 0x85dfc6dcee4c9da36f6473ec02fda283d6c920c641fc8e3a76113c5c227d4aeeb100efcfec977b12d20d571907d05650
```
#### `create`
`ethdo wallet create` creates a new wallet with the given parameters. Options for creating a wallet include:
- `wallet`: the name of the wallet to create (defaults to "primary")
- `type`: the type of wallet to create. This can be either "nd" for a non-deterministic wallet, where private keys are generated randomly, or "hd" for a hierarchical deterministic wallet, where private keys are generated from a seed and path as per [ERC-2333](https://github.com/CarlBeek/EIPs/blob/bls_path/EIPS/eip-2334.md) (defaults to "nd")
- `walletpassphrase`: the passphrase for of the wallet. This is required for hierarchical deterministic wallets, to protect the seed
```sh
$ ethdo wallet create --wallet="Personal wallet" --type="hd" --walletpassphrase="my wallet secret"
```
#### `export`
`ethdo wallet export` exports the wallet and all of its accounts. Options for exporting a wallet include:
- `wallet`: the name of the wallet to export (defaults to "primary")
- `exportpassphrase`: the passphrase with which to encrypt the wallet backup
```sh
$ ethdo wallet export --wallet="Personal wallet" --exportpassphrase="my export secret"
0x01c7a27ad40d45b4ae5be5f...
```
The encrypted wallet export is written to the console; it can be redirected to store it in a file.
```sh
$ ethdo wallet export --wallet="Personal wallet" --exportpassphrase="my export secret" >export.dat
```
#### `import`
`ethdo wallet import` imports a wallet and all of its accounts exported by `ethdo wallet export`. Options for importing a wallet include:
- `importdata`: the data exported by `ethdo wallet export`
- `importpassphrase`: the passphrase that was provided to `ethdo wallet export` to encrypt the data
```sh
$ ethdo wallet import --importdata="0x01c7a27ad40d45b4ae5be5f..." --importpassphrase="my export secret"
```
The encrypted wallet export can be read from a file. For example with Unix systems:
```sh
$ ethdo wallet import --importdata=`cat export.dat` --importpassphrase="my export secret"
```
#### `info`
`ethdo wallet info` provides information about a given wallet. Options include:
- `wallet`: the name of the wallet
```sh
$ ethdo wallet info --wallet="Personal wallet"
Type: hierarchical deterministic
Accounts: 3
```
#### `list`
`ethdo wallet list` lists all wallets in the store.
```sh
$ ethdo wallet list
Personal wallet
```
**N.B.** encrypted wallets will not show up in this list unless the correct passphrase for the store is supplied.
#### `seed`
`ethdo wallet seed` provides the seed for hierarchical deterministic wallets. Options include:
- `wallet`: the name of the wallet
- `walletpassphrase`: the passphrase for the wallet
```sh
$ ethdo wallet seed --wallet="Personal wallet" --walletpassphrase="my wallet secret"
decorate false mail domain gain later motion chair tank muffin smoke involve witness bean shell urge team solve share truly shadow decorate jeans hen
```
### `account` commands
Account commands focus on information about local accounts, generally those used by Geth and Parity but also those from hardware devices.
#### `create`
`ethdo account create` creates a new account with the given parameters. Options for creating an account include:
- `account`: the name of the account to create
- `passphrase`: the passphrase for the account
Note that for hierarchical deterministic wallets you will also need to supply `--walletpassphrase` to unlock the wallet seed.
```sh
$ ethdo account create --account="Personal wallet/Operations" --walletpassphrase="my wallet secret" --passphrase="my account secret"
```
#### `info`
`ethdo account info` provides information about the given account. Options include:
- `account`: the name of the account on which to obtain information
```sh
$ ethdo account info --account="Personal wallet/Operations"
Public key: 0x8e2f9e8cc29658ff37ecc30e95a0807579b224586c185d128cb7a7490784c1ad9b0ab93dbe604ab075b40079931e6670
```
### `signature` commands
Signature commands focus on generation and verification of data signatures.
#### `signature sign`
`ethdo signature sign` signs provided data. Options include:
- `data`: the data to sign, as a hex string
- `domain`: the domain in which to sign the data. This is an 8-byte hex string (default 0x0000000000000000)
- `account`: the account to sign the data
- `passphrase`: the passphrase for the account
```sh
$ ethdo signature sign --data="0x08140077a94642919041503caf5cc1795b23ecf2" --account="Personal wallet/Operations" --passphrase="my account secret"
0x89abe2e544ef3eafe397db036103b1d066ba86497f36ed4ab0264162eadc89c7744a2a08d43cec91df128660e70ecbbe11031b4c2e53682d2b91e67b886429bf8fac9bad8c7b63c5f231cc8d66b1377e06e27138b1ddc64b27c6e593e07ebb4b
```
#### `signature verify`
`ethdo signature verify` verifies signed data. Options include:
- `data`: the data whose signature to verify, as a hex string
- `signature`: the signature to verify, as a hex string
- `account`: the account which signed the data (if available as an account)
- `signer`: the public key of the account which signed the data (if not available as an account)
```sh
$ ethdo signature verify --data="0x08140077a94642919041503caf5cc1795b23ecf2" --signature="0x89abe2e544ef3eafe397db036103b1d066ba86497f36ed4ab0264162eadc89c7744a2a08d43cec91df128660e70ecbbe11031b4c2e53682d2b91e67b886429bf8fac9bad8c7b63c5f231cc8d66b1377e06e27138b1ddc64b27c6e593e07ebb4b" --account="Personal wallet/Operations"
Verified
$ ethdo signature verify --data="0x08140077a94642919041503caf5cc1795b23ecf2" --signature="0x89abe2e544ef3eafe397db036103b1d066ba86497f36ed4ab0264162eadc89c7744a2a08d43cec91df128660e70ecbbe11031b4c2e53682d2b91e67b886429bf8fac9bad8c7b63c5f231cc8d66b1377e06e27138b1ddc64b27c6e593e07ebb4b" --account="Personal wallet/Auctions"
Not verified
$ ethdo signature verify --data="0x08140077a94642919041503caf5cc1795b23ecf2" --signature="0x89abe2e544ef3eafe397db036103b1d066ba86497f36ed4ab0264162eadc89c7744a2a08d43cec91df128660e70ecbbe11031b4c2e53682d2b91e67b886429bf8fac9bad8c7b63c5f231cc8d66b1377e06e27138b1ddc64b27c6e593e07ebb4b" --signer="0x8e2f9e8cc29658ff37ecc30e95a0807579b224586c185d128cb7a7490784c1ad9b0ab93dbe604ab075b40079931e6670"
Verified
```
The same rules apply to `ethereal signature verify` as those in `ethereal signature sign` above.
### `version`
`ethdo version` provides the current version of ethdo. For example:
```sh
$ ethdo version
1.0.0
```
### `validator` commands
Validator commands focus on interaction with Ethereum 2 validators.
#### `depositdata`
`validator depositdata` generates the data required to deposit one or more Ethereum 2 validators.
#### `exit`
`validator exit` sends a transaction to the chain to tell an active validator to exit the validation queue.
```sh
$ ethdo validator exit --account=Validators/1 --passphrase="my validator secret"
```
#### `info`
`validator info` provides information for a given validator.
```sh
$ ethdo validator info --account=Validators/1
Status: Active
Balance: 3.203823585 Ether
Effective balance: 3.1 Ether
```
Additional information is supplied when using `--verbose`
```sh
$ ethdo validator info --account=Validators/1 --verbose
Epoch of data: 3398
Index: 26913
Public key: 0xb3bb6b7a8d809e59544472853d219499765bf01d14de1e0549bd6fc2a86627ac9033264c84cd503b6339e3334726562f
Status: Active
Balance: 3.204026813 Ether
Effective balance: 3.1 Ether
Withdrawal credentials: 0x0033ef3cb10b36d0771ffe8a02bc5bfc7e64ea2f398ce77e25bb78989edbee36
```
If the validator is not an account it can be queried directly with `--pubkey`.
```sh
$ ethdo validator info --pubkey=0x842dd66cfeaeff4397fc7c94f7350d2131ca0c4ad14ff727963be9a1edb4526604970df6010c3da6474a9820fa81642b
Status: Active
Balance: 3.201850307 Ether
Effective balance: 3.1 Ether
```
There is a [HOWTO](https://github.com/wealdtech/ethdo/blob/master/docs/howto.md) that covers details about how to carry out various common tasks.
## Maintainers

View File

@@ -15,12 +15,14 @@ package cmd
import (
"bytes"
"encoding/hex"
"fmt"
"os"
"sort"
"strings"
"unicode/utf8"
"github.com/prysmaticlabs/go-bitfield"
"github.com/spf13/cobra"
"github.com/wealdtech/ethdo/grpc"
string2eth "github.com/wealdtech/go-string2eth"
@@ -62,15 +64,17 @@ In quiet mode this will return 0 if the block information is present and not ski
// General info.
outputIf(verbose, fmt.Sprintf("Parent root: %#x", block.ParentRoot))
outputIf(verbose, fmt.Sprintf("State root: %#x", block.StateRoot))
if utf8.Valid(body.Graffiti) {
fmt.Printf("Graffiti: %s\n", string(body.Graffiti))
} else {
fmt.Printf("Graffiti: %#x\n", body.Graffiti)
if len(body.Graffiti) > 0 && hex.EncodeToString(body.Graffiti) != "0000000000000000000000000000000000000000000000000000000000000000" {
if utf8.Valid(body.Graffiti) {
fmt.Printf("Graffiti: %s\n", string(body.Graffiti))
} else {
fmt.Printf("Graffiti: %#x\n", body.Graffiti)
}
}
// Eth1 data.
eth1Data := body.Eth1Data
fmt.Printf("Ethereum 1 deposit count: %d\n", eth1Data.DepositCount)
outputIf(verbose, fmt.Sprintf("Ethereum 1 deposit count: %d", eth1Data.DepositCount))
outputIf(verbose, fmt.Sprintf("Ethereum 1 deposit root: %#x", eth1Data.DepositRoot))
outputIf(verbose, fmt.Sprintf("Ethereum 1 block hash: %#x", eth1Data.BlockHash))
@@ -81,7 +85,7 @@ In quiet mode this will return 0 if the block information is present and not ski
fmt.Printf("\t%d:\n", i)
fmt.Printf("\t\tCommittee index: %d\n", att.Data.CommitteeIndex)
fmt.Printf("\t\tAttesters: %d\n", countSetBits(att.AggregationBits))
fmt.Printf("\t\tAttesters: %d/%d\n", att.AggregationBits.Count(), att.AggregationBits.Len())
fmt.Printf("\t\tAggregation bits: %s\n", bitsToString(att.AggregationBits))
fmt.Printf("\t\tSlot: %d\n", att.Data.Slot)
fmt.Printf("\t\tBeacon block root: %#x\n", att.Data.BeaconBlockRoot)
@@ -96,15 +100,18 @@ In quiet mode this will return 0 if the block information is present and not ski
fmt.Printf("Attester slashings: %d\n", len(body.AttesterSlashings))
if verbose {
for i, slashing := range body.AttesterSlashings {
fmt.Printf("\t%d:\n", i)
// Say what was slashed.
att1 := slashing.Attestation_1
outputIf(debug, fmt.Sprintf("Attestation 1 attesting indices are %v", att1.AttestingIndices))
att2 := slashing.Attestation_2
outputIf(debug, fmt.Sprintf("Attestation 2 attesting indices are %v", att2.AttestingIndices))
slashedIndices := intersection(att1.AttestingIndices, att2.AttestingIndices)
if len(slashedIndices) == 0 {
continue
}
fmt.Printf("\t%d:\n", i)
fmt.Println("\t\tSlashed validators:")
for _, slashedIndex := range slashedIndices {
validator, err := grpc.FetchValidatorByIndex(eth2GRPCConn, slashedIndex)
@@ -170,24 +177,18 @@ func intersection(set1 []uint64, set2 []uint64) []uint64 {
sort.Slice(set1, func(i, j int) bool { return set1[i] < set1[j] })
sort.Slice(set2, func(i, j int) bool { return set2[i] < set2[j] })
res := make([]uint64, 0)
if len(set1) < len(set2) {
set1, set2 = set2, set1
}
set1Pos := 0
set2Pos := 0
set2LastIndex := len(set2) - 1
for set1Pos := range set1 {
for set1[set1Pos] == set2[set2Pos] {
res = append(res, set1[set1Pos])
if set2Pos == set2LastIndex {
break
}
for set1Pos < len(set1) && set2Pos < len(set2) {
switch {
case set1[set1Pos] < set2[set2Pos]:
set1Pos++
case set2[set2Pos] < set1[set1Pos]:
set2Pos++
}
for set1[set1Pos] > set2[set2Pos] {
if set2Pos == set2LastIndex {
break
}
default:
res = append(res, set1[set1Pos])
set1Pos++
set2Pos++
}
}
@@ -195,43 +196,25 @@ func intersection(set1 []uint64, set2 []uint64) []uint64 {
return res
}
// countSetBits counts the number of bits that are set in the given byte array.
func countSetBits(input []byte) int {
total := 0
for _, x := range input {
item := uint8(x)
for item > 0 {
if item&0x01 == 1 {
total++
}
item >>= 1
}
}
return total
}
func bitsToString(input bitfield.Bitlist) string {
bits := int(input.Len())
func bitsToString(input []byte) string {
elements := make([]string, len(input))
for i, x := range input {
item := uint8(x)
mask := uint8(0x80)
element := ""
for mask > 0 {
if item&mask != 0 {
element = fmt.Sprintf("%s", element)
} else {
element = fmt.Sprintf("%s✕", element)
}
mask >>= 1
res := ""
for i := 0; i < bits; i++ {
if input.BitAt(uint64(i)) {
res = fmt.Sprintf("%s✓", res)
} else {
res = fmt.Sprintf("%s✕", res)
}
if i%8 == 7 {
res = fmt.Sprintf("%s ", res)
}
elements[i] = element
}
return strings.Join(elements, " ")
return strings.TrimSpace(res)
}
func init() {
blockCmd.AddCommand(blockInfoCmd)
blockFlags(blockInfoCmd)
blockInfoCmd.Flags().Int64Var(&blockInfoSlot, "slot", -1, "the default slot")
}

View File

@@ -36,21 +36,18 @@ In quiet mode this will return 0 if the chain information can be obtained, other
config, err := grpc.FetchChainConfig(eth2GRPCConn)
errCheck(err, "Failed to obtain beacon chain configuration")
genesisTime, err := grpc.FetchGenesis(eth2GRPCConn)
genesisTime, err := grpc.FetchGenesisTime(eth2GRPCConn)
errCheck(err, "Failed to obtain genesis time")
if quiet {
os.Exit(_exitSuccess)
}
fmt.Printf("Genesis time:\t\t%s\n", genesisTime.Format(time.UnixDate))
slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(uint64))
fmt.Printf("Current slot:\t\t%d\n", slot)
fmt.Printf("Current epoch:\t\t%d\n", slot/config["SlotsPerEpoch"].(uint64))
outputIf(verbose, fmt.Sprintf("Genesis fork version:\t%0x", config["GenesisForkVersion"].([]byte)))
outputIf(verbose, fmt.Sprintf("Genesis timestamp:\t%v", genesisTime.Unix()))
outputIf(verbose, fmt.Sprintf("Seconds per slot:\t%v", config["SecondsPerSlot"].(uint64)))
outputIf(verbose, fmt.Sprintf("Slots per epoch:\t%v", config["SlotsPerEpoch"].(uint64)))
fmt.Printf("Genesis time: %s\n", genesisTime.Format(time.UnixDate))
outputIf(verbose, fmt.Sprintf("Genesis timestamp: %v", genesisTime.Unix()))
outputIf(verbose, fmt.Sprintf("Genesis fork version: %0x", config["GenesisForkVersion"].([]byte)))
outputIf(verbose, fmt.Sprintf("Seconds per slot: %v", config["SecondsPerSlot"].(uint64)))
outputIf(verbose, fmt.Sprintf("Slots per epoch: %v", config["SlotsPerEpoch"].(uint64)))
os.Exit(_exitSuccess)
},

View File

@@ -38,7 +38,7 @@ In quiet mode this will return 0 if the chain status can be obtained, otherwise
config, err := grpc.FetchChainConfig(eth2GRPCConn)
errCheck(err, "Failed to obtain beacon chain configuration")
genesisTime, err := grpc.FetchGenesis(eth2GRPCConn)
genesisTime, err := grpc.FetchGenesisTime(eth2GRPCConn)
errCheck(err, "Failed to obtain genesis time")
info, err := grpc.FetchChainInfo(eth2GRPCConn)
@@ -50,36 +50,41 @@ In quiet mode this will return 0 if the chain status can be obtained, otherwise
slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(uint64))
if chainStatusSlot {
fmt.Printf("Current slot:\t\t%d\n", slot)
fmt.Printf("Justified slot:\t\t%d", info.GetJustifiedSlot())
fmt.Printf("Current slot: %d\n", slot)
fmt.Printf("Justified slot: %d\n", info.GetJustifiedSlot())
if verbose {
distance := slot - info.GetJustifiedSlot()
fmt.Printf(" (%d)", distance)
fmt.Printf("Justified slot distance: %d\n", distance)
}
fmt.Printf("\n")
fmt.Printf("Finalized slot:\t\t%d", info.GetFinalizedSlot())
fmt.Printf("Finalized slot: %d\n", info.GetFinalizedSlot())
if verbose {
distance := slot - info.GetFinalizedSlot()
fmt.Printf(" (%d)", distance)
fmt.Printf("Finalized slot distance: %d\n", distance)
}
if verbose {
fmt.Printf("Prior justified slot: %d\n", info.GetFinalizedSlot())
distance := slot - info.GetPreviousJustifiedSlot()
fmt.Printf("Prior justified slot distance: %d\n", distance)
}
fmt.Printf("\n")
outputIf(verbose, fmt.Sprintf("Prior justified slot:\t%v (%d)", info.GetPreviousJustifiedSlot(), slot-info.GetPreviousJustifiedSlot()))
} else {
slotsPerEpoch := config["SlotsPerEpoch"].(uint64)
fmt.Printf("Current epoch:\t\t%d\n", slot/slotsPerEpoch)
fmt.Printf("Justified epoch:\t%d", info.GetJustifiedSlot()/slotsPerEpoch)
epoch := slot / slotsPerEpoch
fmt.Printf("Current epoch: %d\n", epoch)
fmt.Printf("Justified epoch: %d\n", info.GetJustifiedSlot()/slotsPerEpoch)
if verbose {
distance := (slot - info.GetJustifiedSlot()) / slotsPerEpoch
fmt.Printf(" (%d)", distance)
fmt.Printf("Justified epoch distance %d\n", distance)
}
fmt.Printf("\n")
fmt.Printf("Finalized epoch:\t%d", info.GetFinalizedSlot()/slotsPerEpoch)
fmt.Printf("Finalized epoch: %d\n", info.GetFinalizedSlot()/slotsPerEpoch)
if verbose {
distance := (slot - info.GetFinalizedSlot()) / slotsPerEpoch
fmt.Printf(" (%d)", distance)
fmt.Printf("Finalized epoch distance: %d\n", distance)
}
if verbose {
fmt.Printf("Prior justified epoch: %d\n", info.GetPreviousJustifiedEpoch())
distance := (slot - info.GetPreviousJustifiedEpoch()) / slotsPerEpoch
fmt.Printf("Prior justified epoch distance: %d\n", distance)
}
fmt.Printf("\n")
outputIf(verbose, fmt.Sprintf("Prior justified epoch:\t%v (%d)", info.GetPreviousJustifiedSlot()/slotsPerEpoch, (slot-info.GetPreviousJustifiedSlot())/slotsPerEpoch))
}
os.Exit(_exitSuccess)

View File

@@ -36,7 +36,7 @@ In quiet mode this will return 0 if the node information can be obtained, otherw
config, err := grpc.FetchChainConfig(eth2GRPCConn)
errCheck(err, "Failed to obtain beacon chain configuration")
genesisTime, err := grpc.FetchGenesis(eth2GRPCConn)
genesisTime, err := grpc.FetchGenesisTime(eth2GRPCConn)
errCheck(err, "Failed to obtain genesis time")
if quiet {
@@ -46,23 +46,19 @@ In quiet mode this will return 0 if the node information can be obtained, otherw
if verbose {
version, metadata, err := grpc.FetchVersion(eth2GRPCConn)
errCheck(err, "Failed to obtain version")
fmt.Printf("Version:\t\t%s\n", version)
fmt.Printf("Version: %s\n", version)
if metadata != "" {
fmt.Printf("Metadata:\t%s\n", metadata)
fmt.Printf("Metadata: %s\n", metadata)
}
}
syncing, err := grpc.FetchSyncing(eth2GRPCConn)
errCheck(err, "Failed to obtain syncing state")
fmt.Printf("Syncing:\t\t%v\n", syncing)
fmt.Printf("Syncing: %v\n", syncing)
fmt.Printf("Genesis time:\t\t%s\n", genesisTime.Format(time.UnixDate))
slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(uint64))
fmt.Printf("Current slot:\t\t%d\n", slot)
fmt.Printf("Current epoch:\t\t%d\n", slot/config["SlotsPerEpoch"].(uint64))
outputIf(verbose, fmt.Sprintf("Genesis fork version:\t%0x", config["GenesisForkVersion"].([]byte)))
outputIf(verbose, fmt.Sprintf("Genesis timestamp:\t%v", genesisTime.Unix()))
outputIf(verbose, fmt.Sprintf("Seconds per slot:\t%v", config["SecondsPerSlot"].(uint64)))
outputIf(verbose, fmt.Sprintf("Slots per epoch:\t%v", config["SlotsPerEpoch"].(uint64)))
fmt.Printf("Current slot: %d\n", slot)
fmt.Printf("Current epoch: %d\n", slot/config["SlotsPerEpoch"].(uint64))
outputIf(verbose, fmt.Sprintf("Genesis timestamp: %v", genesisTime.Unix()))
os.Exit(_exitSuccess)
},

View File

@@ -31,6 +31,8 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
e2types "github.com/wealdtech/go-eth2-types/v2"
filesystem "github.com/wealdtech/go-eth2-wallet-store-filesystem"
s3 "github.com/wealdtech/go-eth2-wallet-store-s3"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@@ -50,6 +52,7 @@ var generate bool
// Root variables, present for all commands.
var rootStore string
var rootAccount string
var rootBaseDir string
var rootStorePassphrase string
var rootWalletPassphrase string
var rootAccountPassphrase string
@@ -90,6 +93,7 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
debug = viper.GetBool("debug")
rootStore = viper.GetString("store")
rootAccount = viper.GetString("account")
rootBaseDir = viper.GetString("basedir")
rootStorePassphrase = viper.GetString("storepassphrase")
rootWalletPassphrase = viper.GetString("walletpassphrase")
rootAccountPassphrase = viper.GetString("passphrase")
@@ -120,8 +124,27 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
if viper.GetString("remote") == "" {
// Set up our wallet store
err := wallet.SetStore(rootStore, []byte(rootStorePassphrase))
errCheck(err, "Failed to set up wallet store")
var store wtypes.Store
switch rootStore {
case "s3":
assert(rootBaseDir == "", "--basedir does not apply for the s3 store")
var err error
store, err = s3.New(s3.WithPassphrase([]byte(rootStorePassphrase)))
errCheck(err, "Failed to access Amazon S3 wallet store")
case "filesystem":
opts := make([]filesystem.Option, 0)
if rootStorePassphrase != "" {
opts = append(opts, filesystem.WithPassphrase([]byte(rootStorePassphrase)))
}
if rootBaseDir != "" {
opts = append(opts, filesystem.WithLocation(rootBaseDir))
}
store = filesystem.New(opts...)
default:
die(fmt.Sprintf("Unsupported wallet store %s", rootStore))
}
err := wallet.UseStore(store)
errCheck(err, "Failed to use defined wallet store")
} else {
err := initRemote()
errCheck(err, "Failed to connect to remote wallet")
@@ -159,6 +182,10 @@ func init() {
if err := viper.BindPFlag("account", RootCmd.PersistentFlags().Lookup("account")); err != nil {
panic(err)
}
RootCmd.PersistentFlags().String("basedir", "", "Base directory for filesystem wallets")
if err := viper.BindPFlag("basedir", RootCmd.PersistentFlags().Lookup("basedir")); err != nil {
panic(err)
}
RootCmd.PersistentFlags().String("storepassphrase", "", "Passphrase for store (if applicable)")
if err := viper.BindPFlag("storepassphrase", RootCmd.PersistentFlags().Lookup("storepassphrase")); err != nil {
panic(err)
@@ -416,8 +443,11 @@ func initRemote() error {
remote = true
remoteAddr = viper.GetString("remote")
clientCert = viper.GetString("client-cert")
assert(clientCert != "", "--remote requires --client-cert")
clientKey = viper.GetString("client-key")
assert(clientKey != "", "--remote requires --client-key")
serverCACert = viper.GetString("server-ca-cert")
assert(serverCACert != "", "--remote requires --server-ca-cert")
// Load the client certificates.
clientPair, err := tls.LoadX509KeyPair(clientCert, clientKey)

View File

@@ -65,15 +65,15 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
withdrawalCredentials := util.SHA256(withdrawalAccount.PublicKey().Marshal())
errCheck(err, "Failed to hash withdrawal credentials")
// TODO fetch this from the node.
withdrawalCredentials[0] = byte(0) // BLSWithdrawalPrefix
// This is hard-coded, to allow deposit data to be generated without a connection to the beacon node.
withdrawalCredentials[0] = byte(0) // BLS_WITHDRAWAL_PREFIX
outputIf(debug, fmt.Sprintf("Withdrawal credentials are %032x", withdrawalCredentials))
assert(validatorDepositDataDepositValue != "", "--depositvalue is required")
val, err := string2eth.StringToGWei(validatorDepositDataDepositValue)
errCheck(err, "Invalid value")
// TODO fetch this from the node.
assert(val >= 1000000000, "deposit value must be at least 1 Ether")
// This is hard-coded, to allow deposit data to be generated without a connection to the beacon node.
assert(val >= 1000000000, "deposit value must be at least 1 Ether") // MIN_DEPOSIT_AMOUNT
// For each key, generate deposit data
outputs := make([]string, 0)
@@ -136,7 +136,7 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
txData = append(txData, signedDepositData.Signature...)
outputs = append(outputs, fmt.Sprintf("%#x", txData))
} else {
outputs = append(outputs, fmt.Sprintf(`{"account":"%s","pubkey":"%048x","withdrawal_credentials":"%032x","signature":"%096x","value":%d,"deposit_data_root":"%032x"}`, fmt.Sprintf("%s/%s", validatorWallet.Name(), validatorAccount.Name()), signedDepositData.PubKey, signedDepositData.WithdrawalCredentials, signedDepositData.Signature, val, depositDataRoot))
outputs = append(outputs, fmt.Sprintf(`{"account":"%s","pubkey":"%048x","withdrawal_credentials":"%032x","signature":"%096x","value":%d,"deposit_data_root":"%032x","version":1}`, fmt.Sprintf("%s/%s", validatorWallet.Name(), validatorAccount.Name()), signedDepositData.PubKey, signedDepositData.WithdrawalCredentials, signedDepositData.Signature, val, depositDataRoot))
}
}

View File

@@ -15,18 +15,27 @@ package cmd
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"strings"
"time"
"github.com/pkg/errors"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/wealdtech/ethdo/grpc"
"github.com/wealdtech/ethdo/util"
e2types "github.com/wealdtech/go-eth2-types/v2"
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
var validatorExitEpoch int64
var validatorExitKey string
var validatorExitJSON string
var validatorExitJSONOutput bool
var validatorExitCmd = &cobra.Command{
Use: "exit",
@@ -35,60 +44,117 @@ var validatorExitCmd = &cobra.Command{
ethdo validator exit --account=primary/validator --passphrase=secret
In quiet mode this will return 0 if the transaction has been sent, otherwise 1.`,
In quiet mode this will return 0 if the transaction has been generated, otherwise 1.`,
Run: func(cmd *cobra.Command, args []string) {
// Sanity checking and setup.
assert(rootAccount != "", "--account is required")
account, err := accountFromPath(rootAccount)
errCheck(err, "Failed to access account")
err = connect()
err := connect()
errCheck(err, "Failed to obtain connect to Ethereum 2 beacon chain node")
// Beacon chain config required for later work.
config, err := grpc.FetchChainConfig(eth2GRPCConn)
errCheck(err, "Failed to obtain beacon chain configuration")
exit, signature := validatorExitHandleInput()
validatorExitHandleExit(exit, signature)
os.Exit(_exitSuccess)
},
}
// Fetch the validator's index.
index, err := grpc.FetchValidatorIndex(eth2GRPCConn, account)
errCheck(err, "Failed to obtain validator index")
outputIf(debug, fmt.Sprintf("Validator index is %d", index))
func validatorExitHandleInput() (*ethpb.VoluntaryExit, e2types.Signature) {
if validatorExitJSON != "" {
return validatorExitHandleJSONInput(validatorExitJSON)
}
if rootAccount != "" {
account, err := accountFromPath(rootAccount)
errCheck(err, "Failed to access account")
return validatorExitHandleAccountInput(account)
}
if validatorExitKey != "" {
privKeyBytes, err := hex.DecodeString(strings.TrimPrefix(validatorExitKey, "0x"))
errCheck(err, fmt.Sprintf("Failed to decode key %s", validatorExitKey))
account, err := util.NewScratchAccount(privKeyBytes, nil)
errCheck(err, "Invalid private key")
return validatorExitHandleAccountInput(account)
}
die("one of --json, --account or --key is required")
return nil, nil
}
// Ensure the validator is active.
state, err := grpc.FetchValidatorState(eth2GRPCConn, account)
errCheck(err, "Failed to obtain validator state")
outputIf(debug, fmt.Sprintf("Validator state is %v", state))
assert(state == ethpb.ValidatorStatus_ACTIVE, "Validator must be active to exit")
func validatorExitHandleJSONInput(input string) (*ethpb.VoluntaryExit, e2types.Signature) {
data := &validatorExitData{}
err := json.Unmarshal([]byte(input), data)
errCheck(err, "Invalid JSON input")
exit := &ethpb.VoluntaryExit{
Epoch: data.Epoch,
ValidatorIndex: data.ValidatorIndex,
}
signature, err := e2types.BLSSignatureFromBytes(data.Signature)
errCheck(err, "Invalid signature")
return exit, signature
}
func validatorExitHandleAccountInput(account e2wtypes.Account) (*ethpb.VoluntaryExit, e2types.Signature) {
exit := &ethpb.VoluntaryExit{}
// Beacon chain config required for later work.
config, err := grpc.FetchChainConfig(eth2GRPCConn)
errCheck(err, "Failed to obtain beacon chain configuration")
secondsPerEpoch := config["SecondsPerSlot"].(uint64) * config["SlotsPerEpoch"].(uint64)
// Fetch the validator's index.
index, err := grpc.FetchValidatorIndex(eth2GRPCConn, account)
errCheck(err, "Failed to obtain validator index")
outputIf(debug, fmt.Sprintf("Validator index is %d", index))
exit.ValidatorIndex = index
// Ensure the validator is active.
state, err := grpc.FetchValidatorState(eth2GRPCConn, account)
errCheck(err, "Failed to obtain validator state")
outputIf(debug, fmt.Sprintf("Validator state is %v", state))
assert(state == ethpb.ValidatorStatus_ACTIVE, "Validator must be active to exit")
if validatorExitEpoch < 0 {
// Ensure the validator has been active long enough to exit.
validator, err := grpc.FetchValidator(eth2GRPCConn, account)
errCheck(err, "Failed to obtain validator information")
outputIf(debug, fmt.Sprintf("Activation epoch is %v", validator.ActivationEpoch))
earliestExitEpoch := validator.ActivationEpoch + config["PersistentCommitteePeriod"].(uint64)
secondsPerEpoch := config["SecondsPerSlot"].(uint64) * config["SlotsPerEpoch"].(uint64)
genesisTime, err := grpc.FetchGenesis(eth2GRPCConn)
genesisTime, err := grpc.FetchGenesisTime(eth2GRPCConn)
errCheck(err, "Failed to obtain genesis time")
currentEpoch := uint64(time.Since(genesisTime).Seconds()) / secondsPerEpoch
assert(currentEpoch >= earliestExitEpoch, fmt.Sprintf("Validator cannot exit until %s ( epoch %d)", genesisTime.Add(time.Duration(secondsPerEpoch*earliestExitEpoch)*time.Second).Format(time.UnixDate), earliestExitEpoch))
assert(currentEpoch >= earliestExitEpoch, fmt.Sprintf("Validator cannot exit until %s ( epoch %d); transaction not sent", genesisTime.Add(time.Duration(secondsPerEpoch*earliestExitEpoch)*time.Second).Format(time.UnixDate), earliestExitEpoch))
outputIf(verbose, "Validator confirmed to be in a suitable state")
exit.Epoch = currentEpoch
} else {
// User-specified epoch; no checks.
exit.Epoch = uint64(validatorExitEpoch)
}
// Set up the transaction.
exit := &ethpb.VoluntaryExit{
Epoch: currentEpoch,
ValidatorIndex: index,
// TODO fetch current fork version from config (currently using genesis fork version)
currentForkVersion := config["GenesisForkVersion"].([]byte)
outputIf(debug, fmt.Sprintf("Current fork version is %x", currentForkVersion))
genesisValidatorsRoot, err := grpc.FetchGenesisValidatorsRoot(eth2GRPCConn)
outputIf(debug, fmt.Sprintf("Genesis validators root is %x", genesisValidatorsRoot))
errCheck(err, "Failed to obtain genesis validators root")
domain := e2types.Domain(e2types.DomainVoluntaryExit, currentForkVersion, genesisValidatorsRoot)
err = account.Unlock([]byte(rootAccountPassphrase))
errCheck(err, "Failed to unlock account; please confirm passphrase is correct")
signature, err := signStruct(account, exit, domain)
errCheck(err, "Failed to sign exit proposal")
return exit, signature
}
// validatorExitHandleExit handles the exit request.
func validatorExitHandleExit(exit *ethpb.VoluntaryExit, signature e2types.Signature) {
if validatorExitJSONOutput {
data := &validatorExitData{
Epoch: exit.Epoch,
ValidatorIndex: exit.ValidatorIndex,
Signature: signature.Marshal(),
}
// TODO fetch current fork version from config (currently using genesis fork version)
currentForkVersion := config["GenesisForkVersion"].([]byte)
// TODO fetch genesis validators root from somewhere.
//domain := e2types.Domain(e2types.DomainVoluntaryExit, currentForkVersion, genesisValidatorsRoot)
domain := e2types.Domain(e2types.DomainVoluntaryExit, currentForkVersion, e2types.ZeroGenesisValidatorsRoot)
err = account.Unlock([]byte(rootAccountPassphrase))
errCheck(err, "Failed to unlock account; please confirm passphrase is correct")
signature, err := signStruct(account, exit, domain)
errCheck(err, "Failed to sign exit proposal")
res, err := json.Marshal(data)
errCheck(err, "Failed to generate JSON")
outputIf(!quiet, string(res))
} else {
proposal := &ethpb.SignedVoluntaryExit{
Exit: exit,
Signature: signature.Marshal(),
@@ -97,17 +163,75 @@ In quiet mode this will return 0 if the transaction has been sent, otherwise 1.`
validatorClient := ethpb.NewBeaconNodeValidatorClient(eth2GRPCConn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
_, err = validatorClient.ProposeExit(ctx, proposal)
_, err := validatorClient.ProposeExit(ctx, proposal)
errCheck(err, "Failed to propose exit")
outputIf(!quiet, "Validator exit transaction sent")
os.Exit(_exitSuccess)
},
}
}
func init() {
validatorCmd.AddCommand(validatorExitCmd)
validatorFlags(validatorExitCmd)
validatorExitCmd.Flags().Int64Var(&validatorExitEpoch, "epoch", -1, "Epoch at which to exit (defaults to now)")
validatorExitCmd.Flags().Int64Var(&validatorExitEpoch, "epoch", -1, "Epoch at which to exit (defaults to current epoch)")
validatorExitCmd.Flags().StringVar(&validatorExitKey, "key", "", "Private key if account not known by ethdo")
validatorExitCmd.Flags().BoolVar(&validatorExitJSONOutput, "json-output", false, "Print JSON transaction; do not broadcast to network")
validatorExitCmd.Flags().StringVar(&validatorExitJSON, "json", "", "Use JSON as created by --json-output to exit")
addTransactionFlags(validatorExitCmd)
}
type validatorExitData struct {
Epoch uint64 `json:"epoch"`
ValidatorIndex uint64 `json:"validator_index"`
Signature []byte `json:"signature"`
}
// MarshalJSON implements custom JSON marshaller.
func (d *validatorExitData) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`{"epoch":%d,"validator_index":%d,"signature":"%#x"}`, d.Epoch, d.ValidatorIndex, d.Signature)), nil
}
// UnmarshalJSON implements custom JSON unmarshaller.
func (d *validatorExitData) UnmarshalJSON(data []byte) error {
var v map[string]interface{}
if err := json.Unmarshal(data, &v); err != nil {
return err
}
if val, exists := v["epoch"]; exists {
var ok bool
epoch, ok := val.(float64)
if !ok {
return errors.New("epoch invalid")
}
d.Epoch = uint64(epoch)
} else {
return errors.New("epoch missing")
}
if val, exists := v["validator_index"]; exists {
var ok bool
validatorIndex, ok := val.(float64)
if !ok {
return errors.New("validator_index invalid")
}
d.ValidatorIndex = uint64(validatorIndex)
} else {
return errors.New("validator_index missing")
}
if val, exists := v["signature"]; exists {
signatureBytes, ok := val.(string)
if !ok {
return errors.New("signature invalid")
}
signature, err := hex.DecodeString(strings.TrimPrefix(signatureBytes, "0x"))
if err != nil {
return errors.Wrap(err, "signature invalid")
}
d.Signature = signature
} else {
return errors.New("signature missing")
}
return nil
}

View File

@@ -52,7 +52,7 @@ In quiet mode this will return 0 if the validator information can be obtained, o
} else {
pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(validatorInfoPubKey, "0x"))
errCheck(err, fmt.Sprintf("Failed to decode public key %s", validatorInfoPubKey))
account, err = util.NewScratchAccount(pubKeyBytes)
account, err = util.NewScratchAccount(nil, pubKeyBytes)
errCheck(err, fmt.Sprintf("Invalid public key %s", validatorInfoPubKey))
}

View File

@@ -30,7 +30,7 @@ var versionCmd = &cobra.Command{
ethdo version.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("1.4.0")
fmt.Println("1.4.11")
if viper.GetBool("verbose") {
buildInfo, ok := dbg.ReadBuildInfo()
if ok {

View File

@@ -1,4 +1,4 @@
// Copyright © 2019 Weald Technology Trading
// Copyright © 2019, 2020 Weald Technology Trading
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -17,10 +17,15 @@ import (
"strings"
"github.com/spf13/cobra"
bip39 "github.com/tyler-smith/go-bip39"
wallet "github.com/wealdtech/go-eth2-wallet"
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
hd "github.com/wealdtech/go-eth2-wallet-hd/v2"
filesystem "github.com/wealdtech/go-eth2-wallet-store-filesystem"
)
var walletCreateType string
var walletCreateSeed string
var walletCreateCmd = &cobra.Command{
Use: "create",
@@ -38,10 +43,24 @@ In quiet mode this will return 0 if the wallet is created successfully, otherwis
var err error
switch strings.ToLower(walletCreateType) {
case "non-deterministic", "nd":
assert(walletCreateSeed == "", "--seed is not allowed with non-deterministic wallets")
_, err = wallet.CreateWallet(walletWallet, wallet.WithType("nd"))
case "hierarchical deterministic", "hd":
assert(rootWalletPassphrase != "", "--walletpassphrase is required for hierarchical deterministic wallets")
_, err = wallet.CreateWallet(walletWallet, wallet.WithType("hd"), wallet.WithPassphrase([]byte(rootWalletPassphrase)))
store := filesystem.New()
encryptor := keystorev4.New()
if walletCreateSeed != "" {
// Creating wallet from a seed.
var seed []byte
seed, err = bip39.MnemonicToByteArray(walletCreateSeed)
errCheck(err, "Failed to decode seed")
// Strip checksum; last byte
seed = seed[:len(seed)-1]
assert(len(seed) == 32, "Seed must have 24 words")
_, err = hd.CreateWalletFromSeed(walletWallet, []byte(rootWalletPassphrase), store, encryptor, seed)
} else {
_, err = hd.CreateWallet(walletWallet, []byte(rootWalletPassphrase), store, encryptor)
}
default:
die("unknown wallet type")
}
@@ -53,4 +72,5 @@ func init() {
walletCmd.AddCommand(walletCreateCmd)
walletFlags(walletCreateCmd)
walletCreateCmd.Flags().StringVar(&walletCreateType, "type", "non-deterministic", "Type of wallet to create (non-deterministic or hierarchical deterministic)")
walletCreateCmd.Flags().StringVar(&walletCreateSeed, "seed", "", "The 24-word seed phrase for a hierarchical deterministic wallet")
}

View File

@@ -37,8 +37,9 @@ var walletImportCmd = &cobra.Command{
In quiet mode this will return 0 if the wallet is imported successfully, otherwise 1.`,
Run: func(cmd *cobra.Command, args []string) {
assert(!remote, "wallet import not available with remote wallets")
assert(walletImportData != "", "--walletimportdata is required")
assert(walletImportData != "", "--importdata is required")
assert(walletImportPassphrase != "", "--importpassphrase is required")
assert(walletWallet == "", "--wallet is not allowed (the wallet will retain its name)")
if !strings.HasPrefix(walletImportData, "0x") {
outputIf(debug, fmt.Sprintf("Reading wallet import from file %s", walletImportData))

View File

@@ -16,6 +16,7 @@ package cmd
import (
"fmt"
"os"
"path/filepath"
"github.com/spf13/cobra"
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
@@ -47,7 +48,7 @@ In quiet mode this will return 0 if the wallet exists, otherwise 1.`,
store := storeProvider.Store()
fmt.Printf("Store: %s\n", store.Name())
if storeLocationProvider, ok := store.(wtypes.StoreLocationProvider); ok {
fmt.Printf("Location: %s\n", storeLocationProvider.Location())
fmt.Printf("Location: %s\n", filepath.Join(storeLocationProvider.Location(), wallet.ID().String()))
}
}
}

View File

@@ -1,4 +1,4 @@
// Copyright © 2019 Weald Technology Trading
// Copyright © 2019, 2020 Weald Technology Trading
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -14,11 +14,12 @@
package cmd
import (
"bytes"
"fmt"
"os"
bip39 "github.com/FactomProject/go-bip39"
"github.com/spf13/cobra"
bip39 "github.com/tyler-smith/go-bip39"
types "github.com/wealdtech/go-eth2-wallet-types/v2"
)
@@ -38,15 +39,23 @@ In quiet mode this will return 0 if the wallet is a hierarchical deterministic w
wallet, err := walletFromPath(walletWallet)
errCheck(err, "Failed to access wallet")
_, ok := wallet.(types.WalletKeyProvider)
assert(ok, fmt.Sprintf("wallets of type %q do not provide keys", wallet.Type()))
assert(ok, fmt.Sprintf("wallets of type %q do not have a seed", wallet.Type()))
err = wallet.Unlock([]byte(rootWalletPassphrase))
errCheck(err, "Failed to unlock wallet")
seed, err := wallet.(types.WalletKeyProvider).Key()
errCheck(err, "Failed to obtain wallet key")
outputIf(debug, fmt.Sprintf("Seed is %#0x", seed))
outputIf(debug, fmt.Sprintf("Seed is %#x", seed))
seedStr, err := bip39.NewMnemonic(seed)
errCheck(err, "Failed to generate seed mnemonic")
// Re-read mnemonimc to ensure correctness.
recalcSeed, err := bip39.MnemonicToByteArray(seedStr)
// Drop checksum (last byte).
errCheck(err, "Failed to recalculate seed")
recalcSeed = recalcSeed[:len(recalcSeed)-1]
outputIf(debug, fmt.Sprintf("Recalc seed is %#x", recalcSeed))
errCheck(err, "Failed to recalculate seed mnemonic")
assert(bytes.Equal(recalcSeed, seed), "Generated invalid mnemonic")
outputIf(!quiet, seedStr)
os.Exit(_exitSuccess)

67
docs/howto.md Normal file
View File

@@ -0,0 +1,67 @@
# How to achieve common tasks with ethdo
## Find out what ethdo can do
To find a list of topics that ethdo can carry out with the `ethdo help` command.
If you want more detailed information about the commands in a topic, they can be seen with the `ethdo help <topic>` command, for example:
```sh
ethdo help wallet
```
## List my wallets
The wallets you can currently access can be seen with the `ethdo wallet list` command.
## Create a new wallet
New wallets can be created with the `ethdo wallet create` command. Each wallet has to have a unique name, for example:
```sh
ethdo wallet create --wallet="My wallet"
```
Additional options are available to decide the type of wallet and encryption.
## Create an HD wallet from an existing seed
HD wallets can be created from an existing seed by adding the `--seed` parameter to `ethdo wallet create`, for example:
```sh
ethdo wallet create --wallet="Recreated wallet" --type=hd --seed="tooth moon mad fun romance athlete envelope next mix divert tip top symbol resemble stock family melody desk sheriff drift bargain need jaguar method"
```
The seed for an existing HD wallet can be obtained with `ethdo wallet seed`.
## Back up a wallet
A wallet can be backed up with the `ethdo wallet export` command. This creates an encrypted backup of the wallet, for example:
```sh
ethdo wallet export --wallet="My wallet" --exportpassphrase="export secret" >export.dat
```
Note that by default the wallet backup is printed to the console, hence the `>export.dat` to redirect it to a file.
## Restore a wallet
A backed up wallet can be restored with the `ethdo wallet import` command, for example:
```sh
ethdo wallet import --importdata=export.dat --importpassphrase="export secret"
```
In this example the wallet to be imported is being read from the `export.dat` file.
Note that if a wallet with the same name already exists it cannot be imported.
## Where is my wallet?
Details of the location of a wallet can be found with the `ethdo wallet info` command, for example:
```sh
ethdo wallet info --verbose --wallet="My wallet"
```
This will provide, amongst other information, a `Location` line giving the directory where the wallet information resides.

244
docs/prysm.md Normal file
View File

@@ -0,0 +1,244 @@
# Using ethdo with Prysm
## Installing ethdo
1. To install `ethdo`, issue the following command:
```sh
GO111MODULE=on go get github.com/wealdtech/ethdo@latest
```
2. Ensure `ethdo` is installed properly by issuing the command:
```sh
ethdo version
```
Ensure the output matches the most recent version listed on the repository's [release history](https://github.com/wealdtech/ethdo/releases/).
## Typical validating setups
This section outlines the process of setting up a configuration with two validators and a single withdrawal account using ethdo.
### Generating a wallet
To create a non-deterministic wallet, where keys generated from random data, issue the command:
```sh
ethdo wallet create --wallet=Validators
```
If you prefer to have a hierarchical deterministic wallet, where keys are generated from a seed, issue the command:
```sh
ethdo wallet create --wallet=Validators --type=hd --walletpassphrase=walletsecret
```
This creates a wallet called "Validators" in the default wallet directory (see https://github.com/wealdtech/ethdo/#wallets-and-accounts for details) which contains the newly generated seed data.
> The `--walletpassphrase` flag and input is required to protect the seed. It is critical that you keep it private and secure.
Once the wallet is created, fetch its data to ensure it exists by issuing the following command:
```sh
ethdo wallet info --wallet=Validators
```
This command will produce output like so:
```sh
Type: non-deterministic
Accounts: 0
```
### Generating accounts
To create two separate accounts with different passphrases, issue the command:
```sh
ethdo account create --account=Validators/1 --passphrase=validator1secret
ethdo account create --account=Validators/2 --passphrase=validator2secret
```
> The two accounts are given different passphrases in the above example. This is not required; all accounts can have the same password if you prefer.
### Creating a withdrawal wallet and account
It is recommended to set up separate wallets for withdrawals and validator nodes. This allows users to have a validator wallet actively running on the node, while a second wallet can be kept securely offline in cold storage.
Creating a withdrawal wallet and account is very similar to the process above to generate the validator wallet. For example:
```sh
ethdo wallet create --wallet=Withdrawal
ethdo account create --account=Withdrawal/Primary --passphrase=withdrawalsecret
```
This creates a wallet called "Withdrawal" and within it an account called "Primary". It is also possible to apply additional protection to the Withdrawal wallet if desired; see the `ethdo` documentation for details.
### Depositing funds for a validator
The validator now requires deposited funds. If you do not have any Göerli Ether, the best approach is to follow the steps at https://prylabs.net/participate to use the faucet and make a deposit -- **however**, for step 3, do not run the commands provided. Instead, run the following command to generate the deposit data requested:
```sh
ethdo validator depositdata \
--validatoraccount=Validators/1 \
--withdrawalaccount=Withdrawal/Primary \
--depositvalue=32Ether \
--passphrase=validator1secret \
--raw
```
The raw data output of this command can be pasted in to the webpage above to generate the required transaction for validator 1 (and can be repeated for validator 2, or as many validators as you wish).
Alternatively, if you have your own Göerli ETH, you can send deposit transactions directly to the Göerli testnet. You can create JSON output containing the deposit data:
```sh
ethdo validator depositdata \
--validatoraccount=Validators/1 \
--withdrawalaccount=Withdrawal/Primary \
--depositvalue=32Ether \
--passphrase=validator1secret
{"account":"Validators/1","pubkey":"a9ca9cf7fa2d0ab1d5d52d2d8f79f68c50c5296bfce81546c254df68eaac0418717b2f9fc6655cbbddb145daeb282c00","withdrawal_credentials":"0059a28dc2db987d59bdfc4ab20b9ad4c83888bcd32456a629aece07de6895aa","signature":"9335b872253fdab328678bd3636115681d52b42fe826c6acb7f1cd1327c6bba48e3231d054e4f274cc7c1c184f28263b13083e01db8c08c17b59f22277dff341f7c96e7a0407a0a31c8563bcf479d31136c833712ae3bfd93ee9ea6abdfa52d4","value":3200000000,"deposit_data_root":"14278c9345eeeb7b2d5307a36ed1c72eea5ed09a30cf7c47525e34f39f564ef5"}
```
This can be passed to [ethereal](https://github.com/wealdtech/ethereal) to send the deposit (replacing `0x21A1A52aba41DB18F9F1D2625e1b19A251F3e0A9` below with your local Göerli account containing the funds and `eth1secret` with that account's passphrase; `ethereal --network=goerli account list --verbose` will provide details of your local accounts and their current funds).
on Linux/OSX:
```sh
DEPOSITDATA=`ethdo validator depositdata \
--validatoraccount=Validators/1 \
--withdrawalaccount=Withdrawal/Primary \
--depositvalue=32Ether \
--passphrase=validator1secret`
ethereal beacon deposit \
--network=goerli \
--data="${DEPOSITDATA}" \
--from=0x21A1A52aba41DB18F9F1D2625e1b19A251F3e0A9 \
--passphrase=eth1secret
```
or on Windows:
```sh
ethdo validator depositdata \
--validatoraccount=Validators/1 \
--withdrawalaccount=Withdrawal/Primary \
--depositvalue=32Ether \
--passphrase=validator1secret >depositdata.json
ethereal beacon deposit \
--network=goerli \
--data=depositdata.json \
--from=0x21A1A52aba41DB18F9F1D2625e1b19A251F3e0A9 \
--passphrase=eth1secret
erase depositdata.json
```
The `ethereal` command can either take a `passphrase`, if the `from` address is a local account (confirm with `ethereal --network=goerli account list`) or a `privatekey` if not.
### Validating
The next step is to start the validator using the validating keys that have been created.
#### Keymanager options
Although options for the wallet keymanager can be supplied directly on the command-line this is not considered best practice, as it exposes sensitive information such as passphrases, so it is better to create a file that contains this information and reference that file.
To create the relevant directory run the following for Linux/OSX:
```sh
mkdir -p ${HOME}/prysm/validator
```
or for Windows:
```sh
mkdir %APPDATA%\prysm\validator
```
and then use your favourite text editor to create a file in this directory called `wallet.json` with the following contents:
```json
{
"accounts": [
"Validators/1",
"Validators/2"
],
"passphrases": [
"validator1secret",
"validator2secret"
]
}
```
#### Starting the validator with Bazel
To start the validator you must supply the desired keymanager and the location of the keymanager options file. Run the following command for Linux/OSX:
```sh
bazel run //validator:validator -- --keymanager=wallet --keymanageropts=${HOME}/prysm/validator/wallet.json
```
or for Windows:
```sh
bazel run //validator:validator -- --keymanager=wallet --keymanageropts=%APPDATA%\prysm\validator\wallet.json
```
#### Starting the validator with Docker
Docker will not have direct access to the wallet created above, and requires the keymanager to be informed of the mapped location of the wallet. Edit the `wallet.json` file to include a location entry, as follows:
```json
{
"location": "/wallets",
"accounts": [
"Validators/1",
"Validators/2"
],
"passphrases": [
"validator1secret",
"validator2secret"
]
}
```
Then run the validator by issuing the following command on Linux:
```sh
docker run -v "${HOME}/prysm/validator:/data" \
-v "${HOME}/.config/ethereum2/wallets:/wallets" \
gcr.io/prysmaticlabs/prysm/validator:latest \
--keymanager=wallet \
--keymanageropts=/data/wallet.json
```
or for OSX:
```sh
docker run -v "${HOME}/prysm/validator:/data" \
-v "${HOME}/Library/Application Support/ethereum2/wallets:/wallets" \
gcr.io/prysmaticlabs/prysm/validator:latest \
--keymanager=wallet \
--keymanageropts=/data/wallet.json
```
or for Windows:
```sh
docker run -v %APPDATA%\prysm\validator:/data" \
-v %APPDATA%\ethereum2\wallets:/wallets" \
gcr.io/prysmaticlabs/prysm/validator:latest \
--keymanager=wallet \
--keymanageropts=/data/wallet.json
```
#### Confirming validation
When the validator is operational, you should see output similar to:
```text
[2020-02-07 10:00:59] INFO node: Validating for public key pubKey=0x85016bd4ca67e57e1438308fdb3d98b74b81428fb09e6d16d2dcbc72f240be090d5faebb63f84d6f35a950fdbb36f910
[2020-02-07 10:00:59] INFO node: Validating for public key pubKey=0x8de04b4cd3f0947f4e76fa2f86fa1cfd33cc2500688f2757e406448c36f0f1255758874b46d72002ad206ed560975d39
```
where each line states a public key that is being used for validating. Confirm that these values match your expectations.

15
docs/troubleshooting.md Normal file
View File

@@ -0,0 +1,15 @@
# Troubleshooting
## Compilation problems
### gcc not found
### cannot find -lstdc++
This is usually an error on linux systems. If you receive errors of this type your computer is missing some files to allow `ethdo` to build. To resolve this run the following command:
```sh
sudo apt install build-essential libstdc++6
```
and then try to install `ethdo` again.

405
docs/usage.md Normal file
View File

@@ -0,0 +1,405 @@
# ethdo commands
ethdo provides features to manage wallets and accounts, as well as interacting with Ethereum 2 nodes and remote signers. Below are a list of all available commands.
Note that the below provides a list of commands rather than a howto guide. Please follow the
### `wallet` commands
#### `accounts`
`ethdo wallet accounts` lists the accounts within a wallet.
```sh
$ ethdo wallet accounts --wallet="Personal wallet"
Auctions
Operations
Spending
```
With the `--verbose` flag this will provide the public key of the accounts.
```sh
$ ethdo wallet accounts --wallet="Personal wallet" --verbose
Auctions: 0x812f340269c315c1d882ae7c13cdaddf862dbdbd482b1836798b2070160dd1e194088cc6f39347782028d1e56bd18674
Operations: 0x8e2f9e8cc29658ff37ecc30e95a0807579b224586c185d128cb7a7490784c1ad9b0ab93dbe604ab075b40079931e6670
Spending: 0x85dfc6dcee4c9da36f6473ec02fda283d6c920c641fc8e3a76113c5c227d4aeeb100efcfec977b12d20d571907d05650
```
#### `create`
`ethdo wallet create` creates a new wallet with the given parameters. Options for creating a wallet include:
- `wallet`: the name of the wallet to create (defaults to "primary")
- `type`: the type of wallet to create. This can be either "nd" for a non-deterministic wallet, where private keys are generated randomly, or "hd" for a hierarchical deterministic wallet, where private keys are generated from a seed and path as per [ERC-2333](https://github.com/CarlBeek/EIPs/blob/bls_path/EIPS/eip-2334.md) (defaults to "nd")
- `walletpassphrase`: the passphrase for of the wallet. This is required for hierarchical deterministic wallets, to protect the seed
- `seed`: for hierarchical deterministic wallets only, use a pre-defined 24-word [BIP-39 seed phrase](https://en.bitcoin.it/wiki/Seed_phrase) to create the wallet. **Warning** The same seed can be imported in to multiple wallets, in which case they will generate the same keys. Please ensure that only a single wallet is active with any single seed phrase
```sh
$ ethdo wallet create --wallet="Personal wallet" --type="hd" --walletpassphrase="my wallet secret"
```
#### `export`
`ethdo wallet export` exports the wallet and all of its accounts. Options for exporting a wallet include:
- `wallet`: the name of the wallet to export (defaults to "primary")
- `exportpassphrase`: the passphrase with which to encrypt the wallet backup
```sh
$ ethdo wallet export --wallet="Personal wallet" --exportpassphrase="my export secret"
0x01c7a27ad40d45b4ae5be5f...
```
The encrypted wallet export is written to the console; it can be redirected to store it in a file.
```sh
$ ethdo wallet export --wallet="Personal wallet" --exportpassphrase="my export secret" >export.dat
```
#### `import`
`ethdo wallet import` imports a wallet and all of its accounts exported by `ethdo wallet export`. Options for importing a wallet include:
- `importdata`: the data exported by `ethdo wallet export`
- `importpassphrase`: the passphrase that was provided to `ethdo wallet export` to encrypt the data
```sh
$ ethdo wallet import --importdata="0x01c7a27ad40d45b4ae5be5f..." --importpassphrase="my export secret"
```
The encrypted wallet export can be read from a file. For example with Unix systems:
```sh
$ ethdo wallet import --importdata=`cat export.dat` --importpassphrase="my export secret"
```
#### `info`
`ethdo wallet info` provides information about a given wallet. Options include:
- `wallet`: the name of the wallet
```sh
$ ethdo wallet info --wallet="Personal wallet"
Type: hierarchical deterministic
Accounts: 3
```
#### `list`
`ethdo wallet list` lists all wallets in the store.
```sh
$ ethdo wallet list
Personal wallet
```
**N.B.** encrypted wallets will not show up in this list unless the correct passphrase for the store is supplied.
#### `seed`
`ethdo wallet seed` provides the seed for hierarchical deterministic wallets. Options include:
- `wallet`: the name of the wallet
- `walletpassphrase`: the passphrase for the wallet
```sh
$ ethdo wallet seed --wallet="Personal wallet" --walletpassphrase="my wallet secret"
decorate false mail domain gain later motion chair tank muffin smoke involve witness bean shell urge team solve share truly shadow decorate jeans hen
```
### `account` commands
Account commands focus on information about local accounts, generally those used by Geth and Parity but also those from hardware devices.
#### `create`
`ethdo account create` creates a new account with the given parameters. Options for creating an account include:
- `account`: the name of the account to create
- `passphrase`: the passphrase for the account
Note that for hierarchical deterministic wallets you will also need to supply `--walletpassphrase` to unlock the wallet seed.
```sh
$ ethdo account create --account="Personal wallet/Operations" --walletpassphrase="my wallet secret" --passphrase="my account secret"
```
#### `import`
`ethdo account import` creates a new account by importing its private key. Options for creating the account include:
- `account`: the name of the account to create
- `passphrase`: the passphrase for the account
- `key`: the private key to import
```sh
$ ethdo account import --account=Validators/123 --key=6dd12d588d1c05ba40e80880ac7e894aa20babdbf16da52eae26b3f267d68032 --passphrase="my account secret"
```
#### `info`
`ethdo account info` provides information about the given account. Options include:
- `account`: the name of the account on which to obtain information
```sh
$ ethdo account info --account="Personal wallet/Operations"
Public key: 0x8e2f9e8cc29658ff37ecc30e95a0807579b224586c185d128cb7a7490784c1ad9b0ab93dbe604ab075b40079931e6670
```
#### `key`
`ethdo account key` provides the private key for an account. Options include:
- `account`: the name of the account on which to obtain information
- `passphrase`: the passphrase for the account
```sh
$ ethdo account key --account=interop/00001 --passphrase=secret
0x51d0b65185db6989ab0b560d6deed19c7ead0e24b9b6372cbecb1f26bdfad000
```
#### `lock`
`ethdo account lock` manually locks an account on a remote signer. Locked accounts cannot carry out signing requests. Options include:
- `account`: the name of the account to lock
Note that this command only works with remote signers; it has no effect on local accounts.
```sh
$ ethdo account lock --account=Validators/123
```
#### `unlock`
`ethdo account unlock` manually unlocks an account on a remote signer. Unlocked accounts cannot carry out signing requests. Options include:
- `account`: the name of the account to unlock
- `passphrase`: the passphrase for the account
Note that this command only works with remote signers; it has no effect on local accounts.
```sh
$ ethdo account unlock --account=Validators/123 --passphrase="my secret passphrase"
```
### `signature` commands
Signature commands focus on generation and verification of data signatures.
#### `signature sign`
`ethdo signature sign` signs provided data. Options include:
- `data`: the data to sign, as a hex string
- `domain`: the domain in which to sign the data. This is a 32-byte hex string
- `account`: the account to sign the data
- `passphrase`: the passphrase for the account
```sh
$ ethdo signature sign --data="0x08140077a94642919041503caf5cc1c89c7744a2a08d43cec91df1795b23ecf2" --account="Personal wallet/Operations" --passphrase="my account secret"
0x87c83b31081744667406a11170c5585a11195621d0d3f796bd9006ac4cb5f61c10bf8c5b3014cd4f792b143a644cae100cb3155e8b00a961287bd9e7a5e18cb3b80930708bc9074d11ff47f1e8b9dd0b633e71bcea725fc3e550fdc259c3d130
```
#### `signature verify`
`ethdo signature verify` verifies signed data. Options include:
- `data`: the data whose signature to verify, as a hex string
- `signature`: the signature to verify, as a hex string
- `account`: the account which signed the data (if available as an account)
- `signer`: the public key of the account which signed the data (if not available as an account)
```sh
$ ethdo signature verify --data="0x08140077a94642919041503caf5cc1c89c7744a2a08d43cec91df1795b23ecf2" --signature="0x87c83b31081744667406a11170c5585a11195621d0d3f796bd9006ac4cb5f61c10bf8c5b3014cd4f792b143a644cae100cb3155e8b00a961287bd9e7a5e18cb3b80930708bc9074d11ff47f1e8b9dd0b633e71bcea725fc3e550fdc259c3d130" --account="Personal wallet/Operations"
Verified
$ ethdo signature verify --data="0x08140077a94642919041503caf5cc1c89c7744a2a08d43cec91df1795b23ecf2" --signature="0x87c83b31081744667406a11170c5585a11195621d0d3f796bd9006ac4cb5f61c10bf8c5b3014cd4f792b143a644cae100cb3155e8b00a961287bd9e7a5e18cb3b80930708bc9074d11ff47f1e8b9dd0b633e71bcea725fc3e550fdc259c3d130" --account="Personal wallet/Auctions"
Not verified
$ ethdo signature verify --data="0x08140077a94642919041503caf5cc1c89c7744a2a08d43cec91df1795b23ecf2" --signature="0x89abe2e544ef3eafe397db036103b1d066ba86497f36ed4ab0264162eadc89c7744a2a08d43cec91df128660e70ecbbe11031b4c2e53682d2b91e67b886429bf8fac9bad8c7b63c5f231cc8d66b1377e06e27138b1ddc64b27c6e593e07ebb4b" --signer="0x8e2f9e8cc29658ff37ecc30e95a0807579b224586c185d128cb7a7490784c1ad9b0ab93dbe604ab075b40079931e6670"
$ ethdo signature verify --data="0x08140077a94642919041503caf5cc1c89c7744a2a08d43cec91df1795b23ecf2" --signature="0x87c83b31081744667406a11170c5585a11195621d0d3f796bd9006ac4cb5f61c10bf8c5b3014cd4f792b143a644cae100cb3155e8b00a961287bd9e7a5e18cb3b80930708bc9074d11ff47f1e8b9dd0b633e71bcea725fc3e550fdc259c3d130" --signer="0xad1868210a0cff7aff22633c003c503d4c199c8dcca13bba5b3232fc784d39d3855936e94ce184c3ce27bf15d4347695"
Verified
```
The same rules apply to `ethereal signature verify` as those in `ethereal signature sign` above.
### `version`
`ethdo version` provides the current version of ethdo. For example:
```sh
$ ethdo version
1.4.0
```
### `block` commands
Block commands focus on providing information about Ethereum 2 blocks.
#### `info`
`ethdo block info` obtains information about a block in Ethereum 2. Options include:
- `slot`: the slot at which to attempt to fetch the block
```sh
$ ethdo block info --slot=80
Attestations: 1
Attester slashings: 0
Deposits: 0
Voluntary exits: 0
```
Additional information is supplied when using `--verbose`
```sh
$ ethdo block info --slot=80 --verbose
Parent root: 0x9a08aab7d5bbc816a9d2c20c79895519da2045e99ac6782ab3d05323a395fe51
State root: 0xc6a2626ba5cb37f984bdc4da4dc93a5012be5b69fdcebc50be70a1181a290265
Ethereum 1 deposit count: 512
Ethereum 1 deposit root: 0x05b88acdde2092e1ecf35714dca0ccf82fb7e73180643f51d3139553136d125f
Ethereum 1 block hash: 0x2b8d87e016376d83b2c04c1e626172a3f8bef3b4a37d7f2f3f76d0c62acdf573
Attestations: 1
0:
Committee index: 0
Attesters: 17
Aggregation bits: ✓✓✓✓✓✓✓✓ ✓✓✓✓✓✓✓✓ ✕✕✕✕✕✕✕✓
Slot: 79
Beacon block root: 0x9a08aab7d5bbc816a9d2c20c79895519da2045e99ac6782ab3d05323a395fe51
Source epoch: 0
Source root: 0x0000000000000000000000000000000000000000000000000000000000000000
Target epoch: 2
Target root: 0xb93273c516fc817e64fab53ff4093f295e5da463582e85e1ca60800e9464faf2
Attester slashings: 0
Deposits: 0
Voluntary exits: 0
```
### `chain` commands
Chain commands focus on providing information about Ethereum 2 chains.
#### `info`
`ethdo chain info` obtains information about an Ethereum 2 chain.
```sh
$ ethdo chain info
Genesis time: Thu Apr 16 08:02:43 BST 2020
```
Additional information is supplied when using `--verbose`
```sh
$ ethdo chain info --verbose
Genesis time: Thu Apr 16 08:02:43 BST 2020
Genesis fork version: 00000000
Seconds per slot: 12
Slots per epoch: 32
```
#### `status`
`ethdo chain status` obtains the status of an Ethereum 2 chain from the node's point of view. Options include:
- `slot` show output in terms of slots rather than epochs
```sh
$ ethdo chain status
Current epoch: 5
Justified epoch: 4
Finalized epoch: 3
```
Additional information is supplied when using `--verbose`
```sh
$ ethdo chain status --verbose
Current epoch: 5
Justified epoch: 4
Justified epoch distance 1
Finalized epoch: 3
Finalized epoch distance: 2
Prior justified epoch: 3
Prior justified epoch distance: 4
```
### `node` commands
Node commands focus on information from an Ethereum 2 node.
#### `info`
`ethdo node info` obtains the information about an Ethereum 2 node.
```sh
$ ethdo node info
Syncing: false
Current slot: 178
Current epoch: 5
```
Additional information is supplied when using `--verbose`
```sh
$ ethdo node info --verbose
Version: Prysm/Git commit: b0aa6e22455e4d9cb8720a259771fbbbd22dc3ec. Built at: 2020-04-16T08:02:43+01:00
Syncing: false
Current slot: 178
Current epoch: 5
Genesis timestamp: 1587020563
```
### `validator` commands
Validator commands focus on interaction with Ethereum 2 validators.
#### `depositdata`
`ethdo validator depositdata` generates the data required to deposit one or more Ethereum 2 validators.
#### `exit`
`ethdo validator exit` sends a transaction to the chain to tell an active validator to exit the validation queue. Options include:
- `epoch` specify an epoch before which this exit is not valid
- `json-output` generate JSON output rather than sending a transaction immediately
- `json` use JSON input created by the `--json-output` option rather than generate data from scratch
```sh
$ ethdo validator exit --account=Validators/1 --passphrase="my validator secret"
```
To send a transaction when the account is not accessible to ethdo accout you can use the validator's private key instead:
```sh
$ ethdo validator exit --key=0x01e748d098d3bcb477d636f19d510399ae18205fadf9814ee67052f88c1f88c0
```
#### `info`
`ethdo validator info` provides information for a given validator.
```sh
$ ethdo validator info --account=Validators/1
Status: Active
Balance: 3.203823585 Ether
Effective balance: 3.1 Ether
```
Additional information is supplied when using `--verbose`
```sh
$ ethdo validator info --account=Validators/1 --verbose
Epoch of data: 3398
Index: 26913
Public key: 0xb3bb6b7a8d809e59544472853d219499765bf01d14de1e0549bd6fc2a86627ac9033264c84cd503b6339e3334726562f
Status: Active
Balance: 3.204026813 Ether
Effective balance: 3.1 Ether
Withdrawal credentials: 0x0033ef3cb10b36d0771ffe8a02bc5bfc7e64ea2f398ce77e25bb78989edbee36
```
If the validator is not an account it can be queried directly with `--pubkey`.
```sh
$ ethdo validator info --pubkey=0x842dd66cfeaeff4397fc7c94f7350d2131ca0c4ad14ff727963be9a1edb4526604970df6010c3da6474a9820fa81642b
Status: Active
Balance: 3.201850307 Ether
Effective balance: 3.1 Ether
```
## Maintainers
Jim McDonald: [@mcdee](https://github.com/mcdee).
## Contribute
Contributions welcome. Please check out [the issues](https://github.com/wealdtech/ethdo/issues).
## License
[Apache-2.0](LICENSE) © 2019, 2020 Weald Technology Trading Ltd

40
go.mod
View File

@@ -3,17 +3,21 @@ module github.com/wealdtech/ethdo
go 1.13
require (
github.com/FactomProject/go-bip39 v0.3.5
github.com/OneOfOne/xxhash v1.2.5 // indirect
github.com/aws/aws-sdk-go v1.30.25 // indirect
github.com/ferranbt/fastssz v0.0.0-20200415074633-b062b680417b // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/golang/protobuf v1.4.0
github.com/gogo/protobuf v1.3.1
github.com/golang/protobuf v1.4.1 // indirect
github.com/google/uuid v1.1.1
github.com/grpc-ecosystem/grpc-gateway v1.14.3 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.14.5 // indirect
github.com/herumi/bls-eth-go-binary v0.0.0-20200508110836-07e8f416e478 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.2.2 // indirect
github.com/mitchellh/mapstructure v1.3.0 // indirect
github.com/pelletier/go-toml v1.7.0 // indirect
github.com/pkg/errors v0.9.1
github.com/prysmaticlabs/ethereumapis v0.0.0-20200414190010-6607cc86ddb7
github.com/prysmaticlabs/ethereumapis v0.0.0-20200511212457-3444ffb75440
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669
github.com/prysmaticlabs/go-ssz v0.0.0-20200101200214-e24db4d9e963
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.2.2 // indirect
@@ -21,17 +25,23 @@ require (
github.com/spf13/cobra v1.0.0
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.6.3
github.com/spf13/viper v1.7.0
github.com/tyler-smith/go-bip39 v1.0.2
github.com/wealdtech/eth2-signer-api v1.3.0
github.com/wealdtech/go-bytesutil v1.1.1
github.com/wealdtech/go-eth2-types/v2 v2.3.0
github.com/wealdtech/go-eth2-util v1.1.4
github.com/wealdtech/go-eth2-wallet v1.9.3
github.com/wealdtech/go-eth2-wallet-types/v2 v2.0.1
github.com/wealdtech/go-eth2-types/v2 v2.3.1
github.com/wealdtech/go-eth2-util v1.1.5
github.com/wealdtech/go-eth2-wallet v1.9.4
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.0.0
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.0.4
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.7.3
github.com/wealdtech/go-eth2-wallet-store-s3 v1.6.3
github.com/wealdtech/go-eth2-wallet-types/v2 v2.0.2
github.com/wealdtech/go-string2eth v1.1.0
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e // indirect
golang.org/x/text v0.3.2 // indirect
google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36 // indirect
google.golang.org/grpc v1.28.1
gopkg.in/ini.v1 v1.55.0 // indirect
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f // indirect
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25 // indirect
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380 // indirect
google.golang.org/grpc v1.29.1
gopkg.in/ini.v1 v1.56.0 // indirect
)

259
go.sum
View File

@@ -1,8 +1,19 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/FactomProject/go-bip39 v0.3.5 h1:l9g92TeqCkC5NZhm72igTpf5yaYDp3Sy4CvnPYknp6U=
github.com/FactomProject/go-bip39 v0.3.5/go.mod h1:ygPVOtW424QxnJMze9XYDeh4wT19V3iVDOqVUl/USkE=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.5 h1:zl/OfRA6nftbBK9qTohYBJ5xvw6C/oNKizR7cZGl3cI=
@@ -10,11 +21,18 @@ github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdII
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.30.7 h1:IaXfqtioP6p9SFAnNfsqdNczbR5UNbYqvcZUSsCAdTY=
github.com/aws/aws-sdk-go v1.30.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.30.15 h1:Sd8QDVzzE8Sl+xNccmdj0HwMrFowv6uVUx9tGsCE1ZE=
github.com/aws/aws-sdk-go v1.30.15/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.30.25 h1:89NXJkfpjnMEnsxkP8MVX+LDsoiLCSqevraLb5y4Mjk=
github.com/aws/aws-sdk-go v1.30.25/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -24,12 +42,14 @@ github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgraph-io/ristretto v0.0.1/go.mod h1:T40EBc7CJke8TkpiYfGGKAeFjSaxuFXhuXRyumBd6RE=
github.com/dgraph-io/ristretto v0.0.2 h1:a5WaUrDa0qm0YrAAS1tUykT5El3kt62KNZZeMxQn3po=
github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -40,11 +60,15 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/ferranbt/fastssz v0.0.0-20200415074633-b062b680417b h1:CxaMtGnKgr9Ar2xLMVddPhnMwYLDsY56w/LxQ/wnsKA=
github.com/ferranbt/fastssz v0.0.0-20200415074633-b062b680417b/go.mod h1:LlFXPmgrgVYsuoFDwV8rDJ9tvt1pLQdjKvU1b5IRES0=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
@@ -52,17 +76,23 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@@ -71,6 +101,9 @@ github.com/golang/protobuf v1.4.0-rc.4/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9c
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -79,32 +112,63 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/grpc-ecosystem/grpc-gateway v1.14.3 h1:OCJlWkOUoTnl0neNGlf4fUm3TmbEtguw7vR+nGtnDjY=
github.com/grpc-ecosystem/grpc-gateway v1.14.3/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0=
github.com/grpc-ecosystem/grpc-gateway v1.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
github.com/grpc-ecosystem/grpc-gateway v1.14.5 h1:aiLxiiVzAXb7wb3lAmubA69IokWOoUNe+E7TdGKh8yw=
github.com/grpc-ecosystem/grpc-gateway v1.14.5/go.mod h1:UJ0EZAp832vCd54Wev9N1BMKEyvcZ5+IM0AwDrnlkEc=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/herumi/bls-eth-go-binary v0.0.0-20200326062426-f58f8b8bd66f h1:fTtKw31DtXHqxb3D9Oqt+CDVXEbyLs7yqa+RNKYw+3I=
github.com/herumi/bls-eth-go-binary v0.0.0-20200326062426-f58f8b8bd66f/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/herumi/bls-eth-go-binary v0.0.0-20200428020417-6dd0e5634b87 h1:23l9wMlu3iMRg5PwI4wuA7sbR77GSF+rnwI0Z/Y4IPc=
github.com/herumi/bls-eth-go-binary v0.0.0-20200428020417-6dd0e5634b87/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20200508110836-07e8f416e478 h1:UMIHMlIgtPmh96SmXdDiEDRbQ2NSroxBQzpEknueoG4=
github.com/herumi/bls-eth-go-binary v0.0.0-20200508110836-07e8f416e478/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -116,22 +180,31 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA=
github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc=
github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU=
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.2.2 h1:dxe5oCinTXiTIcfgmZecdCzPmAJKd46KsCWc35r0TV4=
github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mitchellh/mapstructure v1.3.0 h1:iDwIio/3gk2QtLLEsqU5lInaMzos0hDTz8a6lazSFVw=
github.com/mitchellh/mapstructure v1.3.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
@@ -142,6 +215,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
@@ -152,17 +226,22 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/protolambda/zssz v0.1.3/go.mod h1:a4iwOX5FE7/JkKA+J/PH0Mjo9oXftN6P8NZyL28gpag=
github.com/protolambda/zssz v0.1.4 h1:4jkt8sqwhOVR8B1JebREU/gVX0Ply4GypsV8+RWrDuw=
github.com/protolambda/zssz v0.1.4/go.mod h1:a4iwOX5FE7/JkKA+J/PH0Mjo9oXftN6P8NZyL28gpag=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200414190010-6607cc86ddb7 h1:p1WbKbIHr4tXK6wclFrM78P61Ai2qSWMQGkljbP4H1A=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200414190010-6607cc86ddb7/go.mod h1:5OkRN6UmvgtP+kIewitcEKC7S5KOzLOGtya/Tz+HBns=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200511212457-3444ffb75440 h1:plalLbsEdAKKURjR7u+JUsgD2tyxSa/yitdMyqaWY4E=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200511212457-3444ffb75440/go.mod h1:5OkRN6UmvgtP+kIewitcEKC7S5KOzLOGtya/Tz+HBns=
github.com/prysmaticlabs/go-bitfield v0.0.0-20191017011753-53b773adde52/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669 h1:cX6YRZnZ9sgMqM5U14llxUiXVNJ3u07Res1IIjTOgtI=
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
github.com/prysmaticlabs/go-ssz v0.0.0-20200101200214-e24db4d9e963 h1:Th5ufPIaL5s/7i3gXHTgiTwfsUhWDP/PwFRiI6qV6v0=
github.com/prysmaticlabs/go-ssz v0.0.0-20200101200214-e24db4d9e963/go.mod h1:VecIJZrewdAuhVckySLFt2wAAHRME934bSDurP8ftkc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1fOy4Ee11vHhUFHQNpHhrBneOCNHVXS5w=
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@@ -193,8 +272,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs=
github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw=
github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -206,6 +285,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tyler-smith/go-bip39 v1.0.2 h1:+t3w+KwLXO6154GNJY+qUtIxLTmFjfUmpguQT1OlOT8=
github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/wealdtech/eth2-signer-api v1.3.0 h1:Fs0GfrdhboBKW7zaMvIvUHJaOB1ibpAmRG3lkB53in4=
github.com/wealdtech/eth2-signer-api v1.3.0/go.mod h1:H8OpAoTBl6CaBvZEnhxWDjjWXNc3kwVFKWMAZd6sHlk=
@@ -215,26 +296,27 @@ github.com/wealdtech/go-bytesutil v1.1.1 h1:ocEg3Ke2GkZ4vQw5lp46rmO+pfqCCTgq35gq
github.com/wealdtech/go-bytesutil v1.1.1/go.mod h1:jENeMqeTEU8FNZyDFRVc7KqBdRKSnJ9CCh26TcuNb9s=
github.com/wealdtech/go-ecodec v1.1.0 h1:yggrTSckcPJRaxxOxQF7FPm21kgE8WA6+f5jdq5Kr8o=
github.com/wealdtech/go-ecodec v1.1.0/go.mod h1:PSdBFEB6cltdT7V4E1jbboufMZTZXcQOKG/2PeEjKK4=
github.com/wealdtech/go-eth2-types/v2 v2.3.0 h1:qfmgaCBkH2N11LHCXsRWYz7OOxc+1QXrKHlS9yDnFsw=
github.com/wealdtech/go-eth2-types/v2 v2.3.0/go.mod h1:jDvQ0j5EUtI7x/c3Vscq8TaFzBGlj6DrKz0CABuugkI=
github.com/wealdtech/go-eth2-util v1.1.4 h1:MyM16V7Qhd9q2ZaRa0WteBg2bWb8UplIKjZr8aeBZP0=
github.com/wealdtech/go-eth2-util v1.1.4/go.mod h1:rvkccTN0inLcI76Gq8FBdkuv3tmX+XSJxBr9gdm1WUE=
github.com/wealdtech/go-eth2-wallet v1.9.3 h1:Hna/w4EKBJIs86VprIq7ez063A6kwk31d/O3Gs+MpYc=
github.com/wealdtech/go-eth2-wallet v1.9.3/go.mod h1:ylsiNrJen1Nw8m+c0fWZKp823E87p7RbrFwcI4V2S18=
github.com/wealdtech/go-eth2-types/v2 v2.3.1 h1:2KSUzducArOynCL2prRf4vWU5GjwaPSnSN9oqNgf+dQ=
github.com/wealdtech/go-eth2-types/v2 v2.3.1/go.mod h1:FubkGSavaa+rvmHDMTUVoPdFh00wKg0k5QPW6G52mhw=
github.com/wealdtech/go-eth2-util v1.1.5 h1:4OPbf2yaEQmqDmOIU6UKBfhKTPNZ7skU4lPhueBLx8o=
github.com/wealdtech/go-eth2-util v1.1.5/go.mod h1:wYYmtc9KpQQAaAzWjXSPLgtsJMkoDAmTNN0h6uj3RCA=
github.com/wealdtech/go-eth2-wallet v1.9.4 h1:9XFM1Y7dsyrgNFFCnE3Gd00PAsrpob70SAQqHSPmsBU=
github.com/wealdtech/go-eth2-wallet v1.9.4/go.mod h1:UGd1bAPDEtP+UrFjj3HCbip7jggFGDIQoeGw8/XHMvo=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.0.0 h1:IcpS4VpXhYz+TVupB5n6C6IQzaKwG+Rc8nvgCa/da4c=
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.0.0/go.mod h1:X8WRO5hEwbjx8ZOqoRmtS1ngyflKs25GkP7qGv7yOqE=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.0.1 h1:kiCvdexK3zRC2GwZHSHq+hS+irVNtMs5pNADyumeeRM=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.0.1/go.mod h1:jqmt8pGMm2WCzqiHkPW8ib/GAFNaQzNhqToOGN0qBDs=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.0.1 h1:4lB6GY5oHQn5xwn/Sxm1e9SeVCaxa7q/0hqXUQYUNwU=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.0.1/go.mod h1:jJ3AUHWR0NlPrE6qlOL86pJe14x6K2xFzfmX1brB9Ws=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.7.2 h1:Lc6wVTjIYeD+2hLAIzq1SugTWR527vEX4tEr5v3zxJc=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.7.2/go.mod h1:fyA+GmdE7bd/P93TBcb3aqQ83i0AmcQHu9qPg4HnLlg=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.6.2 h1:xzyQDxbe5nr7xG0ByevTV2S8qkeOZvvjp+leBJcpxXQ=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.6.2/go.mod h1:C+NWsx9AdAfrn5zLbru+ctO+lljVTVCJYcXgFsN7Q9o=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.3.2 h1:vR9ATFkkUAA4Os9wxF/GhN8Rg3HA/1COMRdzqIg/evY=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.3.2/go.mod h1:BQ8aeThx3O7ByvAB2E1FDiHbAlJXAir7nUg5liJw0W4=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.0.1 h1:Ct3RrNJTapBiG2GxVl53Kfgy96f0GEUV7bediTu91u8=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.0.1/go.mod h1:y2XAyxb01jyGq3w2hyVgXadgl+KtlDwq8A9RQt2DE3g=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.0.3/go.mod h1:nNNZNXCP1BrJCu1hLlFUCAQBvCInD4zwE7eslf2U5XQ=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.0.4 h1:/nBbza+ZPY1dn455AnZRRpIEjeUmTRQCS5QdKf6nhrg=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.0.4/go.mod h1:nNNZNXCP1BrJCu1hLlFUCAQBvCInD4zwE7eslf2U5XQ=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.0.3 h1:NfeWHtyjtZt3hmVA7kysNf2w+cB9Y82w6Cv4zWbFRSk=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.0.3/go.mod h1:RDXAfay+PL+apCVLnVtWBUb183m4uug93FBZ0c2cVaw=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.7.3 h1:2nMDDRULzSSa6LCk3044d5J4rXi2HX61nRLyGLXGI3M=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.7.3/go.mod h1:HE1JcXUhWUtJ7F/APzSI/ZTfXjdxbQ15CDe6L0mjtaQ=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.6.3 h1:SD5tsdj9pRdsfWbhpL09X6gDGO9rJvlI6lz2cxpdfA4=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.6.3/go.mod h1:wS8sqBuIcn9QuLR1VlV7JaSKrFiNOMSPDDBYtWWe98c=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.3.3 h1:0cKttlJ5QONJ2ZndVLUVv3RhbEaSU0TKvOI2BIB9j60=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.3.3/go.mod h1:/tvALCsQ07lvqlU+IKKAdwYFYyjIO628bu/Ssv0JRv4=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.0.2 h1:Lhwne1gRUp961fD+eoWrgDbZF5rHwosI2LS5pIdX4Yc=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.0.2/go.mod h1:d7WZ9WvtL3vGSHtSh/jnVh4YO93verLL1dRW2NK5sN4=
github.com/wealdtech/go-indexer v1.0.0 h1:/S4rfWQbSOnnYmwnvuTVatDibZ8o1s9bmTCHO16XINg=
github.com/wealdtech/go-indexer v1.0.0/go.mod h1:u1cjsbsOXsm5jzJDyLmZY7GsrdX8KYXKBXkZcAmk3Zg=
github.com/wealdtech/go-string2eth v1.1.0 h1:USJQmysUrBYYmZs7d45pMb90hRSyEwizP7lZaOZLDAw=
@@ -242,84 +324,157 @@ github.com/wealdtech/go-string2eth v1.1.0/go.mod h1:RUzsLjJtbZaJ/3UKn9kY19a/vCCU
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59 h1:PyXRxSVbvzDGuqYXjHndV7xDzJ7w2K8KD9Ef8GB7KOE=
golang.org/x/crypto v0.0.0-20191105034135-c7e5f84aec59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8=
golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc h1:ZGI/fILM2+ueot/UixBSoj9188jCAxVHEZEGhqq67I4=
golang.org/x/crypto v0.0.0-20200427165652-729f1e841bcc/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 h1:cg5LA/zNPRzIXIWSCxQW10Rvpy94aQh3LT/ShoCpkHw=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJnl/ymnJWAdMuinqL7Y=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200427175716-29b57079015a h1:08u6b1caTT9MQY4wSbmsd4Ulm6DmgNYnbImBuZjGJow=
golang.org/x/sys v0.0.0-20200427175716-29b57079015a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25 h1:OKbAoGs4fGM5cPLlVQLZGYkFC8OnOfgo6tt0Smf9XhM=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36 h1:j7CmVRD4Kec0+f8VuBAc2Ak2MFfXm5Q2/RxuJLL+76E=
google.golang.org/genproto v0.0.0-20200413115906-b5235f65be36/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380 h1:xriR1EgvKfkKxIoU2uUvrMVl+H26359loFFUleSMXFo=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0 h1:rRYRFMVgRv6E0D70Skyfsr28tDXIuuPZyWGMPdMcnXg=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k=
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -328,15 +483,18 @@ google.golang.org/protobuf v1.20.1 h1:ESRXHgpUBG5D2I5mmsQIyYxB/tQIZfSZ8wLyFDf/N/
google.golang.org/protobuf v1.20.1/go.mod h1:KqelGeouBkcbcuB3HCk4/YH2tmNLk6YSWA5LIWeI/lY=
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -346,5 +504,10 @@ gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@@ -18,11 +18,11 @@ import (
"strconv"
"strings"
"github.com/gogo/protobuf/types"
"github.com/pkg/errors"
"github.com/spf13/viper"
"google.golang.org/grpc"
"github.com/golang/protobuf/ptypes/empty"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
@@ -31,10 +31,13 @@ import (
// It tweaks the output to make it easier to work with by setting appropriate
// types.
func FetchChainConfig(conn *grpc.ClientConn) (map[string]interface{}, error) {
if conn == nil {
return nil, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
config, err := beaconClient.GetBeaconConfig(ctx, &empty.Empty{})
config, err := beaconClient.GetBeaconConfig(ctx, &types.Empty{})
if err != nil {
return nil, err
}
@@ -74,6 +77,9 @@ func FetchChainConfig(conn *grpc.ClientConn) (map[string]interface{}, error) {
// FetchValidator fetches the validator definition from the beacon node.
func FetchValidator(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.Validator, error) {
if conn == nil {
return nil, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
@@ -88,6 +94,9 @@ func FetchValidator(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.Valid
// FetchValidatorByIndex fetches the validator definition from the beacon node.
func FetchValidatorByIndex(conn *grpc.ClientConn, index uint64) (*ethpb.Validator, error) {
if conn == nil {
return nil, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
@@ -102,6 +111,9 @@ func FetchValidatorByIndex(conn *grpc.ClientConn, index uint64) (*ethpb.Validato
// FetchValidatorInfo fetches current validator info from the beacon node.
func FetchValidatorInfo(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.ValidatorInfo, error) {
if conn == nil {
return nil, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
@@ -124,15 +136,21 @@ func FetchValidatorInfo(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.V
// FetchChainInfo fetches current chain info from the beacon node.
func FetchChainInfo(conn *grpc.ClientConn) (*ethpb.ChainHead, error) {
if conn == nil {
return nil, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
return beaconClient.GetChainHead(ctx, &empty.Empty{})
return beaconClient.GetChainHead(ctx, &types.Empty{})
}
// FetchBlock fetches a block at a given slot from the beacon node.
func FetchBlock(conn *grpc.ClientConn, slot uint64) (*ethpb.SignedBeaconBlock, error) {
if conn == nil {
return nil, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()

View File

@@ -16,6 +16,7 @@ package grpc
import (
"context"
"github.com/pkg/errors"
"github.com/spf13/viper"
"google.golang.org/grpc"
@@ -25,6 +26,9 @@ import (
// FetchValidatorIndex fetches the index of a validator.
func FetchValidatorIndex(conn *grpc.ClientConn, account wtypes.Account) (uint64, error) {
if conn == nil {
return 0, errors.New("no connection to beacon node")
}
validatorClient := ethpb.NewBeaconNodeValidatorClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
@@ -43,6 +47,9 @@ func FetchValidatorIndex(conn *grpc.ClientConn, account wtypes.Account) (uint64,
// FetchValidatorState fetches the state of a validator.
func FetchValidatorState(conn *grpc.ClientConn, account wtypes.Account) (ethpb.ValidatorStatus, error) {
if conn == nil {
return ethpb.ValidatorStatus_UNKNOWN_STATUS, errors.New("no connection to beacon node")
}
validatorClient := ethpb.NewBeaconNodeValidatorClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
@@ -53,7 +60,7 @@ func FetchValidatorState(conn *grpc.ClientConn, account wtypes.Account) (ethpb.V
}
resp, err := validatorClient.ValidatorStatus(ctx, req)
if err != nil {
return 0, err
return ethpb.ValidatorStatus_UNKNOWN_STATUS, err
}
return resp.Status, nil

View File

@@ -17,31 +17,53 @@ import (
"context"
"time"
"github.com/gogo/protobuf/types"
"github.com/pkg/errors"
"github.com/spf13/viper"
"google.golang.org/grpc"
"github.com/golang/protobuf/ptypes/empty"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
)
// FetchGenesis fetches the genesis time.
func FetchGenesis(conn *grpc.ClientConn) (time.Time, error) {
// FetchGenesisTime fetches the genesis time.
func FetchGenesisTime(conn *grpc.ClientConn) (time.Time, error) {
if conn == nil {
return time.Now(), errors.New("no connection to beacon node")
}
client := ethpb.NewNodeClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
res, err := client.GetGenesis(ctx, &empty.Empty{})
res, err := client.GetGenesis(ctx, &types.Empty{})
if err != nil {
return time.Now(), err
}
return time.Unix(res.GetGenesisTime().Seconds, 0), nil
}
// FetchVersion fetches the version and metadata from the server.
func FetchVersion(conn *grpc.ClientConn) (string, string, error) {
// FetchGenesisValidatorsRoot fetches the genesis validators root.
func FetchGenesisValidatorsRoot(conn *grpc.ClientConn) ([]byte, error) {
if conn == nil {
return nil, errors.New("no connection to beacon node")
}
client := ethpb.NewNodeClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
version, err := client.GetVersion(ctx, &empty.Empty{})
res, err := client.GetGenesis(ctx, &types.Empty{})
if err != nil {
return nil, err
}
return res.GetGenesisValidatorsRoot(), nil
}
// FetchVersion fetches the version and metadata from the server.
func FetchVersion(conn *grpc.ClientConn) (string, string, error) {
if conn == nil {
return "", "", errors.New("no connection to beacon node")
}
client := ethpb.NewNodeClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
version, err := client.GetVersion(ctx, &types.Empty{})
if err != nil {
return "", "", err
}
@@ -50,10 +72,13 @@ func FetchVersion(conn *grpc.ClientConn) (string, string, error) {
// FetchSyncing returns true if the node is syncing, otherwise false.
func FetchSyncing(conn *grpc.ClientConn) (bool, error) {
if conn == nil {
return false, errors.New("no connection to beacon node")
}
client := ethpb.NewNodeClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
syncStatus, err := client.GetSyncStatus(ctx, &empty.Empty{})
syncStatus, err := client.GetSyncStatus(ctx, &types.Empty{})
if err != nil {
return false, err
}

View File

@@ -22,17 +22,38 @@ import (
// ScratchAccount is an account that exists temporarily.
type ScratchAccount struct {
id uuid.UUID
pubKey types.PublicKey
id uuid.UUID
privKey types.PrivateKey
pubKey types.PublicKey
unlocked bool
}
// NewScratchAccount creates a new local account.
func NewScratchAccount(pubKey []byte) (*ScratchAccount, error) {
func NewScratchAccount(privKey []byte, pubKey []byte) (*ScratchAccount, error) {
if len(privKey) > 0 {
return newScratchAccountFromPrivKey(privKey)
} else {
return newScratchAccountFromPubKey(pubKey)
}
}
func newScratchAccountFromPrivKey(privKey []byte) (*ScratchAccount, error) {
key, err := types.BLSPrivateKeyFromBytes(privKey)
if err != nil {
return nil, err
}
return &ScratchAccount{
id: uuid.New(),
privKey: key,
pubKey: key.PublicKey(),
}, nil
}
func newScratchAccountFromPubKey(pubKey []byte) (*ScratchAccount, error) {
key, err := types.BLSPublicKeyFromBytes(pubKey)
if err != nil {
return nil, err
}
return &ScratchAccount{
id: uuid.New(),
pubKey: key,
@@ -56,16 +77,24 @@ func (a *ScratchAccount) Path() string {
}
func (a *ScratchAccount) Lock() {
a.unlocked = false
}
func (a *ScratchAccount) Unlock([]byte) error {
a.unlocked = true
return nil
}
func (a *ScratchAccount) IsUnlocked() bool {
return false
return a.unlocked
}
func (a *ScratchAccount) Sign(data []byte) (types.Signature, error) {
return nil, errors.New("Not implemented")
if !a.IsUnlocked() {
return nil, errors.New("locked")
}
if a.privKey == nil {
return nil, errors.New("no private key")
}
return a.privKey.Sign(data), nil
}