cmd/clef, signer/core: password input fixes (#20960)
* cmd/clef, signer/core: use better terminal input for passwords, make it possible to avoid boot-up warning * all: move commonly used prompter to isolated (small) package * cmd/clef: Add new --acceptWarn to clef README * cmd/clef: rename flag 'acceptWarn' to 'suppress-bootwarn' Co-authored-by: ligi <ligi@ligi.de>
This commit is contained in:
parent
3666da8a4b
commit
e0987f67e0
@ -46,6 +46,7 @@ GLOBAL OPTIONS:
|
|||||||
--stdio-ui Use STDIN/STDOUT as a channel for an external UI. This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user interface, and can be used when Clef is started by an external process.
|
--stdio-ui Use STDIN/STDOUT as a channel for an external UI. This means that an STDIN/STDOUT is used for RPC-communication with a e.g. a graphical user interface, and can be used when Clef is started by an external process.
|
||||||
--stdio-ui-test Mechanism to test interface between Clef and UI. Requires 'stdio-ui'.
|
--stdio-ui-test Mechanism to test interface between Clef and UI. Requires 'stdio-ui'.
|
||||||
--advanced If enabled, issues warnings instead of rejections for suspicious requests. Default off
|
--advanced If enabled, issues warnings instead of rejections for suspicious requests. Default off
|
||||||
|
--suppress-bootwarn If set, does not show the warning during boot
|
||||||
--help, -h show help
|
--help, -h show help
|
||||||
--version, -v print the version
|
--version, -v print the version
|
||||||
```
|
```
|
||||||
|
@ -40,7 +40,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
@ -82,6 +82,10 @@ var (
|
|||||||
Name: "advanced",
|
Name: "advanced",
|
||||||
Usage: "If enabled, issues warnings instead of rejections for suspicious requests. Default off",
|
Usage: "If enabled, issues warnings instead of rejections for suspicious requests. Default off",
|
||||||
}
|
}
|
||||||
|
acceptFlag = cli.BoolFlag{
|
||||||
|
Name: "suppress-bootwarn",
|
||||||
|
Usage: "If set, does not show the warning during boot",
|
||||||
|
}
|
||||||
keystoreFlag = cli.StringFlag{
|
keystoreFlag = cli.StringFlag{
|
||||||
Name: "keystore",
|
Name: "keystore",
|
||||||
Value: filepath.Join(node.DefaultDataDir(), "keystore"),
|
Value: filepath.Join(node.DefaultDataDir(), "keystore"),
|
||||||
@ -196,6 +200,7 @@ The delpw command removes a password for a given address (keyfile).
|
|||||||
logLevelFlag,
|
logLevelFlag,
|
||||||
keystoreFlag,
|
keystoreFlag,
|
||||||
utils.LightKDFFlag,
|
utils.LightKDFFlag,
|
||||||
|
acceptFlag,
|
||||||
},
|
},
|
||||||
Description: `
|
Description: `
|
||||||
The newaccount command creates a new keystore-backed account. It is a convenience-method
|
The newaccount command creates a new keystore-backed account. It is a convenience-method
|
||||||
@ -235,6 +240,7 @@ func init() {
|
|||||||
stdiouiFlag,
|
stdiouiFlag,
|
||||||
testFlag,
|
testFlag,
|
||||||
advancedMode,
|
advancedMode,
|
||||||
|
acceptFlag,
|
||||||
}
|
}
|
||||||
app.Action = signer
|
app.Action = signer
|
||||||
app.Commands = []cli.Command{initCommand,
|
app.Commands = []cli.Command{initCommand,
|
||||||
@ -433,8 +439,10 @@ func initialize(c *cli.Context) error {
|
|||||||
if c.GlobalBool(stdiouiFlag.Name) {
|
if c.GlobalBool(stdiouiFlag.Name) {
|
||||||
logOutput = os.Stderr
|
logOutput = os.Stderr
|
||||||
// If using the stdioui, we can't do the 'confirm'-flow
|
// If using the stdioui, we can't do the 'confirm'-flow
|
||||||
fmt.Fprint(logOutput, legalWarning)
|
if !c.GlobalBool(acceptFlag.Name) {
|
||||||
} else {
|
fmt.Fprint(logOutput, legalWarning)
|
||||||
|
}
|
||||||
|
} else if !c.GlobalBool(acceptFlag.Name) {
|
||||||
if !confirm(legalWarning) {
|
if !confirm(legalWarning) {
|
||||||
return fmt.Errorf("aborted by user")
|
return fmt.Errorf("aborted by user")
|
||||||
}
|
}
|
||||||
@ -910,14 +918,14 @@ func testExternalUI(api *core.SignerAPI) {
|
|||||||
// getPassPhrase retrieves the password associated with clef, either fetched
|
// getPassPhrase retrieves the password associated with clef, either fetched
|
||||||
// from a list of preloaded passphrases, or requested interactively from the user.
|
// from a list of preloaded passphrases, or requested interactively from the user.
|
||||||
// TODO: there are many `getPassPhrase` functions, it will be better to abstract them into one.
|
// TODO: there are many `getPassPhrase` functions, it will be better to abstract them into one.
|
||||||
func getPassPhrase(prompt string, confirmation bool) string {
|
func getPassPhrase(query string, confirmation bool) string {
|
||||||
fmt.Println(prompt)
|
fmt.Println(query)
|
||||||
password, err := console.Stdin.PromptPassword("Password: ")
|
password, err := prompt.Stdin.PromptPassword("Password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read password: %v", err)
|
utils.Fatalf("Failed to read password: %v", err)
|
||||||
}
|
}
|
||||||
if confirmation {
|
if confirmation {
|
||||||
confirm, err := console.Stdin.PromptPassword("Repeat password: ")
|
confirm, err := prompt.Stdin.PromptPassword("Repeat password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read password confirmation: %v", err)
|
utils.Fatalf("Failed to read password confirmation: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
cli "gopkg.in/urfave/cli.v1"
|
cli "gopkg.in/urfave/cli.v1"
|
||||||
@ -226,7 +226,7 @@ func loadSigningKey(keyfile string) *ecdsa.PrivateKey {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
exit(fmt.Errorf("failed to read the keyfile at '%s': %v", keyfile, err))
|
exit(fmt.Errorf("failed to read the keyfile at '%s': %v", keyfile, err))
|
||||||
}
|
}
|
||||||
password, _ := console.Stdin.PromptPassword("Please enter the password for '" + keyfile + "': ")
|
password, _ := prompt.Stdin.PromptPassword("Please enter the password for '" + keyfile + "': ")
|
||||||
key, err := keystore.DecryptKey(keyjson, password)
|
key, err := keystore.DecryptKey(keyjson, password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exit(fmt.Errorf("error decrypting key: %v", err))
|
exit(fmt.Errorf("error decrypting key: %v", err))
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
)
|
)
|
||||||
@ -31,13 +31,13 @@ import (
|
|||||||
// promptPassphrase prompts the user for a passphrase. Set confirmation to true
|
// promptPassphrase prompts the user for a passphrase. Set confirmation to true
|
||||||
// to require the user to confirm the passphrase.
|
// to require the user to confirm the passphrase.
|
||||||
func promptPassphrase(confirmation bool) string {
|
func promptPassphrase(confirmation bool) string {
|
||||||
passphrase, err := console.Stdin.PromptPassword("Password: ")
|
passphrase, err := prompt.Stdin.PromptPassword("Password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read password: %v", err)
|
utils.Fatalf("Failed to read password: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if confirmation {
|
if confirmation {
|
||||||
confirm, err := console.Stdin.PromptPassword("Repeat password: ")
|
confirm, err := prompt.Stdin.PromptPassword("Repeat password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read password confirmation: %v", err)
|
utils.Fatalf("Failed to read password confirmation: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
prompt2 "github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
@ -247,12 +247,12 @@ func getPassPhrase(prompt string, confirmation bool, i int, passwords []string)
|
|||||||
if prompt != "" {
|
if prompt != "" {
|
||||||
fmt.Println(prompt)
|
fmt.Println(prompt)
|
||||||
}
|
}
|
||||||
password, err := console.Stdin.PromptPassword("Password: ")
|
password, err := prompt2.Stdin.PromptPassword("Password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read password: %v", err)
|
utils.Fatalf("Failed to read password: %v", err)
|
||||||
}
|
}
|
||||||
if confirmation {
|
if confirmation {
|
||||||
confirm, err := console.Stdin.PromptPassword("Repeat password: ")
|
confirm, err := prompt2.Stdin.PromptPassword("Repeat password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read password confirmation: %v", err)
|
utils.Fatalf("Failed to read password confirmation: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
@ -521,7 +521,7 @@ func removeDB(ctx *cli.Context) error {
|
|||||||
// confirmAndRemoveDB prompts the user for a last confirmation and removes the
|
// confirmAndRemoveDB prompts the user for a last confirmation and removes the
|
||||||
// folder if accepted.
|
// folder if accepted.
|
||||||
func confirmAndRemoveDB(database string, kind string) {
|
func confirmAndRemoveDB(database string, kind string) {
|
||||||
confirm, err := console.Stdin.PromptConfirm(fmt.Sprintf("Remove %s (%s)?", kind, database))
|
confirm, err := prompt.Stdin.PromptConfirm(fmt.Sprintf("Remove %s (%s)?", kind, database))
|
||||||
switch {
|
switch {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
|
@ -33,7 +33,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
"github.com/ethereum/go-ethereum/ethclient"
|
"github.com/ethereum/go-ethereum/ethclient"
|
||||||
@ -258,7 +258,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
app.After = func(ctx *cli.Context) error {
|
app.After = func(ctx *cli.Context) error {
|
||||||
debug.Exit()
|
debug.Exit()
|
||||||
console.Stdin.Close() // Resets terminal mode.
|
prompt.Stdin.Close() // Resets terminal mode.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/console"
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
@ -210,7 +210,7 @@ func initialize() {
|
|||||||
|
|
||||||
if *mailServerMode {
|
if *mailServerMode {
|
||||||
if len(msPassword) == 0 {
|
if len(msPassword) == 0 {
|
||||||
msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ")
|
msPassword, err = prompt.Stdin.PromptPassword("Please enter the Mail Server password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read Mail Server password: %s", err)
|
utils.Fatalf("Failed to read Mail Server password: %s", err)
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ func configureNode() {
|
|||||||
if *requestMail {
|
if *requestMail {
|
||||||
p2pAccept = true
|
p2pAccept = true
|
||||||
if len(msPassword) == 0 {
|
if len(msPassword) == 0 {
|
||||||
msPassword, err = console.Stdin.PromptPassword("Please enter the Mail Server password: ")
|
msPassword, err = prompt.Stdin.PromptPassword("Please enter the Mail Server password: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read Mail Server password: %s", err)
|
utils.Fatalf("Failed to read Mail Server password: %s", err)
|
||||||
}
|
}
|
||||||
@ -355,7 +355,7 @@ func configureNode() {
|
|||||||
|
|
||||||
if !*asymmetricMode && !*forwarderMode {
|
if !*asymmetricMode && !*forwarderMode {
|
||||||
if len(symPass) == 0 {
|
if len(symPass) == 0 {
|
||||||
symPass, err = console.Stdin.PromptPassword("Please enter the password for symmetric encryption: ")
|
symPass, err = prompt.Stdin.PromptPassword("Please enter the password for symmetric encryption: ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("Failed to read password: %v", err)
|
utils.Fatalf("Failed to read password: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
"github.com/ethereum/go-ethereum/accounts/scwallet"
|
||||||
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
"github.com/ethereum/go-ethereum/accounts/usbwallet"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/internal/jsre"
|
"github.com/ethereum/go-ethereum/internal/jsre"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
@ -35,13 +36,13 @@ import (
|
|||||||
// bridge is a collection of JavaScript utility methods to bride the .js runtime
|
// bridge is a collection of JavaScript utility methods to bride the .js runtime
|
||||||
// environment and the Go RPC connection backing the remote method calls.
|
// environment and the Go RPC connection backing the remote method calls.
|
||||||
type bridge struct {
|
type bridge struct {
|
||||||
client *rpc.Client // RPC client to execute Ethereum requests through
|
client *rpc.Client // RPC client to execute Ethereum requests through
|
||||||
prompter UserPrompter // Input prompter to allow interactive user feedback
|
prompter prompt.UserPrompter // Input prompter to allow interactive user feedback
|
||||||
printer io.Writer // Output writer to serialize any display strings to
|
printer io.Writer // Output writer to serialize any display strings to
|
||||||
}
|
}
|
||||||
|
|
||||||
// newBridge creates a new JavaScript wrapper around an RPC client.
|
// newBridge creates a new JavaScript wrapper around an RPC client.
|
||||||
func newBridge(client *rpc.Client, prompter UserPrompter, printer io.Writer) *bridge {
|
func newBridge(client *rpc.Client, prompter prompt.UserPrompter, printer io.Writer) *bridge {
|
||||||
return &bridge{
|
return &bridge{
|
||||||
client: client,
|
client: client,
|
||||||
prompter: prompter,
|
prompter: prompter,
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/dop251/goja"
|
"github.com/dop251/goja"
|
||||||
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/internal/jsre"
|
"github.com/ethereum/go-ethereum/internal/jsre"
|
||||||
"github.com/ethereum/go-ethereum/internal/jsre/deps"
|
"github.com/ethereum/go-ethereum/internal/jsre/deps"
|
||||||
"github.com/ethereum/go-ethereum/internal/web3ext"
|
"github.com/ethereum/go-ethereum/internal/web3ext"
|
||||||
@ -52,26 +53,26 @@ const DefaultPrompt = "> "
|
|||||||
// Config is the collection of configurations to fine tune the behavior of the
|
// Config is the collection of configurations to fine tune the behavior of the
|
||||||
// JavaScript console.
|
// JavaScript console.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
DataDir string // Data directory to store the console history at
|
DataDir string // Data directory to store the console history at
|
||||||
DocRoot string // Filesystem path from where to load JavaScript files from
|
DocRoot string // Filesystem path from where to load JavaScript files from
|
||||||
Client *rpc.Client // RPC client to execute Ethereum requests through
|
Client *rpc.Client // RPC client to execute Ethereum requests through
|
||||||
Prompt string // Input prompt prefix string (defaults to DefaultPrompt)
|
Prompt string // Input prompt prefix string (defaults to DefaultPrompt)
|
||||||
Prompter UserPrompter // Input prompter to allow interactive user feedback (defaults to TerminalPrompter)
|
Prompter prompt.UserPrompter // Input prompter to allow interactive user feedback (defaults to TerminalPrompter)
|
||||||
Printer io.Writer // Output writer to serialize any display strings to (defaults to os.Stdout)
|
Printer io.Writer // Output writer to serialize any display strings to (defaults to os.Stdout)
|
||||||
Preload []string // Absolute paths to JavaScript files to preload
|
Preload []string // Absolute paths to JavaScript files to preload
|
||||||
}
|
}
|
||||||
|
|
||||||
// Console is a JavaScript interpreted runtime environment. It is a fully fledged
|
// Console is a JavaScript interpreted runtime environment. It is a fully fledged
|
||||||
// JavaScript console attached to a running node via an external or in-process RPC
|
// JavaScript console attached to a running node via an external or in-process RPC
|
||||||
// client.
|
// client.
|
||||||
type Console struct {
|
type Console struct {
|
||||||
client *rpc.Client // RPC client to execute Ethereum requests through
|
client *rpc.Client // RPC client to execute Ethereum requests through
|
||||||
jsre *jsre.JSRE // JavaScript runtime environment running the interpreter
|
jsre *jsre.JSRE // JavaScript runtime environment running the interpreter
|
||||||
prompt string // Input prompt prefix string
|
prompt string // Input prompt prefix string
|
||||||
prompter UserPrompter // Input prompter to allow interactive user feedback
|
prompter prompt.UserPrompter // Input prompter to allow interactive user feedback
|
||||||
histPath string // Absolute path to the console scrollback history
|
histPath string // Absolute path to the console scrollback history
|
||||||
history []string // Scroll history maintained by the console
|
history []string // Scroll history maintained by the console
|
||||||
printer io.Writer // Output writer to serialize any display strings to
|
printer io.Writer // Output writer to serialize any display strings to
|
||||||
}
|
}
|
||||||
|
|
||||||
// New initializes a JavaScript interpreted runtime environment and sets defaults
|
// New initializes a JavaScript interpreted runtime environment and sets defaults
|
||||||
@ -79,7 +80,7 @@ type Console struct {
|
|||||||
func New(config Config) (*Console, error) {
|
func New(config Config) (*Console, error) {
|
||||||
// Handle unset config values gracefully
|
// Handle unset config values gracefully
|
||||||
if config.Prompter == nil {
|
if config.Prompter == nil {
|
||||||
config.Prompter = Stdin
|
config.Prompter = prompt.Stdin
|
||||||
}
|
}
|
||||||
if config.Prompt == "" {
|
if config.Prompt == "" {
|
||||||
config.Prompt = DefaultPrompt
|
config.Prompt = DefaultPrompt
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
"github.com/ethereum/go-ethereum/internal/jsre"
|
"github.com/ethereum/go-ethereum/internal/jsre"
|
||||||
@ -67,10 +68,10 @@ func (p *hookedPrompter) PromptPassword(prompt string) (string, error) {
|
|||||||
func (p *hookedPrompter) PromptConfirm(prompt string) (bool, error) {
|
func (p *hookedPrompter) PromptConfirm(prompt string) (bool, error) {
|
||||||
return false, errors.New("not implemented")
|
return false, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
func (p *hookedPrompter) SetHistory(history []string) {}
|
func (p *hookedPrompter) SetHistory(history []string) {}
|
||||||
func (p *hookedPrompter) AppendHistory(command string) {}
|
func (p *hookedPrompter) AppendHistory(command string) {}
|
||||||
func (p *hookedPrompter) ClearHistory() {}
|
func (p *hookedPrompter) ClearHistory() {}
|
||||||
func (p *hookedPrompter) SetWordCompleter(completer WordCompleter) {}
|
func (p *hookedPrompter) SetWordCompleter(completer prompt.WordCompleter) {}
|
||||||
|
|
||||||
// tester is a console test environment for the console tests to operate on.
|
// tester is a console test environment for the console tests to operate on.
|
||||||
type tester struct {
|
type tester struct {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU Lesser General Public License
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
package console
|
package prompt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
@ -25,9 +25,9 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/console/prompt"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"golang.org/x/crypto/ssh/terminal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CommandlineUI struct {
|
type CommandlineUI struct {
|
||||||
@ -61,17 +61,16 @@ func (ui *CommandlineUI) readString() string {
|
|||||||
func (ui *CommandlineUI) OnInputRequired(info UserInputRequest) (UserInputResponse, error) {
|
func (ui *CommandlineUI) OnInputRequired(info UserInputRequest) (UserInputResponse, error) {
|
||||||
|
|
||||||
fmt.Printf("## %s\n\n%s\n", info.Title, info.Prompt)
|
fmt.Printf("## %s\n\n%s\n", info.Title, info.Prompt)
|
||||||
|
defer fmt.Println("-----------------------")
|
||||||
if info.IsPassword {
|
if info.IsPassword {
|
||||||
fmt.Printf("> ")
|
text, err := prompt.Stdin.PromptPassword("> ")
|
||||||
text, err := terminal.ReadPassword(int(os.Stdin.Fd()))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Failed to read password", "err", err)
|
log.Error("Failed to read password", "error", err)
|
||||||
|
return UserInputResponse{}, err
|
||||||
}
|
}
|
||||||
fmt.Println("-----------------------")
|
return UserInputResponse{text}, nil
|
||||||
return UserInputResponse{string(text)}, err
|
|
||||||
}
|
}
|
||||||
text := ui.readString()
|
text := ui.readString()
|
||||||
fmt.Println("-----------------------")
|
|
||||||
return UserInputResponse{text}, nil
|
return UserInputResponse{text}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user