Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

all: remove personal RPC namespace #30704

Merged
merged 4 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var (
utils.SmartCardDaemonPathFlag,
utils.OverrideCancun,
utils.OverrideVerkle,
utils.EnablePersonal,
utils.EnablePersonal, // deprecated
utils.TxPoolLocalsFlag,
utils.TxPoolNoLocalsFlag,
utils.TxPoolJournalFlag,
Expand Down
8 changes: 1 addition & 7 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,11 +741,6 @@ var (
Value: node.DefaultConfig.BatchResponseMaxSize,
Category: flags.APICategory,
}
EnablePersonal = &cli.BoolFlag{
Name: "rpc.enabledeprecatedpersonal",
Usage: "Enables the (deprecated) personal namespace",
Category: flags.APICategory,
}

// Network Settings
MaxPeersFlag = &cli.IntFlag{
Expand Down Expand Up @@ -1399,9 +1394,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
if ctx.IsSet(JWTSecretFlag.Name) {
cfg.JWTSecret = ctx.String(JWTSecretFlag.Name)
}

if ctx.IsSet(EnablePersonal.Name) {
cfg.EnablePersonal = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we exit geth here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or at least print a warning?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning sgtm!

log.Warn(fmt.Sprintf("Option --%s is deprecated. The 'personal' RPC namespace has been removed.", EnablePersonal.Name))
}

if ctx.IsSet(ExternalSignerFlag.Name) {
Expand Down
6 changes: 6 additions & 0 deletions cmd/utils/flags_legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,12 @@ var (
Usage: "Enable expensive metrics collection and reporting (deprecated)",
Category: flags.DeprecatedCategory,
}
// Deprecated Oct 2024
EnablePersonal = &cli.BoolFlag{
Name: "rpc.enabledeprecatedpersonal",
Usage: "This used to enable the 'personal' namespace.",
Category: flags.DeprecatedCategory,
}
)

// showDeprecated displays deprecated flags that will be soon removed from the codebase.
Expand Down
265 changes: 0 additions & 265 deletions console/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,12 @@ package console
import (
"encoding/json"
"errors"
"fmt"
"io"
"reflect"
"strings"
"time"

"github.com/dop251/goja"
"github.com/ethereum/go-ethereum/accounts/scwallet"
"github.com/ethereum/go-ethereum/accounts/usbwallet"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/console/prompt"
"github.com/ethereum/go-ethereum/internal/jsre"
Expand All @@ -51,268 +48,6 @@ func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writ
}
}

func getJeth(vm *goja.Runtime) *goja.Object {
jeth := vm.Get("jeth")
if jeth == nil {
panic(vm.ToValue("jeth object does not exist"))
}
return jeth.ToObject(vm)
}

// NewAccount is a wrapper around the personal.newAccount RPC method that uses a
// non-echoing password prompt to acquire the passphrase and executes the original
// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call.
func (b *bridge) NewAccount(call jsre.Call) (goja.Value, error) {
var (
password string
confirm string
err error
)
switch {
// No password was specified, prompt the user for it
case len(call.Arguments) == 0:
if password, err = b.prompter.PromptPassword("Passphrase: "); err != nil {
return nil, err
}
if confirm, err = b.prompter.PromptPassword("Repeat passphrase: "); err != nil {
return nil, err
}
if password != confirm {
return nil, errors.New("passwords don't match")
}
// A single string password was specified, use that
case len(call.Arguments) == 1 && call.Argument(0).ToString() != nil:
password = call.Argument(0).ToString().String()
default:
return nil, errors.New("expected 0 or 1 string argument")
}
// Password acquired, execute the call and return
newAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("newAccount"))
if !callable {
return nil, errors.New("jeth.newAccount is not callable")
}
ret, err := newAccount(goja.Null(), call.VM.ToValue(password))
if err != nil {
return nil, err
}
return ret, nil
}

// OpenWallet is a wrapper around personal.openWallet which can interpret and
// react to certain error messages, such as the Trezor PIN matrix request.
func (b *bridge) OpenWallet(call jsre.Call) (goja.Value, error) {
// Make sure we have a wallet specified to open
if call.Argument(0).ToObject(call.VM).ClassName() != "String" {
return nil, errors.New("first argument must be the wallet URL to open")
}
wallet := call.Argument(0)

var passwd goja.Value
if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) {
passwd = call.VM.ToValue("")
} else {
passwd = call.Argument(1)
}
// Open the wallet and return if successful in itself
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
if !callable {
return nil, errors.New("jeth.openWallet is not callable")
}
val, err := openWallet(goja.Null(), wallet, passwd)
if err == nil {
return val, nil
}

// Wallet open failed, report error unless it's a PIN or PUK entry
switch {
case strings.HasSuffix(err.Error(), usbwallet.ErrTrezorPINNeeded.Error()):
val, err = b.readPinAndReopenWallet(call)
if err == nil {
return val, nil
}
val, err = b.readPassphraseAndReopenWallet(call)
if err != nil {
return nil, err
}

case strings.HasSuffix(err.Error(), scwallet.ErrPairingPasswordNeeded.Error()):
// PUK input requested, fetch from the user and call open again
input, err := b.prompter.PromptPassword("Please enter the pairing password: ")
if err != nil {
return nil, err
}
passwd = call.VM.ToValue(input)
if val, err = openWallet(goja.Null(), wallet, passwd); err != nil {
if !strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()) {
return nil, err
}
// PIN input requested, fetch from the user and call open again
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
if err != nil {
return nil, err
}
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil {
return nil, err
}
}

case strings.HasSuffix(err.Error(), scwallet.ErrPINUnblockNeeded.Error()):
// PIN unblock requested, fetch PUK and new PIN from the user
var pukpin string
input, err := b.prompter.PromptPassword("Please enter current PUK: ")
if err != nil {
return nil, err
}
pukpin = input
input, err = b.prompter.PromptPassword("Please enter new PIN: ")
if err != nil {
return nil, err
}
pukpin += input

if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(pukpin)); err != nil {
return nil, err
}

case strings.HasSuffix(err.Error(), scwallet.ErrPINNeeded.Error()):
// PIN input requested, fetch from the user and call open again
input, err := b.prompter.PromptPassword("Please enter current PIN: ")
if err != nil {
return nil, err
}
if val, err = openWallet(goja.Null(), wallet, call.VM.ToValue(input)); err != nil {
return nil, err
}

default:
// Unknown error occurred, drop to the user
return nil, err
}
return val, nil
}

func (b *bridge) readPassphraseAndReopenWallet(call jsre.Call) (goja.Value, error) {
wallet := call.Argument(0)
input, err := b.prompter.PromptPassword("Please enter your passphrase: ")
if err != nil {
return nil, err
}
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
if !callable {
return nil, errors.New("jeth.openWallet is not callable")
}
return openWallet(goja.Null(), wallet, call.VM.ToValue(input))
}

func (b *bridge) readPinAndReopenWallet(call jsre.Call) (goja.Value, error) {
wallet := call.Argument(0)
// Trezor PIN matrix input requested, display the matrix to the user and fetch the data
fmt.Fprintf(b.printer, "Look at the device for number positions\n\n")
fmt.Fprintf(b.printer, "7 | 8 | 9\n")
fmt.Fprintf(b.printer, "--+---+--\n")
fmt.Fprintf(b.printer, "4 | 5 | 6\n")
fmt.Fprintf(b.printer, "--+---+--\n")
fmt.Fprintf(b.printer, "1 | 2 | 3\n\n")

input, err := b.prompter.PromptPassword("Please enter current PIN: ")
if err != nil {
return nil, err
}
openWallet, callable := goja.AssertFunction(getJeth(call.VM).Get("openWallet"))
if !callable {
return nil, errors.New("jeth.openWallet is not callable")
}
return openWallet(goja.Null(), wallet, call.VM.ToValue(input))
}

// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that
// uses a non-echoing password prompt to acquire the passphrase and executes the
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
// the RPC call.
func (b *bridge) UnlockAccount(call jsre.Call) (goja.Value, error) {
if len(call.Arguments) < 1 {
return nil, errors.New("usage: unlockAccount(account, [ password, duration ])")
}

account := call.Argument(0)
// Make sure we have an account specified to unlock.
if goja.IsUndefined(account) || goja.IsNull(account) || account.ExportType().Kind() != reflect.String {
return nil, errors.New("first argument must be the account to unlock")
}

// If password is not given or is the null value, prompt the user for it.
var passwd goja.Value
if goja.IsUndefined(call.Argument(1)) || goja.IsNull(call.Argument(1)) {
fmt.Fprintf(b.printer, "Unlock account %s\n", account)
input, err := b.prompter.PromptPassword("Passphrase: ")
if err != nil {
return nil, err
}
passwd = call.VM.ToValue(input)
} else {
if call.Argument(1).ExportType().Kind() != reflect.String {
return nil, errors.New("password must be a string")
}
passwd = call.Argument(1)
}

// Third argument is the duration how long the account should be unlocked.
duration := goja.Null()
if !goja.IsUndefined(call.Argument(2)) && !goja.IsNull(call.Argument(2)) {
if !isNumber(call.Argument(2)) {
return nil, errors.New("unlock duration must be a number")
}
duration = call.Argument(2)
}

// Send the request to the backend and return.
unlockAccount, callable := goja.AssertFunction(getJeth(call.VM).Get("unlockAccount"))
if !callable {
return nil, errors.New("jeth.unlockAccount is not callable")
}
return unlockAccount(goja.Null(), account, passwd, duration)
}

// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password
// prompt to acquire the passphrase and executes the original RPC method (saved in
// jeth.sign) with it to actually execute the RPC call.
func (b *bridge) Sign(call jsre.Call) (goja.Value, error) {
if nArgs := len(call.Arguments); nArgs < 2 {
return nil, errors.New("usage: sign(message, account, [ password ])")
}
var (
message = call.Argument(0)
account = call.Argument(1)
passwd = call.Argument(2)
)

if goja.IsUndefined(message) || message.ExportType().Kind() != reflect.String {
return nil, errors.New("first argument must be the message to sign")
}
if goja.IsUndefined(account) || account.ExportType().Kind() != reflect.String {
return nil, errors.New("second argument must be the account to sign with")
}

// if the password is not given or null ask the user and ensure password is a string
if goja.IsUndefined(passwd) || goja.IsNull(passwd) {
fmt.Fprintf(b.printer, "Give password for account %s\n", account)
input, err := b.prompter.PromptPassword("Password: ")
if err != nil {
return nil, err
}
passwd = call.VM.ToValue(input)
} else if passwd.ExportType().Kind() != reflect.String {
return nil, errors.New("third argument must be the password to unlock the account")
}

// Send the request to the backend and return
sign, callable := goja.AssertFunction(getJeth(call.VM).Get("sign"))
if !callable {
return nil, errors.New("jeth.sign is not callable")
}
return sign(goja.Null(), message, account, passwd)
}

// Sleep will block the console for the specified number of seconds.
func (b *bridge) Sleep(call jsre.Call) (goja.Value, error) {
if nArgs := len(call.Arguments); nArgs < 1 {
Expand Down
48 changes: 0 additions & 48 deletions console/bridge_test.go

This file was deleted.

Loading