Skip to content

Commit

Permalink
Optionally Save Wallet Password on Web Onboarding (#7930)
Browse files Browse the repository at this point in the history
* persist wallet password to wallet dir if onboarded via web

* add flag

* gaz

* add test

* fmt

Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
  • Loading branch information
rauljordan and prylabs-bulldozer[bot] committed Nov 23, 2020
1 parent a051e68 commit dc897a2
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 15 deletions.
30 changes: 18 additions & 12 deletions shared/featureconfig/config.go
Expand Up @@ -36,18 +36,19 @@ type Flags struct {
PyrmontTestnet bool // PyrmontTestnet defines the flag through which we can enable the node to run on the Pyrmont testnet.

// Feature related flags.
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
SkipBLSVerify bool // Skips BLS verification across the runtime.
EnableBlst bool // Enables new BLS library from supranational.
PruneEpochBoundaryStates bool // PruneEpochBoundaryStates prunes the epoch boundary state before last finalized check point.
EnableSnappyDBCompression bool // EnableSnappyDBCompression in the database.
SlasherProtection bool // SlasherProtection protects validator fron sending over a slashable offense over the network using external slasher.
EnableNoise bool // EnableNoise enables the beacon node to use NOISE instead of SECIO when performing a handshake with another peer.
EnableEth1DataMajorityVote bool // EnableEth1DataMajorityVote uses the Voting With The Majority algorithm to vote for eth1data.
EnablePeerScorer bool // EnablePeerScorer enables experimental peer scoring in p2p.
EnablePruningDepositProofs bool // EnablePruningDepositProofs enables pruning deposit proofs which significantly reduces the size of a deposit
EnableSyncBacktracking bool // EnableSyncBacktracking enables backtracking algorithm when searching for alternative forks during initial sync.
EnableLargerGossipHistory bool // EnableLargerGossipHistory increases the gossip history we store in our caches.
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
SkipBLSVerify bool // Skips BLS verification across the runtime.
EnableBlst bool // Enables new BLS library from supranational.
PruneEpochBoundaryStates bool // PruneEpochBoundaryStates prunes the epoch boundary state before last finalized check point.
EnableSnappyDBCompression bool // EnableSnappyDBCompression in the database.
SlasherProtection bool // SlasherProtection protects validator fron sending over a slashable offense over the network using external slasher.
EnableNoise bool // EnableNoise enables the beacon node to use NOISE instead of SECIO when performing a handshake with another peer.
EnableEth1DataMajorityVote bool // EnableEth1DataMajorityVote uses the Voting With The Majority algorithm to vote for eth1data.
EnablePeerScorer bool // EnablePeerScorer enables experimental peer scoring in p2p.
EnablePruningDepositProofs bool // EnablePruningDepositProofs enables pruning deposit proofs which significantly reduces the size of a deposit
EnableSyncBacktracking bool // EnableSyncBacktracking enables backtracking algorithm when searching for alternative forks during initial sync.
EnableLargerGossipHistory bool // EnableLargerGossipHistory increases the gossip history we store in our caches.
WriteWalletPasswordOnWebOnboarding bool // WriteWalletPasswordOnWebOnboarding writes the password to disk after Prysm web signup.

// Logging related toggles.
DisableGRPCConnectionLogs bool // Disables logging when a new grpc client has connected.
Expand Down Expand Up @@ -206,6 +207,11 @@ func ConfigureValidator(ctx *cli.Context) {
log.Warn("Enabled validator attestation and block slashing protection using an external slasher.")
cfg.SlasherProtection = true
}
if ctx.Bool(writeWalletPasswordOnWebOnboarding.Name) {
log.Warn("Enabled full web mode, wallet password will be written to disk at the wallet directory " +
"upon completing web onboarding.")
cfg.WriteWalletPasswordOnWebOnboarding = true
}
Init(cfg)
}

Expand Down
6 changes: 6 additions & 0 deletions shared/featureconfig/flags.go
Expand Up @@ -84,6 +84,11 @@ var (
Name: "enable-larger-gossip-history",
Usage: "Enables the node to store a larger amount of gossip messages in its cache.",
}
writeWalletPasswordOnWebOnboarding = &cli.BoolFlag{
Name: "write-wallet-password-on-web-onboarding",
Usage: "(Danger): Writes the wallet password to the wallet directory on completing Prysm web onboarding. " +
"We recommend against this flag unless you are an advanced user.",
}
)

// devModeFlags holds list of flags that are set when development mode is on.
Expand All @@ -94,6 +99,7 @@ var devModeFlags = []cli.Flag{

// ValidatorFlags contains a list of all the feature flags that apply to the validator client.
var ValidatorFlags = append(deprecatedFlags, []cli.Flag{
writeWalletPasswordOnWebOnboarding,
enableExternalSlasherProtectionFlag,
ToledoTestnet,
PyrmontTestnet,
Expand Down
4 changes: 3 additions & 1 deletion validator/accounts/wallet/wallet.go
Expand Up @@ -33,7 +33,9 @@ const (
WalletPasswordPromptText = "Wallet password"
// ConfirmPasswordPromptText for confirming a wallet password.
ConfirmPasswordPromptText = "Confirm password"
hashCost = 8
// DefaultWalletPasswordFile used to store a wallet password with appropriate permissions
// if a user signs up via the Prysm web UI via RPC.
DefaultWalletPasswordFile = "walletpassword.txt"
// CheckExistsErrMsg for when there is an error while checking for a wallet
CheckExistsErrMsg = "could not check if wallet exists"
// CheckValidityErrMsg for when there is an error while checking wallet validity
Expand Down
7 changes: 7 additions & 0 deletions validator/node/node.go
Expand Up @@ -247,6 +247,13 @@ func (s *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
var keyManager keymanager.IKeymanager
var err error
walletDir := cliCtx.String(flags.WalletDirFlag.Name)
defaultWalletPasswordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile)
if fileutil.FileExists(defaultWalletPasswordFilePath) {
if err := cliCtx.Set(flags.WalletPasswordFileFlag.Name, defaultWalletPasswordFilePath); err != nil {
return errors.Wrap(err, "could not set default wallet password file path")
}
}
// Read the wallet from the specified path.
w, err := wallet.OpenWalletOrElseCli(cliCtx, func(cliCtx *cli.Context) (*wallet.Wallet, error) {
return nil, nil
Expand Down
2 changes: 2 additions & 0 deletions validator/rpc/BUILD.bazel
Expand Up @@ -17,6 +17,7 @@ go_library(
"//proto/validator/accounts/v2:go_default_library",
"//shared/cmd:go_default_library",
"//shared/event:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/fileutil:go_default_library",
"//shared/pagination:go_default_library",
"//shared/petnames:go_default_library",
Expand Down Expand Up @@ -66,6 +67,7 @@ go_test(
"//proto/validator/accounts/v2:go_default_library",
"//shared/bls:go_default_library",
"//shared/event:go_default_library",
"//shared/featureconfig:go_default_library",
"//shared/fileutil:go_default_library",
"//shared/testutil/assert:go_default_library",
"//shared/testutil/require:go_default_library",
Expand Down
22 changes: 21 additions & 1 deletion validator/rpc/wallet.go
Expand Up @@ -4,10 +4,14 @@ import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"path/filepath"

ptypes "github.com/gogo/protobuf/types"
"github.com/pkg/errors"
pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/fileutil"
"github.com/prysmaticlabs/prysm/shared/rand"
"github.com/prysmaticlabs/prysm/validator/accounts"
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
Expand Down Expand Up @@ -73,6 +77,9 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
}); err != nil {
return nil, err
}
if err := writeWalletPasswordToDisk(walletDir, req.WalletPassword); err != nil {
return nil, status.Error(codes.Internal, "Could not write wallet password to disk")
}
return &pb.CreateWalletResponse{
Wallet: &pb.WalletResponse{
WalletPath: walletDir,
Expand Down Expand Up @@ -101,7 +108,9 @@ func (s *Server) CreateWallet(ctx context.Context, req *pb.CreateWalletRequest)
}); err != nil {
return nil, err
}

if err := writeWalletPasswordToDisk(walletDir, req.WalletPassword); err != nil {
return nil, status.Error(codes.Internal, "Could not write wallet password to disk")
}
return &pb.CreateWalletResponse{
Wallet: &pb.WalletResponse{
WalletPath: walletDir,
Expand Down Expand Up @@ -272,3 +281,14 @@ func (s *Server) initializeWallet(ctx context.Context, cfg *wallet.Config) error
}
return nil
}

func writeWalletPasswordToDisk(walletDir string, password string) error {
if !featureconfig.Get().WriteWalletPasswordOnWebOnboarding {
return nil
}
passwordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile)
if fileutil.FileExists(passwordFilePath) {
return fmt.Errorf("cannot write wallet password file as it already exists %s", passwordFilePath)
}
return fileutil.WriteFile(passwordFilePath, []byte(password))
}
33 changes: 32 additions & 1 deletion validator/rpc/wallet_test.go
Expand Up @@ -5,20 +5,24 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"testing"

ptypes "github.com/gogo/protobuf/types"
"github.com/google/uuid"
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"

pb "github.com/prysmaticlabs/prysm/proto/validator/accounts/v2"
"github.com/prysmaticlabs/prysm/shared/bls"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/fileutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
"github.com/prysmaticlabs/prysm/shared/testutil/require"
"github.com/prysmaticlabs/prysm/validator/accounts"
"github.com/prysmaticlabs/prysm/validator/accounts/wallet"
"github.com/prysmaticlabs/prysm/validator/keymanager"
"github.com/prysmaticlabs/prysm/validator/keymanager/imported"
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
)

func TestServer_CreateWallet_Imported(t *testing.T) {
Expand Down Expand Up @@ -277,3 +281,30 @@ func TestServer_ImportKeystores_OK(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, 3, len(keys))
}

func Test_writeWalletPasswordToDisk(t *testing.T) {
walletDir := setupWalletDir(t)
resetCfg := featureconfig.InitWithReset(&featureconfig.Flags{
WriteWalletPasswordOnWebOnboarding: false,
})
defer resetCfg()
err := writeWalletPasswordToDisk(walletDir, "somepassword")
require.NoError(t, err)

// Expected a silent failure if the feature flag is not enabled.
passwordFilePath := filepath.Join(walletDir, wallet.DefaultWalletPasswordFile)
assert.Equal(t, false, fileutil.FileExists(passwordFilePath))
resetCfg = featureconfig.InitWithReset(&featureconfig.Flags{
WriteWalletPasswordOnWebOnboarding: true,
})
defer resetCfg()
err = writeWalletPasswordToDisk(walletDir, "somepassword")
require.NoError(t, err)

// File should have been written.
assert.Equal(t, true, fileutil.FileExists(passwordFilePath))

// Attempting to write again should trigger an error.
err = writeWalletPasswordToDisk(walletDir, "somepassword")
require.NotNil(t, err)
}

0 comments on commit dc897a2

Please sign in to comment.