cmd/clef: add newaccount command (#20782)
* cmd/clef: add newaccount command * cmd/clef: document clef_New, update API versioning * Update cmd/clef/intapi_changelog.md Co-Authored-By: ligi <ligi@ligi.de> * Update signer/core/uiapi.go Co-Authored-By: ligi <ligi@ligi.de> Co-authored-by: ligi <ligi@ligi.de>
This commit is contained in:
parent
8f05cfa122
commit
c56f4fa808
@ -10,6 +10,17 @@ TL;DR: Given a version number MAJOR.MINOR.PATCH, increment the:
|
|||||||
|
|
||||||
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
|
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
|
||||||
|
|
||||||
|
### 7.0.1
|
||||||
|
|
||||||
|
Added `clef_New` to the internal API calleable from a UI.
|
||||||
|
|
||||||
|
> `New` creates a new password protected Account. The private key is protected with
|
||||||
|
> the given password. Users are responsible to backup the private key that is stored
|
||||||
|
> in the keystore location that was specified when this API was created.
|
||||||
|
> This method is the same as New on the external API, the difference being that
|
||||||
|
> this implementation does not ask for confirmation, since it's initiated by
|
||||||
|
> the user
|
||||||
|
|
||||||
### 7.0.0
|
### 7.0.0
|
||||||
|
|
||||||
- The `message` field was renamed to `messages` in all data signing request methods to better reflect that it's a list, not a value.
|
- The `message` field was renamed to `messages` in all data signing request methods to better reflect that it's a list, not a value.
|
||||||
|
@ -187,6 +187,21 @@ The setpw command stores a password for a given address (keyfile).
|
|||||||
Description: `
|
Description: `
|
||||||
The delpw command removes a password for a given address (keyfile).
|
The delpw command removes a password for a given address (keyfile).
|
||||||
`}
|
`}
|
||||||
|
newAccountCommand = cli.Command{
|
||||||
|
Action: utils.MigrateFlags(newAccount),
|
||||||
|
Name: "newaccount",
|
||||||
|
Usage: "Create a new account",
|
||||||
|
ArgsUsage: "",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
logLevelFlag,
|
||||||
|
keystoreFlag,
|
||||||
|
utils.LightKDFFlag,
|
||||||
|
},
|
||||||
|
Description: `
|
||||||
|
The newaccount command creates a new keystore-backed account. It is a convenience-method
|
||||||
|
which can be used in lieu of an external UI.`,
|
||||||
|
}
|
||||||
|
|
||||||
gendocCommand = cli.Command{
|
gendocCommand = cli.Command{
|
||||||
Action: GenDoc,
|
Action: GenDoc,
|
||||||
Name: "gendoc",
|
Name: "gendoc",
|
||||||
@ -222,7 +237,12 @@ func init() {
|
|||||||
advancedMode,
|
advancedMode,
|
||||||
}
|
}
|
||||||
app.Action = signer
|
app.Action = signer
|
||||||
app.Commands = []cli.Command{initCommand, attestCommand, setCredentialCommand, delCredentialCommand, gendocCommand}
|
app.Commands = []cli.Command{initCommand,
|
||||||
|
attestCommand,
|
||||||
|
setCredentialCommand,
|
||||||
|
delCredentialCommand,
|
||||||
|
newAccountCommand,
|
||||||
|
gendocCommand}
|
||||||
cli.CommandHelpTemplate = utils.OriginCommandHelpTemplate
|
cli.CommandHelpTemplate = utils.OriginCommandHelpTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,6 +402,31 @@ func removeCredential(ctx *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newAccount(c *cli.Context) error {
|
||||||
|
if err := initialize(c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// The newaccount is meant for users using the CLI, since 'real' external
|
||||||
|
// UIs can use the UI-api instead. So we'll just use the native CLI UI here.
|
||||||
|
var (
|
||||||
|
ui = core.NewCommandlineUI()
|
||||||
|
pwStorage storage.Storage = &storage.NoStorage{}
|
||||||
|
ksLoc = c.GlobalString(keystoreFlag.Name)
|
||||||
|
lightKdf = c.GlobalBool(utils.LightKDFFlag.Name)
|
||||||
|
)
|
||||||
|
log.Info("Starting clef", "keystore", ksLoc, "light-kdf", lightKdf)
|
||||||
|
am := core.StartClefAccountManager(ksLoc, true, lightKdf, "")
|
||||||
|
// This gives is us access to the external API
|
||||||
|
apiImpl := core.NewSignerAPI(am, 0, true, ui, nil, false, pwStorage)
|
||||||
|
// This gives us access to the internal API
|
||||||
|
internalApi := core.NewUIServerAPI(apiImpl)
|
||||||
|
addr, err := internalApi.New(context.Background())
|
||||||
|
if err == nil {
|
||||||
|
fmt.Printf("Generated account %v\n", addr.String())
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func initialize(c *cli.Context) error {
|
func initialize(c *cli.Context) error {
|
||||||
// Set up the logger to print everything
|
// Set up the logger to print everything
|
||||||
logOutput := os.Stdout
|
logOutput := os.Stdout
|
||||||
@ -457,7 +502,6 @@ func signer(c *cli.Context) error {
|
|||||||
api core.ExternalAPI
|
api core.ExternalAPI
|
||||||
pwStorage storage.Storage = &storage.NoStorage{}
|
pwStorage storage.Storage = &storage.NoStorage{}
|
||||||
)
|
)
|
||||||
|
|
||||||
configDir := c.GlobalString(configdirFlag.Name)
|
configDir := c.GlobalString(configdirFlag.Name)
|
||||||
if stretchedKey, err := readMasterKey(c, ui); err != nil {
|
if stretchedKey, err := readMasterKey(c, ui); err != nil {
|
||||||
log.Warn("Failed to open master, rules disabled", "err", err)
|
log.Warn("Failed to open master, rules disabled", "err", err)
|
||||||
|
@ -43,7 +43,7 @@ const (
|
|||||||
// ExternalAPIVersion -- see extapi_changelog.md
|
// ExternalAPIVersion -- see extapi_changelog.md
|
||||||
ExternalAPIVersion = "6.0.0"
|
ExternalAPIVersion = "6.0.0"
|
||||||
// InternalAPIVersion -- see intapi_changelog.md
|
// InternalAPIVersion -- see intapi_changelog.md
|
||||||
InternalAPIVersion = "7.0.0"
|
InternalAPIVersion = "7.0.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExternalAPI defines the external API through which signing requests are made.
|
// ExternalAPI defines the external API through which signing requests are made.
|
||||||
@ -395,8 +395,7 @@ func (api *SignerAPI) List(ctx context.Context) ([]common.Address, error) {
|
|||||||
// the given password. Users are responsible to backup the private key that is stored
|
// the given password. Users are responsible to backup the private key that is stored
|
||||||
// in the keystore location thas was specified when this API was created.
|
// in the keystore location thas was specified when this API was created.
|
||||||
func (api *SignerAPI) New(ctx context.Context) (common.Address, error) {
|
func (api *SignerAPI) New(ctx context.Context) (common.Address, error) {
|
||||||
be := api.am.Backends(keystore.KeyStoreType)
|
if be := api.am.Backends(keystore.KeyStoreType); len(be) == 0 {
|
||||||
if len(be) == 0 {
|
|
||||||
return common.Address{}, errors.New("password based accounts not supported")
|
return common.Address{}, errors.New("password based accounts not supported")
|
||||||
}
|
}
|
||||||
if resp, err := api.UI.ApproveNewAccount(&NewAccountRequest{MetadataFromContext(ctx)}); err != nil {
|
if resp, err := api.UI.ApproveNewAccount(&NewAccountRequest{MetadataFromContext(ctx)}); err != nil {
|
||||||
@ -404,7 +403,16 @@ func (api *SignerAPI) New(ctx context.Context) (common.Address, error) {
|
|||||||
} else if !resp.Approved {
|
} else if !resp.Approved {
|
||||||
return common.Address{}, ErrRequestDenied
|
return common.Address{}, ErrRequestDenied
|
||||||
}
|
}
|
||||||
|
return api.newAccount()
|
||||||
|
}
|
||||||
|
|
||||||
|
// newAccount is the internal method to create a new account. It should be used
|
||||||
|
// _after_ user-approval has been obtained
|
||||||
|
func (api *SignerAPI) newAccount() (common.Address, error) {
|
||||||
|
be := api.am.Backends(keystore.KeyStoreType)
|
||||||
|
if len(be) == 0 {
|
||||||
|
return common.Address{}, errors.New("password based accounts not supported")
|
||||||
|
}
|
||||||
// Three retries to get a valid password
|
// Three retries to get a valid password
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
resp, err := api.UI.OnInputRequired(UserInputRequest{
|
resp, err := api.UI.OnInputRequired(UserInputRequest{
|
||||||
|
@ -195,6 +195,16 @@ func (api *UIServerAPI) Import(ctx context.Context, keyJSON json.RawMessage, old
|
|||||||
return be[0].(*keystore.KeyStore).Import(keyJSON, oldPassphrase, newPassphrase)
|
return be[0].(*keystore.KeyStore).Import(keyJSON, oldPassphrase, newPassphrase)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a new password protected Account. The private key is protected with
|
||||||
|
// the given password. Users are responsible to backup the private key that is stored
|
||||||
|
// in the keystore location that was specified when this API was created.
|
||||||
|
// This method is the same as New on the external API, the difference being that
|
||||||
|
// this implementation does not ask for confirmation, since it's initiated by
|
||||||
|
// the user
|
||||||
|
func (api *UIServerAPI) New(ctx context.Context) (common.Address, error) {
|
||||||
|
return api.extApi.newAccount()
|
||||||
|
}
|
||||||
|
|
||||||
// Other methods to be added, not yet implemented are:
|
// Other methods to be added, not yet implemented are:
|
||||||
// - Ruleset interaction: add rules, attest rulefiles
|
// - Ruleset interaction: add rules, attest rulefiles
|
||||||
// - Store metadata about accounts, e.g. naming of accounts
|
// - Store metadata about accounts, e.g. naming of accounts
|
||||||
|
Loading…
Reference in New Issue
Block a user