mirror of
https://github.com/wealdtech/ethdo.git
synced 2026-01-07 21:24:01 -05:00
Tidy-ups
This commit is contained in:
@@ -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,10 +14,12 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
@@ -31,31 +33,48 @@ var accountCreateCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the account is created successfully, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "account create not available with remote wallets")
|
||||
assert(rootAccount != "", "--account is required")
|
||||
assert(viper.GetString("account") != "", "--account is required")
|
||||
|
||||
wallet, err := walletFromPath(rootAccount)
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
outputIf(debug, fmt.Sprintf("Opened wallet %q of type %s", wallet.Name(), wallet.Type()))
|
||||
if wallet.Type() == "hierarchical deterministic" {
|
||||
assert(getWalletPassphrase() != "", "--walletpassphrase is required to create new accounts with hierarchical deterministic wallets")
|
||||
assert(getWalletPassphrase() != "", "walletpassphrase is required to create new accounts with hierarchical deterministic wallets")
|
||||
}
|
||||
locker, isLocker := wallet.(e2wtypes.WalletLocker)
|
||||
if isLocker {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
errCheck(locker.Unlock(ctx, []byte(getWalletPassphrase())), "Failed to unlock wallet")
|
||||
}
|
||||
_, err = accountFromPath(rootAccount)
|
||||
assert(err != nil, "Account already exists")
|
||||
|
||||
err = wallet.Unlock([]byte(getWalletPassphrase()))
|
||||
errCheck(err, "Failed to unlock wallet")
|
||||
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(rootAccount)
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
walletAccountCreator, ok := wallet.(e2wtypes.WalletAccountCreator)
|
||||
assert(ok, "wallet does not allow account creation")
|
||||
|
||||
account, err := walletAccountCreator.CreateAccount(accountName, []byte(getPassphrase()))
|
||||
var account e2wtypes.Account
|
||||
if viper.GetUint("participants") > 0 {
|
||||
// Want a distributed account.
|
||||
distributedCreator, isDistributedCreator := wallet.(e2wtypes.WalletDistributedAccountCreator)
|
||||
assert(isDistributedCreator, "Wallet does not support distributed account creation")
|
||||
outputIf(debug, fmt.Sprintf("Distributed account has %d/%d threshold", viper.GetUint32("signing-threshold"), viper.GetUint32("participants")))
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
account, err = distributedCreator.CreateDistributedAccount(ctx, accountName, viper.GetUint32("participants"), viper.GetUint32("signing-threshold"), []byte(getPassphrase()))
|
||||
} else {
|
||||
creator, isCreator := wallet.(e2wtypes.WalletAccountCreator)
|
||||
assert(isCreator, "Wallet does not support account creation")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
account, err = creator.CreateAccount(ctx, accountName, []byte(getPassphrase()))
|
||||
}
|
||||
errCheck(err, "Failed to create account")
|
||||
|
||||
outputIf(verbose, fmt.Sprintf("0x%048x", account.PublicKey().Marshal()))
|
||||
if pubKeyProvider, ok := account.(e2wtypes.AccountCompositePublicKeyProvider); ok {
|
||||
outputIf(verbose, fmt.Sprintf("%#x", pubKeyProvider.CompositePublicKey().Marshal()))
|
||||
} else if pubKeyProvider, ok := account.(e2wtypes.AccountPublicKeyProvider); ok {
|
||||
outputIf(verbose, fmt.Sprintf("%#x", pubKeyProvider.PublicKey().Marshal()))
|
||||
}
|
||||
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
@@ -63,4 +82,12 @@ In quiet mode this will return 0 if the account is created successfully, otherwi
|
||||
func init() {
|
||||
accountCmd.AddCommand(accountCreateCmd)
|
||||
accountFlags(accountCreateCmd)
|
||||
accountCreateCmd.Flags().Uint32("participants", 0, "Number of participants (for distributed accounts)")
|
||||
if err := viper.BindPFlag("participants", accountCreateCmd.Flags().Lookup("participants")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
accountCreateCmd.Flags().Uint32("signing-threshold", 0, "Signing threshold (for distributed accounts)")
|
||||
if err := viper.BindPFlag("signing-threshold", accountCreateCmd.Flags().Lookup("signing-threshold")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/wealdtech/go-bytesutil"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
@@ -35,32 +37,41 @@ var accountImportCmd = &cobra.Command{
|
||||
In quiet mode this will return 0 if the account is imported successfully, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "account import not available with remote wallets")
|
||||
assert(rootAccount != "", "--account is required")
|
||||
assert(viper.GetString("account") != "", "--account is required")
|
||||
passphrase := getPassphrase()
|
||||
assert(accountImportKey != "", "--key is required")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
key, err := bytesutil.FromHexString(accountImportKey)
|
||||
errCheck(err, "Invalid key")
|
||||
|
||||
w, err := walletFromPath(rootAccount)
|
||||
w, err := walletFromPath(viper.GetString("account"))
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
_, ok := w.(e2wtypes.WalletAccountImporter)
|
||||
assert(ok, fmt.Sprintf("wallets of type %q do not allow importing accounts", w.Type()))
|
||||
|
||||
_, err = accountFromPath(rootAccount)
|
||||
_, err = accountFromPath(ctx, viper.GetString("account"))
|
||||
assert(err != nil, "Account already exists")
|
||||
|
||||
err = w.Unlock([]byte(getWalletPassphrase()))
|
||||
errCheck(err, "Failed to unlock wallet")
|
||||
locker, isLocker := w.(e2wtypes.WalletLocker)
|
||||
if isLocker {
|
||||
errCheck(locker.Unlock(ctx, []byte(getWalletPassphrase())), "Failed to unlock wallet")
|
||||
}
|
||||
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(rootAccount)
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
account, err := w.(e2wtypes.WalletAccountImporter).ImportAccount(accountName, key, []byte(passphrase))
|
||||
account, err := w.(e2wtypes.WalletAccountImporter).ImportAccount(ctx, accountName, key, []byte(passphrase))
|
||||
errCheck(err, "Failed to create account")
|
||||
|
||||
outputIf(verbose, fmt.Sprintf("0x%048x", account.PublicKey().Marshal()))
|
||||
pubKey, err := bestPublicKey(account)
|
||||
if err == nil {
|
||||
outputIf(verbose, fmt.Sprintf("%#x", pubKey.Marshal()))
|
||||
}
|
||||
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -19,8 +19,11 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
pb "github.com/wealdtech/eth2-signer-api/pb/v1"
|
||||
"github.com/spf13/viper"
|
||||
e2types "github.com/wealdtech/go-eth2-types/v2"
|
||||
util "github.com/wealdtech/go-eth2-util"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
var accountInfoCmd = &cobra.Command{
|
||||
@@ -32,33 +35,49 @@ var accountInfoCmd = &cobra.Command{
|
||||
|
||||
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")
|
||||
assert(viper.GetString("account") != "", "--account is required")
|
||||
|
||||
var withdrawalCredentials []byte
|
||||
if remote {
|
||||
listerClient := pb.NewListerClient(remoteGRPCConn)
|
||||
listAccountsReq := &pb.ListAccountsRequest{
|
||||
Paths: []string{
|
||||
rootAccount,
|
||||
},
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
assert(isAccountByNameProvider, "wallet cannot obtain accounts by name")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
account, err := accountByNameProvider.AccountByName(ctx, accountName)
|
||||
errCheck(err, "Failed to obtain account")
|
||||
|
||||
// Disallow wildcards (for now)
|
||||
assert(fmt.Sprintf("%s/%s", wallet.Name(), account.Name()) == viper.GetString("account"), "Mismatched account name")
|
||||
|
||||
if quiet {
|
||||
os.Exit(_exitSuccess)
|
||||
}
|
||||
|
||||
outputIf(verbose, fmt.Sprintf("UUID: %v", account.ID()))
|
||||
var withdrawalPubKey e2types.PublicKey
|
||||
if pubKeyProvider, ok := account.(e2wtypes.AccountPublicKeyProvider); ok {
|
||||
fmt.Printf("Public key: %#x\n", pubKeyProvider.PublicKey().Marshal())
|
||||
// May be overwritten later, but grab it for now.
|
||||
withdrawalPubKey = pubKeyProvider.PublicKey()
|
||||
}
|
||||
if distributedAccount, ok := account.(e2wtypes.DistributedAccount); ok {
|
||||
fmt.Printf("Composite public key: %#x\n", distributedAccount.CompositePublicKey().Marshal())
|
||||
fmt.Printf("Signing threshold: %d/%d\n", distributedAccount.SigningThreshold(), len(distributedAccount.Participants()))
|
||||
withdrawalPubKey = distributedAccount.CompositePublicKey()
|
||||
}
|
||||
if verbose {
|
||||
withdrawalCredentials := util.SHA256(withdrawalPubKey.Marshal())
|
||||
withdrawalCredentials[0] = byte(0) // BLS_WITHDRAWAL_PREFIX
|
||||
fmt.Printf("Withdrawal credentials: %#x\n", withdrawalCredentials)
|
||||
}
|
||||
if pathProvider, ok := account.(e2wtypes.AccountPathProvider); ok {
|
||||
if pathProvider.Path() != "" {
|
||||
fmt.Printf("Path: %s\n", pathProvider.Path())
|
||||
}
|
||||
resp, err := listerClient.ListAccounts(context.Background(), listAccountsReq)
|
||||
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: %#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: %#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()))
|
||||
}
|
||||
|
||||
os.Exit(_exitSuccess)
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
types "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
"github.com/spf13/viper"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
// accountKeyCmd represents the account key command
|
||||
@@ -32,29 +34,33 @@ var accountKeyCmd = &cobra.Command{
|
||||
In quiet mode this will return 0 if the key can be obtained, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "account keys not available with remote wallets")
|
||||
assert(rootAccount != "", "--account is required")
|
||||
assert(viper.GetString("account") != "", "--account is required")
|
||||
|
||||
account, err := accountFromPath(rootAccount)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
account, err := accountFromPath(ctx, viper.GetString("account"))
|
||||
errCheck(err, "Failed to access account")
|
||||
|
||||
_, ok := account.(types.AccountPrivateKeyProvider)
|
||||
assert(ok, fmt.Sprintf("account %q does not provide its private key", rootAccount))
|
||||
privateKeyProvider, isPrivateKeyProvider := account.(e2wtypes.AccountPrivateKeyProvider)
|
||||
assert(isPrivateKeyProvider, fmt.Sprintf("account %q does not provide its private key", viper.GetString("account")))
|
||||
|
||||
unlocked := false
|
||||
for _, passphrase := range getPassphrases() {
|
||||
err = account.Unlock([]byte(passphrase))
|
||||
if err == nil {
|
||||
unlocked = true
|
||||
break
|
||||
if locker, isLocker := account.(e2wtypes.AccountLocker); isLocker {
|
||||
unlocked := false
|
||||
for _, passphrase := range getPassphrases() {
|
||||
err = locker.Unlock(ctx, []byte(passphrase))
|
||||
if err == nil {
|
||||
unlocked = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert(unlocked, "Failed to unlock account to obtain private key")
|
||||
defer errCheck(locker.Lock(context.Background()), "failed to re-lock account")
|
||||
}
|
||||
assert(unlocked, "Failed to unlock account to obtain private key")
|
||||
defer account.Lock()
|
||||
privateKey, err := account.(types.AccountPrivateKeyProvider).PrivateKey()
|
||||
privateKey, err := privateKeyProvider.PrivateKey(ctx)
|
||||
errCheck(err, "Failed to obtain private key")
|
||||
account.Lock()
|
||||
|
||||
outputIf(!quiet, fmt.Sprintf("%#064x", privateKey.Marshal()))
|
||||
outputIf(!quiet, fmt.Sprintf("%#x", privateKey.Marshal()))
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -15,11 +15,11 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
pb "github.com/wealdtech/eth2-signer-api/pb/v1"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
var accountLockCmd = &cobra.Command{
|
||||
@@ -31,26 +31,28 @@ var accountLockCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the account is locked, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(remote, "account lock only works with remote wallets")
|
||||
assert(rootAccount != "", "--account is required")
|
||||
assert(viper.GetString("account") != "", "--account is required")
|
||||
|
||||
client := pb.NewAccountManagerClient(remoteGRPCConn)
|
||||
lockReq := &pb.LockAccountRequest{
|
||||
Account: rootAccount,
|
||||
}
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
assert(isAccountByNameProvider, "wallet cannot obtain accounts by name")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
resp, err := client.Lock(ctx, lockReq)
|
||||
errCheck(err, "Failed in attempt to lock account")
|
||||
switch resp.State {
|
||||
case pb.ResponseState_DENIED:
|
||||
die("Lock request denied")
|
||||
case pb.ResponseState_FAILED:
|
||||
die("Lock request failed")
|
||||
case pb.ResponseState_SUCCEEDED:
|
||||
outputIf(!quiet, "Lock request succeeded")
|
||||
os.Exit(_exitSuccess)
|
||||
}
|
||||
account, err := accountByNameProvider.AccountByName(ctx, accountName)
|
||||
errCheck(err, "Failed to obtain account")
|
||||
|
||||
locker, isLocker := account.(e2wtypes.AccountLocker)
|
||||
assert(isLocker, "Account does not support locking")
|
||||
|
||||
ctx, cancel = context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
err = locker.Lock(ctx)
|
||||
cancel()
|
||||
errCheck(err, "Failed to lock account")
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,8 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
pb "github.com/wealdtech/eth2-signer-api/pb/v1"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
var accountUnlockCmd = &cobra.Command{
|
||||
@@ -31,25 +32,36 @@ var accountUnlockCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the account is unlocked, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(remote, "account unlock only works with remote wallets")
|
||||
assert(rootAccount != "", "--account is required")
|
||||
assert(viper.GetString("account") != "", "--account is required")
|
||||
|
||||
client := pb.NewAccountManagerClient(remoteGRPCConn)
|
||||
unlocked := false
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
assert(isAccountByNameProvider, "wallet cannot obtain accounts by name")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
account, err := accountByNameProvider.AccountByName(ctx, accountName)
|
||||
errCheck(err, "Failed to obtain account")
|
||||
|
||||
locker, isLocker := account.(e2wtypes.AccountLocker)
|
||||
assert(isLocker, "Account does not support unlocking")
|
||||
|
||||
unlocked := false
|
||||
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 {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
err := locker.Unlock(ctx, []byte(passphrase))
|
||||
cancel()
|
||||
if err == nil {
|
||||
// Success.
|
||||
unlocked = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
assert(unlocked, "Failed to unlock account")
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
|
||||
83
cmd/accountwithdrawalcredentials.go
Normal file
83
cmd/accountwithdrawalcredentials.go
Normal file
@@ -0,0 +1,83 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
util "github.com/wealdtech/go-eth2-util"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
var accountWithdrawalCredentialsCmd = &cobra.Command{
|
||||
Use: "withdrawalcredentials",
|
||||
Short: "Provide withdrawal credentials for an account",
|
||||
Long: `Provide withdrawal credentials for an account. For example:
|
||||
|
||||
ethdo account withdrawalcredentials --account="Validators/1"
|
||||
|
||||
In quiet mode this will return 0 if the account exists, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
assert(viper.GetString("account") != "" || viper.GetString("pubkey") != "", "account or pubkey is required")
|
||||
|
||||
var pubKey []byte
|
||||
if viper.GetString("pubkey") != "" {
|
||||
var err error
|
||||
pubKey, err = hex.DecodeString(strings.TrimPrefix(viper.GetString("pubkey"), "0x"))
|
||||
errCheck(err, "Failed to decode supplied public key")
|
||||
} else {
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
assert(isAccountByNameProvider, "wallet cannot obtain accounts by name")
|
||||
account, err := accountByNameProvider.AccountByName(ctx, accountName)
|
||||
errCheck(err, "Failed to obtain account")
|
||||
|
||||
key, err := bestPublicKey(account)
|
||||
errCheck(err, "Account does not provide a public key")
|
||||
pubKey = key.Marshal()
|
||||
}
|
||||
|
||||
if quiet {
|
||||
os.Exit(_exitSuccess)
|
||||
}
|
||||
|
||||
withdrawalCredentials := util.SHA256(pubKey)
|
||||
withdrawalCredentials[0] = byte(0) // BLS_WITHDRAWAL_PREFIX
|
||||
fmt.Printf("%#x\n", withdrawalCredentials)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
accountCmd.AddCommand(accountWithdrawalCredentialsCmd)
|
||||
accountFlags(accountWithdrawalCredentialsCmd)
|
||||
accountWithdrawalCredentialsCmd.Flags().String("pubkey", "", "Public key (overrides account)")
|
||||
if err := viper.BindPFlag("pubkey", accountCreateCmd.Flags().Lookup("pubkey")); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
@@ -48,44 +49,49 @@ In quiet mode this will return 0 if the block information is present and not ski
|
||||
config, err := grpc.FetchChainConfig(eth2GRPCConn)
|
||||
errCheck(err, "Failed to obtain beacon chain configuration")
|
||||
slotsPerEpoch := config["SlotsPerEpoch"].(uint64)
|
||||
secondsPerSlot := config["SecondsPerSlot"].(uint64)
|
||||
|
||||
genesisTime, err := grpc.FetchGenesisTime(eth2GRPCConn)
|
||||
errCheck(err, "Failed to obtain beacon chain genesis")
|
||||
|
||||
assert(blockInfoStream || blockInfoSlot != 0, "--slot or --stream is required")
|
||||
assert(!blockInfoStream || blockInfoSlot == -1, "--slot and --stream are not supported together")
|
||||
|
||||
var slot uint64
|
||||
if blockInfoSlot < 0 {
|
||||
slot, err = grpc.FetchLatestFilledSlot(eth2GRPCConn)
|
||||
errCheck(err, "Failed to obtain slot of latest block")
|
||||
} else {
|
||||
slot = uint64(blockInfoSlot)
|
||||
}
|
||||
assert(slot > 0, "slot must be greater than 0")
|
||||
|
||||
signedBlock, err := grpc.FetchBlock(eth2GRPCConn, slot)
|
||||
errCheck(err, "Failed to obtain block")
|
||||
if signedBlock == nil {
|
||||
outputIf(!quiet, "No block at that slot")
|
||||
os.Exit(_exitFailure)
|
||||
}
|
||||
outputBlock(signedBlock, genesisTime, secondsPerSlot, slotsPerEpoch)
|
||||
|
||||
if blockInfoStream {
|
||||
stream, err := grpc.StreamBlocks(eth2GRPCConn)
|
||||
errCheck(err, "Failed to obtain block stream")
|
||||
for {
|
||||
fmt.Println()
|
||||
signedBlock, err := stream.Recv()
|
||||
errCheck(err, "Failed to obtain block")
|
||||
if signedBlock != nil {
|
||||
fmt.Println("")
|
||||
outputBlock(signedBlock, slotsPerEpoch)
|
||||
outputBlock(signedBlock, genesisTime, secondsPerSlot, slotsPerEpoch)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
assert(blockInfoSlot != 0, "--slot is required")
|
||||
var slot uint64
|
||||
if blockInfoSlot < 0 {
|
||||
slot, err = grpc.FetchLatestFilledSlot(eth2GRPCConn)
|
||||
errCheck(err, "Failed to obtain slot of latest block")
|
||||
} else {
|
||||
slot = uint64(blockInfoSlot)
|
||||
}
|
||||
assert(slot > 0, "slot must be greater than 0")
|
||||
|
||||
signedBlock, err := grpc.FetchBlock(eth2GRPCConn, slot)
|
||||
errCheck(err, "Failed to obtain block")
|
||||
if signedBlock == nil {
|
||||
outputIf(!quiet, "No block at that slot")
|
||||
os.Exit(_exitFailure)
|
||||
}
|
||||
outputBlock(signedBlock, slotsPerEpoch)
|
||||
}
|
||||
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
|
||||
func outputBlock(signedBlock *ethpb.SignedBeaconBlock, slotsPerEpoch uint64) {
|
||||
func outputBlock(signedBlock *ethpb.SignedBeaconBlock, genesisTime time.Time, secondsPerSlot uint64, slotsPerEpoch uint64) {
|
||||
block := signedBlock.Block
|
||||
body := block.Body
|
||||
|
||||
@@ -94,6 +100,7 @@ func outputBlock(signedBlock *ethpb.SignedBeaconBlock, slotsPerEpoch uint64) {
|
||||
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("Timestamp: %v\n", time.Unix(genesisTime.Unix()+int64(block.Slot*secondsPerSlot), 0))
|
||||
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))
|
||||
|
||||
@@ -43,8 +43,12 @@ In quiet mode this will return 0 if the chain information can be obtained, other
|
||||
os.Exit(_exitSuccess)
|
||||
}
|
||||
|
||||
fmt.Printf("Genesis time: %s\n", genesisTime.Format(time.UnixDate))
|
||||
outputIf(verbose, fmt.Sprintf("Genesis timestamp: %v", genesisTime.Unix()))
|
||||
if genesisTime.Unix() == 0 {
|
||||
fmt.Println("Genesis time: undefined")
|
||||
} else {
|
||||
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)))
|
||||
@@ -64,3 +68,11 @@ func timestampToSlot(genesis int64, timestamp int64, secondsPerSlot uint64) uint
|
||||
}
|
||||
return uint64(timestamp-genesis) / secondsPerSlot
|
||||
}
|
||||
|
||||
func slotToTimestamp(genesis int64, slot uint64, secondsPerSlot uint64) int64 {
|
||||
return genesis + int64(slot*secondsPerSlot)
|
||||
}
|
||||
|
||||
func epochToTimestamp(genesis int64, slot uint64, secondsPerSlot uint64, slotsPerEpoch uint64) int64 {
|
||||
return genesis + int64(slot*secondsPerSlot*slotsPerEpoch)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ In quiet mode this will return 0 if the chain status can be obtained, otherwise
|
||||
os.Exit(_exitSuccess)
|
||||
}
|
||||
|
||||
slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(uint64))
|
||||
now := time.Now()
|
||||
slot := timestampToSlot(genesisTime.Unix(), now.Unix(), config["SecondsPerSlot"].(uint64))
|
||||
if chainStatusSlot {
|
||||
fmt.Printf("Current slot: %d\n", slot)
|
||||
fmt.Printf("Justified slot: %d\n", info.GetJustifiedSlot())
|
||||
@@ -87,6 +88,18 @@ In quiet mode this will return 0 if the chain status can be obtained, otherwise
|
||||
}
|
||||
}
|
||||
|
||||
if verbose {
|
||||
slotsPerEpoch := config["SlotsPerEpoch"].(uint64)
|
||||
secondsPerSlot := config["SecondsPerSlot"].(uint64)
|
||||
epochStartSlot := (slot / slotsPerEpoch) * slotsPerEpoch
|
||||
fmt.Printf("Epoch slots: %d-%d\n", epochStartSlot, epochStartSlot+slotsPerEpoch-1)
|
||||
nextSlot := slotToTimestamp(genesisTime.Unix(), slot+1, secondsPerSlot)
|
||||
fmt.Printf("Time until next slot: %2.1fs\n", float64(time.Until(time.Unix(nextSlot, 0)).Milliseconds())/1000)
|
||||
nextEpoch := epochToTimestamp(genesisTime.Unix(), slot/slotsPerEpoch+1, secondsPerSlot, slotsPerEpoch)
|
||||
fmt.Printf("Slots until next epoch: %d\n", (slot/slotsPerEpoch+1)*slotsPerEpoch-slot)
|
||||
fmt.Printf("Time until next epoch: %2.1fs\n", float64(time.Until(time.Unix(nextEpoch, 0)).Milliseconds())/1000)
|
||||
}
|
||||
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
|
||||
failures = true
|
||||
}
|
||||
}
|
||||
outputIf(!quiet, fmt.Sprintf("Deposit for %q verified", deposit.Name))
|
||||
outputIf(!quiet, fmt.Sprintf("Deposit %q verified", deposit.Name))
|
||||
}
|
||||
|
||||
if failures {
|
||||
|
||||
@@ -55,10 +55,14 @@ In quiet mode this will return 0 if the node information can be obtained, otherw
|
||||
errCheck(err, "Failed to obtain syncing state")
|
||||
fmt.Printf("Syncing: %v\n", syncing)
|
||||
|
||||
slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(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()))
|
||||
if genesisTime.Unix() == 0 {
|
||||
fmt.Println("Not reached genesis")
|
||||
} else {
|
||||
slot := timestampToSlot(genesisTime.Unix(), time.Now().Unix(), config["SecondsPerSlot"].(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)
|
||||
},
|
||||
|
||||
229
cmd/root.go
229
cmd/root.go
@@ -15,28 +15,25 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
e2types "github.com/wealdtech/go-eth2-types/v2"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
dirk "github.com/wealdtech/go-eth2-wallet-dirk"
|
||||
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"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
@@ -46,19 +43,12 @@ var debug bool
|
||||
|
||||
// Root variables, present for all commands.
|
||||
var rootStore string
|
||||
var rootAccount string
|
||||
var rootBaseDir string
|
||||
|
||||
// Store for wallet actions.
|
||||
var store wtypes.Store
|
||||
var store e2wtypes.Store
|
||||
|
||||
// Remote connection.
|
||||
var remote bool
|
||||
var remoteAddr string
|
||||
var clientCert string
|
||||
var clientKey string
|
||||
var serverCACert string
|
||||
var remoteGRPCConn *grpc.ClientConn
|
||||
|
||||
// Prysm connection.
|
||||
var eth2GRPCConn *grpc.ClientConn
|
||||
@@ -87,8 +77,6 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
|
||||
verbose = viper.GetBool("verbose")
|
||||
debug = viper.GetBool("debug")
|
||||
rootStore = viper.GetString("store")
|
||||
rootAccount = viper.GetString("account")
|
||||
rootBaseDir = viper.GetString("basedir")
|
||||
|
||||
if quiet && verbose {
|
||||
fmt.Println("Cannot supply both quiet and verbose flags")
|
||||
@@ -101,7 +89,7 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
|
||||
// Set up our wallet store
|
||||
switch rootStore {
|
||||
case "s3":
|
||||
assert(rootBaseDir == "", "--basedir does not apply for the s3 store")
|
||||
assert(viper.GetString("base-dir") == "", "--basedir does not apply for the s3 store")
|
||||
var err error
|
||||
store, err = s3.New(s3.WithPassphrase([]byte(getStorePassphrase())))
|
||||
errCheck(err, "Failed to access Amazon S3 wallet store")
|
||||
@@ -110,8 +98,8 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
|
||||
if getStorePassphrase() != "" {
|
||||
opts = append(opts, filesystem.WithPassphrase([]byte(getStorePassphrase())))
|
||||
}
|
||||
if rootBaseDir != "" {
|
||||
opts = append(opts, filesystem.WithLocation(rootBaseDir))
|
||||
if viper.GetString("base-dir") != "" {
|
||||
opts = append(opts, filesystem.WithLocation(viper.GetString("base-dir")))
|
||||
}
|
||||
store = filesystem.New(opts...)
|
||||
default:
|
||||
@@ -120,8 +108,7 @@ func persistentPreRun(cmd *cobra.Command, args []string) {
|
||||
err := e2wallet.UseStore(store)
|
||||
errCheck(err, "Failed to use defined wallet store")
|
||||
} else {
|
||||
err := initRemote()
|
||||
errCheck(err, "Failed to connect to remote wallet")
|
||||
remote = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,6 +213,7 @@ func initConfig() {
|
||||
}
|
||||
|
||||
viper.SetEnvPrefix("ETHDO")
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
@@ -246,7 +234,7 @@ func outputIf(condition bool, msg string) {
|
||||
}
|
||||
|
||||
// walletFromPath obtains a wallet given a path specification.
|
||||
func walletFromPath(path string) (wtypes.Wallet, error) {
|
||||
func walletFromPath(path string) (e2wtypes.Wallet, error) {
|
||||
walletName, _, err := e2wallet.WalletAndAccountNames(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -262,7 +250,7 @@ func walletFromPath(path string) (wtypes.Wallet, error) {
|
||||
}
|
||||
|
||||
// accountFromPath obtains an account given a path specification.
|
||||
func accountFromPath(path string) (wtypes.Account, error) {
|
||||
func accountFromPath(ctx context.Context, path string) (e2wtypes.Account, error) {
|
||||
wallet, err := walletFromPath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -277,34 +265,27 @@ func accountFromPath(path string) (wtypes.Account, error) {
|
||||
|
||||
if wallet.Type() == "hierarchical deterministic" && strings.HasPrefix(accountName, "m/") {
|
||||
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")
|
||||
|
||||
locker, isLocker := wallet.(e2wtypes.WalletLocker)
|
||||
if isLocker {
|
||||
err = locker.Unlock(ctx, []byte(viper.GetString("wallet-passphrase")))
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid wallet passphrase")
|
||||
}
|
||||
defer errCheck(locker.Lock(context.Background()), "failed to re-lock account")
|
||||
}
|
||||
defer wallet.Lock()
|
||||
}
|
||||
return wallet.AccountByName(accountName)
|
||||
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
if !isAccountByNameProvider {
|
||||
return nil, errors.New("wallet cannot obtain accounts by name")
|
||||
}
|
||||
return accountByNameProvider.AccountByName(ctx, accountName)
|
||||
}
|
||||
|
||||
// accountsFromPath obtains 0 or more accounts given a path specification.
|
||||
func accountsFromPath(path string) ([]wtypes.Account, error) {
|
||||
accounts := make([]wtypes.Account, 0)
|
||||
|
||||
// Quick check to see if it's a single account
|
||||
account, err := accountFromPath(path)
|
||||
if err == nil && account != nil {
|
||||
accounts = append(accounts, account)
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
wallet, err := walletFromPath(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, accountSpec, err := e2wallet.WalletAndAccountNames(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
func accountsFromPath(ctx context.Context, wallet e2wtypes.Wallet, accountSpec string) ([]e2wtypes.Account, error) {
|
||||
accounts := make([]e2wtypes.Account, 0)
|
||||
|
||||
if accountSpec == "" {
|
||||
accountSpec = "^.*$"
|
||||
@@ -313,7 +294,7 @@ func accountsFromPath(path string) ([]wtypes.Account, error) {
|
||||
}
|
||||
re := regexp.MustCompile(accountSpec)
|
||||
|
||||
for account := range wallet.Accounts() {
|
||||
for account := range wallet.Accounts(ctx) {
|
||||
if re.Match([]byte(account.Name())) {
|
||||
accounts = append(accounts, account)
|
||||
}
|
||||
@@ -327,49 +308,6 @@ func accountsFromPath(path string) ([]wtypes.Account, error) {
|
||||
return accounts, nil
|
||||
}
|
||||
|
||||
// signStruct signs an arbitrary structure.
|
||||
func signStruct(account wtypes.Account, data interface{}, domain []byte) (e2types.Signature, error) {
|
||||
objRoot, err := ssz.HashTreeRoot(data)
|
||||
outputIf(debug, fmt.Sprintf("Object root is %x", objRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signRoot(account, objRoot, domain)
|
||||
}
|
||||
|
||||
// SigningContainer is the container for signing roots with a domain.
|
||||
// Contains SSZ sizes to allow for correct calculation of root.
|
||||
type SigningContainer struct {
|
||||
Root []byte `ssz-size:"32"`
|
||||
Domain []byte `ssz-size:"32"`
|
||||
}
|
||||
|
||||
// signRoot signs a root.
|
||||
func signRoot(account wtypes.Account, root [32]byte, domain []byte) (e2types.Signature, error) {
|
||||
container := &SigningContainer{
|
||||
Root: root[:],
|
||||
Domain: domain,
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Signing container:\n\troot: %x\n\tdomain: %x", container.Root, container.Domain))
|
||||
signingRoot, err := ssz.HashTreeRoot(container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Signing root: %x", signingRoot))
|
||||
return sign(account, signingRoot[:])
|
||||
}
|
||||
|
||||
// sign signs arbitrary data.
|
||||
func sign(account wtypes.Account, data []byte) (e2types.Signature, error) {
|
||||
if !account.IsUnlocked() {
|
||||
return nil, errors.New("account must be unlocked to sign")
|
||||
}
|
||||
|
||||
outputIf(debug, fmt.Sprintf("Signing %x (%d)", data, len(data)))
|
||||
return account.Sign(data)
|
||||
}
|
||||
|
||||
// connect connects to an Ethereum 2 endpoint.
|
||||
func connect() error {
|
||||
connection := ""
|
||||
@@ -391,46 +329,77 @@ func connect() error {
|
||||
return err
|
||||
}
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to access client certificate/key")
|
||||
}
|
||||
|
||||
tlsCfg := &tls.Config{
|
||||
Certificates: []tls.Certificate{clientPair},
|
||||
}
|
||||
if serverCACert != "" {
|
||||
// Load the CA for the server certificate.
|
||||
serverCA, err := ioutil.ReadFile(serverCACert)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to access CA certificate")
|
||||
// bestPublicKey returns the best public key for operations.
|
||||
// It prefers the composite public key if present, otherwise the public key.
|
||||
func bestPublicKey(account e2wtypes.Account) (e2types.PublicKey, error) {
|
||||
var pubKey e2types.PublicKey
|
||||
publicKeyProvider, isCompositePublicKeyProvider := account.(e2wtypes.AccountCompositePublicKeyProvider)
|
||||
if isCompositePublicKeyProvider {
|
||||
pubKey = publicKeyProvider.CompositePublicKey()
|
||||
} else {
|
||||
publicKeyProvider, isPublicKeyProvider := account.(e2wtypes.AccountPublicKeyProvider)
|
||||
if isPublicKeyProvider {
|
||||
pubKey = publicKeyProvider.PublicKey()
|
||||
} else {
|
||||
return nil, errors.New("account does not provide a public key")
|
||||
}
|
||||
cp := x509.NewCertPool()
|
||||
if !cp.AppendCertsFromPEM(serverCA) {
|
||||
return errors.Wrap(err, "failed to add CA certificate")
|
||||
}
|
||||
tlsCfg.RootCAs = cp
|
||||
}
|
||||
|
||||
clientCreds := credentials.NewTLS(tlsCfg)
|
||||
|
||||
opts := []grpc.DialOption{
|
||||
// Require TLS.
|
||||
grpc.WithTransportCredentials(clientCreds),
|
||||
// Block until server responds.
|
||||
grpc.WithBlock(),
|
||||
}
|
||||
remoteGRPCConn, err = grpc.Dial(remoteAddr, opts...)
|
||||
return err
|
||||
return pubKey, nil
|
||||
}
|
||||
|
||||
// remotesToEndpoints generates endpoints from remote addresses.
|
||||
func remotesToEndpoints(remotes []string) ([]*dirk.Endpoint, error) {
|
||||
endpoints := make([]*dirk.Endpoint, 0)
|
||||
for _, remote := range remotes {
|
||||
parts := strings.Split(remote, ":")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("invalid remote %q", remote)
|
||||
}
|
||||
port, err := strconv.ParseUint(parts[1], 10, 32)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("invalid port in remote %q", remote))
|
||||
}
|
||||
endpoints = append(endpoints, dirk.NewEndpoint(parts[0], uint32(port)))
|
||||
}
|
||||
return endpoints, nil
|
||||
}
|
||||
|
||||
// Oepn a wallet, local or remote.
|
||||
func openWallet() (e2wtypes.Wallet, error) {
|
||||
var err error
|
||||
// Obtain the name of the wallet.
|
||||
walletName := viper.GetString("wallet")
|
||||
if walletName == "" {
|
||||
walletName, _, err = e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to obtain wallet name")
|
||||
}
|
||||
if walletName == "" {
|
||||
return nil, errors.New("no wallet name provided")
|
||||
}
|
||||
|
||||
return openNamedWallet(walletName)
|
||||
}
|
||||
|
||||
// Open a named wallet, local or remote.
|
||||
func openNamedWallet(walletName string) (e2wtypes.Wallet, error) {
|
||||
if viper.GetString("remote") != "" {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
assert(viper.GetString("client-cert") != "", "remote connections require client-cert")
|
||||
assert(viper.GetString("client-key") != "", "remote connections require client-key")
|
||||
credentials, err := dirk.ComposeCredentials(ctx, viper.GetString("client-cert"), viper.GetString("client-key"), viper.GetString("server-ca-cert"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to build dirk credentials")
|
||||
}
|
||||
|
||||
endpoints, err := remotesToEndpoints([]string{viper.GetString("remote")})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse remote servers")
|
||||
}
|
||||
|
||||
return dirk.OpenWallet(ctx, walletName, credentials, endpoints)
|
||||
}
|
||||
return walletFromPath(walletName)
|
||||
}
|
||||
|
||||
@@ -15,11 +15,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var signatureData string
|
||||
var signatureDomain string
|
||||
|
||||
// signatureCmd represents the signature command
|
||||
var signatureCmd = &cobra.Command{
|
||||
Use: "signature",
|
||||
@@ -32,7 +31,23 @@ func init() {
|
||||
RootCmd.AddCommand(signatureCmd)
|
||||
}
|
||||
|
||||
var dataFlag *pflag.Flag
|
||||
var domainFlag *pflag.Flag
|
||||
|
||||
func signatureFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().StringVar(&signatureData, "data", "", "the hex string of data")
|
||||
cmd.Flags().StringVar(&signatureDomain, "domain", "", "the hex string of the BLS domain (defaults to 0x0000000000000000)")
|
||||
if dataFlag == nil {
|
||||
cmd.Flags().String("data", "", "the data, as a hex string")
|
||||
dataFlag = cmd.Flags().Lookup("data")
|
||||
if err := viper.BindPFlag("signature-data", dataFlag); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cmd.Flags().String("domain", "0x0000000000000000000000000000000000000000000000000000000000000000", "the BLS domain, as a hex string")
|
||||
domainFlag = cmd.Flags().Lookup("domain")
|
||||
if err := viper.BindPFlag("signature-domain", domainFlag); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
cmd.Flags().AddFlag(dataFlag)
|
||||
cmd.Flags().AddFlag(domainFlag)
|
||||
}
|
||||
}
|
||||
|
||||
110
cmd/signatureaggregate.go
Normal file
110
cmd/signatureaggregate.go
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright © 2017-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 (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/herumi/bls-eth-go-binary/bls"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/wealdtech/ethdo/util"
|
||||
)
|
||||
|
||||
var signatureAggregateSignatures []string
|
||||
|
||||
// signatureAggregateCmd represents the signature aggregate command
|
||||
var signatureAggregateCmd = &cobra.Command{
|
||||
Use: "aggregate",
|
||||
Short: "Aggregate signatures",
|
||||
Long: `Aggregate signatures, either threshold or absolute. For example:
|
||||
|
||||
ethdo signature aggregate --signatures=0x5f24e819400c6a8ee2bfc014343cd971b7eb707320025a7bcd83e621e26c35b7,
|
||||
|
||||
Signatures are specified as "signature" for simple aggregation, and as "id:signature" for threshold aggregation.
|
||||
|
||||
In quiet mode this will return 0 if the signatures can be aggregated, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(len(signatureAggregateSignatures) > 1, "multiple signatures required to aggregate")
|
||||
var signature *bls.Sign
|
||||
var err error
|
||||
if strings.Contains(signatureAggregateSignatures[0], ":") {
|
||||
signature, err = generateThresholdSignature()
|
||||
} else {
|
||||
signature, err = generateAggregateSignature()
|
||||
}
|
||||
errCheck(err, "Failed to aggregate signature")
|
||||
|
||||
outputIf(!quiet, fmt.Sprintf("%#x", signature.Serialize()))
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
|
||||
func generateThresholdSignature() (*bls.Sign, error) {
|
||||
ids := make([]bls.ID, len(signatureAggregateSignatures))
|
||||
sigs := make([]bls.Sign, len(signatureAggregateSignatures))
|
||||
|
||||
for i := range signatureAggregateSignatures {
|
||||
parts := strings.Split(signatureAggregateSignatures[i], ":")
|
||||
if len(parts) != 2 {
|
||||
return nil, errors.New("invalid threshold signature format")
|
||||
}
|
||||
id, err := strconv.ParseUint(parts[0], 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "invalid threshold signature ID")
|
||||
}
|
||||
ids[i] = *util.BLSID(id)
|
||||
sigBytes, err := hex.DecodeString(strings.TrimPrefix(parts[1], "0x"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "invalid threshold signature ID")
|
||||
}
|
||||
if err := sigs[i].Deserialize(sigBytes); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid signature")
|
||||
}
|
||||
}
|
||||
|
||||
var compositeSig bls.Sign
|
||||
if err := compositeSig.Recover(sigs, ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &compositeSig, nil
|
||||
}
|
||||
|
||||
func generateAggregateSignature() (*bls.Sign, error) {
|
||||
sigs := make([]bls.Sign, len(signatureAggregateSignatures))
|
||||
for i := range signatureAggregateSignatures {
|
||||
sigBytes, err := hex.DecodeString(strings.TrimPrefix(signatureAggregateSignatures[i], "0x"))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to decode signature")
|
||||
}
|
||||
if err := sigs[i].Deserialize(sigBytes); err != nil {
|
||||
return nil, errors.Wrap(err, "invalid signature")
|
||||
}
|
||||
}
|
||||
var aggregateSig bls.Sign
|
||||
aggregateSig.Aggregate(sigs)
|
||||
|
||||
return &aggregateSig, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
signatureCmd.AddCommand(signatureAggregateCmd)
|
||||
signatureAggregateCmd.Flags().StringArrayVar(&signatureAggregateSignatures, "signature", nil, "a signature to aggregate (supply once for each signature)")
|
||||
signatureFlags(signatureAggregateCmd)
|
||||
}
|
||||
@@ -20,9 +20,10 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
pb "github.com/wealdtech/eth2-signer-api/pb/v1"
|
||||
"github.com/wealdtech/go-bytesutil"
|
||||
e2types "github.com/wealdtech/go-eth2-types/v2"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
// signatureSignCmd represents the signature sign command
|
||||
@@ -31,59 +32,46 @@ var signatureSignCmd = &cobra.Command{
|
||||
Short: "Sign a 32-byte piece of data",
|
||||
Long: `Sign presented data. For example:
|
||||
|
||||
ethereal signature sign --data=0x5f24e819400c6a8ee2bfc014343cd971b7eb707320025a7bcd83e621e26c35b7 --account="Personal wallet/Operations" --passphrase="my account passphrase"
|
||||
ethdo signature sign --data=0x5f24e819400c6a8ee2bfc014343cd971b7eb707320025a7bcd83e621e26c35b7 --account="Personal wallet/Operations" --passphrase="my account passphrase"
|
||||
|
||||
In quiet mode this will return 0 if the data can be signed, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(signatureData != "", "--data is required")
|
||||
data, err := bytesutil.FromHexString(signatureData)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
assert(viper.GetString("signature-data") != "", "--data is required")
|
||||
data, err := bytesutil.FromHexString(viper.GetString("signature-data"))
|
||||
errCheck(err, "Failed to parse data")
|
||||
assert(len(data) == 32, "data to sign must be 32 bytes")
|
||||
|
||||
domain := e2types.Domain(e2types.DomainType([4]byte{0, 0, 0, 0}), e2types.ZeroForkVersion, e2types.ZeroGenesisValidatorsRoot)
|
||||
if signatureDomain != "" {
|
||||
domainBytes, err := bytesutil.FromHexString(signatureDomain)
|
||||
if viper.GetString("signature-domain") != "" {
|
||||
domain, err = bytesutil.FromHexString(viper.GetString("signature-domain"))
|
||||
errCheck(err, "Failed to parse domain")
|
||||
assert(len(domainBytes) == 32, "Domain data invalid")
|
||||
domain = domainBytes
|
||||
assert(len(domain) == 32, "Domain data invalid")
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Domain is %#x", domain))
|
||||
|
||||
assert(rootAccount != "", "--account is required")
|
||||
assert(viper.GetString("account") != "", "--account is required")
|
||||
|
||||
var signature e2types.Signature
|
||||
if remote {
|
||||
signClient := pb.NewSignerClient(remoteGRPCConn)
|
||||
signReq := &pb.SignRequest{
|
||||
Id: &pb.SignRequest_Account{Account: rootAccount},
|
||||
Data: data,
|
||||
Domain: domain,
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
resp, err := signClient.Sign(ctx, signReq)
|
||||
errCheck(err, "Failed to sign")
|
||||
switch resp.State {
|
||||
case pb.ResponseState_DENIED:
|
||||
die("Signing request denied")
|
||||
case pb.ResponseState_FAILED:
|
||||
die("Signing request failed")
|
||||
case pb.ResponseState_SUCCEEDED:
|
||||
signature, err = e2types.BLSSignatureFromBytes(resp.Signature)
|
||||
errCheck(err, "Invalid signature")
|
||||
}
|
||||
} else {
|
||||
account, err := accountFromPath(rootAccount)
|
||||
errCheck(err, "Failed to access account for signing")
|
||||
err = account.Unlock([]byte(getPassphrase()))
|
||||
errCheck(err, "Failed to unlock account for signing")
|
||||
var fixedSizeData [32]byte
|
||||
copy(fixedSizeData[:], data)
|
||||
defer account.Lock()
|
||||
signature, err = signRoot(account, fixedSizeData, domain)
|
||||
errCheck(err, "Failed to sign data")
|
||||
}
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
outputIf(!quiet, fmt.Sprintf("0x%096x", signature.Marshal()))
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
assert(isAccountByNameProvider, "wallet does not support obtaining accounts by name")
|
||||
|
||||
account, err := accountByNameProvider.AccountByName(ctx, accountName)
|
||||
errCheck(err, "Failed to obtain account")
|
||||
|
||||
var fixedSizeData [32]byte
|
||||
copy(fixedSizeData[:], data)
|
||||
signature, err := signRoot(account, fixedSizeData, domain)
|
||||
errCheck(err, "Failed to sign")
|
||||
|
||||
outputIf(!quiet, fmt.Sprintf("%#x", signature.Marshal()))
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -15,17 +15,20 @@ package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/spf13/cobra"
|
||||
pb "github.com/wealdtech/eth2-signer-api/pb/v1"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/wealdtech/go-bytesutil"
|
||||
e2types "github.com/wealdtech/go-eth2-types/v2"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
var signatureVerifySignature string
|
||||
var signatureVerifyPubKey string
|
||||
var signatureVerifySigner string
|
||||
|
||||
// signatureVerifyCmd represents the signature verify command
|
||||
var signatureVerifyCmd = &cobra.Command{
|
||||
@@ -33,12 +36,12 @@ var signatureVerifyCmd = &cobra.Command{
|
||||
Short: "Verify signed data",
|
||||
Long: `Verify signed data. For example:
|
||||
|
||||
ethereal signature verify --data=0x5f24e819400c6a8ee2bfc014343cd971b7eb707320025a7bcd83e621e26c35b7 --signature=0x8888... --account="Personal wallet/Operations"
|
||||
ethdo signature verify --data=0x5f24e819400c6a8ee2bfc014343cd971b7eb707320025a7bcd83e621e26c35b7 --signature=0x8888... --account="Personal wallet/Operations"
|
||||
|
||||
In quiet mode this will return 0 if the data can be signed, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(signatureData != "", "--data is required")
|
||||
data, err := bytesutil.FromHexString(signatureData)
|
||||
assert(viper.GetString("signature-data") != "", "--data is required")
|
||||
data, err := bytesutil.FromHexString(viper.GetString("signature-data"))
|
||||
errCheck(err, "Failed to parse data")
|
||||
assert(len(data) == 32, "data to verify must be 32 bytes")
|
||||
|
||||
@@ -49,45 +52,44 @@ In quiet mode this will return 0 if the data can be signed, otherwise 1.`,
|
||||
errCheck(err, "Invalid signature")
|
||||
|
||||
domain := e2types.Domain(e2types.DomainType([4]byte{0, 0, 0, 0}), e2types.ZeroForkVersion, e2types.ZeroGenesisValidatorsRoot)
|
||||
if signatureDomain != "" {
|
||||
domainBytes, err := bytesutil.FromHexString(signatureDomain)
|
||||
if viper.GetString("signature-domain") != "" {
|
||||
domain, err = bytesutil.FromHexString(viper.GetString("signature-domain"))
|
||||
errCheck(err, "Failed to parse domain")
|
||||
assert(len(domainBytes) == 32, "Domain data invalid")
|
||||
assert(len(domain) == 32, "Domain data invalid")
|
||||
}
|
||||
|
||||
var pubKey e2types.PublicKey
|
||||
assert(signatureVerifyPubKey == "" || rootAccount == "", "Either --pubkey or --account should be supplied")
|
||||
if rootAccount != "" {
|
||||
if remote {
|
||||
listerClient := pb.NewListerClient(remoteGRPCConn)
|
||||
listAccountsReq := &pb.ListAccountsRequest{
|
||||
Paths: []string{
|
||||
rootAccount,
|
||||
},
|
||||
}
|
||||
resp, err := listerClient.ListAccounts(context.Background(), listAccountsReq)
|
||||
errCheck(err, "Failed to access account")
|
||||
assert(resp.State == pb.ResponseState_SUCCEEDED, "Failed to obtain account")
|
||||
assert(len(resp.Accounts) == 1, "No such account")
|
||||
pubKey, err = e2types.BLSPublicKeyFromBytes(resp.Accounts[0].PublicKey)
|
||||
errCheck(err, "Invalid public key provided for account")
|
||||
} else {
|
||||
account, err := accountFromPath(rootAccount)
|
||||
errCheck(err, "Unknown account")
|
||||
pubKey = account.PublicKey()
|
||||
}
|
||||
assert(signatureVerifySigner != "" || viper.GetString("account") != "", "Either --signer or --account should be supplied")
|
||||
if viper.GetString("account") != "" {
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
assert(isAccountByNameProvider, "wallet cannot obtain accounts by name")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
account, err := accountByNameProvider.AccountByName(ctx, accountName)
|
||||
errCheck(err, "Failed to obtain account")
|
||||
pubKey, err = bestPublicKey(account)
|
||||
errCheck(err, "Failed to obtain account's public key")
|
||||
} else {
|
||||
pubKeyBytes, err := bytesutil.FromHexString(signatureVerifyPubKey)
|
||||
pubKeyBytes, err := bytesutil.FromHexString(signatureVerifySigner)
|
||||
errCheck(err, "Invalid public key")
|
||||
pubKey, err = e2types.BLSPublicKeyFromBytes(pubKeyBytes)
|
||||
errCheck(err, "Invalid public key")
|
||||
}
|
||||
container := &SigningContainer{
|
||||
outputIf(debug, fmt.Sprintf("Public key is %#x", pubKey.Marshal()))
|
||||
container := &signingContainer{
|
||||
Root: data,
|
||||
Domain: domain,
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Data root is %#x", data))
|
||||
outputIf(debug, fmt.Sprintf("Domain is %#x", domain))
|
||||
root, err := ssz.HashTreeRoot(container)
|
||||
errCheck(err, "Failed to create signing root")
|
||||
outputIf(debug, fmt.Sprintf("Signing root is %#x", root))
|
||||
|
||||
verified := signature.Verify(root[:], pubKey)
|
||||
if !verified {
|
||||
@@ -103,5 +105,5 @@ func init() {
|
||||
signatureCmd.AddCommand(signatureVerifyCmd)
|
||||
signatureFlags(signatureVerifyCmd)
|
||||
signatureVerifyCmd.Flags().StringVar(&signatureVerifySignature, "signature", "", "the signature to verify")
|
||||
signatureVerifyCmd.Flags().StringVar(&signatureVerifyPubKey, "signer", "", "the public key of the signer (only if --account is not supplied)")
|
||||
signatureVerifyCmd.Flags().StringVar(&signatureVerifySigner, "signer", "", "the public key of the signer (only if --account is not supplied)")
|
||||
}
|
||||
|
||||
160
cmd/signing.go
Normal file
160
cmd/signing.go
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright © 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 (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/spf13/viper"
|
||||
e2types "github.com/wealdtech/go-eth2-types/v2"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
// signStruct signs an arbitrary structure.
|
||||
func signStruct(account wtypes.Account, data interface{}, domain []byte) (e2types.Signature, error) {
|
||||
objRoot, err := ssz.HashTreeRoot(data)
|
||||
outputIf(debug, fmt.Sprintf("Object root is %#x", objRoot))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return signRoot(account, objRoot, domain)
|
||||
}
|
||||
|
||||
// SigningContainer is the container for signing roots with a domain.
|
||||
// Contains SSZ sizes to allow for correct calculation of root.
|
||||
type signingContainer struct {
|
||||
Root []byte `ssz-size:"32"`
|
||||
Domain []byte `ssz-size:"32"`
|
||||
}
|
||||
|
||||
// signRoot signs a root.
|
||||
func signRoot(account wtypes.Account, root [32]byte, domain []byte) (e2types.Signature, error) {
|
||||
if _, isProtectingSigner := account.(e2wtypes.AccountProtectingSigner); isProtectingSigner {
|
||||
// Signer signs the data to sign itself.
|
||||
return signGeneric(account, root[:], domain)
|
||||
}
|
||||
|
||||
// Build the signing data manually.
|
||||
container := &signingContainer{
|
||||
Root: root[:],
|
||||
Domain: domain,
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Signing container:\n root: %#x\n domain: %#x", container.Root, container.Domain))
|
||||
signingRoot, err := ssz.HashTreeRoot(container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Signing root: %#x", signingRoot))
|
||||
return sign(account, signingRoot[:])
|
||||
}
|
||||
|
||||
func signGeneric(account wtypes.Account, data []byte, domain []byte) (e2types.Signature, error) {
|
||||
alreadyUnlocked, err := unlock(account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Signing %x (%d)", data, len(data)))
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
signer, isProtectingSigner := account.(e2wtypes.AccountProtectingSigner)
|
||||
if !isProtectingSigner {
|
||||
return nil, errors.New("account does not provide generic signing")
|
||||
}
|
||||
|
||||
signature, err := signer.SignGeneric(ctx, data, domain)
|
||||
errCheck(err, "failed to sign")
|
||||
if !alreadyUnlocked {
|
||||
if err := lock(account); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to lock account")
|
||||
}
|
||||
}
|
||||
return signature, err
|
||||
}
|
||||
|
||||
// sign signs arbitrary data, handling unlocking and locking as required.
|
||||
func sign(account wtypes.Account, data []byte) (e2types.Signature, error) {
|
||||
alreadyUnlocked, err := unlock(account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Signing %x (%d)", data, len(data)))
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
signer, isSigner := account.(e2wtypes.AccountSigner)
|
||||
if !isSigner {
|
||||
return nil, errors.New("account does not provide signing")
|
||||
}
|
||||
|
||||
signature, err := signer.Sign(ctx, data)
|
||||
errCheck(err, "failed to sign")
|
||||
if !alreadyUnlocked {
|
||||
if err := lock(account); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to lock account")
|
||||
}
|
||||
}
|
||||
return signature, err
|
||||
}
|
||||
|
||||
// unlock attempts to unlock an account. It returns true if the account was already unlocked.
|
||||
func unlock(account e2wtypes.Account) (bool, error) {
|
||||
locker, isAccountLocker := account.(e2wtypes.AccountLocker)
|
||||
if !isAccountLocker {
|
||||
outputIf(debug, "Account does not support unlocking")
|
||||
// This account doesn't support unlocking; return okay.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
alreadyUnlocked, err := locker.IsUnlocked(ctx)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "unable to ascertain if account is unlocked")
|
||||
}
|
||||
|
||||
if alreadyUnlocked {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Not already unlocked; attempt to unlock it.
|
||||
for _, passphrase := range getPassphrases() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
err = locker.Unlock(ctx, []byte(passphrase))
|
||||
cancel()
|
||||
if err == nil {
|
||||
// Unlocked.
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Failed to unlock it.
|
||||
return false, errors.New("failed to unlock account")
|
||||
}
|
||||
|
||||
// lock attempts to lock an account.
|
||||
func lock(account e2wtypes.Account) error {
|
||||
locker, isAccountLocker := account.(e2wtypes.AccountLocker)
|
||||
if !isAccountLocker {
|
||||
return nil
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
return locker.Lock(ctx)
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -21,9 +22,11 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/go-ssz"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/wealdtech/ethdo/grpc"
|
||||
e2types "github.com/wealdtech/go-eth2-types/v2"
|
||||
util "github.com/wealdtech/go-eth2-util"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
string2eth "github.com/wealdtech/go-string2eth"
|
||||
)
|
||||
|
||||
@@ -47,28 +50,34 @@ The information generated can be passed to ethereal to create a deposit from the
|
||||
|
||||
In quiet mode this will return 0 if the the data can be generated correctly, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
assert(validatorDepositDataValidatorAccount != "", "--validatoraccount is required")
|
||||
validatorWallet, err := walletFromPath(validatorDepositDataValidatorAccount)
|
||||
validatorWalletName, validatorAccountSpec, err := e2wallet.WalletAndAccountNames(validatorDepositDataValidatorAccount)
|
||||
errCheck(err, "Failed to obtain wallet and account names")
|
||||
validatorWallet, err := openNamedWallet(validatorWalletName)
|
||||
errCheck(err, "Failed to obtain validator wallet")
|
||||
validatorAccounts, err := accountsFromPath(validatorDepositDataValidatorAccount)
|
||||
validatorAccounts, err := accountsFromPath(ctx, validatorWallet, validatorAccountSpec)
|
||||
errCheck(err, "Failed to obtain validator account")
|
||||
assert(len(validatorAccounts) > 0, "Failed to obtain validator account")
|
||||
if len(validatorAccounts) == 1 {
|
||||
outputIf(debug, fmt.Sprintf("Validator public key is %048x", validatorAccounts[0].PublicKey().Marshal()))
|
||||
} else {
|
||||
for _, validatorAccount := range validatorAccounts {
|
||||
outputIf(verbose, fmt.Sprintf("Creating deposit for %s/%s", validatorWallet.Name(), validatorAccount.Name()))
|
||||
outputIf(debug, fmt.Sprintf("Validator public key is %048x", validatorAccount.PublicKey().Marshal()))
|
||||
}
|
||||
|
||||
for _, validatorAccount := range validatorAccounts {
|
||||
outputIf(verbose, fmt.Sprintf("Creating deposit for %s/%s", validatorWallet.Name(), validatorAccount.Name()))
|
||||
pubKey, err := bestPublicKey(validatorAccount)
|
||||
errCheck(err, "Validator account does not provide a public key")
|
||||
outputIf(debug, fmt.Sprintf("Validator public key is %#x", pubKey.Marshal()))
|
||||
}
|
||||
|
||||
assert(validatorDepositDataWithdrawalAccount != "" || validatorDepositDataWithdrawalPubKey != "", "--withdrawalaccount or --withdrawalpubkey is required")
|
||||
var withdrawalCredentials []byte
|
||||
if validatorDepositDataWithdrawalAccount != "" {
|
||||
withdrawalAccount, err := accountFromPath(validatorDepositDataWithdrawalAccount)
|
||||
withdrawalAccount, err := accountFromPath(ctx, validatorDepositDataWithdrawalAccount)
|
||||
errCheck(err, "Failed to obtain withdrawal account")
|
||||
outputIf(debug, fmt.Sprintf("Withdrawal public key is %048x", withdrawalAccount.PublicKey().Marshal()))
|
||||
withdrawalCredentials = util.SHA256(withdrawalAccount.PublicKey().Marshal())
|
||||
pubKey, err := bestPublicKey(withdrawalAccount)
|
||||
errCheck(err, "Withdrawal account does not provide a public key")
|
||||
outputIf(debug, fmt.Sprintf("Withdrawal public key is %#x", pubKey.Marshal()))
|
||||
withdrawalCredentials = util.SHA256(pubKey.Marshal())
|
||||
errCheck(err, "Failed to hash withdrawal credentials")
|
||||
} else {
|
||||
withdrawalPubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(validatorDepositDataWithdrawalPubKey, "0x"))
|
||||
@@ -81,7 +90,7 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
|
||||
}
|
||||
// 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))
|
||||
outputIf(debug, fmt.Sprintf("Withdrawal credentials are %#x", withdrawalCredentials))
|
||||
|
||||
assert(validatorDepositDataDepositValue != "", "--depositvalue is required")
|
||||
val, err := string2eth.StringToGWei(validatorDepositDataDepositValue)
|
||||
@@ -92,12 +101,14 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
|
||||
// For each key, generate deposit data
|
||||
outputs := make([]string, 0)
|
||||
for _, validatorAccount := range validatorAccounts {
|
||||
validatorPubKey, err := bestPublicKey(validatorAccount)
|
||||
errCheck(err, "Validator account does not provide a public key")
|
||||
depositData := struct {
|
||||
PubKey []byte `ssz-size:"48"`
|
||||
WithdrawalCredentials []byte `ssz-size:"32"`
|
||||
Value uint64
|
||||
}{
|
||||
PubKey: validatorAccount.PublicKey().Marshal(),
|
||||
PubKey: validatorPubKey.Marshal(),
|
||||
WithdrawalCredentials: withdrawalCredentials,
|
||||
Value: val,
|
||||
}
|
||||
@@ -124,17 +135,7 @@ 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))
|
||||
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")
|
||||
|
||||
signedDepositData := struct {
|
||||
@@ -143,12 +144,18 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
|
||||
Value uint64
|
||||
Signature []byte `ssz-size:"96"`
|
||||
}{
|
||||
PubKey: validatorAccount.PublicKey().Marshal(),
|
||||
PubKey: validatorPubKey.Marshal(),
|
||||
WithdrawalCredentials: withdrawalCredentials,
|
||||
Value: val,
|
||||
Signature: signature.Marshal(),
|
||||
}
|
||||
outputIf(debug, fmt.Sprintf("Signed deposit data:\n\tPublic key: %x\n\tWithdrawal credentials: %x\n\tValue: %d\n\tSignature: %x", signedDepositData.PubKey, signedDepositData.WithdrawalCredentials, signedDepositData.Value, signedDepositData.Signature))
|
||||
if debug {
|
||||
fmt.Printf("Signed deposit data:\n")
|
||||
fmt.Printf(" Public key: %#x\n", signedDepositData.PubKey)
|
||||
fmt.Printf(" Withdrawal credentials: %#x\n", signedDepositData.WithdrawalCredentials)
|
||||
fmt.Printf(" Value: %d\n", signedDepositData.Value)
|
||||
fmt.Printf(" Signature: %#x\n", signedDepositData.Signature)
|
||||
}
|
||||
|
||||
depositDataRoot, err := ssz.HashTreeRoot(signedDepositData)
|
||||
errCheck(err, "Failed to generate deposit data root")
|
||||
@@ -167,7 +174,7 @@ In quiet mode this will return 0 if the the data can be generated correctly, oth
|
||||
txData = append(txData, depositDataRoot[:]...)
|
||||
// Validator public key (pad to 32-byte boundary)
|
||||
txData = append(txData, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30}...)
|
||||
txData = append(txData, validatorAccount.PublicKey().Marshal()...)
|
||||
txData = append(txData, validatorPubKey.Marshal()...)
|
||||
txData = append(txData, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}...)
|
||||
// Withdrawal credentials
|
||||
txData = append(txData, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20}...)
|
||||
@@ -177,7 +184,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":2}`, fmt.Sprintf("%s/%s", validatorWallet.Name(), validatorAccount.Name()), signedDepositData.PubKey, signedDepositData.WithdrawalCredentials, signedDepositData.Signature, val, depositDataRoot))
|
||||
outputs = append(outputs, fmt.Sprintf(`{"name":"Deposit for %s","account":"%s","pubkey":"%#x","withdrawal_credentials":"%#x","signature":"%#x","value":%d,"deposit_data_root":"%#x","version":2}`, fmt.Sprintf("%s/%s", validatorWallet.Name(), validatorAccount.Name()), fmt.Sprintf("%s/%s", validatorWallet.Name(), validatorAccount.Name()), signedDepositData.PubKey, signedDepositData.WithdrawalCredentials, signedDepositData.Signature, val, depositDataRoot))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,30 +46,33 @@ var validatorExitCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the transaction has been generated, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
err := connect()
|
||||
errCheck(err, "Failed to obtain connect to Ethereum 2 beacon chain node")
|
||||
|
||||
exit, signature := validatorExitHandleInput()
|
||||
validatorExitHandleExit(exit, signature)
|
||||
exit, signature := validatorExitHandleInput(ctx)
|
||||
validatorExitHandleExit(ctx, exit, signature)
|
||||
os.Exit(_exitSuccess)
|
||||
},
|
||||
}
|
||||
|
||||
func validatorExitHandleInput() (*ethpb.VoluntaryExit, e2types.Signature) {
|
||||
func validatorExitHandleInput(ctx context.Context) (*ethpb.VoluntaryExit, e2types.Signature) {
|
||||
if validatorExitJSON != "" {
|
||||
return validatorExitHandleJSONInput(validatorExitJSON)
|
||||
}
|
||||
if rootAccount != "" {
|
||||
account, err := accountFromPath(rootAccount)
|
||||
if viper.GetString("account") != "" {
|
||||
account, err := accountFromPath(ctx, viper.GetString("account"))
|
||||
errCheck(err, "Failed to access account")
|
||||
return validatorExitHandleAccountInput(account)
|
||||
return validatorExitHandleAccountInput(ctx, 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)
|
||||
return validatorExitHandleAccountInput(ctx, account)
|
||||
}
|
||||
die("one of --json, --account or --key is required")
|
||||
return nil, nil
|
||||
@@ -88,7 +91,7 @@ func validatorExitHandleJSONInput(input string) (*ethpb.VoluntaryExit, e2types.S
|
||||
return exit, signature
|
||||
}
|
||||
|
||||
func validatorExitHandleAccountInput(account e2wtypes.Account) (*ethpb.VoluntaryExit, e2types.Signature) {
|
||||
func validatorExitHandleAccountInput(ctx context.Context, account e2wtypes.Account) (*ethpb.VoluntaryExit, e2types.Signature) {
|
||||
exit := ðpb.VoluntaryExit{}
|
||||
|
||||
// Beacon chain config required for later work.
|
||||
@@ -141,23 +144,19 @@ func validatorExitHandleAccountInput(account e2wtypes.Account) (*ethpb.Voluntary
|
||||
errCheck(err, "Failed to obtain genesis validators root")
|
||||
domain := e2types.Domain(e2types.DomainVoluntaryExit, currentForkVersion, genesisValidatorsRoot)
|
||||
|
||||
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")
|
||||
alreadyUnlocked, err := unlock(account)
|
||||
errCheck(err, "Failed to unlock account; please confirm passphrase is correct")
|
||||
signature, err := signStruct(account, exit, domain)
|
||||
if !alreadyUnlocked {
|
||||
errCheck(lock(account), "Failed to re-lock account")
|
||||
}
|
||||
errCheck(err, "Failed to sign exit proposal")
|
||||
|
||||
return exit, signature
|
||||
}
|
||||
|
||||
// validatorExitHandleExit handles the exit request.
|
||||
func validatorExitHandleExit(exit *ethpb.VoluntaryExit, signature e2types.Signature) {
|
||||
func validatorExitHandleExit(ctx context.Context, exit *ethpb.VoluntaryExit, signature e2types.Signature) {
|
||||
if validatorExitJSONOutput {
|
||||
data := &validatorExitData{
|
||||
Epoch: exit.Epoch,
|
||||
@@ -174,8 +173,6 @@ func validatorExitHandleExit(exit *ethpb.VoluntaryExit, signature e2types.Signat
|
||||
}
|
||||
|
||||
validatorClient := ethpb.NewBeaconNodeValidatorClient(eth2GRPCConn)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
_, err := validatorClient.ProposeExit(ctx, proposal)
|
||||
errCheck(err, "Failed to propose exit")
|
||||
outputIf(!quiet, "Validator exit transaction sent")
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -22,9 +23,11 @@ import (
|
||||
|
||||
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"
|
||||
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"
|
||||
string2eth "github.com/wealdtech/go-string2eth"
|
||||
)
|
||||
|
||||
@@ -40,15 +43,23 @@ var validatorInfoCmd = &cobra.Command{
|
||||
In quiet mode this will return 0 if the validator information can be obtained, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
// Sanity checking and setup.
|
||||
assert(rootAccount != "" || validatorInfoPubKey != "", "--account or --pubkey is required")
|
||||
assert(viper.GetString("account") != "" || validatorInfoPubKey != "", "--account or --pubkey is required")
|
||||
|
||||
err := connect()
|
||||
errCheck(err, "Failed to obtain connection to Ethereum 2 beacon chain node")
|
||||
|
||||
var account types.Account
|
||||
if rootAccount != "" {
|
||||
account, err = accountFromPath(rootAccount)
|
||||
errCheck(err, "Failed to access account")
|
||||
var account e2wtypes.Account
|
||||
if viper.GetString("account") != "" {
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
_, accountName, err := e2wallet.WalletAndAccountNames(viper.GetString("account"))
|
||||
errCheck(err, "Failed to obtain account name")
|
||||
accountByNameProvider, isAccountByNameProvider := wallet.(e2wtypes.WalletAccountByNameProvider)
|
||||
assert(isAccountByNameProvider, "wallet cannot obtain accounts by name")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
account, err = accountByNameProvider.AccountByName(ctx, accountName)
|
||||
errCheck(err, "Failed to obtain account")
|
||||
} else {
|
||||
pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(validatorInfoPubKey, "0x"))
|
||||
errCheck(err, fmt.Sprintf("Failed to decode public key %s", validatorInfoPubKey))
|
||||
|
||||
@@ -30,7 +30,7 @@ var versionCmd = &cobra.Command{
|
||||
|
||||
ethdo version.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Println("1.4.21")
|
||||
fmt.Println("1.5.0-prerelease")
|
||||
if viper.GetBool("verbose") {
|
||||
buildInfo, ok := dbg.ReadBuildInfo()
|
||||
if ok {
|
||||
|
||||
@@ -15,10 +15,10 @@ package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var walletWallet string
|
||||
|
||||
// walletCmd represents the wallet command
|
||||
var walletCmd = &cobra.Command{
|
||||
Use: "wallet",
|
||||
@@ -30,6 +30,16 @@ func init() {
|
||||
RootCmd.AddCommand(walletCmd)
|
||||
}
|
||||
|
||||
var walletFlag *pflag.Flag
|
||||
|
||||
func walletFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().StringVar(&walletWallet, "wallet", "", "Name of the wallet")
|
||||
if walletFlag == nil {
|
||||
cmd.Flags().String("wallet", "", "Name of the wallet")
|
||||
walletFlag = cmd.Flags().Lookup("wallet")
|
||||
if err := viper.BindPFlag("wallet", walletFlag); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
cmd.Flags().AddFlag(walletFlag)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
pb "github.com/wealdtech/eth2-signer-api/pb/v1"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
var walletAccountsCmd = &cobra.Command{
|
||||
@@ -32,52 +32,35 @@ var walletAccountsCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the wallet holds any addresses, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(walletWallet != "", "--wallet is required")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
assert(viper.GetString("wallet") != "", "wallet is required")
|
||||
|
||||
wallet, err := openWallet()
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
hasAccounts := false
|
||||
|
||||
if remote {
|
||||
listerClient := pb.NewListerClient(remoteGRPCConn)
|
||||
listAccountsReq := &pb.ListAccountsRequest{
|
||||
Paths: []string{
|
||||
walletWallet,
|
||||
},
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
accountsResp, err := listerClient.ListAccounts(ctx, listAccountsReq)
|
||||
errCheck(err, "Failed to access wallet")
|
||||
assert(accountsResp.State == pb.ResponseState_SUCCEEDED, "Request to list wallet accounts failed")
|
||||
walletPrefixLen := len(walletWallet) + 1
|
||||
for _, account := range accountsResp.Accounts {
|
||||
hasAccounts = true
|
||||
if verbose {
|
||||
fmt.Printf("%s\n", account.Name[walletPrefixLen:])
|
||||
fmt.Printf("\tPublic key: %#048x\n", account.PublicKey)
|
||||
} else if !quiet {
|
||||
fmt.Printf("%s\n", account.Name[walletPrefixLen:])
|
||||
for account := range wallet.Accounts(ctx) {
|
||||
hasAccounts = true
|
||||
outputIf(!quiet, account.Name())
|
||||
if verbose {
|
||||
fmt.Printf(" UUID: %v\n", account.ID())
|
||||
pubKeyProvider, isProvider := account.(e2wtypes.AccountPublicKeyProvider)
|
||||
if isProvider {
|
||||
fmt.Printf(" Public key: %#x\n", pubKeyProvider.PublicKey().Marshal())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wallet, err := walletFromPath(walletWallet)
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
for account := range wallet.Accounts() {
|
||||
hasAccounts = true
|
||||
if verbose {
|
||||
fmt.Printf("%s\n\tUUID:\t\t%s\n\tPublic key:\t0x%048x\n", account.Name(), account.ID(), account.PublicKey().Marshal())
|
||||
} else if !quiet {
|
||||
fmt.Printf("%s\n", account.Name())
|
||||
compositePubKeyProvider, isProvider := account.(e2wtypes.AccountCompositePublicKeyProvider)
|
||||
if isProvider {
|
||||
fmt.Printf(" Composite public key: %#x\n", compositePubKeyProvider.CompositePublicKey().Marshal())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if quiet {
|
||||
if hasAccounts {
|
||||
os.Exit(_exitSuccess)
|
||||
}
|
||||
os.Exit(_exitFailure)
|
||||
if hasAccounts {
|
||||
os.Exit(_exitSuccess)
|
||||
}
|
||||
os.Exit(_exitFailure)
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
bip39 "github.com/tyler-smith/go-bip39"
|
||||
distributed "github.com/wealdtech/go-eth2-wallet-distributed"
|
||||
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
|
||||
hd "github.com/wealdtech/go-eth2-wallet-hd/v2"
|
||||
nd "github.com/wealdtech/go-eth2-wallet-nd/v2"
|
||||
@@ -35,18 +38,24 @@ var walletCreateCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the wallet is created successfully, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "wallet create not available with remote wallets")
|
||||
assert(walletWallet != "", "--wallet is required")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
assert(viper.GetString("remote") == "", "wallet create not available with remote wallets")
|
||||
assert(viper.GetString("wallet") != "", "--wallet is required")
|
||||
assert(walletCreateType != "", "--type is required")
|
||||
|
||||
var err error
|
||||
switch strings.ToLower(walletCreateType) {
|
||||
case "non-deterministic", "nd":
|
||||
assert(walletCreateSeed == "", "--seed is not allowed with non-deterministic wallets")
|
||||
err = walletCreateND(walletWallet)
|
||||
err = walletCreateND(ctx, viper.GetString("wallet"))
|
||||
case "hierarchical deterministic", "hd":
|
||||
assert(getWalletPassphrase() != "", "--walletpassphrase is required for hierarchical deterministic wallets")
|
||||
err = walletCreateHD(walletWallet, getWalletPassphrase(), walletCreateSeed)
|
||||
err = walletCreateHD(ctx, viper.GetString("wallet"), getWalletPassphrase(), walletCreateSeed)
|
||||
case "distributed":
|
||||
assert(walletCreateSeed == "", "--seed is not allowed with distributed wallets")
|
||||
err = walletCreateDistributed(ctx, viper.GetString("wallet"))
|
||||
default:
|
||||
die("unknown wallet type")
|
||||
}
|
||||
@@ -55,13 +64,19 @@ In quiet mode this will return 0 if the wallet is created successfully, otherwis
|
||||
}
|
||||
|
||||
// walletCreateND creates a non-deterministic wallet.
|
||||
func walletCreateND(name string) error {
|
||||
_, err := nd.CreateWallet(name, store, keystorev4.New())
|
||||
func walletCreateND(ctx context.Context, name string) error {
|
||||
_, err := nd.CreateWallet(ctx, name, store, keystorev4.New())
|
||||
return err
|
||||
}
|
||||
|
||||
// walletCreateDistributed creates a distributed wallet.
|
||||
func walletCreateDistributed(ctx context.Context, name string) error {
|
||||
_, err := distributed.CreateWallet(ctx, name, store, keystorev4.New())
|
||||
return err
|
||||
}
|
||||
|
||||
// walletCreateND creates a hierarchical-deterministic wallet.
|
||||
func walletCreateHD(name string, passphrase string, seedPhrase string) error {
|
||||
func walletCreateHD(ctx context.Context, name string, passphrase string, seedPhrase string) error {
|
||||
encryptor := keystorev4.New()
|
||||
if seedPhrase != "" {
|
||||
// Create wallet from a user-supplied seed.
|
||||
@@ -71,11 +86,11 @@ func walletCreateHD(name string, passphrase string, seedPhrase string) error {
|
||||
// Strip checksum; last byte.
|
||||
seed = seed[:len(seed)-1]
|
||||
assert(len(seed) == 32, "Seed must have 24 words")
|
||||
_, err = hd.CreateWalletFromSeed(name, []byte(passphrase), store, encryptor, seed)
|
||||
_, err = hd.CreateWalletFromSeed(ctx, name, []byte(passphrase), store, encryptor, seed)
|
||||
return err
|
||||
}
|
||||
// Create wallet with a random seed.
|
||||
_, err := hd.CreateWallet(name, []byte(passphrase), store, encryptor)
|
||||
_, err := hd.CreateWallet(ctx, name, []byte(passphrase), store, encryptor)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
@@ -30,10 +31,10 @@ var walletDeleteCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the wallet has been deleted, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "wallet delete not available with remote wallets")
|
||||
assert(walletWallet != "", "--wallet is required")
|
||||
assert(viper.GetString("remote") == "", "wallet delete not available with remote wallets")
|
||||
assert(viper.GetString("wallet") != "", "--wallet is required")
|
||||
|
||||
wallet, err := walletFromPath(walletWallet)
|
||||
wallet, err := walletFromPath(viper.GetString("wallet"))
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
storeProvider, ok := wallet.(wtypes.StoreProvider)
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
types "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
@@ -32,17 +34,20 @@ var walletExportCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the wallet is able to be exported, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "wallet export not available with remote wallets")
|
||||
assert(walletWallet != "", "--wallet is required")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
assert(viper.GetString("remote") == "", "wallet export not available with remote wallets")
|
||||
assert(viper.GetString("wallet") != "", "--wallet is required")
|
||||
assert(walletExportPassphrase != "", "--exportpassphrase is required")
|
||||
|
||||
wallet, err := walletFromPath(walletWallet)
|
||||
wallet, err := walletFromPath(viper.GetString("wallet"))
|
||||
errCheck(err, "Failed to access wallet")
|
||||
|
||||
_, ok := wallet.(types.WalletExporter)
|
||||
assert(ok, fmt.Sprintf("wallets of type %q do not allow exporting accounts", wallet.Type()))
|
||||
|
||||
exportData, err := wallet.(types.WalletExporter).Export([]byte(walletExportPassphrase))
|
||||
exportData, err := wallet.(types.WalletExporter).Export(ctx, []byte(walletExportPassphrase))
|
||||
errCheck(err, "Failed to export wallet")
|
||||
|
||||
outputIf(!quiet, fmt.Sprintf("0x%x", exportData))
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/wealdtech/go-bytesutil"
|
||||
"github.com/wealdtech/go-ecodec"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
@@ -40,10 +41,10 @@ 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(viper.GetString("remote") == "", "wallet import not available with remote wallets")
|
||||
assert(walletImportData != "", "--importdata is required")
|
||||
assert(walletImportPassphrase != "", "--importpassphrase is required")
|
||||
assert(walletWallet == "", "--wallet is not allowed (the wallet will retain its name)")
|
||||
assert(viper.GetString("wallet") == "", "--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))
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
@@ -31,10 +33,13 @@ var walletInfoCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the wallet exists, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "wallet info not available with remote wallets")
|
||||
assert(walletWallet != "", "--wallet is required")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
wallet, err := walletFromPath(walletWallet)
|
||||
assert(viper.GetString("remote") == "", "wallet info not available with remote wallets")
|
||||
assert(viper.GetString("wallet") != "", "--wallet is required")
|
||||
|
||||
wallet, err := walletFromPath(viper.GetString("wallet"))
|
||||
errCheck(err, "unknown wallet")
|
||||
|
||||
if quiet {
|
||||
@@ -55,7 +60,7 @@ In quiet mode this will return 0 if the wallet exists, otherwise 1.`,
|
||||
|
||||
// Count the accounts.
|
||||
accounts := 0
|
||||
for range wallet.Accounts() {
|
||||
for range wallet.Accounts(ctx) {
|
||||
accounts++
|
||||
}
|
||||
fmt.Printf("Accounts: %d\n", accounts)
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
e2wallet "github.com/wealdtech/go-eth2-wallet"
|
||||
)
|
||||
|
||||
@@ -30,17 +31,14 @@ var walletListCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if any wallets are found, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "wallet list not available with remote wallets")
|
||||
assert(viper.GetString("remote") == "", "wallet list not available with remote wallets")
|
||||
assert(viper.GetString("wallet") == "", "wallet list does not take a --wallet parameter")
|
||||
|
||||
walletsFound := false
|
||||
if remote {
|
||||
die("Remote wallets cannot be listed")
|
||||
} else {
|
||||
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()))
|
||||
}
|
||||
for w := range e2wallet.Wallets() {
|
||||
walletsFound = true
|
||||
outputIf(!quiet && !verbose, w.Name())
|
||||
outputIf(verbose, fmt.Sprintf("%s\n UUID: %s", w.Name(), w.ID().String()))
|
||||
}
|
||||
|
||||
if !walletsFound {
|
||||
|
||||
@@ -15,12 +15,14 @@ package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
bip39 "github.com/tyler-smith/go-bip39"
|
||||
types "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
)
|
||||
|
||||
var walletSeedCmd = &cobra.Command{
|
||||
@@ -32,18 +34,25 @@ var walletSeedCmd = &cobra.Command{
|
||||
|
||||
In quiet mode this will return 0 if the wallet is a hierarchical deterministic wallet, otherwise 1.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
assert(!remote, "wallet seed not available with remote wallets")
|
||||
assert(walletWallet != "", "--wallet is required")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
assert(viper.GetString("remote") == "", "wallet seed not available with remote wallets")
|
||||
assert(viper.GetString("wallet") != "", "--wallet is required")
|
||||
assert(getWalletPassphrase() != "", "--walletpassphrase is required")
|
||||
|
||||
wallet, err := walletFromPath(walletWallet)
|
||||
wallet, err := walletFromPath(viper.GetString("wallet"))
|
||||
errCheck(err, "Failed to access wallet")
|
||||
_, ok := wallet.(types.WalletKeyProvider)
|
||||
_, ok := wallet.(e2wtypes.WalletKeyProvider)
|
||||
assert(ok, fmt.Sprintf("wallets of type %q do not have a seed", wallet.Type()))
|
||||
|
||||
err = wallet.Unlock([]byte(getWalletPassphrase()))
|
||||
errCheck(err, "Failed to unlock wallet")
|
||||
seed, err := wallet.(types.WalletKeyProvider).Key()
|
||||
locker, isLocker := wallet.(e2wtypes.WalletLocker)
|
||||
if isLocker {
|
||||
errCheck(locker.Unlock(ctx, []byte(getWalletPassphrase())), "Failed to unlock wallet")
|
||||
}
|
||||
keyProvider, isKeyProvider := wallet.(e2wtypes.WalletKeyProvider)
|
||||
assert(isKeyProvider, "Wallet does not provide key")
|
||||
seed, err := keyProvider.Key(ctx)
|
||||
errCheck(err, "Failed to obtain wallet key")
|
||||
outputIf(debug, fmt.Sprintf("Seed is %#x", seed))
|
||||
seedStr, err := bip39.NewMnemonic(seed)
|
||||
|
||||
27
go.mod
27
go.mod
@@ -8,6 +8,7 @@ require (
|
||||
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/herumi/bls-eth-go-binary v0.0.0-20200719025738-3e30d132e8f6
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/mapstructure v1.3.2 // indirect
|
||||
github.com/pelletier/go-toml v1.8.0 // indirect
|
||||
@@ -20,25 +21,25 @@ require (
|
||||
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/pflag v1.0.5
|
||||
github.com/spf13/viper v1.7.0
|
||||
github.com/tyler-smith/go-bip39 v1.0.2
|
||||
github.com/wealdtech/eth2-signer-api v1.4.0
|
||||
github.com/wealdtech/eth2-signer-api v1.5.2
|
||||
github.com/wealdtech/go-bytesutil v1.1.1
|
||||
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-types/v2 v2.5.0
|
||||
github.com/wealdtech/go-eth2-util v1.5.0
|
||||
github.com/wealdtech/go-eth2-wallet v1.11.0
|
||||
github.com/wealdtech/go-eth2-wallet-dirk v1.0.0
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.0.1
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.0.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-eth2-wallet-hd/v2 v2.2.0
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.2.0
|
||||
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.1
|
||||
github.com/wealdtech/go-eth2-wallet-store-s3 v1.8.0
|
||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.5.0
|
||||
github.com/wealdtech/go-string2eth v1.1.0
|
||||
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
|
||||
google.golang.org/grpc v1.30.0
|
||||
gopkg.in/ini.v1 v1.57.0 // indirect
|
||||
)
|
||||
|
||||
150
go.sum
150
go.sum
@@ -14,7 +14,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
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=
|
||||
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
||||
@@ -26,10 +25,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.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/aws/aws-sdk-go v1.33.5 h1:p2fr1ryvNTU6avUWLI+/H7FGv0TBIjzVM5WDgXBBv4U=
|
||||
github.com/aws/aws-sdk-go v1.33.5/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=
|
||||
@@ -53,6 +52,8 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
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/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI=
|
||||
github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
@@ -64,7 +65,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
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=
|
||||
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=
|
||||
@@ -74,45 +74,37 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
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=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
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=
|
||||
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/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
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=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
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/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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=
|
||||
@@ -128,7 +120,6 @@ github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoA
|
||||
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.13.0/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.14.6 h1:8ERzHx8aj1Sc47mu9n/AksaKCSWrMchFtkdrS4BIj5o=
|
||||
@@ -154,12 +145,20 @@ 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-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/herumi/bls-eth-go-binary v0.0.0-20200624084043-9b7da5962ccb h1:rVlcEzuK/AJKzJp890JoSpJdU3hgak53oMB9mypa05s=
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20200624084043-9b7da5962ccb/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20200703070911-61704dac4ad1 h1:da7FT3Bhp8GCx6TwDPQio/7GLRLR5hcZvoRb89hfc08=
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20200703070911-61704dac4ad1/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20200706085701-832d8c2c0f7d h1:P8yaFmLwc5ZlUx2sHuawcdQvpv5/0GM+WEGJ07ljN3g=
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20200706085701-832d8c2c0f7d/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20200719025738-3e30d132e8f6 h1:xOOHoKwCj0WXm60FqRxQ0u8cLr+kq5DJUlPspEPsu/s=
|
||||
github.com/herumi/bls-eth-go-binary v0.0.0-20200719025738-3e30d132e8f6/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/jackc/puddle v1.1.1 h1:PJAw7H/9hoWC4Kf3J8iNmL1SwA6E8vfsLqBiL+F6CtI=
|
||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
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=
|
||||
@@ -198,7 +197,6 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
|
||||
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.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
|
||||
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
@@ -210,8 +208,9 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
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/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
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=
|
||||
@@ -230,20 +229,14 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
|
||||
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/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=
|
||||
@@ -252,6 +245,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
|
||||
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/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y=
|
||||
github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10=
|
||||
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=
|
||||
@@ -262,14 +257,12 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
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.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=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
@@ -278,7 +271,6 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
@@ -289,64 +281,78 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
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=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
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/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk=
|
||||
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.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/eth2-signer-api v1.5.0 h1:XkaEk7Y0vFbqUstHcCjVGssoqJy4zYnBcF76em1oWX8=
|
||||
github.com/wealdtech/eth2-signer-api v1.5.0/go.mod h1:5wlLQ7NO7nbXo3znJOwIWHN8S4C3xHcZ0uOg9Ue4mvg=
|
||||
github.com/wealdtech/eth2-signer-api v1.5.1 h1:RQb1xyZEcHGpVFNpTEKzLbGH/H04Ajb6y99b2sd8gVs=
|
||||
github.com/wealdtech/eth2-signer-api v1.5.1/go.mod h1:5wlLQ7NO7nbXo3znJOwIWHN8S4C3xHcZ0uOg9Ue4mvg=
|
||||
github.com/wealdtech/eth2-signer-api v1.5.2 h1:3jw8MW0r7KlX9bme0q6j+QMa8osRhEnKLkgkECH6xcU=
|
||||
github.com/wealdtech/eth2-signer-api v1.5.2/go.mod h1:5wlLQ7NO7nbXo3znJOwIWHN8S4C3xHcZ0uOg9Ue4mvg=
|
||||
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.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-types/v2 v2.4.3 h1:VFYVYw9J2P/HFXi7T9HX7vzM+xx6BZ4od5PlVsUP5OE=
|
||||
github.com/wealdtech/go-eth2-types/v2 v2.4.3/go.mod h1:hhKa4ZFaNU2fwUjEh8GYr8wKg5D1W4QyxZ3xpsb/2hw=
|
||||
github.com/wealdtech/go-eth2-types/v2 v2.5.0 h1:L8sl3yoICAbn3134CBLNUt0o5h2voe0Es2KD5O9r8YQ=
|
||||
github.com/wealdtech/go-eth2-types/v2 v2.5.0/go.mod h1:321w9X26lAnNa/lQJi2A6Lap5IsNORoLwFPoJ1i8QvY=
|
||||
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-util v1.3.0 h1:aX1+PnxB904GIf5JE9GRKYPuGQJsCT+Q7PG9BMeFN40=
|
||||
github.com/wealdtech/go-eth2-util v1.3.0/go.mod h1:nSHpt/mdwn1LyLiNzjGPH1DDIYdBENLFaY1fSRr+aKg=
|
||||
github.com/wealdtech/go-eth2-util v1.5.0 h1:b3fgyvoq/WocW9LkWT7zcO5VCKzKLCc97rPrk/B9oIc=
|
||||
github.com/wealdtech/go-eth2-util v1.5.0/go.mod h1:0PGWeWWc6qjky/aNjdPdguJdZ2HSEHHCA+3cTjvT+Hk=
|
||||
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 v1.11.0 h1:2KfrWDqF4sWGgk4N5+DaYmh0hOnqiCl0P4vCz5mx17U=
|
||||
github.com/wealdtech/go-eth2-wallet v1.11.0/go.mod h1:E9ZRNO4JNdi27ys7oc+xWWucXu4IGfV5q1vWC9X3oqg=
|
||||
github.com/wealdtech/go-eth2-wallet-dirk v1.0.0 h1:1QUcWILF3h4OLCgTPpWklvRSuPu0fqrt15jwSm7CSC4=
|
||||
github.com/wealdtech/go-eth2-wallet-dirk v1.0.0/go.mod h1:VTzjJ51dedvYPr4huI7g7KXZVTpGR6ZrCDQwBxJpLck=
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.0.1 h1:3BxMII8T6t16g6lWcYWXjfdvaw8rXuwMQx9h0TG5wRg=
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.0.1/go.mod h1:Ha/8S+SCLEuSfXHdvhTLwnKaEF47o6gzQ+FURKwftvU=
|
||||
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.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-hd/v2 v2.2.0 h1:L+yrAn8TC9DQUw+S7moOJxQTp2jrHCoAZLpI747Nx2g=
|
||||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.2.0/go.mod h1:lhSwtkIO/Pfg5kz8k50yrDgj7ZQaElCPsXnixlrQn/I=
|
||||
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-nd/v2 v2.2.0 h1:h4eePfG0ANOJYMonmIYOvxJ9uLmBEX4APb2O8Vhtv6k=
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.2.0/go.mod h1:Un2EtseZWSObmTBjgkt7Qz2am54S/0115jrF83lto1U=
|
||||
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-filesystem v1.16.0 h1:sWuSrAKdWSphiQCVcThozaFgTrwemXNXDI5CnFcP02s=
|
||||
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.0/go.mod h1:FvjUHDbBuZrytZGOfhLWgtBoxtrWhvkD47ABrUXvHs4=
|
||||
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.1 h1:l9YV6OBqcxp5fjscK63lzuCUIye8ANACjJdpm5ULGS8=
|
||||
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.16.1/go.mod h1:Zxhj/4i8nRpk4LTTqFKbfI2KyvO3uqLMerNXqKZKDK0=
|
||||
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-s3 v1.8.0 h1:+q7p58NvOEfEDw8NgEoNaSG/s1eFHpyg91NEobA6RF0=
|
||||
github.com/wealdtech/go-eth2-wallet-store-s3 v1.8.0/go.mod h1:OxYD+d79StAOHigNaI5bWuvjhanEyrD4MqTj8hIvt2Y=
|
||||
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-store-scratch v1.5.0/go.mod h1:RMIIV5/N8TgukTVzyumQd7AplpC440ZXDSk8VffeEwQ=
|
||||
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-eth2-wallet-types/v2 v2.3.0-beta4 h1:VmpgUSr+aUexFmC2AYlQ7zpeAy0w0mcK58ihpDeMCL8=
|
||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.3.0-beta4/go.mod h1:5tVjyWK/jIzKaD+L8SCmHnc/eT9k+Fmm7zd8SwNB7jA=
|
||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.3.0 h1:PsCvp/lw7+h8Q0V3jL0f+/w2VmgS7m0mH48lbv/c2LY=
|
||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.3.0/go.mod h1:SLST6Pw/2wOEfsMYvIQjWlxbWX+jaZu8jIEbZJc4K5Q=
|
||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.5.0 h1:J29mbkSCUMl2xdu8Lg6U+JptFGfmli6xl04DAHtq9aM=
|
||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.5.0/go.mod h1:X9kYUH/E5YMqFMZ4xL6MJanABUkJGaH/yPZRT2o+yYA=
|
||||
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=
|
||||
@@ -365,12 +371,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
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-20200604202706-70a84ac30bf9 h1:vEg9joUBmeBcK9iSJftGNf3coIG4HqZElCPehJsfAYM=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
|
||||
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/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=
|
||||
@@ -405,12 +413,12 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR
|
||||
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-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/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
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=
|
||||
@@ -419,7 +427,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
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=
|
||||
@@ -437,15 +444,13 @@ 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-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/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/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=
|
||||
@@ -482,7 +487,6 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl
|
||||
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=
|
||||
@@ -496,54 +500,60 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx
|
||||
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/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/genproto v0.0.0-20200710124503-20a17af7bd0e h1:k+p/u26/lVeNEpdxSeUrm7rTvoFckBKaf7gTzgmHyDA=
|
||||
google.golang.org/genproto v0.0.0-20200710124503-20a17af7bd0e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200711021454-869866162049 h1:YFTFpQhgvrLrmxtiIncJxFXeCyq84ixuKWVCaCAi9Oc=
|
||||
google.golang.org/genproto v0.0.0-20200711021454-869866162049/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20200715011427-11fb19a81f2c h1:6DWnZZ6EY/59QRRQttZKiktVL23UuQYs7uy75MhhLRM=
|
||||
google.golang.org/genproto v0.0.0-20200715011427-11fb19a81f2c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
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.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.30.0 h1:M5a8xTlYTxwMn5ZFkwhRabsygDY5G8TYLyQDBxJNAxE=
|
||||
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
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.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=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
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.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=
|
||||
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=
|
||||
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.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
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=
|
||||
|
||||
@@ -20,11 +20,10 @@ import (
|
||||
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||||
wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
"github.com/spf13/viper"
|
||||
e2wtypes "github.com/wealdtech/go-eth2-wallet-types/v2"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// FetchChainConfig fetches the chain configuration from the beacon node.
|
||||
@@ -125,7 +124,7 @@ func FetchValidatorCommittees(conn *grpc.ClientConn, epoch uint64) (map[uint64][
|
||||
}
|
||||
|
||||
// FetchValidator fetches the validator definition from the beacon node.
|
||||
func FetchValidator(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.Validator, error) {
|
||||
func FetchValidator(conn *grpc.ClientConn, account e2wtypes.Account) (*ethpb.Validator, error) {
|
||||
if conn == nil {
|
||||
return nil, errors.New("no connection to beacon node")
|
||||
}
|
||||
@@ -133,9 +132,18 @@ func FetchValidator(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.Valid
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
var pubKey []byte
|
||||
if pubKeyProvider, ok := account.(e2wtypes.AccountCompositePublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.CompositePublicKey().Marshal()
|
||||
} else if pubKeyProvider, ok := account.(e2wtypes.AccountPublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.PublicKey().Marshal()
|
||||
} else {
|
||||
return nil, errors.New("Unable to obtain public key")
|
||||
}
|
||||
|
||||
req := ðpb.GetValidatorRequest{
|
||||
QueryFilter: ðpb.GetValidatorRequest_PublicKey{
|
||||
PublicKey: account.PublicKey().Marshal(),
|
||||
PublicKey: pubKey,
|
||||
},
|
||||
}
|
||||
return beaconClient.GetValidator(ctx, req)
|
||||
@@ -159,7 +167,7 @@ func FetchValidatorByIndex(conn *grpc.ClientConn, index uint64) (*ethpb.Validato
|
||||
}
|
||||
|
||||
// FetchValidatorBalance fetches the validator balance from the beacon node.
|
||||
func FetchValidatorBalance(conn *grpc.ClientConn, account wtypes.Account) (uint64, error) {
|
||||
func FetchValidatorBalance(conn *grpc.ClientConn, account e2wtypes.Account) (uint64, error) {
|
||||
if conn == nil {
|
||||
return 0, errors.New("no connection to beacon node")
|
||||
}
|
||||
@@ -167,8 +175,17 @@ func FetchValidatorBalance(conn *grpc.ClientConn, account wtypes.Account) (uint6
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
var pubKey []byte
|
||||
if pubKeyProvider, ok := account.(e2wtypes.AccountCompositePublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.CompositePublicKey().Marshal()
|
||||
} else if pubKeyProvider, ok := account.(e2wtypes.AccountPublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.PublicKey().Marshal()
|
||||
} else {
|
||||
return 0, errors.New("Unable to obtain public key")
|
||||
}
|
||||
|
||||
res, err := beaconClient.ListValidatorBalances(ctx, ðpb.ListValidatorBalancesRequest{
|
||||
PublicKeys: [][]byte{account.PublicKey().Marshal()},
|
||||
PublicKeys: [][]byte{pubKey},
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
@@ -180,7 +197,7 @@ func FetchValidatorBalance(conn *grpc.ClientConn, account wtypes.Account) (uint6
|
||||
}
|
||||
|
||||
// FetchValidatorPerformance fetches the validator performance from the beacon node.
|
||||
func FetchValidatorPerformance(conn *grpc.ClientConn, account wtypes.Account) (bool, bool, bool, uint64, int64, error) {
|
||||
func FetchValidatorPerformance(conn *grpc.ClientConn, account e2wtypes.Account) (bool, bool, bool, uint64, int64, error) {
|
||||
if conn == nil {
|
||||
return false, false, false, 0, 0, errors.New("no connection to beacon node")
|
||||
}
|
||||
@@ -188,8 +205,17 @@ func FetchValidatorPerformance(conn *grpc.ClientConn, account wtypes.Account) (b
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
var pubKey []byte
|
||||
if pubKeyProvider, ok := account.(e2wtypes.AccountCompositePublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.CompositePublicKey().Marshal()
|
||||
} else if pubKeyProvider, ok := account.(e2wtypes.AccountPublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.PublicKey().Marshal()
|
||||
} else {
|
||||
return false, false, false, 0, 0, errors.New("Unable to obtain public key")
|
||||
}
|
||||
|
||||
req := ðpb.ValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{account.PublicKey().Marshal()},
|
||||
PublicKeys: [][]byte{pubKey},
|
||||
}
|
||||
res, err := beaconClient.GetValidatorPerformance(ctx, req)
|
||||
if err != nil {
|
||||
@@ -207,7 +233,7 @@ func FetchValidatorPerformance(conn *grpc.ClientConn, account wtypes.Account) (b
|
||||
}
|
||||
|
||||
// FetchValidatorInfo fetches current validator info from the beacon node.
|
||||
func FetchValidatorInfo(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.ValidatorInfo, error) {
|
||||
func FetchValidatorInfo(conn *grpc.ClientConn, account e2wtypes.Account) (*ethpb.ValidatorInfo, error) {
|
||||
if conn == nil {
|
||||
return nil, errors.New("no connection to beacon node")
|
||||
}
|
||||
@@ -220,9 +246,18 @@ func FetchValidatorInfo(conn *grpc.ClientConn, account wtypes.Account) (*ethpb.V
|
||||
return nil, errors.Wrap(err, "failed to contact beacon node")
|
||||
}
|
||||
|
||||
var pubKey []byte
|
||||
if pubKeyProvider, ok := account.(e2wtypes.AccountCompositePublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.CompositePublicKey().Marshal()
|
||||
} else if pubKeyProvider, ok := account.(e2wtypes.AccountPublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.PublicKey().Marshal()
|
||||
} else {
|
||||
return nil, errors.New("Unable to obtain public key")
|
||||
}
|
||||
|
||||
changeSet := ðpb.ValidatorChangeSet{
|
||||
Action: ethpb.SetAction_SET_VALIDATOR_KEYS,
|
||||
PublicKeys: [][]byte{account.PublicKey().Marshal()},
|
||||
PublicKeys: [][]byte{pubKey},
|
||||
}
|
||||
err = stream.Send(changeSet)
|
||||
if err != nil {
|
||||
|
||||
@@ -33,9 +33,18 @@ func FetchValidatorIndex(conn *grpc.ClientConn, account wtypes.Account) (uint64,
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
var pubKey []byte
|
||||
if pubKeyProvider, ok := account.(wtypes.AccountCompositePublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.CompositePublicKey().Marshal()
|
||||
} else if pubKeyProvider, ok := account.(wtypes.AccountPublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.PublicKey().Marshal()
|
||||
} else {
|
||||
return 0, errors.New("Unable to obtain public key")
|
||||
}
|
||||
|
||||
// Fetch the account.
|
||||
req := ðpb.ValidatorIndexRequest{
|
||||
PublicKey: account.PublicKey().Marshal(),
|
||||
PublicKey: pubKey,
|
||||
}
|
||||
resp, err := validatorClient.ValidatorIndex(ctx, req)
|
||||
if err != nil {
|
||||
@@ -54,9 +63,18 @@ func FetchValidatorState(conn *grpc.ClientConn, account wtypes.Account) (ethpb.V
|
||||
ctx, cancel := context.WithTimeout(context.Background(), viper.GetDuration("timeout"))
|
||||
defer cancel()
|
||||
|
||||
var pubKey []byte
|
||||
if pubKeyProvider, ok := account.(wtypes.AccountCompositePublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.CompositePublicKey().Marshal()
|
||||
} else if pubKeyProvider, ok := account.(wtypes.AccountPublicKeyProvider); ok {
|
||||
pubKey = pubKeyProvider.PublicKey().Marshal()
|
||||
} else {
|
||||
return ethpb.ValidatorStatus_UNKNOWN_STATUS, errors.New("Unable to obtain public key")
|
||||
}
|
||||
|
||||
// Fetch the account.
|
||||
req := ðpb.ValidatorStatusRequest{
|
||||
PublicKey: account.PublicKey().Marshal(),
|
||||
PublicKey: pubKey,
|
||||
}
|
||||
resp, err := validatorClient.ValidatorStatus(ctx, req)
|
||||
if err != nil {
|
||||
|
||||
31
util/bls.go
Normal file
31
util/bls.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright © 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 util
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/herumi/bls-eth-go-binary/bls"
|
||||
)
|
||||
|
||||
// BLSID turns a uint64 in to a BLS identifier.
|
||||
func BLSID(id uint64) *bls.ID {
|
||||
var res bls.ID
|
||||
buf := [8]byte{}
|
||||
binary.LittleEndian.PutUint64(buf[:], id)
|
||||
if err := res.SetLittleEndian(buf[:]); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &res
|
||||
}
|
||||
Reference in New Issue
Block a user