Skip to content

Commit

Permalink
Addressing 1/3 of smartnode-issues-601
Browse files Browse the repository at this point in the history
This PR updates the Rebuild command path to support: 1) opt-in partial rebuilds, 2) errors associated to public keys and 3) detailed logging related to response data.

This is one of 3 planned PRs to update this code path. The follow-up PRs will address other code paths performing wallet rebuild and update logging to improve UX by informing callers where to learn more about the underlying API/command.
  • Loading branch information
SolezOfScience committed Aug 9, 2024
1 parent c9f73b4 commit 5085b10
Show file tree
Hide file tree
Showing 7 changed files with 406 additions and 32 deletions.
4 changes: 2 additions & 2 deletions client/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ func (r *WalletRequester) Masquerade(address common.Address) (*types.ApiResponse
}

// Rebuild the validator keys associated with the wallet
func (r *WalletRequester) Rebuild() (*types.ApiResponse[api.WalletRebuildData], error) {
return client.SendGetRequest[api.WalletRebuildData](r, "rebuild", "Rebuild", nil)
func (r *WalletRequester) Rebuild(enablePartialRebuild bool) (*types.ApiResponse[api.WalletRebuildData], error) {
return client.SendGetRequest[api.WalletRebuildData](r, "rebuild", "Rebuild", map[string]string{"enable-partial-rebuild": strconv.FormatBool(enablePartialRebuild)})
}

// Recover wallet
Expand Down
3 changes: 3 additions & 0 deletions rocketpool-cli/commands/wallet/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ func RegisterCommands(app *cli.App, name string, aliases []string) {
Name: "rebuild",
Aliases: []string{"b"},
Usage: "Rebuild validator keystores from derived keys",
Flags: []cli.Flag{
enablePartialRebuild,
},
Action: func(c *cli.Context) error {
// Validate args
utils.ValidateArgCount(c, 0)
Expand Down
59 changes: 35 additions & 24 deletions rocketpool-cli/commands/wallet/rebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package wallet

import (
"fmt"
"github.com/rocket-pool/smartnode/v2/rocketpool-cli/utils"
"os"

"github.com/rocket-pool/node-manager-core/wallet"
"github.com/rocket-pool/smartnode/v2/rocketpool-cli/client"
"github.com/rocket-pool/smartnode/v2/rocketpool-cli/utils"
"github.com/urfave/cli/v2"
)

Expand Down Expand Up @@ -54,41 +54,52 @@ func rebuildWallet(c *cli.Context) error {
}(customKeyPasswordFile)
}

var enablePartialRebuildValue = true
if enablePartialRebuild.Name != "" {
enablePartialRebuildValue = c.Bool(enablePartialRebuild.Name)
}

// Log
fmt.Println("Rebuilding node validator keystores...")
fmt.Printf("Partial rebuild enabled: %s.\n", enablePartialRebuild.Name)

// Rebuild wallet
response, err := rp.Api.Wallet.Rebuild()
if err != nil {
return err
response, _ := rp.Api.Wallet.Rebuild(enablePartialRebuildValue)

// Handle and print failure reasons with associated public keys
if len(response.Data.FailureReasons) > 0 {
fmt.Println("Failure reasons:")
for pubkey, reason := range response.Data.FailureReasons {
fmt.Printf("Public Key: %s - Failure Reason: %s\n", pubkey.Hex(), reason)
}
} else {
fmt.Println("No failures reported.")
}

// Log & return
fmt.Println("The node wallet was successfully rebuilt.")
if len(response.Data.ValidatorKeys) > 0 {
fmt.Println("The response for rebuilding the node wallet was successfully received.")
if len(response.Data.RebuiltValidatorKeys) > 0 {
fmt.Println("Validator keys:")
for _, key := range response.Data.ValidatorKeys {
for _, key := range response.Data.RebuiltValidatorKeys {
fmt.Println(key.Hex())
}
fmt.Println()
} else {
fmt.Println("No validator keys were found.")
}

if !utils.Confirm("Would you like to restart your Validator Client now so it can attest with the recovered keys?") {
fmt.Println("Please restart the Validator Client manually at your earliest convenience to load the keys.")
return nil
}
if !utils.Confirm("Would you like to restart your Validator Client now so it can attest with the recovered keys?") {
fmt.Println("Please restart the Validator Client manually at your earliest convenience to load the keys.")
return nil
}

// Restart the VC
fmt.Println("Restarting Validator Client...")
_, err = rp.Api.Service.RestartVc()
if err != nil {
fmt.Printf("Error restarting Validator Client: %s\n", err.Error())
fmt.Println("Please restart the Validator Client manually at your earliest convenience to load the keys.")
return nil
// Restart the VC
fmt.Println("Restarting Validator Client...")
_, err = rp.Api.Service.RestartVc()
if err != nil {
fmt.Printf("Error restarting Validator Client: %s\n", err.Error())
fmt.Println("Please restart the Validator Client manually at your earliest convenience to load the keys.")
return nil
}
fmt.Println("Validator Client restarted successfully.")
} else {
fmt.Println("No validator keys were found.")
}
fmt.Println("Validator Client restarted successfully.")

return nil
}
5 changes: 5 additions & 0 deletions rocketpool-cli/commands/wallet/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ var (
Aliases: []string{"a"},
Usage: "If you are recovering a wallet that was not generated by the Smartnode and don't know the derivation path or index of it, enter the address here. The Smartnode will search through its library of paths and indices to try to find it.",
}
enablePartialRebuild = &cli.StringSliceFlag{
Name: "enable-partial-rebuild",
Aliases: []string{"epr"},
Usage: "Allows the wallet rebuild process to partially succeed, responding with public keys for successfully rebuilt targets and errors for rebuild failures",
}
)

// Prompt for a new wallet password
Expand Down
13 changes: 8 additions & 5 deletions rocketpool-daemon/api/wallet/rebuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package wallet

import (
"fmt"
"net/url"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/gorilla/mux"
"github.com/rocket-pool/node-manager-core/utils/input"
"net/url"

"github.com/rocket-pool/node-manager-core/api/server"
"github.com/rocket-pool/node-manager-core/api/types"
Expand All @@ -24,7 +24,9 @@ func (f *walletRebuildContextFactory) Create(args url.Values) (*walletRebuildCon
c := &walletRebuildContext{
handler: f.handler,
}
return c, nil
inputError := server.ValidateOptionalArg("enable-partial-rebuild", args, input.ValidateBool, &c.enablePartialRebuild, nil)

return c, inputError
}

func (f *walletRebuildContextFactory) RegisterRoute(router *mux.Router) {
Expand All @@ -38,7 +40,8 @@ func (f *walletRebuildContextFactory) RegisterRoute(router *mux.Router) {
// ===============

type walletRebuildContext struct {
handler *WalletHandler
handler *WalletHandler
enablePartialRebuild bool
}

func (c *walletRebuildContext) PrepareData(data *api.WalletRebuildData, opts *bind.TransactOpts) (types.ResponseStatus, error) {
Expand All @@ -56,7 +59,7 @@ func (c *walletRebuildContext) PrepareData(data *api.WalletRebuildData, opts *bi
}

// Recover validator keys
data.ValidatorKeys, err = vMgr.RecoverMinipoolKeys(false)
data.RebuiltValidatorKeys, data.FailureReasons, err = vMgr.RecoverMinipoolKeysWithPartial(false, c.enablePartialRebuild)
if err != nil {
return types.ResponseStatus_Error, fmt.Errorf("error recovering minipool keys: %w", err)
}
Expand Down
Loading

0 comments on commit 5085b10

Please sign in to comment.