From 99dd0a1b58199173f75a3754a8092986c3aeb313 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Thu, 15 Feb 2018 11:46:04 +0100 Subject: [PATCH] signer: refactoring + documentation --- cmd/signer/README.md | 75 +++++++++++++++++++++++-- cmd/signer/{ => core}/abihelper.go | 12 ++-- cmd/signer/{ => core}/abihelper_test.go | 6 +- cmd/signer/{ => core}/api.go | 69 ++++++++++------------- cmd/signer/{ => core}/api_test.go | 18 +++--- cmd/signer/{ => core}/auditlog.go | 2 +- cmd/signer/{ => core}/cliui.go | 4 +- cmd/signer/{ => core}/stdioui.go | 2 +- cmd/signer/{ => core}/types.go | 14 ++--- cmd/signer/main.go | 29 +++++----- cmd/signer/rules/rules.go | 32 +++++------ cmd/signer/rules/rules_test.go | 34 +++++------ 12 files changed, 175 insertions(+), 122 deletions(-) rename cmd/signer/{ => core}/abihelper.go (96%) rename cmd/signer/{ => core}/abihelper_test.go (99%) rename cmd/signer/{ => core}/api.go (91%) rename cmd/signer/{ => core}/api_test.go (95%) rename cmd/signer/{ => core}/auditlog.go (99%) rename cmd/signer/{ => core}/cliui.go (99%) rename cmd/signer/{ => core}/stdioui.go (99%) rename cmd/signer/{ => core}/types.go (84%) diff --git a/cmd/signer/README.md b/cmd/signer/README.md index dad2f2bc04..4def84e014 100644 --- a/cmd/signer/README.md +++ b/cmd/signer/README.md @@ -174,9 +174,9 @@ None Signs a transactions and responds with the signed transaction in RLP encoded form. #### Arguments - 1. from [address]: account to send the transaction from 2. transaction object: - - `to` [address]: receiver account + - `from` [address]: account to send the transaction from + - `to` [address]: receiver account. If omitted or `0x`, will cause contract creation. - `gas` [number]: maximum amount of gas to burn - `gasPrice` [number]: gas price - `value` [number:optional]: amount of Wei to send with the transaction @@ -196,8 +196,8 @@ None "jsonrpc": "2.0", "method": "account_signTransaction", "params": [ - "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", { + "from": "0x1923f626bb8dc025849e00f99c25fe2b2f7fb0db", "gas": "0x55555", "gasPrice": "0x1234", "input": "0xabcd", @@ -209,11 +209,64 @@ None } { - "id": 2, "jsonrpc": "2.0", - "result": "0xf86480821234830555559407a565b7ed7d7a678680a4c162885bedbb695fe0821234802ea028f9ebeff90732eae45692a11c4ca2ef7f631a0a25bf8763d093e770c4ec464aa01fae77b24617913e718b989be78bc1aabb2fed3f2d4e3b93bd36759f1b5b4904" + "id": 67, + "error": { + "code": -32000, + "message": "Request denied" + } } ``` +#### Sample call with ABI-data + + +``` +{ + "jsonrpc": "2.0", + "method": "account_signTransaction", + "params": [ + { + "from": "0x694267f14675d7e1b9494fd8d72fefe1755710fa", + "gas": "0x333", + "gasPrice": "0x1", + "nonce": "0x0", + "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", + "value": "0x0", + "data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012" + }, + "safeSend(address)" + ], + "id": 67 +} + +{ + "jsonrpc": "2.0", + "id": 67, + "result": { + "raw": "0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", + "tx": { + "nonce": "0x0", + "gasPrice": "0x1", + "gas": "0x333", + "to": "0x07a565b7ed7d7a678680a4c162885bedbb695fe0", + "value": "0x0", + "input": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012", + "v": "0x26", + "r": "0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e", + "s": "0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663", + "hash": "0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e" + } + } +} +``` + +Bash example: +```bash +#curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","method":"account_signTransaction","params":[{"from":"0x694267f14675d7e1b9494fd8d72fefe1755710fa","gas":"0x333","gasPrice":"0x1","nonce":"0x0","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0", "value":"0x0", "data":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"},"safeSend(address)"],"id":67}' http://localhost:8550/ + +{"jsonrpc":"2.0","id":67,"result":{"raw":"0xf88380018203339407a565b7ed7d7a678680a4c162885bedbb695fe080a44401a6e4000000000000000000000000000000000000000000000000000000000000001226a0223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20ea02aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","tx":{"nonce":"0x0","gasPrice":"0x1","gas":"0x333","to":"0x07a565b7ed7d7a678680a4c162885bedbb695fe0","value":"0x0","input":"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012","v":"0x26","r":"0x223a7c9bcf5531c99be5ea7082183816eb20cfe0bbc322e97cc5c7f71ab8b20e","s":"0x2aadee6b34b45bb15bc42d9c09de4a6754e7000908da72d48cc7704971491663","hash":"0xeba2df809e7a612a0a0d444ccfa5c839624bdc00dd29e3340d46df3870f8a30e"}}} +``` + ### account_sign @@ -395,7 +448,8 @@ By starting the signer with the switch `--stdio-ui-test`, the signer will invoke denials. This can be used during development to ensure that the API is (at least somewhat) correctly implemented. See `pythonsigner`, which can be invoked via `python3 pythonsigner.py test` to perform the 'denial-handshake-test'. -**work in progress** +All methods in this API uses object-based parameters, so that there can be no mixups of parameters: each piece of data is accessed by key. + ### ApproveTx @@ -560,6 +614,15 @@ The UI should show the info to the user. Does not expect response. ``` +### OnApproved + +`OnApprovedTx` is called when a transaction has been approved and signed. The call contains the return value that will be sent to the external caller. The return value from this method is ignored - the reason for having this callback is to allow the ruleset to keep track of approved transactions. + +When implementing rate-limited rules, this callback should be used. + +TLDR; Use this method to keep track of signed transactions, instead of using the data in `ApproveTx`. + + ### Rules for UI apis A UI should conform to the following rules. diff --git a/cmd/signer/abihelper.go b/cmd/signer/core/abihelper.go similarity index 96% rename from cmd/signer/abihelper.go rename to cmd/signer/core/abihelper.go index 521ae7b45a..625d5cbdf9 100644 --- a/cmd/signer/abihelper.go +++ b/cmd/signer/core/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 signer +package core import ( // "bytes" @@ -157,25 +157,25 @@ func MethodSelectorToAbi(selector string) ([]byte, error) { } -type abiDb struct { +type AbiDb struct { db map[string]string } // NewAbiDBFromFile loads signature database from file, and // errors if the file is not valid json. Does no other validation of contents -func NewAbiDBFromFile(path string) (*abiDb, error) { +func NewAbiDBFromFile(path string) (*AbiDb, error) { raw, err := ioutil.ReadFile(path) if err != nil { return nil, err } - db := new(abiDb) + db := new(AbiDb) json.Unmarshal(raw, &db.db) return db, nil } // LookupMethodSelector checks the given 4byte-sequence against the known ABI methods. // OBS: This method does not validate the match, it's assumed the caller will do so -func (db *abiDb) LookupMethodSelector(id []byte) (string, error) { +func (db *AbiDb) LookupMethodSelector(id []byte) (string, error) { if len(id) != 4 { return "", fmt.Errorf("Expected 4-byte id, got %d", len(id)) } @@ -185,6 +185,6 @@ func (db *abiDb) LookupMethodSelector(id []byte) (string, error) { } return "", fmt.Errorf("Signature %v not found", sig) } -func (db *abiDb) Size() int { +func (db *AbiDb) Size() int { return len(db.db) } diff --git a/cmd/signer/abihelper_test.go b/cmd/signer/core/abihelper_test.go similarity index 99% rename from cmd/signer/abihelper_test.go rename to cmd/signer/core/abihelper_test.go index 3117df09de..b3a662c71d 100644 --- a/cmd/signer/abihelper_test.go +++ b/cmd/signer/core/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 signer +package core import ( "fmt" @@ -176,13 +176,13 @@ func TestCalldataDecoding(t *testing.T) { func TestSelectorUnmarshalling(t *testing.T) { var ( - db *abiDb + db *AbiDb err error abistring []byte abistruct abi.ABI ) - db, err = NewAbiDBFromFile("4byte.json") + db, err = NewAbiDBFromFile("../4byte.json") if err != nil { t.Fatal(err) } diff --git a/cmd/signer/api.go b/cmd/signer/core/api.go similarity index 91% rename from cmd/signer/api.go rename to cmd/signer/core/api.go index 03a182d849..8e9f4c2d3b 100644 --- a/cmd/signer/api.go +++ b/cmd/signer/core/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 signer +package core import ( "context" @@ -69,7 +69,7 @@ type SignerUI interface { // 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 + // 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) @@ -86,8 +86,8 @@ type SignerUI interface { type SignerAPI struct { chainID *big.Int am *accounts.Manager - ui SignerUI - abidb abiDb + UI SignerUI + abidb AbiDb } // Metadata about a request @@ -201,7 +201,7 @@ func (ew errorWrapper) String() string { // 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 { +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 @@ -242,7 +242,7 @@ func (api *SignerAPI) List(ctx context.Context) (Accounts, error) { accs = append(accs, acc) } } - result, err := api.ui.ApproveListing(&ListRequest{Accounts: accs, Meta: MetadataFromContext(ctx)}) + result, err := api.UI.ApproveListing(&ListRequest{Accounts: accs, Meta: MetadataFromContext(ctx)}) if err != nil { return nil, err } @@ -261,7 +261,7 @@ func (api *SignerAPI) New(ctx context.Context) (accounts.Account, error) { if len(be) == 0 { return accounts.Account{}, errors.New("password based accounts not supported") } - resp, err := api.ui.ApproveNewAccount(&NewAccountRequest{MetadataFromContext(ctx)}) + resp, err := api.UI.ApproveNewAccount(&NewAccountRequest{MetadataFromContext(ctx)}) if err != nil { return accounts.Account{}, err @@ -277,33 +277,25 @@ func (api *SignerAPI) New(ctx context.Context) (accounts.Account, error) { // UI-modifications to requests func logDiff(original *SignTxRequest, new *SignTxResponse) bool { modified := false - if f0, f1 := original.Transaction.From, new.Transaction.From; !reflect.DeepEqual(f0, f1) { log.Info("Sender-account changed by UI", "was", f0, "is", f1) modified = true } - if t0, t1 := original.Transaction.To, new.Transaction.To; !reflect.DeepEqual(t0, t1) { log.Info("Recipient-account changed by UI", "was", t0, "is", t1) modified = true } - if g0, g1 := (*big.Int)(original.Transaction.Gas), (*big.Int)(new.Transaction.Gas); g0 != g1 { - if g0 == nil || g1 == nil || g0.Cmp(g1) != 0 { - modified = true - log.Info("Gas changed by UI", "was", g0, "is", g1) - } + if g0, g1 := big.Int(original.Transaction.Gas), big.Int(new.Transaction.Gas); g0.Cmp(&g1) != 0 { + modified = true + log.Info("Gas changed by UI", "was", g0, "is", g1) } - if g0, g1 := (*big.Int)(original.Transaction.GasPrice), (*big.Int)(new.Transaction.GasPrice); g0 != g1 { - if g0 == nil || g1 == nil || g0.Cmp(g1) != 0 { - modified = true - log.Info("GasPrice changed by UI", "was", g0, "is", g1) - } + if g0, g1 := big.Int(original.Transaction.GasPrice), big.Int(new.Transaction.GasPrice); g0.Cmp(&g1) != 0 { + modified = true + log.Info("GasPrice changed by UI", "was", g0, "is", g1) } - if v0, v1 := (*big.Int)(original.Transaction.Value), (*big.Int)(new.Transaction.Value); v0 != v1 { - if v0 == nil || v1 == nil || v0.Cmp(v1) != 0 { - modified = true - log.Info("Value changed by UI", "was", v0, "is", v1) - } + if v0, v1 := big.Int(original.Transaction.Value), big.Int(new.Transaction.Value); v0.Cmp(&v1) != 0 { + modified = true + log.Info("Value changed by UI", "was", v0, "is", v1) } if d0, d1 := original.Transaction.Data, new.Transaction.Data; d0 != d1 { d0s := "" @@ -320,11 +312,8 @@ func logDiff(original *SignTxRequest, new *SignTxResponse) bool { } } if n0, n1 := original.Transaction.Nonce, new.Transaction.Nonce; n0 != n1 { - - if n0 == nil || n1 == nil || (*n0) != (*n1) { - modified = true - log.Info("Nonce changed by UI", "was", n0, "is", n1) - } + modified = true + log.Info("Nonce changed by UI", "was", n0, "is", n1) } return modified } @@ -386,12 +375,12 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth *args.Input = nil } req := SignTxRequest{ - Transaction: args, - Meta: MetadataFromContext(ctx), - Callinfo:api.determineCallInfo(data, methodSelector), + Transaction: args, + Meta: MetadataFromContext(ctx), + Callinfo: api.determineCallInfo(data, methodSelector), } // Process approval - result, err = api.ui.ApproveTx(&req) + result, err = api.UI.ApproveTx(&req) if err != nil { return nil, err } @@ -415,7 +404,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth // The one to sign is the one that was returned from the UI signedTx, err := wallet.SignTxWithPassphrase(acc, result.Password, unsignedTx, api.chainID) if err != nil { - api.ui.ShowError(err.Error()) + api.UI.ShowError(err.Error()) return nil, err } @@ -423,7 +412,7 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth response := ethapi.SignTransactionResult{rlpdata, signedTx} // Finally, send the signed tx to the UI - api.ui.OnApprovedTx(response) + api.UI.OnApprovedTx(response) // ...and to the external caller return &response, nil @@ -443,7 +432,7 @@ func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, da // 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)} - res, err := api.ui.ApproveSignData(req) + res, err := api.UI.ApproveSignData(req) if err != nil { return nil, err @@ -460,7 +449,7 @@ func (api *SignerAPI) Sign(ctx context.Context, addr common.MixedcaseAddress, da // Assemble sign the data with the wallet signature, err := wallet.SignHashWithPassphrase(account, res.Password, sighash) if err != nil { - api.ui.ShowError(err.Error()) + api.UI.ShowError(err.Error()) return nil, err } signature[64] += 27 // Transform V from 0/1 to 27/28 according to the yellow paper @@ -509,7 +498,7 @@ 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)}) + res, err := api.UI.ApproveExport(&ExportRequest{Address: addr, Meta: MetadataFromContext(ctx)}) if err != nil { return nil, err @@ -537,7 +526,7 @@ func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Acco if len(be) == 0 { return Account{}, errors.New("password based accounts not supported") } - res, err := api.ui.ApproveImport(&ImportRequest{Meta: MetadataFromContext(ctx)}) + res, err := api.UI.ApproveImport(&ImportRequest{Meta: MetadataFromContext(ctx)}) if err != nil { return Account{}, err @@ -547,7 +536,7 @@ func (api *SignerAPI) Import(ctx context.Context, keyJSON json.RawMessage) (Acco } acc, err := be[0].(*keystore.KeyStore).Import(keyJSON, res.OldPassword, res.NewPassword) if err != nil { - api.ui.ShowError(err.Error()) + 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/core/api_test.go similarity index 95% rename from cmd/signer/api_test.go rename to cmd/signer/core/api_test.go index 38f2c56aaf..2c8e35cc21 100644 --- a/cmd/signer/api_test.go +++ b/cmd/signer/core/api_test.go @@ -1,4 +1,4 @@ -package signer +package core import ( "bytes" @@ -35,9 +35,9 @@ func (ui *HeadlessUI) ApproveTx(request *SignTxRequest) (SignTxResponse, error) case "Y": return SignTxResponse{request.Transaction, true, <-ui.controller}, nil case "M": //Modify - old := (*big.Int)(request.Transaction.Value) - newVal := big.NewInt(0).Add(old, big.NewInt(1)) - request.Transaction.Value = (*hexutil.Big)(newVal) + old := big.Int(request.Transaction.Value) + newVal := big.NewInt(0).Add(&old, big.NewInt(1)) + request.Transaction.Value = hexutil.Big(*newVal) return SignTxResponse{request.Transaction, true, <-ui.controller}, nil default: return SignTxResponse{request.Transaction, false, ""}, nil @@ -106,7 +106,7 @@ func setup(t *testing.T) (*SignerAPI, chan string) { controller := make(chan string, 10) - db, err := NewAbiDBFromFile(fmt.Sprintf("./4byte.json")) + db, err := NewAbiDBFromFile(fmt.Sprintf("../4byte.json")) if err != nil { utils.Fatalf(err.Error()) @@ -238,9 +238,9 @@ func TestSignData(t *testing.T) { } func mkTestTx(from common.MixedcaseAddress) SendTxArgs { to := common.NewMixedcaseAddress(common.HexToAddress("0x1337")) - gas := (*hexutil.Big)(big.NewInt(21000)) - gasPrice := (*hexutil.Big)(big.NewInt(2000000000)) - value := (*hexutil.Big)(big.NewInt(1e18)) + gas := (hexutil.Big)(*big.NewInt(21000)) + gasPrice := (hexutil.Big)(*big.NewInt(2000000000)) + value := (hexutil.Big)(*big.NewInt(1e18)) nonce := (hexutil.Uint64)(0) data := hexutil.Bytes(common.Hex2Bytes("01020304050607080a")) tx := SendTxArgs{ @@ -250,7 +250,7 @@ func mkTestTx(from common.MixedcaseAddress) SendTxArgs { GasPrice: gasPrice, Value: value, Data: &data, - Nonce: &nonce} + Nonce: nonce} return tx } diff --git a/cmd/signer/auditlog.go b/cmd/signer/core/auditlog.go similarity index 99% rename from cmd/signer/auditlog.go rename to cmd/signer/core/auditlog.go index 007faf45ef..c5cb0ffb40 100644 --- a/cmd/signer/auditlog.go +++ b/cmd/signer/core/auditlog.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 signer +package core import ( "context" diff --git a/cmd/signer/cliui.go b/cmd/signer/core/cliui.go similarity index 99% rename from cmd/signer/cliui.go rename to cmd/signer/core/cliui.go index 7222744f8f..de4ab466ca 100644 --- a/cmd/signer/cliui.go +++ b/cmd/signer/core/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 signer +package core import ( "bufio" @@ -181,7 +181,7 @@ func (ui *CommandlineUI) ApproveImport(request *ImportRequest) (ImportResponse, } // ApproveListing prompt the user for confirmation to list accounts -// the list of accounts to list can be modified by the ui +// the list of accounts to list can be modified by the UI func (ui *CommandlineUI) ApproveListing(request *ListRequest) (ListResponse, error) { ui.mu.Lock() diff --git a/cmd/signer/stdioui.go b/cmd/signer/core/stdioui.go similarity index 99% rename from cmd/signer/stdioui.go rename to cmd/signer/core/stdioui.go index 9bc4ca60b2..a42ff845a5 100644 --- a/cmd/signer/stdioui.go +++ b/cmd/signer/core/stdioui.go @@ -15,7 +15,7 @@ // along with go-ethereum. If not, see . // -package signer +package core import ( "context" diff --git a/cmd/signer/types.go b/cmd/signer/core/types.go similarity index 84% rename from cmd/signer/types.go rename to cmd/signer/core/types.go index b91af6625e..03c3a58ff3 100644 --- a/cmd/signer/types.go +++ b/cmd/signer/core/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 signer +package core import ( "encoding/json" @@ -66,10 +66,10 @@ type TransactionArg struct { type SendTxArgs struct { From common.MixedcaseAddress `json:"from"` To *common.MixedcaseAddress `json:"to"` - Gas *hexutil.Big `json:"gas"` - GasPrice *hexutil.Big `json:"gasPrice"` - Value *hexutil.Big `json:"value"` - Nonce *hexutil.Uint64 `json:"nonce"` + Gas hexutil.Big `json:"gas"` + GasPrice hexutil.Big `json:"gasPrice"` + Value hexutil.Big `json:"value"` + Nonce hexutil.Uint64 `json:"nonce"` // We accept "data" and "input" for backwards-compatibility reasons. Data *hexutil.Bytes `json:"data"` Input *hexutil.Bytes `json:"input"` @@ -91,7 +91,7 @@ func (args *SendTxArgs) toTransaction() *types.Transaction { input = *args.Input } if args.To == nil { - return types.NewContractCreation(uint64(*args.Nonce), (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input) + return types.NewContractCreation(uint64(args.Nonce), (*big.Int)(&args.Value), (*big.Int)(&args.Gas), (*big.Int)(&args.GasPrice), input) } - return types.NewTransaction(uint64(*args.Nonce), (*args.To).Address(), (*big.Int)(args.Value), (*big.Int)(args.Gas), (*big.Int)(args.GasPrice), input) + return types.NewTransaction(uint64(args.Nonce), args.To.Address(), (*big.Int)(&args.Value), (*big.Int)(&args.Gas), (*big.Int)(&args.GasPrice), input) } diff --git a/cmd/signer/main.go b/cmd/signer/main.go index 398d1e2197..fa612f0258 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 signer +package main import ( "fmt" @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" "gopkg.in/urfave/cli.v1" + "github.com/ethereum/go-ethereum/cmd/signer/core" ) func main() { @@ -90,7 +91,7 @@ func main() { app.Action = func(c *cli.Context) error { var ( - ui SignerUI + ui core.SignerUI ) // Set up the logger to print everything logOutput := os.Stdout @@ -100,14 +101,14 @@ func main() { log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(c.Int("loglevel")), log.StreamHandler(logOutput, log.TerminalFormat(true)))) if c.Bool("stdio-ui") { - ui = NewStdIOUI() + ui = core.NewStdIOUI() } else { - ui = NewCommandlineUI() + ui = core.NewCommandlineUI() } if c.Bool("stdio-ui") { log.Info("Using stdin/stdout as UI-channel") } - db, err := NewAbiDBFromFile(c.String("4bytedb")) + db, err := core.NewAbiDBFromFile(c.String("4bytedb")) if err != nil { utils.Fatalf(err.Error()) @@ -115,12 +116,12 @@ func main() { log.Info("Loaded 4byte db", "signatures", db.Size(), "file", c.String("4bytedb")) var ( - api ExternalAPI + api core.ExternalAPI listener net.Listener server = rpc.NewServer() ) - api_impl := NewSignerAPI( + api_impl := core.NewSignerAPI( c.Int64(utils.NetworkIdFlag.Name), c.String("keystore"), c.Bool(utils.NoUSBFlag.Name), @@ -131,7 +132,7 @@ func main() { // Audit logging if logfile := c.String("auditlog"); logfile != "" { - api, err = NewAuditLogger(logfile, api_impl) + api, err = core.NewAuditLogger(logfile, api_impl) if err != nil { utils.Fatalf(err.Error()) } @@ -170,7 +171,7 @@ func main() { } -func testExternalUI(api *SignerAPI) { +func testExternalUI(api *core.SignerAPI) { ctx := context.WithValue(context.Background(), "remote", "signer binary") ctx = context.WithValue(ctx, "scheme", "in-proc") @@ -178,17 +179,17 @@ func testExternalUI(api *SignerAPI) { errs := make([]string, 0) - api.ui.ShowInfo("Testing 'ShowInfo'") - api.ui.ShowError("Testing 'ShowError'") + api.UI.ShowInfo("Testing 'ShowInfo'") + api.UI.ShowError("Testing 'ShowError'") checkErr := func(method string, err error) { - if err != nil && err != ErrRequestDenied { + if err != nil && err != core.ErrRequestDenied { errs = append(errs, fmt.Sprintf("%v: %v", method, err.Error())) } } var err error - _, err = api.SignTransaction(ctx, SendTxArgs{From:common.MixedcaseAddress{}}, nil) + _, err = api.SignTransaction(ctx, core.SendTxArgs{From:common.MixedcaseAddress{}}, nil) checkErr("SignTransaction", err) _, err = api.Sign(ctx, common.MixedcaseAddress{}, common.Hex2Bytes("01020304")) checkErr("Sign", err) @@ -201,7 +202,7 @@ func testExternalUI(api *SignerAPI) { _, err = api.Import(ctx, json.RawMessage{}) checkErr("Import", err) - api.ui.ShowInfo("Tests completed") + api.UI.ShowInfo("Tests completed") if len(errs) > 0 { log.Error("Got errors") diff --git a/cmd/signer/rules/rules.go b/cmd/signer/rules/rules.go index 65cf467f60..b0b40045d1 100644 --- a/cmd/signer/rules/rules.go +++ b/cmd/signer/rules/rules.go @@ -19,7 +19,6 @@ package rules import ( "encoding/json" "fmt" - "github.com/ethereum/go-ethereum/cmd/signer" "github.com/ethereum/go-ethereum/cmd/signer/rules/deps" "github.com/ethereum/go-ethereum/cmd/signer/storage" "github.com/ethereum/go-ethereum/internal/ethapi" @@ -27,6 +26,7 @@ import ( "github.com/robertkrimen/otto" "os" "strings" + "github.com/ethereum/go-ethereum/cmd/signer/core" ) var ( @@ -48,7 +48,7 @@ func consoleOutput(call otto.FunctionCall) otto.Value { // file for each defined UI-method type rulesetUi struct { vm *otto.Otto // The JS vm - next signer.SignerUI // The next handler, for manual processing + next core.SignerUI // The next handler, for manual processing storage storage.Storage } @@ -104,45 +104,45 @@ func (r *rulesetUi) checkApproval(jsfunc string, jsarg []byte, err error) error return fmt.Errorf("rejected") } -func (r *rulesetUi) ApproveTx(request *signer.SignTxRequest) (signer.SignTxResponse, error) { +func (r *rulesetUi) ApproveTx(request *core.SignTxRequest) (core.SignTxResponse, error) { jsonreq, err := json.Marshal(request) if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil { - return signer.SignTxResponse{Transaction: request.Transaction, Approved: true, Password: ""}, nil + return core.SignTxResponse{Transaction: request.Transaction, Approved: true, Password: ""}, nil } - return signer.SignTxResponse{Approved: false}, err + return core.SignTxResponse{Approved: false}, err } -func (r *rulesetUi) ApproveSignData(request *signer.SignDataRequest) (signer.SignDataResponse, error) { +func (r *rulesetUi) ApproveSignData(request *core.SignDataRequest) (core.SignDataResponse, error) { jsonreq, err := json.Marshal(request) if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil { - return signer.SignDataResponse{Approved: true, Password: ""}, nil + return core.SignDataResponse{Approved: true, Password: ""}, nil } - return signer.SignDataResponse{Approved: false, Password: ""}, err + return core.SignDataResponse{Approved: false, Password: ""}, err } -func (r *rulesetUi) ApproveExport(request *signer.ExportRequest) (signer.ExportResponse, error) { +func (r *rulesetUi) ApproveExport(request *core.ExportRequest) (core.ExportResponse, error) { jsonreq, err := json.Marshal(request) if err = r.checkApproval("ApproveTx", jsonreq, err); err == nil { - return signer.ExportResponse{Approved: true}, nil + return core.ExportResponse{Approved: true}, nil } - return signer.ExportResponse{Approved: false}, err + return core.ExportResponse{Approved: false}, err } -func (r *rulesetUi) ApproveImport(request *signer.ImportRequest) (signer.ImportResponse, error) { +func (r *rulesetUi) ApproveImport(request *core.ImportRequest) (core.ImportResponse, error) { // This cannot be handled by rules, requires setting a password // dispatch to next return r.next.ApproveImport(request) } -func (r *rulesetUi) ApproveListing(request *signer.ListRequest) (signer.ListResponse, error) { +func (r *rulesetUi) ApproveListing(request *core.ListRequest) (core.ListResponse, error) { jsonreq, err := json.Marshal(request) if err = r.checkApproval("ApproveListing", jsonreq, err); err == nil { - return signer.ListResponse{Accounts: request.Accounts}, nil + return core.ListResponse{Accounts: request.Accounts}, nil } - return signer.ListResponse{}, err + return core.ListResponse{}, err } -func (r *rulesetUi) ApproveNewAccount(request *signer.NewAccountRequest) (signer.NewAccountResponse, error) { +func (r *rulesetUi) ApproveNewAccount(request *core.NewAccountRequest) (core.NewAccountResponse, error) { // This cannot be handled by rules, requires setting a password // dispatch to next return r.next.ApproveNewAccount(request) diff --git a/cmd/signer/rules/rules_test.go b/cmd/signer/rules/rules_test.go index c283d6d5d0..fe738da8c3 100644 --- a/cmd/signer/rules/rules_test.go +++ b/cmd/signer/rules/rules_test.go @@ -3,13 +3,13 @@ package rules import ( "fmt" "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/cmd/signer" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/internal/ethapi" "math/big" "testing" + "github.com/ethereum/go-ethereum/cmd/signer/core" ) const JS = ` @@ -66,11 +66,11 @@ func initRuleEngine(js string) (*rulesetUi, error) { } func TestListRequest(t *testing.T) { - accs := make([]signer.Account, 5) + accs := make([]core.Account, 5) for i, _ := range accs { addr := fmt.Sprintf("000000000000000000000000000000000000000%x", i) - acc := signer.Account{ + acc := core.Account{ Address: common.BytesToAddress(common.Hex2Bytes(addr)), URL: accounts.URL{Scheme: "test", Path: fmt.Sprintf("acc-%d", i)}, } @@ -84,9 +84,9 @@ func TestListRequest(t *testing.T) { t.Errorf("Couldn't create evaluator %v", err) return } - resp, err := r.ApproveListing(&signer.ListRequest{ + resp, err := r.ApproveListing(&core.ListRequest{ accs, - signer.Metadata{ + core.Metadata{ "remoteip", "localip", "inproc", }, }) @@ -126,12 +126,12 @@ func TestSignTxRequest(t *testing.T) { return } fmt.Printf("to %v", to.Address().String()) - resp, err := r.ApproveTx(&signer.SignTxRequest{ - Transaction: signer.SendTxArgs{ + resp, err := r.ApproveTx(&core.SignTxRequest{ + Transaction: core.SendTxArgs{ From: *from, To: to}, Callinfo: "", - Meta: signer.Metadata{"remoteip", "localip", "inproc"}, + Meta: core.Metadata{"remoteip", "localip", "inproc"}, }) if err != nil { t.Errorf("Unexpected error %v", err) @@ -290,7 +290,7 @@ const ExampleTxWindow = ` ` -func dummyTx(value *hexutil.Big) *signer.SignTxRequest { +func dummyTx(value hexutil.Big) *core.SignTxRequest { to, _ := mixAddr("000000000000000000000000000000000000dead") from, _ := mixAddr("000000000000000000000000000000000000dead") @@ -298,17 +298,17 @@ func dummyTx(value *hexutil.Big) *signer.SignTxRequest { gas := hexutil.Big(*big.NewInt(21000)) gasPrice := hexutil.Big(*big.NewInt(2000000)) - return &signer.SignTxRequest{ - Transaction: signer.SendTxArgs{ + return &core.SignTxRequest{ + Transaction: core.SendTxArgs{ From: *from, To: to, Value: value, - Nonce: &n, - GasPrice: &gas, - Gas: &gasPrice, + Nonce: n, + GasPrice: gas, + Gas: gasPrice, }, Callinfo: "Warning, all your base are bellong to us", - Meta: signer.Metadata{"remoteip", "localip", "inproc"}, + Meta: core.Metadata{"remoteip", "localip", "inproc"}, } } func dummySigned(value *big.Int) *types.Transaction { @@ -335,7 +335,7 @@ func TestLimitWindow(t *testing.T) { h := hexutil.Big(*v) // The first three should succeed for i := 0; i < 3; i++ { - unsigned := dummyTx(&h) + unsigned := dummyTx(h) resp, err := r.ApproveTx(unsigned) if err != nil { t.Errorf("Unexpected error %v", err) @@ -352,7 +352,7 @@ func TestLimitWindow(t *testing.T) { r.OnApprovedTx(response) } // Fourth should fail - resp, err := r.ApproveTx(dummyTx(&h)) + resp, err := r.ApproveTx(dummyTx(h)) if resp.Approved { t.Errorf("Expected check to resolve to 'Reject'") }