Compare commits

...

15 Commits

Author SHA1 Message Date
Jim McDonald
f2bb5e0d51 Improve error message. 2020-06-22 11:46:53 +01:00
Jim McDonald
f5fc8b363d Merge branch 'master' of github.com:wealdtech/ethdo 2020-06-22 11:06:37 +01:00
Jim McDonald
a31509f7d6 Rework passphrase handling 2020-06-22 11:06:25 +01:00
Jim McDonald
4b451ec2fa Add explicit validator indices for attestations. 2020-06-22 08:08:32 +01:00
Jim McDonald
a8fee14b89 Tidy up use of functions when displaying chain status. 2020-06-22 08:07:19 +01:00
Jim McDonald
9cfb1b5637 Merge pull request #11 from dsystems-io/patch-1
Fixed output for "Justified epoch distance"
2020-06-19 22:24:46 +01:00
Distributed Systems
df1724f763 Fixed output for "Justified epoch distance"
Small inconsistency in output.
2020-06-19 21:38:30 +01:00
Jim McDonald
f1a586ca56 Add information about gopath 2020-06-18 13:33:08 +01:00
Jim McDonald
b9cb926662 Provide output for verified deposits 2020-06-18 10:15:17 +01:00
Jim McDonald
220cc21356 Bump deposit version 2020-06-11 20:38:47 +01:00
Jim McDonald
5bc7c1a26c Bump deposit version 2020-06-11 20:37:04 +01:00
Jim McDonald
4c3237cd0d Tidy up 2020-06-11 13:32:30 +01:00
Jim McDonald
7215e04a69 Provide withdrawal credentials as part of account info.
Supply clearer message when validator depositdata cannot reach a beacon
node.
2020-06-09 21:01:39 +01:00
Jim McDonald
71e9c0471b Update README 2020-06-08 16:24:23 +01:00
Jim McDonald
1a6f402fb8 Add ability to verify wallet exports 2020-06-08 16:13:35 +01:00
25 changed files with 708 additions and 213 deletions

View File

@@ -5,7 +5,7 @@
A command-line tool for managing common tasks in Ethereum 2.
** Please note that this library uses standards that are not yet final, and as such may result in changes that alter public and private keys. Do not use this library for production use just yet **
**Please note that this tool and its underlying libraries have not yet undergone a security audit; use at your own risk.**
## Table of Contents
@@ -118,6 +118,18 @@ 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.
## Rules for account passphrases
Account passphrases are used in various places in `ethdo`. Where they are used, the following rules apply:
- commands that require passphrases to operate, for example unlocking an account, can be supplied with multiple passphrases. If they are, then each passphrase is tried until one succeeds or they all fail
- commands that require passphrases to create, for example creating an account, must be supplied with a single passphrase. If more than one passphrase is supplied the command will fail
In addition, the following rules apply to passphrases supplied on the command line:
- passphrases **must not** start with `0x`
- passphrases **must not** contain the comma (,) character
# Commands
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).

View File

@@ -18,6 +18,8 @@ import (
"os"
"github.com/spf13/cobra"
e2wallet "github.com/wealdtech/go-eth2-wallet"
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
var accountCreateCmd = &cobra.Command{
@@ -31,24 +33,26 @@ In quiet mode this will return 0 if the account is created successfully, otherwi
Run: func(cmd *cobra.Command, args []string) {
assert(!remote, "account create not available with remote wallets")
assert(rootAccount != "", "--account is required")
assert(rootAccountPassphrase != "", "--passphrase is required")
w, err := walletFromPath(rootAccount)
wallet, err := walletFromPath(rootAccount)
errCheck(err, "Failed to access wallet")
if w.Type() == "hierarchical deterministic" {
assert(rootWalletPassphrase != "", "--walletpassphrase is required to create new accounts with hierarchical deterministic wallets")
if wallet.Type() == "hierarchical deterministic" {
assert(getWalletPassphrase() != "", "--walletpassphrase is required to create new accounts with hierarchical deterministic wallets")
}
_, err = accountFromPath(rootAccount)
assert(err != nil, "Account already exists")
err = w.Unlock([]byte(rootWalletPassphrase))
err = wallet.Unlock([]byte(getWalletPassphrase()))
errCheck(err, "Failed to unlock wallet")
_, accountName, err := walletAndAccountNamesFromPath(rootAccount)
errCheck(err, "Failed to obtain accout name")
_, accountName, err := e2wallet.WalletAndAccountNames(rootAccount)
errCheck(err, "Failed to obtain account name")
account, err := w.CreateAccount(accountName, []byte(rootAccountPassphrase))
walletAccountCreator, ok := wallet.(e2wtypes.WalletAccountCreator)
assert(ok, "wallet does not allow account creation")
account, err := walletAccountCreator.CreateAccount(accountName, []byte(getPassphrase()))
errCheck(err, "Failed to create account")
outputIf(verbose, fmt.Sprintf("0x%048x", account.PublicKey().Marshal()))

View File

@@ -19,7 +19,8 @@ import (
"github.com/spf13/cobra"
"github.com/wealdtech/go-bytesutil"
types "github.com/wealdtech/go-eth2-wallet-types/v2"
e2wallet "github.com/wealdtech/go-eth2-wallet"
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
var accountImportKey string
@@ -35,7 +36,7 @@ In quiet mode this will return 0 if the account is imported successfully, otherw
Run: func(cmd *cobra.Command, args []string) {
assert(!remote, "account import not available with remote wallets")
assert(rootAccount != "", "--account is required")
assert(rootAccountPassphrase != "", "--passphrase is required")
passphrase := getPassphrase()
assert(accountImportKey != "", "--key is required")
key, err := bytesutil.FromHexString(accountImportKey)
@@ -44,19 +45,19 @@ In quiet mode this will return 0 if the account is imported successfully, otherw
w, err := walletFromPath(rootAccount)
errCheck(err, "Failed to access wallet")
_, ok := w.(types.WalletAccountImporter)
_, ok := w.(e2wtypes.WalletAccountImporter)
assert(ok, fmt.Sprintf("wallets of type %q do not allow importing accounts", w.Type()))
_, err = accountFromPath(rootAccount)
assert(err != nil, "Account already exists")
err = w.Unlock([]byte(rootWalletPassphrase))
err = w.Unlock([]byte(getWalletPassphrase()))
errCheck(err, "Failed to unlock wallet")
_, accountName, err := walletAndAccountNamesFromPath(rootAccount)
_, accountName, err := e2wallet.WalletAndAccountNames(rootAccount)
errCheck(err, "Failed to obtain account name")
account, err := w.(types.WalletAccountImporter).ImportAccount(accountName, key, []byte(rootAccountPassphrase))
account, err := w.(e2wtypes.WalletAccountImporter).ImportAccount(accountName, key, []byte(passphrase))
errCheck(err, "Failed to create account")
outputIf(verbose, fmt.Sprintf("0x%048x", account.PublicKey().Marshal()))

View File

@@ -20,6 +20,7 @@ import (
"github.com/spf13/cobra"
pb "github.com/wealdtech/eth2-signer-api/pb/v1"
util "github.com/wealdtech/go-eth2-util"
)
var accountInfoCmd = &cobra.Command{
@@ -33,6 +34,7 @@ In quiet mode this will return 0 if the account exists, otherwise 1.`,
Run: func(cmd *cobra.Command, args []string) {
assert(rootAccount != "", "--account is required")
var withdrawalCredentials []byte
if remote {
listerClient := pb.NewListerClient(remoteGRPCConn)
listAccountsReq := &pb.ListAccountsRequest{
@@ -44,13 +46,18 @@ In quiet mode this will return 0 if the account exists, otherwise 1.`,
errCheck(err, "Failed to access account")
assert(resp.State == pb.ResponseState_SUCCEEDED, "No such account")
assert(len(resp.Accounts) == 1, "No such account")
fmt.Printf("Public key: %#048x\n", resp.Accounts[0].PublicKey)
fmt.Printf("Public key: %#x\n", resp.Accounts[0].PublicKey)
withdrawalCredentials = util.SHA256(resp.Accounts[0].PublicKey)
withdrawalCredentials[0] = byte(0) // BLS_WITHDRAWAL_PREFIX
outputIf(verbose, fmt.Sprintf("Withdrawal credentials: %#x", withdrawalCredentials))
} else {
account, err := accountFromPath(rootAccount)
errCheck(err, "Failed to access wallet")
outputIf(verbose, fmt.Sprintf("UUID: %v", account.ID()))
outputIf(!quiet, fmt.Sprintf("Public key: %#048x", account.PublicKey().Marshal()))
outputIf(!quiet, fmt.Sprintf("Public key: %#x", account.PublicKey().Marshal()))
withdrawalCredentials = util.SHA256(account.PublicKey().Marshal())
withdrawalCredentials[0] = byte(0) // BLS_WITHDRAWAL_PREFIX
outputIf(verbose, fmt.Sprintf("Withdrawal credentials: %#x", withdrawalCredentials))
outputIf(verbose && account.Path() != "", fmt.Sprintf("Path: %s", account.Path()))
}

View File

@@ -40,9 +40,15 @@ In quiet mode this will return 0 if the key can be obtained, otherwise 1.`,
_, ok := account.(types.AccountPrivateKeyProvider)
assert(ok, fmt.Sprintf("account %q does not provide its private key", rootAccount))
assert(rootAccountPassphrase != "", "--passphrase is required")
err = account.Unlock([]byte(rootAccountPassphrase))
errCheck(err, "Failed to unlock account to obtain private key")
unlocked := false
for _, passphrase := range getPassphrases() {
err = account.Unlock([]byte(passphrase))
if err == nil {
unlocked = true
break
}
}
assert(unlocked, "Failed to unlock account to obtain private key")
defer account.Lock()
privateKey, err := account.(types.AccountPrivateKeyProvider).PrivateKey()
errCheck(err, "Failed to obtain private key")

View File

@@ -35,23 +35,23 @@ In quiet mode this will return 0 if the account is unlocked, otherwise 1.`,
assert(rootAccount != "", "--account is required")
client := pb.NewAccountManagerClient(remoteGRPCConn)
unlockReq := &pb.UnlockAccountRequest{
Account: rootAccount,
Passphrase: []byte(rootAccountPassphrase),
}
unlocked := false
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
resp, err := client.Unlock(ctx, unlockReq)
errCheck(err, "Failed in attempt to unlock account")
switch resp.State {
case pb.ResponseState_DENIED:
die("Unlock request denied")
case pb.ResponseState_FAILED:
die("Unlock request failed")
case pb.ResponseState_SUCCEEDED:
outputIf(!quiet, "Unlock request succeeded")
os.Exit(_exitSuccess)
for _, passphrase := range getPassphrases() {
unlockReq := &pb.UnlockAccountRequest{
Account: rootAccount,
Passphrase: []byte(passphrase),
}
resp, err := client.Unlock(ctx, unlockReq)
errCheck(err, "Failed in attempt to unlock account")
if resp.State == pb.ResponseState_SUCCEEDED {
unlocked = true
break
}
}
assert(unlocked, "Failed to unlock account")
os.Exit(_exitSuccess)
},
}

View File

@@ -45,6 +45,10 @@ In quiet mode this will return 0 if the block information is present and not ski
err := connect()
errCheck(err, "Failed to obtain connection to Ethereum 2 beacon chain block")
config, err := grpc.FetchChainConfig(eth2GRPCConn)
errCheck(err, "Failed to obtain beacon chain configuration")
slotsPerEpoch := config["SlotsPerEpoch"].(uint64)
if blockInfoStream {
stream, err := grpc.StreamBlocks(eth2GRPCConn)
errCheck(err, "Failed to obtain block stream")
@@ -53,7 +57,7 @@ In quiet mode this will return 0 if the block information is present and not ski
errCheck(err, "Failed to obtain block")
if signedBlock != nil {
fmt.Println("")
outputBlock(signedBlock)
outputBlock(signedBlock, slotsPerEpoch)
}
}
@@ -62,6 +66,7 @@ In quiet mode this will return 0 if the block information is present and not ski
var slot uint64
if blockInfoSlot < 0 {
slot, err = grpc.FetchLatestFilledSlot(eth2GRPCConn)
errCheck(err, "Failed to obtain slot of latest block")
} else {
slot = uint64(blockInfoSlot)
}
@@ -73,14 +78,14 @@ In quiet mode this will return 0 if the block information is present and not ski
outputIf(!quiet, "No block at that slot")
os.Exit(_exitFailure)
}
outputBlock(signedBlock)
outputBlock(signedBlock, slotsPerEpoch)
}
os.Exit(_exitSuccess)
},
}
func outputBlock(signedBlock *ethpb.SignedBeaconBlock) {
func outputBlock(signedBlock *ethpb.SignedBeaconBlock, slotsPerEpoch uint64) {
block := signedBlock.Block
body := block.Body
@@ -88,6 +93,7 @@ func outputBlock(signedBlock *ethpb.SignedBeaconBlock) {
bodyRoot, err := ssz.HashTreeRoot(block)
errCheck(err, "Failed to calculate block body root")
fmt.Printf("Slot: %d\n", block.Slot)
fmt.Printf("Epoch: %d\n", block.Slot/slotsPerEpoch)
fmt.Printf("Block root: %#x\n", bodyRoot)
outputIf(verbose, fmt.Sprintf("Parent root: %#x", block.ParentRoot))
outputIf(verbose, fmt.Sprintf("State root: %#x", block.StateRoot))
@@ -105,15 +111,30 @@ func outputBlock(signedBlock *ethpb.SignedBeaconBlock) {
outputIf(verbose, fmt.Sprintf("Ethereum 1 deposit root: %#x", eth1Data.DepositRoot))
outputIf(verbose, fmt.Sprintf("Ethereum 1 block hash: %#x", eth1Data.BlockHash))
validatorCommittees := make(map[uint64][][]uint64)
// Attestations.
fmt.Printf("Attestations: %d\n", len(body.Attestations))
if verbose {
for i, att := range body.Attestations {
fmt.Printf("\t%d:\n", i)
// Fetch committees for this epoch if not already obtained.
committees, exists := validatorCommittees[att.Data.Slot]
if !exists {
attestationEpoch := att.Data.Slot / slotsPerEpoch
epochCommittees, err := grpc.FetchValidatorCommittees(eth2GRPCConn, attestationEpoch)
errCheck(err, "Failed to obtain committees")
for k, v := range epochCommittees {
validatorCommittees[k] = v
}
committees = validatorCommittees[att.Data.Slot]
}
fmt.Printf("\t\tCommittee index: %d\n", att.Data.CommitteeIndex)
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\tAttesting indices: %s\n", attestingIndices(att.AggregationBits, committees[att.Data.CommitteeIndex]))
fmt.Printf("\t\tSlot: %d\n", att.Data.Slot)
fmt.Printf("\t\tBeacon block root: %#x\n", att.Data.BeaconBlockRoot)
fmt.Printf("\t\tSource epoch: %d\n", att.Data.Source.Epoch)
@@ -157,18 +178,17 @@ func outputBlock(signedBlock *ethpb.SignedBeaconBlock) {
fmt.Printf("\t\t\tAttestation 1 beacon block root: %#x\n", att1.Data.BeaconBlockRoot)
fmt.Printf("\t\t\tAttestation 2 beacon block root: %#x\n", att2.Data.BeaconBlockRoot)
}
} else {
if att1.Data.Source.Epoch < att2.Data.Source.Epoch &&
att1.Data.Target.Epoch > att2.Data.Target.Epoch {
fmt.Printf("\t\tSurround voted:\n")
fmt.Printf("\t\t\tAttestation 1 vote: %d->%d\n", att1.Data.Source.Epoch, att1.Data.Target.Epoch)
fmt.Printf("\t\t\tAttestation 2 vote: %d->%d\n", att2.Data.Source.Epoch, att2.Data.Target.Epoch)
}
} else if att1.Data.Source.Epoch < att2.Data.Source.Epoch &&
att1.Data.Target.Epoch > att2.Data.Target.Epoch {
fmt.Printf("\t\tSurround voted:\n")
fmt.Printf("\t\t\tAttestation 1 vote: %d->%d\n", att1.Data.Source.Epoch, att1.Data.Target.Epoch)
fmt.Printf("\t\t\tAttestation 2 vote: %d->%d\n", att2.Data.Source.Epoch, att2.Data.Target.Epoch)
}
}
}
// TODO Proposer slashings once proposer slashings exist.
fmt.Printf("Proposer slashings: %d\n", len(body.ProposerSlashings))
// TODO verbose proposer slashings.
// Deposits.
fmt.Printf("Deposits: %d\n", len(body.Deposits))
@@ -237,6 +257,17 @@ func bitsToString(input bitfield.Bitlist) string {
return strings.TrimSpace(res)
}
func attestingIndices(input bitfield.Bitlist, indices []uint64) string {
bits := int(input.Len())
res := ""
for i := 0; i < bits; i++ {
if input.BitAt(uint64(i)) {
res = fmt.Sprintf("%s%d ", res, indices[i])
}
}
return strings.TrimSpace(res)
}
func init() {
blockCmd.AddCommand(blockInfoCmd)
blockFlags(blockInfoCmd)

View File

@@ -70,12 +70,12 @@ In quiet mode this will return 0 if the chain status can be obtained, otherwise
slotsPerEpoch := config["SlotsPerEpoch"].(uint64)
epoch := slot / slotsPerEpoch
fmt.Printf("Current epoch: %d\n", epoch)
fmt.Printf("Justified epoch: %d\n", info.GetJustifiedSlot()/slotsPerEpoch)
fmt.Printf("Justified epoch: %d\n", info.GetJustifiedEpoch())
if verbose {
distance := (slot - info.GetJustifiedSlot()) / slotsPerEpoch
fmt.Printf("Justified epoch distance %d\n", distance)
fmt.Printf("Justified epoch distance: %d\n", distance)
}
fmt.Printf("Finalized epoch: %d\n", info.GetFinalizedSlot()/slotsPerEpoch)
fmt.Printf("Finalized epoch: %d\n", info.GetFinalizedEpoch())
if verbose {
distance := (slot - info.GetFinalizedSlot()) / slotsPerEpoch
fmt.Printf("Finalized epoch distance: %d\n", distance)

32
cmd/deposit.go Normal file
View File

@@ -0,0 +1,32 @@
// Copyright © 2019 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd
import (
"github.com/spf13/cobra"
)
// depositCmd represents the deposit command
var depositCmd = &cobra.Command{
Use: "deposit",
Short: "Manage Ethereum 2 deposits",
Long: `Manage Ethereum 2 deposits.`,
}
func init() {
RootCmd.AddCommand(depositCmd)
}
func depositFlags(cmd *cobra.Command) {
}

235
cmd/depositverify.go Normal file
View File

@@ -0,0 +1,235 @@
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd
import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
e2types "github.com/wealdtech/go-eth2-types/v2"
util "github.com/wealdtech/go-eth2-util"
string2eth "github.com/wealdtech/go-string2eth"
)
type depositData struct {
Name string `json:"name,omitempty"`
Account string `json:"account,omitempty"`
PublicKey string `json:"pubkey"`
WithdrawalCredentials string `json:"withdrawal_credentials"`
Signature string `json:"signature"`
DepositDataRoot string `json:"deposit_data_root"`
Value uint64 `json:"value"`
Version uint64 `json:"version"`
}
var depositVerifyData string
var depositVerifyWithdrawalPubKey string
var depositVerifyValidatorPubKey string
var depositVerifyDepositValue string
var depositVerifyCmd = &cobra.Command{
Use: "verify",
Short: "Verify deposit data matches requirements",
Long: `Verify deposit data matches requirements. For example:
ethdo deposit verify --data=depositdata.json --withdrawalaccount=primary/current --value="32 Ether"
The information generated can be passed to ethereal to create a deposit from the Ethereum 1 chain.
In quiet mode this will return 0 if the the data can be generated correctly, otherwise 1.`,
Run: func(cmd *cobra.Command, args []string) {
assert(depositVerifyData != "", "--data is required")
deposits, err := depositDataFromJSON(depositVerifyData)
errCheck(err, "Failed to fetch deposit data")
withdrawalCredentials := ""
if depositVerifyWithdrawalPubKey != "" {
withdrawalPubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(depositVerifyWithdrawalPubKey, "0x"))
errCheck(err, "Invalid withdrawal public key")
assert(len(withdrawalPubKeyBytes) == 48, "Public key should be 48 bytes")
withdrawalPubKey, err := e2types.BLSPublicKeyFromBytes(withdrawalPubKeyBytes)
errCheck(err, "Value supplied with --withdrawalpubkey is not a valid public key")
withdrawalBytes := util.SHA256(withdrawalPubKey.Marshal())
withdrawalBytes[0] = 0 // BLS_WITHDRAWAL_PREFIX
withdrawalCredentials = fmt.Sprintf("%x", withdrawalBytes)
}
outputIf(debug, fmt.Sprintf("Withdrawal credentials are %s", withdrawalCredentials))
depositValue := uint64(0)
if depositVerifyDepositValue != "" {
depositValue, err = string2eth.StringToGWei(depositVerifyDepositValue)
errCheck(err, "Invalid value")
// This is hard-coded, to allow deposit data to be generated without a connection to the beacon node.
assert(depositValue >= 1000000000, "deposit value must be at least 1 Ether") // MIN_DEPOSIT_AMOUNT
}
validatorPubKeys := make(map[string]bool)
if depositVerifyValidatorPubKey != "" {
validatorPubKeys, err = validatorPubKeysFromInput(depositVerifyValidatorPubKey)
errCheck(err, "Failed to obtain validator public key(s))")
}
failures := false
for i, deposit := range deposits {
if withdrawalCredentials != "" {
if deposit.WithdrawalCredentials != withdrawalCredentials {
outputIf(!quiet, fmt.Sprintf("Invalid withdrawal credentials for deposit %d", i))
failures = true
}
}
if depositValue != 0 {
if deposit.Value != depositValue {
outputIf(!quiet, fmt.Sprintf("Invalid deposit value for deposit %d", i))
failures = true
}
}
if len(validatorPubKeys) != 0 {
if _, exists := validatorPubKeys[deposit.PublicKey]; !exists {
outputIf(!quiet, fmt.Sprintf("Unknown validator public key for deposit %d", i))
failures = true
}
}
outputIf(!quiet, fmt.Sprintf("Deposit for %q verified", deposit.Name))
}
if failures {
os.Exit(_exitFailure)
}
os.Exit(_exitSuccess)
},
}
func validatorPubKeysFromInput(input string) (map[string]bool, error) {
pubKeys := make(map[string]bool)
var err error
var data []byte
// Input could be a public key or a path to public keys.
if strings.HasPrefix(input, "0x") {
// Looks like a public key.
pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(input, "0x"))
if err != nil {
return nil, errors.Wrap(err, "public key is not a hex string")
}
if len(pubKeyBytes) != 48 {
return nil, errors.New("public key should be 48 bytes")
}
pubKey, err := e2types.BLSPublicKeyFromBytes(pubKeyBytes)
if err != nil {
return nil, errors.Wrap(err, "invalid public key")
}
pubKeys[fmt.Sprintf("%x", pubKey.Marshal())] = true
} else {
// Assume it's a path to a file of public keys.
data, err = ioutil.ReadFile(input)
if err != nil {
return nil, errors.Wrap(err, "failed to find public key file")
}
lines := bytes.Split(bytes.Replace(data, []byte("\r\n"), []byte("\n"), -1), []byte("\n"))
if len(lines) == 0 {
return nil, errors.New("file has no public keys")
}
for _, line := range lines {
if len(line) == 0 {
continue
}
pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(string(line), "0x"))
if err != nil {
return nil, errors.Wrap(err, "public key is not a hex string")
}
if len(pubKeyBytes) != 48 {
return nil, errors.New("public key should be 48 bytes")
}
pubKey, err := e2types.BLSPublicKeyFromBytes(pubKeyBytes)
if err != nil {
return nil, errors.Wrap(err, "invalid public key")
}
pubKeys[fmt.Sprintf("%x", pubKey.Marshal())] = true
}
}
return pubKeys, nil
}
func depositDataFromJSON(input string) ([]*depositData, error) {
var err error
var data []byte
// Input could be JSON or a path to JSON
switch {
case strings.HasPrefix(input, "{"):
// Looks like JSON
data = []byte("[" + input + "]")
case strings.HasPrefix(input, "["):
// Looks like JSON array
data = []byte(input)
default:
// Assume it's a path to JSON
data, err = ioutil.ReadFile(input)
if err != nil {
return nil, errors.Wrap(err, "failed to find deposit data file")
}
if data[0] == '{' {
data = []byte("[" + string(data) + "]")
}
}
var depositData []*depositData
err = json.Unmarshal(data, &depositData)
if err != nil {
return nil, errors.Wrap(err, "data is not valid JSON")
}
if len(depositData) == 0 {
return nil, errors.New("no deposits supplied")
}
minVersion := depositData[0].Version
maxVersion := depositData[0].Version
for i := range depositData {
if depositData[i].PublicKey == "" {
return nil, fmt.Errorf("no public key for deposit %d", i)
}
if depositData[i].DepositDataRoot == "" {
return nil, fmt.Errorf("no data root for deposit %d", i)
}
if depositData[i].Signature == "" {
return nil, fmt.Errorf("no signature for deposit %d", i)
}
if depositData[i].WithdrawalCredentials == "" {
return nil, fmt.Errorf("no withdrawal credentials for deposit %d", i)
}
if depositData[i].Value < 1000000000 {
return nil, fmt.Errorf("Deposit amount too small for deposit %d", i)
}
if depositData[i].Version > maxVersion {
maxVersion = depositData[i].Version
}
if depositData[i].Version < minVersion {
minVersion = depositData[i].Version
}
}
return depositData, nil
}
func init() {
depositCmd.AddCommand(depositVerifyCmd)
depositFlags(depositVerifyCmd)
depositVerifyCmd.Flags().StringVar(&depositVerifyData, "data", "", "JSON data, or path to JSON data")
depositVerifyCmd.Flags().StringVar(&depositVerifyWithdrawalPubKey, "withdrawalpubkey", "", "Public key of the account to which the validator funds will be withdrawn")
depositVerifyCmd.Flags().StringVar(&depositVerifyDepositValue, "depositvalue", "", "Value of the amount to be deposited")
depositVerifyCmd.Flags().StringVar(&depositVerifyValidatorPubKey, "validatorpubkey", "", "Public key(s) of the account(s) that will be carrying out validation")
}

39
cmd/passphrases.go Normal file
View File

@@ -0,0 +1,39 @@
// Copyright © 2019 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd
import "github.com/spf13/viper"
// getStorePassphrases() fetches the store passphrase supplied by the user.
func getStorePassphrase() string {
return viper.GetString("store-passphrase")
}
// getWalletPassphrases() fetches the wallet passphrase supplied by the user.
func getWalletPassphrase() string {
return viper.GetString("wallet-passphrase")
}
// getPassphrases() fetches the passphrases supplied by the user.
func getPassphrases() []string {
return viper.GetStringSlice("passphrase")
}
// getPassphrase fetches the passphrase supplied by the user.
func getPassphrase() string {
passphrases := getPassphrases()
assert(len(passphrases) != 0, "passphrase is required")
assert(len(passphrases) == 1, "multiple passphrases supplied; cannot continue")
return passphrases[0]
}

View File

@@ -31,13 +31,12 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/viper"
e2types "github.com/wealdtech/go-eth2-types/v2"
e2wallet "github.com/wealdtech/go-eth2-wallet"
filesystem "github.com/wealdtech/go-eth2-wallet-store-filesystem"
s3 "github.com/wealdtech/go-eth2-wallet-store-s3"
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
wallet "github.com/wealdtech/go-eth2-wallet"
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
)
var cfgFile string
@@ -49,9 +48,6 @@ var debug bool
var rootStore string
var rootAccount string
var rootBaseDir string
var rootStorePassphrase string
var rootWalletPassphrase string
var rootAccountPassphrase string
// Store for wallet actions.
var store wtypes.Store
@@ -93,9 +89,6 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
rootStore = viper.GetString("store")
rootAccount = viper.GetString("account")
rootBaseDir = viper.GetString("basedir")
rootStorePassphrase = viper.GetString("storepassphrase")
rootWalletPassphrase = viper.GetString("walletpassphrase")
rootAccountPassphrase = viper.GetString("passphrase")
if quiet && verbose {
fmt.Println("Cannot supply both quiet and verbose flags")
@@ -110,12 +103,12 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
case "s3":
assert(rootBaseDir == "", "--basedir does not apply for the s3 store")
var err error
store, err = s3.New(s3.WithPassphrase([]byte(rootStorePassphrase)))
store, err = s3.New(s3.WithPassphrase([]byte(getStorePassphrase())))
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 getStorePassphrase() != "" {
opts = append(opts, filesystem.WithPassphrase([]byte(getStorePassphrase())))
}
if rootBaseDir != "" {
opts = append(opts, filesystem.WithLocation(rootBaseDir))
@@ -124,7 +117,7 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
default:
die(fmt.Sprintf("Unsupported wallet store %s", rootStore))
}
err := wallet.UseStore(store)
err := e2wallet.UseStore(store)
errCheck(err, "Failed to use defined wallet store")
} else {
err := initRemote()
@@ -164,18 +157,18 @@ func init() {
panic(err)
}
RootCmd.PersistentFlags().String("basedir", "", "Base directory for filesystem wallets")
if err := viper.BindPFlag("basedir", RootCmd.PersistentFlags().Lookup("basedir")); err != nil {
if err := viper.BindPFlag("base-dir", 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 {
if err := viper.BindPFlag("store-passphrase", RootCmd.PersistentFlags().Lookup("storepassphrase")); err != nil {
panic(err)
}
RootCmd.PersistentFlags().String("walletpassphrase", "", "Passphrase for wallet (if applicable)")
if err := viper.BindPFlag("walletpassphrase", RootCmd.PersistentFlags().Lookup("walletpassphrase")); err != nil {
if err := viper.BindPFlag("wallet-passphrase", RootCmd.PersistentFlags().Lookup("walletpassphrase")); err != nil {
panic(err)
}
RootCmd.PersistentFlags().String("passphrase", "", "Passphrase for account (if applicable)")
RootCmd.PersistentFlags().StringSlice("passphrase", nil, "Passphrase for account (if applicable)")
if err := viper.BindPFlag("passphrase", RootCmd.PersistentFlags().Lookup("passphrase")); err != nil {
panic(err)
}
@@ -252,37 +245,20 @@ func outputIf(condition bool, msg string) {
}
}
// walletAndAccountNamesFromPath breaks a path in to wallet and account names.
func walletAndAccountNamesFromPath(path string) (string, string, error) {
if len(path) == 0 {
return "", "", errors.New("invalid account format")
}
index := strings.Index(path, "/")
if index == -1 {
// Just the wallet
return path, "", nil
}
if index == len(path)-1 {
// Trailing /
return path[:index], "", nil
}
return path[:index], path[index+1:], nil
}
// walletFromPath obtains a wallet given a path specification.
func walletFromPath(path string) (wtypes.Wallet, error) {
walletName, _, err := walletAndAccountNamesFromPath(path)
walletName, _, err := e2wallet.WalletAndAccountNames(path)
if err != nil {
return nil, err
}
w, err := wallet.OpenWallet(walletName)
wallet, err := e2wallet.OpenWallet(walletName)
if err != nil {
if strings.Contains(err.Error(), "failed to decrypt wallet") {
return nil, errors.New("Incorrect store passphrase")
}
return nil, err
}
return w, nil
return wallet, nil
}
// accountFromPath obtains an account given a path specification.
@@ -291,7 +267,7 @@ func accountFromPath(path string) (wtypes.Account, error) {
if err != nil {
return nil, err
}
_, accountName, err := walletAndAccountNamesFromPath(path)
_, accountName, err := e2wallet.WalletAndAccountNames(path)
if err != nil {
return nil, err
}
@@ -300,8 +276,8 @@ func accountFromPath(path string) (wtypes.Account, error) {
}
if wallet.Type() == "hierarchical deterministic" && strings.HasPrefix(accountName, "m/") {
assert(rootWalletPassphrase != "", "--walletpassphrase is required for direct path derivations")
err = wallet.Unlock([]byte(rootWalletPassphrase))
assert(getWalletPassphrase() != "", "--walletpassphrase is required for direct path derivations")
err = wallet.Unlock([]byte(viper.GetString("wallet-passphrase")))
if err != nil {
return nil, errors.New("invalid wallet passphrase")
}
@@ -325,7 +301,7 @@ func accountsFromPath(path string) ([]wtypes.Account, error) {
if err != nil {
return nil, err
}
_, accountSpec, err := walletAndAccountNamesFromPath(path)
_, accountSpec, err := e2wallet.WalletAndAccountNames(path)
if err != nil {
return nil, err
}

View File

@@ -74,7 +74,7 @@ In quiet mode this will return 0 if the data can be signed, otherwise 1.`,
} else {
account, err := accountFromPath(rootAccount)
errCheck(err, "Failed to access account for signing")
err = account.Unlock([]byte(rootAccountPassphrase))
err = account.Unlock([]byte(getPassphrase()))
errCheck(err, "Failed to unlock account for signing")
var fixedSizeData [32]byte
copy(fixedSizeData[:], data)

View File

@@ -112,7 +112,10 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
err := connect()
errCheck(err, "Failed to connect to beacon node")
config, err := grpc.FetchChainConfig(eth2GRPCConn)
errCheck(err, "Failed to obtain chain configuration")
if err != nil {
outputIf(!quiet, "Could not connect to beacon node; supply a connection with --connection or provide a fork version with --forkversion to generate a deposit")
os.Exit(_exitFailure)
}
genesisForkVersion, exists := config["GenesisForkVersion"]
assert(exists, "Failed to obtain genesis fork version")
forkVersion = genesisForkVersion.([]byte)
@@ -121,8 +124,15 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
domain := e2types.Domain(e2types.DomainDeposit, forkVersion, e2types.ZeroGenesisValidatorsRoot)
outputIf(debug, fmt.Sprintf("Domain is %x", domain))
err = validatorAccount.Unlock([]byte(rootAccountPassphrase))
errCheck(err, "Failed to unlock validator account")
unlocked := false
for _, passphrase := range getPassphrases() {
err = validatorAccount.Unlock([]byte(passphrase))
if err == nil {
unlocked = true
break
}
}
assert(unlocked, "Failed to unlock validator account")
signature, err := signStruct(validatorAccount, depositData, domain)
validatorAccount.Lock()
errCheck(err, "Failed to generate deposit data signature")
@@ -167,7 +177,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","version":1}`, 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":2}`, fmt.Sprintf("%s/%s", validatorWallet.Name(), validatorAccount.Name()), signedDepositData.PubKey, signedDepositData.WithdrawalCredentials, signedDepositData.Signature, val, depositDataRoot))
}
}

View File

@@ -94,7 +94,11 @@ func validatorExitHandleAccountInput(account e2wtypes.Account) (*ethpb.Voluntary
// 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)
secondsPerSlot, ok := config["SecondsPerSlot"].(uint64)
assert(ok, "Failed to obtain seconds per slot from chain")
slotsPerEpoch, ok := config["SlotsPerEpoch"].(uint64)
assert(ok, "Failed to obtain slots per epoch from chain")
secondsPerEpoch := secondsPerSlot * slotsPerEpoch
// Fetch the validator's index.
index, err := grpc.FetchValidatorIndex(eth2GRPCConn, account)
@@ -113,7 +117,9 @@ func validatorExitHandleAccountInput(account e2wtypes.Account) (*ethpb.Voluntary
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)
shardCommitteePeriod, ok := config["ShardCommitteePeriod"].(uint64)
assert(ok, "Failed to obtain shard committee period from chain")
earliestExitEpoch := validator.ActivationEpoch + shardCommitteePeriod
genesisTime, err := grpc.FetchGenesisTime(eth2GRPCConn)
errCheck(err, "Failed to obtain genesis time")
@@ -135,8 +141,15 @@ func validatorExitHandleAccountInput(account e2wtypes.Account) (*ethpb.Voluntary
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")
unlocked := false
for _, passphrase := range getPassphrases() {
err = account.Unlock([]byte(passphrase))
if err == nil {
unlocked = true
break
}
}
assert(unlocked, "Failed to unlock account; please confirm passphrase is correct")
signature, err := signStruct(account, exit, domain)
errCheck(err, "Failed to sign exit proposal")

View File

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

View File

@@ -45,8 +45,8 @@ In quiet mode this will return 0 if the wallet is created successfully, otherwis
assert(walletCreateSeed == "", "--seed is not allowed with non-deterministic wallets")
err = walletCreateND(walletWallet)
case "hierarchical deterministic", "hd":
assert(rootWalletPassphrase != "", "--walletpassphrase is required for hierarchical deterministic wallets")
err = walletCreateHD(walletWallet, rootWalletPassphrase, walletCreateSeed)
assert(getWalletPassphrase() != "", "--walletpassphrase is required for hierarchical deterministic wallets")
err = walletCreateHD(walletWallet, getWalletPassphrase(), walletCreateSeed)
default:
die("unknown wallet type")
}

View File

@@ -14,18 +14,22 @@
package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/google/uuid"
"github.com/spf13/cobra"
"github.com/wealdtech/go-bytesutil"
wallet "github.com/wealdtech/go-eth2-wallet"
"github.com/wealdtech/go-ecodec"
e2wallet "github.com/wealdtech/go-eth2-wallet"
)
var walletImportData string
var walletImportPassphrase string
var walletImportVerify bool
var walletImportCmd = &cobra.Command{
Use: "import",
@@ -52,8 +56,42 @@ In quiet mode this will return 0 if the wallet is imported successfully, otherwi
importData, err := bytesutil.FromHexString(walletImportData)
errCheck(err, "Failed to decode wallet data")
_, err = wallet.ImportWallet(importData, []byte(walletImportPassphrase))
errCheck(err, "Failed to import wallet")
if walletImportVerify {
type accountInfo struct {
Name string `json:"name"`
}
type walletInfo struct {
ID uuid.UUID `json:"uuid"`
Name string `json:"name"`
Type string `json:"type"`
}
type export struct {
Wallet *walletInfo `json:"wallet"`
Accounts []*accountInfo `json:"accounts"`
}
data, err := ecodec.Decrypt(importData, []byte(walletImportPassphrase))
errCheck(err, "Failed to decrypt wallet")
ext := &export{}
err = json.Unmarshal(data, ext)
errCheck(err, "Failed to read wallet")
outputIf(!quiet, fmt.Sprintf("Wallet name: %s", ext.Wallet.Name))
outputIf(!quiet, fmt.Sprintf("Wallet type: %s", ext.Wallet.Type))
outputIf(verbose, fmt.Sprintf("Wallet UUID: %s", ext.Wallet.ID))
if verbose {
fmt.Printf("Wallet accounts:\n")
for _, account := range ext.Accounts {
outputIf(verbose, fmt.Sprintf(" %s", account.Name))
}
} else {
outputIf(!quiet, fmt.Sprintf("Wallet accounts: %d", len(ext.Accounts)))
}
} else {
_, err = e2wallet.ImportWallet(importData, []byte(walletImportPassphrase))
errCheck(err, "Failed to import wallet")
}
os.Exit(_exitSuccess)
},
@@ -64,4 +102,5 @@ func init() {
walletFlags(walletImportCmd)
walletImportCmd.Flags().StringVar(&walletImportData, "importdata", "", "The data to import, or the name of a file to read")
walletImportCmd.Flags().StringVar(&walletImportPassphrase, "importpassphrase", "", "Passphrase protecting the data to import")
walletImportCmd.Flags().BoolVar(&walletImportVerify, "verify", false, "Verify the wallet can be imported, but do not import it")
}

View File

@@ -18,7 +18,7 @@ import (
"os"
"github.com/spf13/cobra"
wallet "github.com/wealdtech/go-eth2-wallet"
e2wallet "github.com/wealdtech/go-eth2-wallet"
)
var walletListCmd = &cobra.Command{
@@ -36,7 +36,7 @@ In quiet mode this will return 0 if any wallets are found, otherwise 1.`,
if remote {
die("Remote wallets cannot be listed")
} else {
for w := range wallet.Wallets() {
for w := range e2wallet.Wallets() {
walletsFound = true
outputIf(!quiet && !verbose, w.Name())
outputIf(verbose, fmt.Sprintf("%s\n\tUUID:\t\t%s", w.Name(), w.ID().String()))

View File

@@ -34,14 +34,14 @@ In quiet mode this will return 0 if the wallet is a hierarchical deterministic w
Run: func(cmd *cobra.Command, args []string) {
assert(!remote, "wallet seed not available with remote wallets")
assert(walletWallet != "", "--wallet is required")
assert(rootWalletPassphrase != "", "--walletpassphrase is required")
assert(getWalletPassphrase() != "", "--walletpassphrase is required")
wallet, err := walletFromPath(walletWallet)
errCheck(err, "Failed to access wallet")
_, ok := wallet.(types.WalletKeyProvider)
assert(ok, fmt.Sprintf("wallets of type %q do not have a seed", wallet.Type()))
err = wallet.Unlock([]byte(rootWalletPassphrase))
err = wallet.Unlock([]byte(getWalletPassphrase()))
errCheck(err, "Failed to unlock wallet")
seed, err := wallet.(types.WalletKeyProvider).Key()
errCheck(err, "Failed to obtain wallet key")

View File

@@ -13,3 +13,21 @@ sudo apt install build-essential libstdc++6
and then try to install `ethdo` again.
## ethdo not found after installing
This is usually due to an incorrectly set path. Go installs its binaries (such as `ethdo`) in a particular location. The defaults are:
- Linux, Mac: `$HOME/go/bin`
- Windows: `%USERPROFILE%\go\bin`
You must add these paths to be able to access `ethdo`. To add the path on linux or OSX type:
```sh
export PATH=$PATH:$(go env GOPATH)/bin
```
and on Windows type:
```sh
setx /M path "%PATH%;%USERPROFILE%\go\bin"
```

View File

@@ -69,6 +69,7 @@ $ ethdo wallet export --wallet="Personal wallet" --exportpassphrase="my export s
`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
- `verify`: confirm information about the wallet import without importing it
```sh
$ ethdo wallet import --importdata="0x01c7a27ad40d45b4ae5be5f..." --importpassphrase="my export secret"

35
go.mod
View File

@@ -4,40 +4,41 @@ go 1.13
require (
github.com/OneOfOne/xxhash v1.2.5 // indirect
github.com/ferranbt/fastssz v0.0.0-20200514094935-99fccaf93472 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gogo/protobuf v1.3.1
github.com/google/uuid v1.1.1
github.com/grpc-ecosystem/grpc-gateway v1.14.6 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/mitchellh/mapstructure v1.3.1 // indirect
github.com/mitchellh/mapstructure v1.3.2 // indirect
github.com/pelletier/go-toml v1.8.0 // indirect
github.com/pkg/errors v0.9.1
github.com/prysmaticlabs/ethereumapis v0.0.0-20200528232825-cf963636d24e
github.com/prysmaticlabs/go-bitfield v0.0.0-20200322041314-62c2aee71669
github.com/prysmaticlabs/go-ssz v0.0.0-20200101200214-e24db4d9e963
github.com/prysmaticlabs/ethereumapis v0.0.0-20200619200018-174e3b90d786
github.com/prysmaticlabs/go-bitfield v0.0.0-20200618145306-2ae0807bef65
github.com/prysmaticlabs/go-ssz v0.0.0-20200612203617-6d5c9aa213ae
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/afero v1.3.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
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.7.0
github.com/tyler-smith/go-bip39 v1.0.2
github.com/wealdtech/eth2-signer-api v1.3.0
github.com/wealdtech/eth2-signer-api v1.4.0
github.com/wealdtech/go-bytesutil v1.1.1
github.com/wealdtech/go-eth2-types/v2 v2.4.0
github.com/wealdtech/go-eth2-util v1.2.0
github.com/wealdtech/go-eth2-wallet v1.10.0
github.com/wealdtech/go-ecodec v1.1.0
github.com/wealdtech/go-eth2-types/v2 v2.4.2
github.com/wealdtech/go-eth2-util v1.2.2
github.com/wealdtech/go-eth2-wallet v1.10.2
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.0.0
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.0
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.1.0
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.15.0
github.com/wealdtech/go-eth2-wallet-store-s3 v1.7.0
github.com/wealdtech/go-eth2-wallet-types/v2 v2.1.0
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.3
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.1.2
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.15.2
github.com/wealdtech/go-eth2-wallet-store-s3 v1.7.2
github.com/wealdtech/go-eth2-wallet-types/v2 v2.2.0
github.com/wealdtech/go-string2eth v1.1.0
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b // indirect
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect
golang.org/x/text v0.3.3 // indirect
google.golang.org/genproto v0.0.0-20200620020550-bd6e04640131 // indirect
google.golang.org/grpc v1.29.1
gopkg.in/ini.v1 v1.57.0 // indirect
)

163
go.sum
View File

@@ -26,12 +26,10 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
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/aws/aws-sdk-go v1.31.7 h1:TCA+pXKvzDMA3vVqhK21cCy5GarC8pTQb/DrVOWI3iY=
github.com/aws/aws-sdk-go v1.31.7/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.32.6 h1:HoswAabUWgnrUF7X/9dr4WRgrr8DyscxXvTDm7Qw/5c=
github.com/aws/aws-sdk-go v1.32.6/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=
@@ -64,8 +62,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
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/ferranbt/fastssz v0.0.0-20200514094935-99fccaf93472 h1:maoKvILdMk6CSWHanFcUdxXIZGKD9YpWIaVbUQ/4kfg=
github.com/ferranbt/fastssz v0.0.0-20200514094935-99fccaf93472/go.mod h1:LlFXPmgrgVYsuoFDwV8rDJ9tvt1pLQdjKvU1b5IRES0=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
@@ -101,8 +97,6 @@ github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
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=
github.com/golang/protobuf v1.4.0-rc.4 h1:+EOh4OY6tjM6ZueeUKinl1f0U2820HzQOuf1iqMnsks=
github.com/golang/protobuf v1.4.0-rc.4/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
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=
@@ -136,10 +130,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg
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.12.2/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
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/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o=
github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
@@ -163,12 +154,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
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/herumi/bls-eth-go-binary v0.0.0-20200522010937-01d282b5380b h1:mu+F5uA3Y68oB6KXZqWlASKMetbNufhQx2stMI+sD+Y=
github.com/herumi/bls-eth-go-binary v0.0.0-20200522010937-01d282b5380b/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20200618063237-4d3c66ab099d h1:ZLYUT27mOTH+ogU6Sov6xs1zqYi9cRJ6ksBEELXC8R4=
github.com/herumi/bls-eth-go-binary v0.0.0-20200618063237-4d3c66ab099d/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/herumi/bls-eth-go-binary v0.0.0-20200621110855-298ffb6847bc h1:1ANh6XSZu8Quo4d03TDFhqiFjgUicMdavTtPm6B+RfE=
github.com/herumi/bls-eth-go-binary v0.0.0-20200621110855-298ffb6847bc/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=
@@ -183,6 +172,7 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
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/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -210,18 +200,14 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
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.3.0 h1:iDwIio/3gk2QtLLEsqU5lInaMzos0hDTz8a6lazSFVw=
github.com/mitchellh/mapstructure v1.3.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.3.1 h1:cCBH2gTD2K0OtLlv/Y5H01VQCqmlDxz30kS5Y5bqfLA=
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
github.com/mitchellh/mapstructure v1.3.2/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=
github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -229,6 +215,7 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
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=
@@ -245,15 +232,21 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
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-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/ethereumapis v0.0.0-20200528232825-cf963636d24e h1:AvUpoH1sezZmue9NKyHxk7HpD6ajzLVh9m6YCyFwgSw=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200528232825-cf963636d24e/go.mod h1:UQrDJAnxOPXPxvzECD1fmiKAw84LIYcoX2Op7KEUfGk=
github.com/protolambda/zssz v0.1.5 h1:7fjJjissZIIaa2QcvmhS/pZISMX21zVITt49sW1ouek=
github.com/protolambda/zssz v0.1.5/go.mod h1:a4iwOX5FE7/JkKA+J/PH0Mjo9oXftN6P8NZyL28gpag=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200619200018-174e3b90d786 h1:bJiOTV2sYykacsxViyRltztQY0DyjT/uFoVRZkEaxsY=
github.com/prysmaticlabs/ethereumapis v0.0.0-20200619200018-174e3b90d786/go.mod h1:rs05kpTfWKl0KflsBWzBQFstoyPFMTWQTbxSAyGHe78=
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-bitfield v0.0.0-20200617184054-d57b8c55ea83 h1:HujNkiChDhXhDOlpYtwJu42VFn5Vp1yt+QAEJy03RjU=
github.com/prysmaticlabs/go-bitfield v0.0.0-20200617184054-d57b8c55ea83/go.mod h1:hCwmef+4qXWjv0jLDbQdWnL0Ol7cS7/lCSS26WR+u6s=
github.com/prysmaticlabs/go-bitfield v0.0.0-20200618145306-2ae0807bef65 h1:hJfAWrlxx7SKpn4S/h2JGl2HHwA1a2wSS3HAzzZ0F+U=
github.com/prysmaticlabs/go-bitfield v0.0.0-20200618145306-2ae0807bef65/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/prysmaticlabs/go-ssz v0.0.0-20200612203617-6d5c9aa213ae h1:7qd0Af1ozWKBU3c93YW2RH+/09hJns9+ftqWUZyts9c=
github.com/prysmaticlabs/go-ssz v0.0.0-20200612203617-6d5c9aa213ae/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=
@@ -274,8 +267,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.3.0 h1:Ysnmjh1Di8EaWaBv40CYR4IdaIsBc5996Gh1oZzCBKk=
github.com/spf13/afero v1.3.0/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
@@ -306,52 +299,54 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
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=
github.com/wealdtech/eth2-signer-api v1.4.0 h1:y/Bg2SfTT5nGfwyIz7mILWE+BokeDOUE1eZ0jVqPBeA=
github.com/wealdtech/eth2-signer-api v1.4.0/go.mod h1:5wlLQ7NO7nbXo3znJOwIWHN8S4C3xHcZ0uOg9Ue4mvg=
github.com/wealdtech/go-bytesutil v1.0.1 h1:6xzMM+VEHf5WNh1PsIFcRwScgcno+CP8Rw1rGvT6Cew=
github.com/wealdtech/go-bytesutil v1.0.1/go.mod h1:jENeMqeTEU8FNZyDFRVc7KqBdRKSnJ9CCh26TcuNb9s=
github.com/wealdtech/go-bytesutil v1.1.1 h1:ocEg3Ke2GkZ4vQw5lp46rmO+pfqCCTgq35gqOy8JKVc=
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.1 h1:2KSUzducArOynCL2prRf4vWU5GjwaPSnSN9oqNgf+dQ=
github.com/wealdtech/go-eth2-types/v2 v2.3.1/go.mod h1:FubkGSavaa+rvmHDMTUVoPdFh00wKg0k5QPW6G52mhw=
github.com/wealdtech/go-eth2-types/v2 v2.4.0 h1:1sFuNENHka/BYHY9F6f1gQqE3dCCQxKODEHc+3RK8fI=
github.com/wealdtech/go-eth2-types/v2 v2.4.0/go.mod h1:azyBA/qeMC5sa3BuNm3spje96rHMmW0dyZkJzog8NIk=
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-util v1.2.0 h1:ineLDTrFN8zpb7+R2lWrm1HMmTFxlirtcCsppKoVix0=
github.com/wealdtech/go-eth2-util v1.2.0/go.mod h1:UNDR21GfVCq429DP+RyFVl2iKkHaMI8B8r7F44NECkU=
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 v1.10.0 h1:WX6wZQvGwXtu3+L9d9HCW7WWrw6522ur2XiPI6W1lYg=
github.com/wealdtech/go-eth2-wallet v1.10.0/go.mod h1:vqB02WIpP0SL+Ug8p4Q8BqVkwPyO1SEarOHAqppjqHE=
github.com/wealdtech/go-eth2-types/v2 v2.4.1 h1:8Brj7MvJk3EUkYBQ8A5bWLleIc3/W1Jr1tApzTXtW1A=
github.com/wealdtech/go-eth2-types/v2 v2.4.1/go.mod h1:gqvLvmdw5CaDJUmClvmLRp653Ugf0VlGO9ZoWdi7mLY=
github.com/wealdtech/go-eth2-types/v2 v2.4.2 h1:EkOvP8Ma0Ru7WIh0haoST97rc0PYm2AJpuWG1HzgfCI=
github.com/wealdtech/go-eth2-types/v2 v2.4.2/go.mod h1:hhKa4ZFaNU2fwUjEh8GYr8wKg5D1W4QyxZ3xpsb/2hw=
github.com/wealdtech/go-eth2-util v1.2.1 h1:ReY7XWgTgXf1Fi9MoRLodD1H7rCVMFHMHJKHXoHYNQE=
github.com/wealdtech/go-eth2-util v1.2.1/go.mod h1:PPhVwXc9gv1omyf/Ik4h97jL77HdCEzlEUX4P5wDqQw=
github.com/wealdtech/go-eth2-util v1.2.2 h1:LALunpMSJFvu89RHS1zl6RjZ52805utRvd12RtquB54=
github.com/wealdtech/go-eth2-util v1.2.2/go.mod h1:R3VlTd69B2Jf58s62ChcyXt11ZK1/36CTplTuyR/6dE=
github.com/wealdtech/go-eth2-wallet v1.10.1 h1:Inp0Mk8noUoJIMSBc+W+Si+WhPvs04pcTJrcMuYrNzM=
github.com/wealdtech/go-eth2-wallet v1.10.1/go.mod h1:nB3aarecFrhJLXjKhl+N6jhnbtymb/yAQQ9n1AankR8=
github.com/wealdtech/go-eth2-wallet v1.10.2 h1:oUgi6Ih5fA9thhIipzXMSaLkiwDQXwT8q3bCOLpCr7s=
github.com/wealdtech/go-eth2-wallet v1.10.2/go.mod h1:8H9pgp5K7X1kU1cJMS/B3DrMZF74ZlwBThownrcRYgk=
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.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-hd/v2 v2.1.0 h1:gB3wFIovLgS7GVNU81mpCgekfUmGm8H/f6WtG6xqEJw=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.0/go.mod h1:6voi4JG8G7inZ1bGx41xL2z+YJZc6rr6echT0AUtUdw=
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-nd/v2 v2.1.0 h1:d8JOfWRd39c7w3BLud3eErJH4xSa3tdrMOZjeFXXg0c=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.1.0/go.mod h1:DTnJWJ5/O56pxqXAR53H4t8K80Rrtop5pmTSOc5tCFA=
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-filesystem v1.15.0 h1:iNwHjCj9zGpybEO9URx7AmHWET1PrnkfKcpLYUyFFxw=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.15.0/go.mod h1:qjU0CZ12duEMCTGORb4bjeUncvy5vUSTVOtwI+/A4A8=
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-s3 v1.7.0 h1:aYMCj2WMCLPbXcITrXx22+P5vhfRW0I1Y1NuJxp5XK0=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.7.0/go.mod h1:dT5tX+uTFI16qdt4On7KCmxx96V7xYn+vdUJUzPDdyo=
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-store-scratch v1.4.0/go.mod h1:F+CGazuwGZpxa+2nmr8T1zC3rC0mTTZyO3UFmimNwSs=
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-eth2-wallet-types/v2 v2.1.0 h1:Zl36EPHI/4SYgjnx+mmYRVKLDdrFpWkT39ClRKYiL7U=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.1.0/go.mod h1:6mlZXBwEeyeAKj22OF+b3E0RFnwoOBM/BXIdAo5QG2M=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.1 h1:L4L445Uvd1Uw+Af4I9Bu29e8OCJOhYgN9lKmzjRhNwQ=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.1/go.mod h1:1IC4wOz0SIySMld5tRi4Vb0cpe7tOwqP0hS2LsrGJ34=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.2 h1:Rrpit3nuxKOUKE7poDcs2x9MZOaodd+mact+KL+/S98=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.2/go.mod h1:STigKib4ZSefVvJjx88V2QpUGaoyUE1TiupcpsHpvKE=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.3 h1:JJwCr0NfMnS0xI7gSE+GqENXBxNIfySoC3NtxK8dG1o=
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.1.3/go.mod h1:STigKib4ZSefVvJjx88V2QpUGaoyUE1TiupcpsHpvKE=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.1.1 h1:ziEpwVutiAdP0+LsVsC+nlfhgc4kwQAaUNpPz/rJ+CM=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.1.1/go.mod h1:IEWuITdIQTImjHju0crCJkvGus05n1HmoMZmO+EDil8=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.1.2 h1:j3cKJ02Js83ygvZOmbb+GA2iSCAQDYhY5nNdm7anzjQ=
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.1.2/go.mod h1:IssxoHII0ewO1VysMfCmdJP1D00tRhRhXIhhaEXIOVE=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.15.1 h1:HlJZp6xyJ14nd+IFPV8TvtJyumKe0RbHIG+PKEeqxTk=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.15.1/go.mod h1:C4m7Xv0gCgb7XUwCxxJp+45YX8Qfn1vrE0UOSHD/QfE=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.15.2 h1:Z4Pw7/Mlp6jJLoJnhgov8M1011HP/Pb3YYqcdYGCy6Q=
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.15.2/go.mod h1:GSMbVCewjbxRrw32m6YCd9DOzCRjAXB3qUOQnr58JEs=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.7.1 h1:EFX2SfWQ9zi7lJ/Jy1WsVBHQuTdGp8Z/Q+uuxNFpBQA=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.7.1/go.mod h1:LDmyvkgcaY4rGnGBQwf1uc02m0dMSebm9nRHx7feVHU=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.7.2 h1:a7GWfFd139CODvvkuTbRIuRwAAjb55sFDGRh177KXGk=
github.com/wealdtech/go-eth2-wallet-store-s3 v1.7.2/go.mod h1:VWvXScZKUWHbhQpadLX8Yj+mc8U/i4zGthQJee+o3xg=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.4.1 h1:uw2Kqqfcr7NMBHM0x/JpKkr1XpKr+zeASOXhOV6xobk=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.4.1/go.mod h1:psrxFO0Df0R+2iGD8Wdvb5AAYBY7zx+4/qtULaJ57IY=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.4.2 h1:GvG3ZuzxbqFjGUaGoa8Tz7XbPlDA33G6nHQbSZInC3g=
github.com/wealdtech/go-eth2-wallet-store-scratch v1.4.2/go.mod h1:+TbqLmJuT98PWi/xW1bp5nwZbKz+SIJYVh/+NUkmnb4=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.1.1 h1:RGvhM7C85ptEdVsCDQNt+fJrF0SrMnUb0gkgtU75ifI=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.1.1/go.mod h1:608wNFKrwPzwjWeQVRE/rHnHkrRmmTCUhFg2/Bgkbvs=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.2.0 h1:SfoBlW2LYjW05uHhnTZaezX37gbRsp+VYtxWT6SeAME=
github.com/wealdtech/go-eth2-wallet-types/v2 v2.2.0/go.mod h1:XEvrlKFnHLbg1tj4Dep76XKASeS13TBpvdeXmvLiH+k=
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=
@@ -369,14 +364,13 @@ golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnf
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-20190820162420-60c769a6c586/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-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/crypto v0.0.0-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/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=
@@ -413,10 +407,10 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
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-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJnl/ymnJWAdMuinqL7Y=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b h1:IYiJPiJfzktmDAO1HQiwjMjwjlYKHAL7KzeD544RJPs=
golang.org/x/net v0.0.0-20200528225125-3c3fba18258b/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/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=
@@ -443,16 +437,18 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
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-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/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200620081246-981b61492c35 h1:wb/9mP8eUAmHfkM8RmpeLq6nUA7c2i5+bQOtcDftjaE=
golang.org/x/sys v0.0.0-20200620081246-981b61492c35/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/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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=
@@ -498,12 +494,12 @@ google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBr
google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
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/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200528191852-705c0b31589b h1:nl5tymnV+50ACFZUDAP+xFCe3Zh3SWdMDx+ernZSKNA=
google.golang.org/genproto v0.0.0-20200528191852-705c0b31589b/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200620020550-bd6e04640131 h1:IXNofpkLhv80L3TJQvj2YQLnMHZgAktycswvtXwQiRk=
google.golang.org/genproto v0.0.0-20200620020550-bd6e04640131/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
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=
@@ -515,16 +511,12 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
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.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=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.20.1 h1:ESRXHgpUBG5D2I5mmsQIyYxB/tQIZfSZ8wLyFDf/N/U=
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=
@@ -541,8 +533,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
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.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
@@ -552,10 +542,9 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
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=

View File

@@ -91,6 +91,39 @@ func FetchLatestFilledSlot(conn *grpc.ClientConn) (uint64, error) {
return chainHead.HeadSlot, nil
}
// FetchValidatorCommittees fetches the validator committees for a given epoch.
func FetchValidatorCommittees(conn *grpc.ClientConn, epoch uint64) (map[uint64][][]uint64, 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()
req := &ethpb.ListCommitteesRequest{
QueryFilter: &ethpb.ListCommitteesRequest_Epoch{
Epoch: epoch,
},
}
resp, err := beaconClient.ListBeaconCommittees(ctx, req)
if err != nil {
return nil, errors.Wrap(err, "failed to obtain committees")
}
res := make(map[uint64][][]uint64)
for slot, committees := range resp.Committees {
res[slot] = make([][]uint64, len(resp.Committees))
for i, committee := range committees.Committees {
res[slot][uint64(i)] = make([]uint64, len(committee.ValidatorIndices))
indices := make([]uint64, len(committee.ValidatorIndices))
copy(indices, committee.ValidatorIndices)
res[slot][uint64(i)] = indices
}
}
return res, nil
}
// FetchValidator fetches the validator definition from the beacon node.
func FetchValidator(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.Validator, error) {
if conn == nil {
@@ -125,6 +158,54 @@ func FetchValidatorByIndex(conn *grpc.ClientConn, index uint64) (*ethpb.Validato
return beaconClient.GetValidator(ctx, req)
}
// FetchValidatorBalance fetches the validator balance from the beacon node.
func FetchValidatorBalance(conn *grpc.ClientConn, account wtypes.Account) (uint64, error) {
if conn == nil {
return 0, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
res, err := beaconClient.ListValidatorBalances(ctx, &ethpb.ListValidatorBalancesRequest{
PublicKeys: [][]byte{account.PublicKey().Marshal()},
})
if err != nil {
return 0, err
}
if len(res.Balances) == 0 {
return 0, errors.New("unknown validator")
}
return res.Balances[0].Balance, nil
}
// FetchValidatorPerformance fetches the validator performance from the beacon node.
func FetchValidatorPerformance(conn *grpc.ClientConn, account wtypes.Account) (bool, bool, bool, uint64, int64, error) {
if conn == nil {
return false, false, false, 0, 0, errors.New("no connection to beacon node")
}
beaconClient := ethpb.NewBeaconChainClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
defer cancel()
req := &ethpb.ValidatorPerformanceRequest{
PublicKeys: [][]byte{account.PublicKey().Marshal()},
}
res, err := beaconClient.GetValidatorPerformance(ctx, req)
if err != nil {
return false, false, false, 0, 0, err
}
if len(res.InclusionDistances) == 0 {
return false, false, false, 0, 0, errors.New("unknown validator")
}
return res.CorrectlyVotedHead[0],
res.CorrectlyVotedSource[0],
res.CorrectlyVotedTarget[0],
res.InclusionDistances[0],
int64(res.BalancesAfterEpochTransition[0]) - int64(res.BalancesBeforeEpochTransition[0]),
err
}
// FetchValidatorInfo fetches current validator info from the beacon node.
func FetchValidatorInfo(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.ValidatorInfo, error) {
if conn == nil {