signer: implement account_Version on external API

This commit is contained in:
Martin Holst Swende 2018-11-11 17:21:01 +01:00
parent 22633db7c9
commit 9838abaca4
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
4 changed files with 49 additions and 38 deletions

View file

@ -1,7 +1,6 @@
package external package external
import ( import (
"errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
@ -48,6 +47,7 @@ func (eb *ExternalBackend) Subscribe(sink chan<- accounts.WalletEvent) event.Sub
type ExternalSigner struct { type ExternalSigner struct {
client *rpc.Client client *rpc.Client
endpoint string endpoint string
status string
cacheMu sync.RWMutex cacheMu sync.RWMutex
cache []accounts.Account cache []accounts.Account
} }
@ -57,10 +57,17 @@ func NewExternalSigner(endpoint string) (*ExternalSigner, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &ExternalSigner{ extsigner := &ExternalSigner{
client: client, client: client,
endpoint: endpoint, 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 { func (api *ExternalSigner) URL() accounts.URL {
@ -71,7 +78,7 @@ func (api *ExternalSigner) URL() accounts.URL {
} }
func (api *ExternalSigner) Status() (string, error) { func (api *ExternalSigner) Status() (string, error) {
return "ok", nil return api.status, nil
} }
func (api *ExternalSigner) Open(passphrase string) error { func (api *ExternalSigner) Open(passphrase string) error {
@ -138,7 +145,6 @@ func (api *ExternalSigner) SignText(account accounts.Account, text []byte)([]byt
return api.signHash(account, accounts.TextHash(text)) return api.signHash(account, accounts.TextHash(text))
} }
func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
res := ethapi.SignTransactionResult{} res := ethapi.SignTransactionResult{}
to := common.NewMixedcaseAddress(*tx.To()) to := common.NewMixedcaseAddress(*tx.To())
@ -174,17 +180,8 @@ func (api *ExternalSigner) listAccounts() ([]common.Address, error) {
} }
return res, nil 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) { 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 var sig hexutil.Bytes
if err := api.client.Call(&sig, "account_signData", "application/clique", a, rlpBlock); err != nil { if err := api.client.Call(&sig, "account_signData", "application/clique", a, rlpBlock); err != nil {
return nil, err 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 sig[64] -= 27 // Transform V from 27/28 to 0/1 for Clique use
return sig, nil 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
}

View file

@ -49,12 +49,6 @@ import (
"gopkg.in/urfave/cli.v1" "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 = ` const legalWarning = `
WARNING! WARNING!
@ -479,8 +473,8 @@ func signer(c *cli.Context) error {
} }
ui.OnSignerStartup(core.StartupInfo{ ui.OnSignerStartup(core.StartupInfo{
Info: map[string]interface{}{ Info: map[string]interface{}{
"extapi_version": ExternalAPIVersion, "extapi_version": core.ExternalAPIVersion,
"intapi_version": InternalAPIVersion, "intapi_version": core.InternalAPIVersion,
"extapi_http": extapiURL, "extapi_http": extapiURL,
"extapi_ipc": ipcapiURL, "extapi_ipc": ipcapiURL,
}, },

View file

@ -36,8 +36,14 @@ import (
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
const (
// numberOfAccountsToDerive For hardware wallets, the number of accounts to derive // numberOfAccountsToDerive For hardware wallets, the number of accounts to derive
const numberOfAccountsToDerive = 10 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. // ExternalAPI defines the external API through which signing requests are made.
type ExternalAPI interface { type ExternalAPI interface {
@ -47,7 +53,7 @@ type ExternalAPI interface {
New(ctx context.Context) (accounts.Account, error) New(ctx context.Context) (accounts.Account, error)
// SignTransaction request to sign the specified transaction // SignTransaction request to sign the specified transaction
SignTransaction(ctx context.Context, args SendTxArgs, methodSelector *string) (*ethapi.SignTransactionResult, error) 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) Sign(ctx context.Context, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error)
// Export - request to export an account // Export - request to export an account
Export(ctx context.Context, addr common.Address) (json.RawMessage, error) 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 // Should be moved to Internal API, in next phase when we have
// bi-directional communication // bi-directional communication
//Import(ctx context.Context, keyJSON json.RawMessage) (Account, error) //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 // 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 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
}

View file

@ -80,14 +80,13 @@ func (l *AuditLogger) Export(ctx context.Context, addr common.Address) (json.Raw
return j, e return j, e
} }
//func (l *AuditLogger) Import(ctx context.Context, keyJSON json.RawMessage) (Account, error) { func (l *AuditLogger) Version(ctx context.Context) (string, error) {
// // Don't actually log the json contents l.log.Info("Version", "type", "request", "metadata", MetadataFromContext(ctx).String())
// l.log.Info("Import", "type", "request", "metadata", MetadataFromContext(ctx).String(), data, err := l.api.Version(ctx)
// "keyJSON size", len(keyJSON)) l.log.Info("Version", "type", "response", "data", data, "error", err)
// a, e := l.api.Import(ctx, keyJSON) return data, err
// l.log.Info("Import", "type", "response", "addr", a.String(), "error", e)
// return a, e }
//}
func NewAuditLogger(path string, api ExternalAPI) (*AuditLogger, error) { func NewAuditLogger(path string, api ExternalAPI) (*AuditLogger, error) {
l := log.New("api", "signer") l := log.New("api", "signer")