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. | ||||
| 
 | ||||
| ### 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 | ||||
| 
 | ||||
| - 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: ` | ||||
| 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{ | ||||
| 		Action: GenDoc, | ||||
| 		Name:   "gendoc", | ||||
| @ -222,7 +237,12 @@ func init() { | ||||
| 		advancedMode, | ||||
| 	} | ||||
| 	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 | ||||
| } | ||||
| 
 | ||||
| @ -382,6 +402,31 @@ func removeCredential(ctx *cli.Context) error { | ||||
| 	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 { | ||||
| 	// Set up the logger to print everything
 | ||||
| 	logOutput := os.Stdout | ||||
| @ -457,7 +502,6 @@ func signer(c *cli.Context) error { | ||||
| 		api       core.ExternalAPI | ||||
| 		pwStorage storage.Storage = &storage.NoStorage{} | ||||
| 	) | ||||
| 
 | ||||
| 	configDir := c.GlobalString(configdirFlag.Name) | ||||
| 	if stretchedKey, err := readMasterKey(c, ui); err != nil { | ||||
| 		log.Warn("Failed to open master, rules disabled", "err", err) | ||||
|  | ||||
| @ -43,7 +43,7 @@ const ( | ||||
| 	// ExternalAPIVersion -- see extapi_changelog.md
 | ||||
| 	ExternalAPIVersion = "6.0.0" | ||||
| 	// InternalAPIVersion -- see intapi_changelog.md
 | ||||
| 	InternalAPIVersion = "7.0.0" | ||||
| 	InternalAPIVersion = "7.0.1" | ||||
| ) | ||||
| 
 | ||||
| // 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
 | ||||
| // in the keystore location thas was specified when this API was created.
 | ||||
| func (api *SignerAPI) New(ctx context.Context) (common.Address, error) { | ||||
| 	be := api.am.Backends(keystore.KeyStoreType) | ||||
| 	if len(be) == 0 { | ||||
| 	if be := api.am.Backends(keystore.KeyStoreType); len(be) == 0 { | ||||
| 		return common.Address{}, errors.New("password based accounts not supported") | ||||
| 	} | ||||
| 	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 { | ||||
| 		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
 | ||||
| 	for i := 0; i < 3; i++ { | ||||
| 		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) | ||||
| } | ||||
| 
 | ||||
| // 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:
 | ||||
| // - Ruleset interaction: add rules, attest rulefiles
 | ||||
| // - Store metadata about accounts, e.g. naming of accounts
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user