diff --git a/cmd/signer/abihelper.go b/cmd/signer/abihelper.go
index f36e927816..521ae7b45a 100644
--- a/cmd/signer/abihelper.go
+++ b/cmd/signer/abihelper.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see .
-package main
+package signer
import (
// "bytes"
diff --git a/cmd/signer/abihelper_test.go b/cmd/signer/abihelper_test.go
index 2df9d8fe54..3117df09de 100644
--- a/cmd/signer/abihelper_test.go
+++ b/cmd/signer/abihelper_test.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see .
-package main
+package signer
import (
"fmt"
diff --git a/cmd/signer/api.go b/cmd/signer/api.go
index 0d9bc863de..d36efe9b91 100644
--- a/cmd/signer/api.go
+++ b/cmd/signer/api.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see .
-package main
+package signer
import (
"context"
@@ -39,6 +39,47 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
+// ExternalAPI defines the external API through which signing requests are made.
+type ExternalAPI interface {
+ // List available accounts
+ List(ctx context.Context) (Accounts, error)
+ // New request to create a new account
+ New(ctx context.Context) (accounts.Account, error)
+ // SignTransaction request to sign the specified transaction
+ SignTransaction(ctx context.Context, from common.MixedcaseAddress, args TransactionArg, methodSelector *string) (hexutil.Bytes, error)
+ // Sign - request to sign the given data (plus prefix)
+ Sign(ctx context.Context, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error)
+ // EcRecover - request to perform ecrecover
+ EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error)
+ // Export - request to export an account
+ Export(ctx context.Context, addr common.Address) (json.RawMessage, error)
+ // Import - request to import an account
+ Import(ctx context.Context, keyJSON json.RawMessage) (Account, error)
+}
+
+// SignerUI specifies what method a UI needs to implement to be able to be used as a UI for the signer
+type SignerUI interface {
+
+ // ApproveTx prompt the user for confirmation to request to sign Transaction
+ ApproveTx(request *SignTxRequest) (SignTxResponse, error)
+ // ApproveSignData prompt the user for confirmation to request to sign data
+ ApproveSignData(request *SignDataRequest) (SignDataResponse, error)
+ // ApproveExport prompt the user for confirmation to export encrypted Account json
+ ApproveExport(request *ExportRequest) (ExportResponse, error)
+ // ApproveImport prompt the user for confirmation to import Account json
+ ApproveImport(request *ImportRequest) (ImportResponse, error)
+ // ApproveListing prompt the user for confirmation to list accounts
+ // the list of accounts to list can be modified by the ui
+ ApproveListing(request *ListRequest) (ListResponse, error)
+ // ApproveNewAccount prompt the user for confirmation to create new Account, and reveal to caller
+ ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error)
+ // ShowError displays error message to user
+ ShowError(message string)
+ // ShowInfo displays info message to user
+ ShowInfo(message string)
+}
+
+// SignerAPI defines the actual implementation of ExternalAPI
type SignerAPI struct {
chainID *big.Int
am *accounts.Manager
@@ -46,13 +87,14 @@ type SignerAPI struct {
abidb abiDb
}
-// Metadata about the request
+// Metadata about a request
type Metadata struct {
Remote string `json:"remote"`
Local string `json:"local"`
Scheme string `json:"scheme"`
}
+// MetadataFromContext extracts Metadata from a given context.Context
func MetadataFromContext(ctx context.Context) Metadata {
m := Metadata{"NA", "NA", "NA"}
@@ -68,6 +110,7 @@ func MetadataFromContext(ctx context.Context) Metadata {
return m
}
+// String implements Stringer interface
func (m Metadata) String() string {
s, err := json.Marshal(m)
if err == nil {
@@ -76,7 +119,7 @@ func (m Metadata) String() string {
return err.Error()
}
-// types for the requests/response types
+// types for the requests/response types between signer and UI
type (
// SignTxRequest contains info about a Transaction to sign
SignTxRequest struct {
@@ -152,48 +195,16 @@ func (ew errorWrapper) String() string {
return fmt.Sprintf("%s\n%s", ew.msg, ew.err)
}
-type ExternalAPI interface {
- List(ctx context.Context) (Accounts, error)
- New(ctx context.Context) (accounts.Account, error)
- SignTransaction(ctx context.Context, from common.MixedcaseAddress, args TransactionArg, methodSelector *string) (hexutil.Bytes, error)
- Sign(ctx context.Context, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error)
- EcRecover(ctx context.Context, data, sig hexutil.Bytes) (common.Address, error)
- Export(ctx context.Context, addr common.Address) (json.RawMessage, error)
- Import(ctx context.Context, keyJSON json.RawMessage) (Account, error)
-}
-
-// SignerUI specifies what method a UI needs to implement to be able to be used as a UI
-// for the signer
-type SignerUI interface {
-
- // ApproveTx prompt the user for confirmation to request to sign Transaction
- ApproveTx(request *SignTxRequest) (SignTxResponse, error)
- // ApproveSignData prompt the user for confirmation to request to sign data
- ApproveSignData(request *SignDataRequest) (SignDataResponse, error)
- // ApproveExport prompt the user for confirmation to export encrypted Account json
- ApproveExport(request *ExportRequest) (ExportResponse, error)
- // ApproveImport prompt the user for confirmation to import Account json
- ApproveImport(request *ImportRequest) (ImportResponse, error)
- // ApproveListing prompt the user for confirmation to list accounts
- // the list of accounts to list can be modified by the ui
- ApproveListing(request *ListRequest) (ListResponse, error)
- // ApproveNewAccount prompt the user for confirmation to create new Account, and reveal to caller
- ApproveNewAccount(request *NewAccountRequest) (NewAccountResponse, error)
- // ShowError displays error message to user
- ShowError(message string)
- // ShowInfo displays info message to user
- ShowInfo(message string)
-}
-
// NewSignerAPI creates a new API that can be used for Account management.
// ksLocation specifies the directory where to store the password protected private
// key that is generated when a new Account is created.
// noUSB disables USB support that is required to support hardware devices such as
// ledger and trezor.
func NewSignerAPI(chainID int64, ksLocation string, noUSB bool, ui SignerUI, abidb *abiDb, lightKDF bool) *SignerAPI {
- var backends []accounts.Backend
-
- n, p := keystore.StandardScryptN, keystore.StandardScryptP
+ var (
+ backends []accounts.Backend
+ n, p = keystore.StandardScryptN, keystore.StandardScryptP
+ )
if lightKDF {
n, p = keystore.LightScryptN, keystore.LightScryptP
}
@@ -201,7 +212,6 @@ func NewSignerAPI(chainID int64, ksLocation string, noUSB bool, ui SignerUI, abi
if len(ksLocation) > 0 {
backends = append(backends, keystore.NewKeyStore(ksLocation, n, p))
}
-
if !noUSB {
// Start a USB hub for Ledger hardware wallets
if ledgerhub, err := usbwallet.NewLedgerHub(); err != nil {
@@ -224,7 +234,6 @@ func NewSignerAPI(chainID int64, ksLocation string, noUSB bool, ui SignerUI, abi
// List returns the set of wallet this signer manages. Each wallet can contain
// multiple accounts.
func (api *SignerAPI) List(ctx context.Context) (Accounts, error) {
-
var accs []Account
for _, wallet := range api.am.Wallets() {
for _, acc := range wallet.Accounts() {
@@ -232,7 +241,6 @@ func (api *SignerAPI) List(ctx context.Context) (Accounts, error) {
accs = append(accs, acc)
}
}
-
result, err := api.ui.ApproveListing(&ListRequest{Accounts: accs, Meta: MetadataFromContext(ctx)})
if err != nil {
return nil, err
@@ -319,14 +327,11 @@ func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
// SignTransaction signs the given Transaction and returns it in an RLP encoded form
// that can be posted to `eth_sendRawTransaction`.
func (api *SignerAPI) SignTransaction(ctx context.Context, from common.MixedcaseAddress, args TransactionArg, methodSelector *string) (hexutil.Bytes, error) {
-
var (
err error
result SignTxResponse
)
-
req := SignTxRequest{Transaction: args, From: from, Meta: MetadataFromContext(ctx)}
-
data := args.Data
if len(data) > 3 {
// Try to make sense of the data
@@ -354,7 +359,6 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, from common.Mixedcase
}
}
}
-
result, err = api.ui.ApproveTx(&req)
if err != nil {
return nil, err
@@ -374,7 +378,6 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, from common.Mixedcase
if err != nil {
return nil, err
}
-
var tx = toTransaction(&result.Transaction)
// The one to sign is the one that was returned from the UI
@@ -396,9 +399,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, from common.Mixedcase
//
// https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, data hexutil.Bytes) (hexutil.Bytes, error) {
-
sighash, msg := signHash(data)
-
// We make the request prior to looking up if we actually have the account, to prevent
// account-enumeration via the API
req := &SignDataRequest{Address: addr, Rawdata: data, Message: msg, Hash: sighash, Meta: MetadataFromContext(ctx)}
@@ -410,7 +411,6 @@ func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, da
if !res.Approved {
return nil, ErrRequestDenied
}
-
// Look up the wallet containing the requested signer
account := accounts.Account{Address: addr.Address()}
wallet, err := api.am.Find(account)
@@ -425,7 +425,6 @@ func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, da
}
signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper
return signature, nil
-
}
// EcRecover returns the address for the Account that was used to create the signature.
@@ -446,7 +445,6 @@ func (api *SignerAPI) EcRecover(ctx context.Context, data, sig hexutil.Bytes) (c
return common.Address{}, fmt.Errorf("invalid Ethereum signature (V is not 27 or 28)")
}
sig[64] -= 27 // Transform yellow paper V from 27/28 to 0/1
-
hash, _ := signHash(data)
rpk, err := crypto.Ecrecover(hash, sig)
if err != nil {
@@ -471,7 +469,6 @@ func signHash(data []byte) ([]byte, string) {
// Export returns encrypted private key associated with the given address in web3 keystore format.
func (api *SignerAPI) Export(ctx context.Context, addr common.Address) (json.RawMessage, error) {
-
res, err := api.ui.ApproveExport(&ExportRequest{Address: addr, Meta: MetadataFromContext(ctx)})
if err != nil {
@@ -480,17 +477,14 @@ func (api *SignerAPI) Export(ctx context.Context, addr common.Address) (json.Raw
if !res.Approved {
return nil, ErrRequestDenied
}
-
// Look up the wallet containing the requested signer
wallet, err := api.am.Find(accounts.Account{Address: addr})
if err != nil {
return nil, err
}
-
if wallet.URL().Scheme != keystore.KeyStoreScheme {
return nil, fmt.Errorf("Account is not a keystore-account")
}
-
return ioutil.ReadFile(wallet.URL().Path)
}
@@ -498,13 +492,11 @@ func (api *SignerAPI) Export(ctx context.Context, addr common.Address) (json.Raw
// in web3 keystore format. It will decrypt the keyJSON with the given passphrase and on successful
// decryption it will encrypt the key with the given newPassphrase and store it in the keystore.
func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Account, error) {
-
be := api.am.Backends(keystore.KeyStoreType)
if len(be) == 0 {
return Account{}, errors.New("password based accounts not supported")
}
-
res, err := api.ui.ApproveImport(&ImportRequest{Meta: MetadataFromContext(ctx)})
if err != nil {
@@ -513,13 +505,10 @@ func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Acco
if !res.Approved {
return Account{}, ErrRequestDenied
}
-
acc, err := be[0].(*keystore.KeyStore).Import(keyJSON, res.OldPassword, res.NewPassword)
if err != nil {
api.ui.ShowError(err.Error())
return Account{}, err
}
-
return Account{Typ: "Account", URL: acc.URL, Address: acc.Address}, nil
-
}
diff --git a/cmd/signer/api_test.go b/cmd/signer/api_test.go
index 9a6fc30897..dbf0d6f7da 100644
--- a/cmd/signer/api_test.go
+++ b/cmd/signer/api_test.go
@@ -1,4 +1,4 @@
-package main
+package signer
import (
"bytes"
diff --git a/cmd/signer/auditlog.go b/cmd/signer/auditlog.go
index 744a833176..d47f27b71b 100644
--- a/cmd/signer/auditlog.go
+++ b/cmd/signer/auditlog.go
@@ -1,4 +1,20 @@
-package main
+// Copyright 2017 The go-ethereum Authors
+// This file is part of go-ethereum.
+//
+// go-ethereum is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// go-ethereum is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with go-ethereum. If not, see .
+
+package signer
import (
"context"
diff --git a/cmd/signer/cliui.go b/cmd/signer/cliui.go
index b729b13de3..b74e0f702a 100644
--- a/cmd/signer/cliui.go
+++ b/cmd/signer/cliui.go
@@ -13,7 +13,7 @@
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see .
-package main
+package signer
import (
"bufio"
diff --git a/cmd/signer/main.go b/cmd/signer/main.go
index 51576a77cd..897bd38191 100644
--- a/cmd/signer/main.go
+++ b/cmd/signer/main.go
@@ -16,7 +16,7 @@
// signer is a utility that can be used so sign transactions and
// arbitrary data.
-package main
+package signer
import (
"fmt"
diff --git a/cmd/signer/stdioui.go b/cmd/signer/stdioui.go
index 9d677c0b9f..5476c7b8f7 100644
--- a/cmd/signer/stdioui.go
+++ b/cmd/signer/stdioui.go
@@ -15,7 +15,7 @@
// along with go-ethereum. If not, see .
//
-package main
+package signer
import (
"github.com/ethereum/go-ethereum/log"
diff --git a/cmd/signer/types.go b/cmd/signer/types.go
index 1195142495..825638ef66 100644
--- a/cmd/signer/types.go
+++ b/cmd/signer/types.go
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see .
-package main
+package signer
import (
"encoding/json"