diff --git a/accounts/external/backend.go b/accounts/external/backend.go index 03d75e1661..3e57aa8f13 100644 --- a/accounts/external/backend.go +++ b/accounts/external/backend.go @@ -1,7 +1,6 @@ package external import ( - "errors" "fmt" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts" @@ -31,7 +30,7 @@ func NewExternalBackend(endpoint string) (*ExternalBackend, error) { return nil, err } return &ExternalBackend{ - signers: []accounts.Wallet{ signer}, + signers: []accounts.Wallet{signer}, }, nil } @@ -48,6 +47,7 @@ func (eb *ExternalBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Sub type ExternalSigner struct { client *rpc.Client endpoint string + status string cacheMu sync.RWMutex cache []accounts.Account } @@ -57,10 +57,17 @@ func NewExternalSigner(endpoint string) (*ExternalSigner, error) { if err != nil { return nil, err } - return &ExternalSigner{ + extsigner := &ExternalSigner{ client: client, endpoint: endpoint, - }, nil + } + // Check if reachable + version, err := extsigner.pingVersion() + if err != nil { + return nil, err + } + extsigner.status = fmt.Sprintf("ok [version=%v]", version) + return extsigner, nil } func (api *ExternalSigner) URL() accounts.URL { @@ -71,7 +78,7 @@ func (api *ExternalSigner) URL() accounts.URL { } func (api *ExternalSigner) Status() (string, error) { - return "ok", nil + return api.status, nil } func (api *ExternalSigner) Open(passphrase string) error { @@ -107,8 +114,8 @@ func (api *ExternalSigner) Accounts() []accounts.Account { func (api *ExternalSigner) Contains(account accounts.Account) bool { api.cacheMu.RLock() defer api.cacheMu.RUnlock() - for _, a := range api.cache{ - if a.Address == account.Address && (account.URL == (accounts.URL{}) || account.URL == api.URL()){ + for _, a := range api.cache { + if a.Address == account.Address && (account.URL == (accounts.URL{}) || account.URL == api.URL()) { return true } } @@ -134,11 +141,10 @@ func (api *ExternalSigner) SignCliqueHeader(account accounts.Account, header *ty return api.signHash(account, accounts.CliqueHash(header).Bytes()) } -func (api *ExternalSigner) SignText(account accounts.Account, text []byte)([]byte, error){ +func (api *ExternalSigner) SignText(account accounts.Account, text []byte) ([]byte, error) { return api.signHash(account, accounts.TextHash(text)) } - func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { res := ethapi.SignTransactionResult{} to := common.NewMixedcaseAddress(*tx.To()) @@ -174,17 +180,8 @@ func (api *ExternalSigner) listAccounts() ([]common.Address, error) { } return res, nil } -func (api *ExternalSigner) newAccount() (common.Address, error) { - var res accounts.Account - if err := api.client.Call(&res, "account_new"); err != nil { - return common.Address{}, err - } - return res.Address, nil -} + func (api *ExternalSigner) signCliqueBlock(a common.Address, rlpBlock hexutil.Bytes) (hexutil.Bytes, error) { - if api == nil { - return nil, errors.New("External API not initialized") - } var sig hexutil.Bytes if err := api.client.Call(&sig, "account_signData", "application/clique", a, rlpBlock); err != nil { return nil, err @@ -195,3 +192,11 @@ func (api *ExternalSigner) signCliqueBlock(a common.Address, rlpBlock hexutil.By sig[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use return sig, nil } + +func (api *ExternalSigner) pingVersion() (string, error) { + var v string + if err := api.client.Call(&v, "account_version"); err != nil { + return "", err + } + return v, nil +} diff --git a/cmd/clef/main.go b/cmd/clef/main.go index 519d63b3c1..e2b85288dd 100644 --- a/cmd/clef/main.go +++ b/cmd/clef/main.go @@ -49,12 +49,6 @@ import ( "gopkg.in/urfave/cli.v1" ) -// ExternalAPIVersion -- see extapi_changelog.md -const ExternalAPIVersion = "4.0.0" - -// InternalAPIVersion -- see intapi_changelog.md -const InternalAPIVersion = "3.0.0" - const legalWarning = ` WARNING! @@ -479,8 +473,8 @@ func signer(c *cli.Context) error { } ui.OnSignerStartup(core.StartupInfo{ Info: map[string]interface{}{ - "extapi_version": ExternalAPIVersion, - "intapi_version": InternalAPIVersion, + "extapi_version": core.ExternalAPIVersion, + "intapi_version": core.InternalAPIVersion, "extapi_http": extapiURL, "extapi_ipc": ipcapiURL, }, diff --git a/signer/core/api.go b/signer/core/api.go index eeedc40913..6354b3c3c3 100644 --- a/signer/core/api.go +++ b/signer/core/api.go @@ -36,8 +36,14 @@ import ( "github.com/ethereum/go-ethereum/rlp" ) -// numberOfAccountsToDerive For hardware wallets, the number of accounts to derive -const numberOfAccountsToDerive = 10 +const ( + // numberOfAccountsToDerive For hardware wallets, the number of accounts to derive + numberOfAccountsToDerive = 10 + // ExternalAPIVersion -- see extapi_changelog.md + ExternalAPIVersion = "4.0.0" + // InternalAPIVersion -- see intapi_changelog.md + InternalAPIVersion = "3.0.0" +) // ExternalAPI defines the external API through which signing requests are made. type ExternalAPI interface { @@ -47,7 +53,7 @@ type ExternalAPI interface { New(ctx context.Context) (accounts.Account, error) // SignTransaction request to sign the specified transaction SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) - // Sign - request to sign the given data (plus prefix) + // Sign - resquest to sign the given data (plus prefix) Sign(ctx context.Context, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error) // Export - request to export an account Export(ctx context.Context, addr common.Address) (json.RawMessage, error) @@ -55,6 +61,7 @@ type ExternalAPI interface { // Should be moved to Internal API, in next phase when we have // bi-directional communication //Import(ctx context.Context, keyJSON json.RawMessage) (Account, error) + Version(ctx context.Context) (string, error) } // SignerUI specifies what method a UI needs to implement to be able to be used as a UI for the signer @@ -610,3 +617,9 @@ func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Acco } return Account{Typ: "Account", URL: acc.URL, Address: acc.Address}, nil } + +// Returns the external api version. This method does not require user acceptance. Available methods are +// available via enumeration anyway, and this info does not contain user-specific data +func (api *SignerAPI) Version(ctx context.Context) (string, error) { + return ExternalAPIVersion, nil +} diff --git a/signer/core/auditlog.go b/signer/core/auditlog.go index 1f9c909185..0cb6c9c473 100644 --- a/signer/core/auditlog.go +++ b/signer/core/auditlog.go @@ -80,14 +80,13 @@ func (l *AuditLogger) Export(ctx context.Context, addr common.Address) (json.Raw return j, e } -//func (l *AuditLogger) Import(ctx context.Context, keyJSON json.RawMessage) (Account, error) { -// // Don't actually log the json contents -// l.log.Info("Import", "type", "request", "metadata", MetadataFromContext(ctx).String(), -// "keyJSON size", len(keyJSON)) -// a, e := l.api.Import(ctx, keyJSON) -// l.log.Info("Import", "type", "response", "addr", a.String(), "error", e) -// return a, e -//} +func (l *AuditLogger) Version(ctx context.Context) (string, error) { + l.log.Info("Version", "type", "request", "metadata", MetadataFromContext(ctx).String()) + data, err := l.api.Version(ctx) + l.log.Info("Version", "type", "response", "data", data, "error", err) + return data, err + +} func NewAuditLogger(path string, api ExternalAPI) (*AuditLogger, error) { l := log.New("api", "signer")