Remove keystore keymanager from validator (#5236)

* Remove keystore keymanager from validator

* Update dependency

* Update validator/flags/flags.go

* Update validator/flags/flags.go

Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com>
This commit is contained in:
Jim McDonald
2020-03-30 05:49:02 +01:00
committed by GitHub
parent b2375aeccf
commit 46008770c1
18 changed files with 74 additions and 526 deletions

View File

@@ -15,7 +15,7 @@ var (
// DataDirFlag defines a path on disk.
DataDirFlag = &cli.StringFlag{
Name: "datadir",
Usage: "Data directory for the databases and keystore",
Usage: "Data directory for the databases",
Value: DefaultDataDir(),
}
// EnableTracingFlag defines a flag to enable p2p message tracing.

View File

@@ -17,9 +17,7 @@ go_library(
"//shared/debug:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/logutil:go_default_library",
"//shared/params:go_default_library",
"//shared/version:go_default_library",
"//validator/accounts:go_default_library",
"//validator/flags:go_default_library",
"//validator/node:go_default_library",
"@com_github_joonix_log//:go_default_library",
@@ -52,7 +50,6 @@ go_image(
"//shared/logutil:go_default_library",
"//shared/params:go_default_library",
"//shared/version:go_default_library",
"//validator/accounts:go_default_library",
"//validator/flags:go_default_library",
"//validator/node:go_default_library",
"@com_github_joonix_log//:go_default_library",

View File

@@ -1,31 +0,0 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["account.go"],
importpath = "github.com/prysmaticlabs/prysm/validator/accounts",
visibility = [
"//validator:__pkg__",
"//validator:__subpackages__",
],
deps = [
"//contracts/deposit-contract:go_default_library",
"//shared/keystore:go_default_library",
"//shared/params:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@org_golang_x_crypto//ssh/terminal:go_default_library",
],
)
go_test(
name = "go_default_test",
size = "small",
srcs = ["account_test.go"],
embed = [":go_default_library"],
deps = [
"//shared/keystore:go_default_library",
"//shared/params:go_default_library",
"//shared/testutil:go_default_library",
],
)

View File

@@ -1,159 +0,0 @@
package accounts
import (
"bufio"
"encoding/hex"
"fmt"
"io"
"os"
"strings"
"github.com/pkg/errors"
contract "github.com/prysmaticlabs/prysm/contracts/deposit-contract"
"github.com/prysmaticlabs/prysm/shared/keystore"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh/terminal"
)
var log = logrus.WithField("prefix", "accounts")
// DecryptKeysFromKeystore extracts a set of validator private keys from
// an encrypted keystore directory and a password string.
func DecryptKeysFromKeystore(directory string, password string) (map[string]*keystore.Key, error) {
validatorPrefix := params.BeaconConfig().ValidatorPrivkeyFileName
ks := keystore.NewKeystore(directory)
validatorKeys, err := ks.GetKeys(directory, validatorPrefix, password, true /* warnOnFail */)
if err != nil {
return nil, errors.Wrap(err, "could not get private key")
}
return validatorKeys, nil
}
// VerifyAccountNotExists checks if a validator has not yet created an account
// and keystore in the provided directory string.
func VerifyAccountNotExists(directory string, password string) error {
if directory == "" || password == "" {
return errors.New("expected a path to the validator keystore and password to be provided, received nil")
}
shardWithdrawalKeyFile := params.BeaconConfig().WithdrawalPrivkeyFileName
validatorKeyFile := params.BeaconConfig().ValidatorPrivkeyFileName
// First, if the keystore already exists, throws an error as there can only be
// one keystore per validator client.
ks := keystore.NewKeystore(directory)
if _, err := ks.GetKeys(directory, shardWithdrawalKeyFile, password, false /* warnOnFail */); err == nil {
return fmt.Errorf("keystore at path already exists: %s", shardWithdrawalKeyFile)
}
if _, err := ks.GetKeys(directory, validatorKeyFile, password, false /* warnOnFail */); err == nil {
return fmt.Errorf("keystore at path already exists: %s", validatorKeyFile)
}
return nil
}
// NewValidatorAccount sets up a validator client's secrets and generates the necessary deposit data
// parameters needed to deposit into the deposit contract on the ETH1.0 chain. Specifically, this
// generates a BLS private and public key, and then logs the serialized deposit input hex string
// to be used in an ETH1.0 transaction by the validator.
func NewValidatorAccount(directory string, password string) error {
shardWithdrawalKeyFile := directory + params.BeaconConfig().WithdrawalPrivkeyFileName
validatorKeyFile := directory + params.BeaconConfig().ValidatorPrivkeyFileName
ks := keystore.NewKeystore(directory)
// If the keystore does not exists at the path, we create a new one for the validator.
shardWithdrawalKey, err := keystore.NewKey()
if err != nil {
return err
}
shardWithdrawalKeyFile = shardWithdrawalKeyFile + hex.EncodeToString(shardWithdrawalKey.PublicKey.Marshal())[:12]
if err := ks.StoreKey(shardWithdrawalKeyFile, shardWithdrawalKey, password); err != nil {
return errors.Wrap(err, "unable to store key")
}
log.WithField(
"path",
shardWithdrawalKeyFile,
).Info("Keystore generated for shard withdrawals at path")
validatorKey, err := keystore.NewKey()
if err != nil {
return err
}
validatorKeyFile = validatorKeyFile + hex.EncodeToString(validatorKey.PublicKey.Marshal())[:12]
if err := ks.StoreKey(validatorKeyFile, validatorKey, password); err != nil {
return errors.Wrap(err, "unable to store key")
}
log.WithField(
"path",
validatorKeyFile,
).Info("Keystore generated for validator signatures at path")
data, depositRoot, err := keystore.DepositInput(validatorKey, shardWithdrawalKey, params.BeaconConfig().MaxEffectiveBalance)
if err != nil {
return errors.Wrap(err, "unable to generate deposit data")
}
testAcc, err := contract.Setup()
if err != nil {
return errors.Wrap(err, "unable to create simulated backend")
}
testAcc.TxOpts.GasLimit = 1000000
tx, err := testAcc.Contract.Deposit(testAcc.TxOpts, data.PublicKey, data.WithdrawalCredentials, data.Signature, depositRoot)
if err != nil {
return errors.Wrap(err, "unable to create deposit transaction")
}
log.Info(`Account creation complete! Copy and paste the raw transaction data shown below when issuing a transaction into the ETH1.0 deposit contract to activate your validator client`)
fmt.Printf(`
========================Raw Transaction Data=======================
%#x
===================================================================
`, tx.Data())
return nil
}
// Exists checks if a validator account at a given keystore path exists.
func Exists(keystorePath string) (bool, error) {
/* #nosec */
f, err := os.Open(keystorePath)
if err != nil {
return false, nil
}
defer func() {
if err := f.Close(); err != nil {
log.Fatal(err)
}
}()
_, err = f.Readdirnames(1) // Or f.Readdir(1)
if err == io.EOF {
return false, nil
}
return true, err
}
// CreateValidatorAccount creates a validator account from the given cli context.
func CreateValidatorAccount(path string, passphrase string) (string, string, error) {
if passphrase == "" {
reader := bufio.NewReader(os.Stdin)
log.Info("Create a new validator account for eth2")
log.Info("Enter a password:")
bytePassword, err := terminal.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
log.Fatalf("Could not read account password: %v", err)
}
text := string(bytePassword)
passphrase = strings.Replace(text, "\n", "", -1)
log.Infof("Keystore path to save your private keys (leave blank for default %s):", path)
text, err = reader.ReadString('\n')
if err != nil {
log.Fatal(err)
}
text = strings.Replace(text, "\n", "", -1)
if text != "" {
path = text
}
}
if err := NewValidatorAccount(path, passphrase); err != nil {
return "", "", errors.Wrapf(err, "could not initialize validator account")
}
return path, passphrase, nil
}

View File

@@ -1,37 +0,0 @@
package accounts
import (
"io/ioutil"
"os"
"testing"
"github.com/prysmaticlabs/prysm/shared/keystore"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
)
func TestNewValidatorAccount_AccountExists(t *testing.T) {
directory := testutil.TempDir() + "/testkeystore"
defer os.RemoveAll(directory)
validatorKey, err := keystore.NewKey()
if err != nil {
t.Fatalf("Cannot create new key: %v", err)
}
ks := keystore.NewKeystore(directory)
if err := ks.StoreKey(directory+params.BeaconConfig().ValidatorPrivkeyFileName, validatorKey, ""); err != nil {
t.Fatalf("Unable to store key %v", err)
}
if err := NewValidatorAccount(directory, ""); err != nil {
t.Errorf("Should support multiple keys: %v", err)
}
files, _ := ioutil.ReadDir(directory)
if len(files) != 3 {
t.Errorf("multiple validators were not created only %v files in directory", len(files))
for _, f := range files {
t.Errorf("%v\n", f.Name())
}
}
if err := os.RemoveAll(directory); err != nil {
t.Fatalf("Could not remove directory: %v", err)
}
}

View File

@@ -73,12 +73,10 @@ go_test(
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/keystore:go_default_library",
"//shared/mock:go_default_library",
"//shared/params:go_default_library",
"//shared/roughtime:go_default_library",
"//shared/testutil:go_default_library",
"//validator/accounts:go_default_library",
"//validator/db:go_default_library",
"//validator/internal:go_default_library",
"//validator/keymanager:go_default_library",

View File

@@ -9,48 +9,44 @@ import (
"github.com/prysmaticlabs/prysm/shared"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/keystore"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/validator/accounts"
"github.com/prysmaticlabs/prysm/validator/keymanager"
logTest "github.com/sirupsen/logrus/hooks/test"
)
var _ = shared.Service(&ValidatorService{})
var validatorKey *keystore.Key
var validatorPubKey [48]byte
var keyMap map[[48]byte]*keystore.Key
var keyMapThreeValidators map[[48]byte]*keystore.Key
var validatorPubKey *bls.PublicKey
var secKeyMap map[[48]byte]*bls.SecretKey
var pubKeyMap map[[48]byte]*bls.PublicKey
var secKeyMapThreeValidators map[[48]byte]*bls.SecretKey
var pubKeyMapThreeValidators map[[48]byte]*bls.PublicKey
var testKeyManager keymanager.KeyManager
var testKeyManagerThreeValidators keymanager.KeyManager
func keySetup() {
keyMap = make(map[[48]byte]*keystore.Key)
keyMapThreeValidators = make(map[[48]byte]*keystore.Key)
validatorKey, _ = keystore.NewKey()
copy(validatorPubKey[:], validatorKey.PublicKey.Marshal())
keyMap[validatorPubKey] = validatorKey
pubKeyMap = make(map[[48]byte]*bls.PublicKey)
secKeyMap = make(map[[48]byte]*bls.SecretKey)
pubKeyMapThreeValidators = make(map[[48]byte]*bls.PublicKey)
secKeyMapThreeValidators = make(map[[48]byte]*bls.SecretKey)
sks := make([]*bls.SecretKey, 1)
sks[0] = validatorKey.SecretKey
sks[0] = bls.RandKey()
testKeyManager = keymanager.NewDirect(sks)
validatorPubKey = sks[0].PublicKey()
sks = make([]*bls.SecretKey, 3)
for i := 0; i < 3; i++ {
vKey, _ := keystore.NewKey()
secKey := bls.RandKey()
var pubKey [48]byte
copy(pubKey[:], vKey.PublicKey.Marshal())
keyMapThreeValidators[pubKey] = vKey
sks[i] = vKey.SecretKey
copy(pubKey[:], secKey.PublicKey().Marshal())
secKeyMapThreeValidators[pubKey] = secKey
pubKeyMapThreeValidators[pubKey] = secKey.PublicKey()
sks[i] = secKey
}
testKeyManagerThreeValidators = keymanager.NewDirect(sks)
}
func TestMain(m *testing.M) {
dir := testutil.TempDir() + "/keystore1"
defer os.RemoveAll(dir)
accounts.NewValidatorAccount(dir, "1234")
keySetup()
os.Exit(m.Run())
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/golang/mock/gomock"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
logTest "github.com/sirupsen/logrus/hooks/test"
@@ -18,7 +19,7 @@ func TestSubmitAggregateAndProof_GetDutiesRequestFailure(t *testing.T) {
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{}}
defer finish()
validator.SubmitAggregateAndProof(context.Background(), 0, validatorPubKey)
validator.SubmitAggregateAndProof(context.Background(), 0, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Could not fetch validator assignment")
}
@@ -29,7 +30,7 @@ func TestSubmitAggregateAndProof_Ok(t *testing.T) {
validator.duties = &ethpb.DutiesResponse{
Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
},
},
}
@@ -60,7 +61,7 @@ func TestSubmitAggregateAndProof_Ok(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.SignedAggregateSubmitRequest{}),
).Return(&ethpb.SignedAggregateSubmitResponse{}, nil)
validator.SubmitAggregateAndProof(context.Background(), 0, validatorPubKey)
validator.SubmitAggregateAndProof(context.Background(), 0, bytesutil.ToBytes48(validatorPubKey.Marshal()))
}
func TestWaitForSlotTwoThird_WaitCorrectly(t *testing.T) {

View File

@@ -13,6 +13,7 @@ import (
"github.com/prysmaticlabs/go-bitfield"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/roughtime"
@@ -27,7 +28,7 @@ func TestRequestAttestation_ValidatorDutiesRequestFailure(t *testing.T) {
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{}}
defer finish()
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Could not fetch validator assignment")
}
@@ -38,7 +39,7 @@ func TestAttestToBlockHead_SubmitAttestationRequestFailure(t *testing.T) {
defer finish()
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
CommitteeIndex: 5,
Committee: make([]uint64, 111),
ValidatorIndex: 0,
@@ -60,7 +61,7 @@ func TestAttestToBlockHead_SubmitAttestationRequestFailure(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.Attestation{}),
).Return(nil, errors.New("something went wrong"))
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Could not submit attestation to beacon node")
}
@@ -71,7 +72,7 @@ func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) {
committee := []uint64{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
CommitteeIndex: 5,
Committee: committee,
ValidatorIndex: validatorIndex,
@@ -98,7 +99,7 @@ func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) {
generatedAttestation = att
}).Return(&ethpb.AttestResponse{}, nil /* error */)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
aggregationBitfield := bitfield.NewBitlist(uint64(len(committee)))
aggregationBitfield.SetBitAt(4, true)
@@ -116,7 +117,7 @@ func TestAttestToBlockHead_AttestsCorrectly(t *testing.T) {
t.Fatal(err)
}
sig, err := validator.keyManager.Sign(validatorPubKey, root)
sig, err := validator.keyManager.Sign(bytesutil.ToBytes48(validatorPubKey.Marshal()), root)
if err != nil {
t.Fatal(err)
}
@@ -140,7 +141,7 @@ func TestAttestToBlockHead_BlocksDoubleAtt(t *testing.T) {
committee := []uint64{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
CommitteeIndex: 5,
Committee: committee,
ValidatorIndex: validatorIndex,
@@ -164,8 +165,8 @@ func TestAttestToBlockHead_BlocksDoubleAtt(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.Attestation{}),
).Return(&ethpb.AttestResponse{}, nil /* error */)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Attempted to make a slashable attestation, rejected")
}
@@ -181,7 +182,7 @@ func TestAttestToBlockHead_BlocksSurroundAtt(t *testing.T) {
committee := []uint64{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
CommitteeIndex: 5,
Committee: committee,
ValidatorIndex: validatorIndex,
@@ -205,7 +206,7 @@ func TestAttestToBlockHead_BlocksSurroundAtt(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.Attestation{}),
).Return(&ethpb.AttestResponse{}, nil /* error */)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
m.validatorClient.EXPECT().GetAttestationData(
gomock.Any(), // ctx
@@ -216,7 +217,7 @@ func TestAttestToBlockHead_BlocksSurroundAtt(t *testing.T) {
Source: &ethpb.Checkpoint{Root: []byte("C"), Epoch: 0},
}, nil)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Attempted to make a slashable attestation, rejected")
}
@@ -232,7 +233,7 @@ func TestAttestToBlockHead_BlocksSurroundedAtt(t *testing.T) {
committee := []uint64{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
CommitteeIndex: 5,
Committee: committee,
ValidatorIndex: validatorIndex,
@@ -256,7 +257,7 @@ func TestAttestToBlockHead_BlocksSurroundedAtt(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.Attestation{}),
).Return(&ethpb.AttestResponse{}, nil /* error */)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
m.validatorClient.EXPECT().GetAttestationData(
gomock.Any(), // ctx
@@ -267,7 +268,7 @@ func TestAttestToBlockHead_BlocksSurroundedAtt(t *testing.T) {
Source: &ethpb.Checkpoint{Root: []byte("C"), Epoch: 1},
}, nil)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Attempted to make a slashable attestation, rejected")
}
@@ -293,7 +294,7 @@ func TestAttestToBlockHead_DoesNotAttestBeforeDelay(t *testing.T) {
).Return(&ethpb.AttestResponse{}, nil /* error */).Times(0)
timer := time.NewTimer(1 * time.Second)
go validator.SubmitAttestation(context.Background(), 0, validatorPubKey)
go validator.SubmitAttestation(context.Background(), 0, bytesutil.ToBytes48(validatorPubKey.Marshal()))
<-timer.C
}
@@ -310,7 +311,7 @@ func TestAttestToBlockHead_DoesAttestAfterDelay(t *testing.T) {
committee := []uint64{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
CommitteeIndex: 5,
Committee: committee,
ValidatorIndex: validatorIndex,
@@ -337,7 +338,7 @@ func TestAttestToBlockHead_DoesAttestAfterDelay(t *testing.T) {
gomock.Any(),
).Return(&ethpb.AttestResponse{}, nil).Times(1)
validator.SubmitAttestation(context.Background(), 0, validatorPubKey)
validator.SubmitAttestation(context.Background(), 0, bytesutil.ToBytes48(validatorPubKey.Marshal()))
}
func TestAttestToBlockHead_CorrectBitfieldLength(t *testing.T) {
@@ -347,7 +348,7 @@ func TestAttestToBlockHead_CorrectBitfieldLength(t *testing.T) {
committee := []uint64{0, 3, 4, 2, validatorIndex, 6, 8, 9, 10}
validator.duties = &ethpb.DutiesResponse{Duties: []*ethpb.DutiesResponse_Duty{
{
PublicKey: validatorKey.PublicKey.Marshal(),
PublicKey: validatorPubKey.Marshal(),
CommitteeIndex: 5,
Committee: committee,
ValidatorIndex: validatorIndex,
@@ -373,7 +374,7 @@ func TestAttestToBlockHead_CorrectBitfieldLength(t *testing.T) {
generatedAttestation = att
}).Return(&ethpb.AttestResponse{}, nil /* error */)
validator.SubmitAttestation(context.Background(), 30, validatorPubKey)
validator.SubmitAttestation(context.Background(), 30, bytesutil.ToBytes48(validatorPubKey.Marshal()))
if len(generatedAttestation.AggregationBits) != 2 {
t.Errorf("Wanted length %d, received %d", 2, len(generatedAttestation.AggregationBits))

View File

@@ -9,6 +9,7 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/go-bitfield"
slashpb "github.com/prysmaticlabs/prysm/proto/slashing"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
@@ -22,7 +23,7 @@ type mocks struct {
}
func setup(t *testing.T) (*validator, *mocks, func()) {
valDB := db.SetupDB(t, [][48]byte{validatorPubKey})
valDB := db.SetupDB(t, [][48]byte{bytesutil.ToBytes48(validatorPubKey.Marshal())})
ctrl := gomock.NewController(t)
m := &mocks{
validatorClient: internal.NewMockBeaconNodeValidatorClient(ctrl),
@@ -42,7 +43,7 @@ func TestProposeBlock_DoesNotProposeGenesisBlock(t *testing.T) {
hook := logTest.NewGlobal()
validator, _, finish := setup(t)
defer finish()
validator.ProposeBlock(context.Background(), 0, validatorPubKey)
validator.ProposeBlock(context.Background(), 0, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Assigned to genesis slot, skipping proposal")
}
@@ -57,7 +58,7 @@ func TestProposeBlock_DomainDataFailed(t *testing.T) {
gomock.Any(), // epoch
).Return(nil /*response*/, errors.New("uh oh"))
validator.ProposeBlock(context.Background(), 1, validatorPubKey)
validator.ProposeBlock(context.Background(), 1, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Failed to sign randao reveal")
}
@@ -76,7 +77,7 @@ func TestProposeBlock_RequestBlockFailed(t *testing.T) {
gomock.Any(), // block request
).Return(nil /*response*/, errors.New("uh oh"))
validator.ProposeBlock(context.Background(), 1, validatorPubKey)
validator.ProposeBlock(context.Background(), 1, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Failed to request block from beacon node")
}
@@ -105,7 +106,7 @@ func TestProposeBlock_ProposeBlockFailed(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.SignedBeaconBlock{}),
).Return(nil /*response*/, errors.New("uh oh"))
validator.ProposeBlock(context.Background(), 1, validatorPubKey)
validator.ProposeBlock(context.Background(), 1, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Failed to propose block")
}
@@ -139,10 +140,10 @@ func TestProposeBlock_BlocksDoubleProposal(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.SignedBeaconBlock{}),
).Return(&ethpb.ProposeResponse{}, nil /*error*/)
validator.ProposeBlock(context.Background(), params.BeaconConfig().SlotsPerEpoch*5+2, validatorPubKey)
validator.ProposeBlock(context.Background(), params.BeaconConfig().SlotsPerEpoch*5+2, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsDoNotContain(t, hook, "Tried to sign a double proposal")
validator.ProposeBlock(context.Background(), params.BeaconConfig().SlotsPerEpoch*5+2, validatorPubKey)
validator.ProposeBlock(context.Background(), params.BeaconConfig().SlotsPerEpoch*5+2, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Tried to sign a double proposal")
}
@@ -177,10 +178,10 @@ func TestProposeBlock_BlocksDoubleProposal_After54KEpochs(t *testing.T) {
).Return(&ethpb.ProposeResponse{}, nil /*error*/)
farFuture := (params.BeaconConfig().WeakSubjectivityPeriod + 9) * params.BeaconConfig().SlotsPerEpoch
validator.ProposeBlock(context.Background(), farFuture, validatorPubKey)
validator.ProposeBlock(context.Background(), farFuture, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsDoNotContain(t, hook, "Tried to sign a double proposal")
validator.ProposeBlock(context.Background(), farFuture, validatorPubKey)
validator.ProposeBlock(context.Background(), farFuture, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsContain(t, hook, "Tried to sign a double proposal")
}
@@ -215,11 +216,11 @@ func TestProposeBlock_AllowsPastProposals(t *testing.T) {
).Times(2).Return(&ethpb.ProposeResponse{}, nil /*error*/)
farAhead := (params.BeaconConfig().WeakSubjectivityPeriod + 9) * params.BeaconConfig().SlotsPerEpoch
validator.ProposeBlock(context.Background(), farAhead, validatorPubKey)
validator.ProposeBlock(context.Background(), farAhead, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsDoNotContain(t, hook, "Tried to sign a double proposal")
past := (params.BeaconConfig().WeakSubjectivityPeriod - 400) * params.BeaconConfig().SlotsPerEpoch
validator.ProposeBlock(context.Background(), past, validatorPubKey)
validator.ProposeBlock(context.Background(), past, bytesutil.ToBytes48(validatorPubKey.Marshal()))
testutil.AssertLogsDoNotContain(t, hook, "Tried to sign a double proposal")
}
@@ -247,7 +248,7 @@ func TestProposeBlock_BroadcastsBlock(t *testing.T) {
gomock.AssignableToTypeOf(&ethpb.SignedBeaconBlock{}),
).Return(&ethpb.ProposeResponse{}, nil /*error*/)
validator.ProposeBlock(context.Background(), 1, validatorPubKey)
validator.ProposeBlock(context.Background(), 1, bytesutil.ToBytes48(validatorPubKey.Marshal()))
}
func TestProposeBlock_BroadcastsBlock_WithGraffiti(t *testing.T) {
@@ -281,7 +282,7 @@ func TestProposeBlock_BroadcastsBlock_WithGraffiti(t *testing.T) {
return &ethpb.ProposeResponse{}, nil
})
validator.ProposeBlock(context.Background(), 1, validatorPubKey)
validator.ProposeBlock(context.Background(), 1, bytesutil.ToBytes48(validatorPubKey.Marshal()))
if string(sentBlock.Block.Body.Graffiti) != string(validator.graffiti) {
t.Errorf("Block was broadcast with the wrong graffiti field, wanted \"%v\", got \"%v\"", string(validator.graffiti), string(sentBlock.Block.Body.Graffiti))

View File

@@ -21,22 +21,17 @@ var (
Name: "tls-cert",
Usage: "Certificate for secure gRPC. Pass this and the tls-key flag in order to use gRPC securely.",
}
// KeystorePathFlag defines the location of the keystore directory for a validator's account.
KeystorePathFlag = &cli.StringFlag{
Name: "keystore-path",
Usage: "Path to the desired keystore directory",
}
// UnencryptedKeysFlag specifies a file path of a JSON file of unencrypted validator keys as an
// alternative from launching the validator client from decrypting a keystore directory.
// UnencryptedKeysFlag specifies a file path of a JSON file of unencrypted validator keys; this should only
// be used for test networks.
UnencryptedKeysFlag = &cli.StringFlag{
Name: "unencrypted-keys",
Usage: "Filepath to a JSON file of unencrypted validator keys for easier launching of the validator client",
Usage: "Filepath to a JSON file of unencrypted validator keys for launching the validator client on test networks",
Value: "",
}
// KeyManager specifies the key manager to use.
KeyManager = &cli.StringFlag{
Name: "keymanager",
Usage: "The keymanger to use (unencrypted, interop, keystore, wallet)",
Usage: "For specifying the keymanager to use (remote, wallet, unencrypted, interop)",
Value: "",
}
// KeyManagerOpts specifies the key manager options.
@@ -45,11 +40,6 @@ var (
Usage: "The options for the keymanger, either a JSON string or path to same",
Value: "",
}
// PasswordFlag defines the password value for storing and retrieving validator private keys from the keystore.
PasswordFlag = &cli.StringFlag{
Name: "password",
Usage: "String value of the password for your validator private keys",
}
// DisablePenaltyRewardLogFlag defines the ability to not log reward/penalty information during deployment
DisablePenaltyRewardLogFlag = &cli.BoolFlag{
Name: "disable-rewards-penalties-logging",

View File

@@ -5,7 +5,6 @@ go_library(
srcs = [
"direct.go",
"direct_interop.go",
"direct_keystore.go",
"direct_unencrypted.go",
"keymanager.go",
"log.go",
@@ -19,7 +18,6 @@ go_library(
"//shared/bls:go_default_library",
"//shared/bytesutil:go_default_library",
"//shared/interop:go_default_library",
"//validator/accounts:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
@@ -29,7 +27,6 @@ go_library(
"@com_github_wealdtech_go_eth2_wallet_types_v2//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
"@org_golang_x_crypto//ssh/terminal:go_default_library",
],
)

View File

@@ -1,121 +0,0 @@
package keymanager
import (
"encoding/json"
"os"
"os/user"
"path/filepath"
"runtime"
"strings"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/validator/accounts"
"golang.org/x/crypto/ssh/terminal"
)
// Keystore is a key manager that loads keys from a standard keystore.
type Keystore struct {
*Direct
}
type keystoreOpts struct {
Path string `json:"path"`
Passphrase string `json:"passphrase"`
}
var keystoreOptsHelp = `The keystore key manager generates keys and stores them in a local encrypted store. The options are:
- path This is the filesystem path to where keys will be stored. Defaults to the user's home directory if not supplied
- passphrase This is the passphrase used to encrypt keys. Will be asked for if not supplied
A sample set of options are:
{
"path": "/home/me/keys", // Store the keys in '/home/me/keys'
"passphrase": "secret" // Use the passphrase 'secret' to encrypt and decrypt keys
}`
// NewKeystore creates a key manager populated with the keys from the keystore at the given path.
func NewKeystore(input string) (KeyManager, string, error) {
opts := &keystoreOpts{}
err := json.Unmarshal([]byte(input), opts)
if err != nil {
return nil, keystoreOptsHelp, err
}
if strings.Contains(opts.Path, "$") || strings.Contains(opts.Path, "~") || strings.Contains(opts.Path, "%") {
log.WithField("path", opts.Path).Warn("Keystore path contains unexpanded shell expansion characters")
}
if opts.Path == "" {
opts.Path = defaultValidatorDir()
}
exists, err := accounts.Exists(opts.Path)
if err != nil {
return nil, keystoreOptsHelp, err
}
if !exists {
// If an account does not exist, we create a new one and start the node.
opts.Path, opts.Passphrase, err = accounts.CreateValidatorAccount(opts.Path, opts.Passphrase)
if err != nil {
return nil, keystoreOptsHelp, err
}
} else {
if opts.Passphrase == "" {
log.Info("Enter your validator account password:")
bytePassword, err := terminal.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
return nil, keystoreOptsHelp, err
}
text := string(bytePassword)
opts.Passphrase = strings.Replace(text, "\n", "", -1)
}
if err := accounts.VerifyAccountNotExists(opts.Path, opts.Passphrase); err == nil {
log.Info("No account found, creating new validator account...")
}
}
keyMap, err := accounts.DecryptKeysFromKeystore(opts.Path, opts.Passphrase)
if err != nil {
return nil, keystoreOptsHelp, err
}
km := &Unencrypted{
Direct: &Direct{
publicKeys: make(map[[48]byte]*bls.PublicKey),
secretKeys: make(map[[48]byte]*bls.SecretKey),
},
}
for _, key := range keyMap {
pubKey := bytesutil.ToBytes48(key.PublicKey.Marshal())
km.publicKeys[pubKey] = key.PublicKey
km.secretKeys[pubKey] = key.SecretKey
}
return km, "", nil
}
func homeDir() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
if usr, err := user.Current(); err == nil {
return usr.HomeDir
}
return ""
}
func defaultValidatorDir() string {
// Try to place the data folder in the user's home dir
home := homeDir()
if home != "" {
if runtime.GOOS == "darwin" {
return filepath.Join(home, "Library", "Eth2Validators")
} else if runtime.GOOS == "windows" {
return filepath.Join(home, "AppData", "Roaming", "Eth2Validators")
} else {
return filepath.Join(home, ".eth2validators")
}
}
// As we cannot guess a stable location, return empty and handle later
return ""
}

View File

@@ -11,9 +11,7 @@ import (
"github.com/prysmaticlabs/prysm/shared/debug"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/logutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/version"
"github.com/prysmaticlabs/prysm/validator/accounts"
"github.com/prysmaticlabs/prysm/validator/flags"
"github.com/prysmaticlabs/prysm/validator/node"
"github.com/sirupsen/logrus"
@@ -39,8 +37,6 @@ var appFlags = []cli.Flag{
flags.BeaconRPCProviderFlag,
flags.CertFlag,
flags.GraffitiFlag,
flags.KeystorePathFlag,
flags.PasswordFlag,
flags.DisablePenaltyRewardLogFlag,
flags.UnencryptedKeysFlag,
flags.InteropStartIndex,
@@ -81,68 +77,6 @@ func main() {
starts proposer services, shardp2p connections, and more`
app.Version = version.GetVersion()
app.Action = startNode
app.Commands = []*cli.Command{
{
Name: "accounts",
Category: "accounts",
Usage: "defines useful functions for interacting with the validator client's account",
Subcommands: []*cli.Command{
{
Name: "create",
Description: `creates a new validator account keystore containing private keys for Ethereum Serenity -
this command outputs a deposit data string which can be used to deposit Ether into the ETH1.0 deposit
contract in order to activate the validator client`,
Flags: []cli.Flag{
flags.KeystorePathFlag,
flags.PasswordFlag,
},
Action: func(ctx *cli.Context) error {
featureconfig.ConfigureValidator(ctx)
// Use custom config values if the --no-custom-config flag is set.
if !ctx.Bool(flags.NoCustomConfigFlag.Name) {
log.Info("Using custom parameter configuration")
if featureconfig.Get().MinimalConfig {
log.Warn("Using Minimal Config")
params.UseMinimalConfig()
} else {
log.Warn("Using Demo Config")
params.UseDemoBeaconConfig()
}
}
if keystoreDir, _, err := accounts.CreateValidatorAccount(ctx.String(flags.KeystorePathFlag.Name), ctx.String(flags.PasswordFlag.Name)); err != nil {
log.WithError(err).Fatalf("Could not create validator at path: %s", keystoreDir)
}
return nil
},
},
{
Name: "keys",
Description: `lists the private keys for 'keystore' keymanager keys`,
Flags: []cli.Flag{
flags.KeystorePathFlag,
flags.PasswordFlag,
},
Action: func(ctx *cli.Context) error {
if ctx.String(flags.KeystorePathFlag.Name) == "" {
log.Fatalf("%s is required", flags.KeystorePathFlag.Name)
}
if ctx.String(flags.PasswordFlag.Name) == "" {
log.Fatalf("%s is required", flags.PasswordFlag.Name)
}
keystores, err := accounts.DecryptKeysFromKeystore(ctx.String(flags.KeystorePathFlag.Name), ctx.String(flags.PasswordFlag.Name))
if err != nil {
log.WithError(err).Fatalf("Failed to decrypt keystore keys at path %s", ctx.String(flags.KeystorePathFlag.Name))
}
for _, v := range keystores {
fmt.Printf("Public key: %#x private key: %#x\n", v.PublicKey.Marshal(), v.SecretKey.Marshal())
}
return nil
},
},
},
},
}
app.Flags = appFlags
app.Before = func(ctx *cli.Context) error {

View File

@@ -7,7 +7,6 @@ go_test(
embed = [":go_default_library"],
deps = [
"//shared/testutil:go_default_library",
"//validator/accounts:go_default_library",
"@in_gopkg_urfave_cli_v2//:go_default_library",
],
)

View File

@@ -218,37 +218,25 @@ func selectKeyManager(ctx *cli.Context) (keymanager.KeyManager, error) {
manager = "interop"
opts = fmt.Sprintf(`{"keys":%d,"offset":%d}`, numValidatorKeys, ctx.Uint64(flags.InteropStartIndex.Name))
log.Warn(fmt.Sprintf("--interop-num-validators and --interop-start-index flags are deprecated. Please use --keymanager=interop --keymanageropts='%s'", opts))
} else if keystorePath := ctx.String(flags.KeystorePathFlag.Name); keystorePath != "" {
manager = "keystore"
opts = fmt.Sprintf(`{"path":%q,"passphrase":%q}`, keystorePath, ctx.String(flags.PasswordFlag.Name))
log.Warn(fmt.Sprintf("--keystore-path flag is deprecated. Please use --keymanager=keystore --keymanageropts='%s'", opts))
} else {
// Default if no choice made
manager = "keystore"
passphrase := ctx.String(flags.PasswordFlag.Name)
if passphrase == "" {
log.Warn("Implicit selection of keymanager is deprecated. Please use --keymanager=keystore or select a different keymanager")
} else {
opts = fmt.Sprintf(`{"passphrase":%q}`, passphrase)
log.Warn(`Implicit selection of keymanager is deprecated. Please use --keymanager=keystore --keymanageropts='{"passphrase":"<password>"}' or select a different keymanager`)
}
}
}
if manager == "" {
return nil, fmt.Errorf("please supply a keymanager with --keymanager")
}
var km keymanager.KeyManager
var help string
var err error
switch manager {
case "remote":
km, help, err = keymanager.NewRemoteWallet(opts)
case "wallet":
km, help, err = keymanager.NewWallet(opts)
case "interop":
km, help, err = keymanager.NewInterop(opts)
case "unencrypted":
km, help, err = keymanager.NewUnencrypted(opts)
case "keystore":
km, help, err = keymanager.NewKeystore(opts)
case "wallet":
km, help, err = keymanager.NewWallet(opts)
case "remote":
km, help, err = keymanager.NewRemoteWallet(opts)
default:
return nil, fmt.Errorf("unknown keymanager %q", manager)
}

View File

@@ -3,10 +3,10 @@ package node
import (
"flag"
"os"
"path/filepath"
"testing"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/validator/accounts"
"gopkg.in/urfave/cli.v2"
)
@@ -14,18 +14,14 @@ import (
func TestNode_Builds(t *testing.T) {
app := cli.App{}
set := flag.NewFlagSet("test", 0)
set.String("datadir", testutil.TempDir()+"/datadir", "the node data directory")
dir := testutil.TempDir() + "/keystore1"
defer os.RemoveAll(dir)
defer os.RemoveAll(testutil.TempDir() + "/datadir")
set.String("keystore-path", dir, "path to keystore")
set.String("password", "1234", "validator account password")
tmpDir := testutil.TempDir()
defer os.RemoveAll(tmpDir)
set.String("datadir", filepath.Join(tmpDir, "datadir"), "the node data directory")
set.String("keymanager", "interop", "key manager")
set.String("keymanageropts", `{"keys":16,"offset":0}`, `key manager options`)
set.String("verbosity", "debug", "log verbosity")
context := cli.NewContext(&app, set, nil)
if err := accounts.NewValidatorAccount(dir, "1234"); err != nil {
t.Fatalf("Could not create validator account: %v", err)
}
_, err := NewValidatorClient(context)
if err != nil {
t.Fatalf("Failed to create ValidatorClient: %v", err)

View File

@@ -77,8 +77,6 @@ var appHelpFlagGroups = []flagGroup{
flags.CertFlag,
flags.KeyManager,
flags.KeyManagerOpts,
flags.KeystorePathFlag,
flags.PasswordFlag,
flags.DisablePenaltyRewardLogFlag,
flags.UnencryptedKeysFlag,
flags.GraffitiFlag,