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:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user