signer: add ipc capability+review concerns

This commit is contained in:
Martin Holst Swende 2018-03-11 22:52:57 +01:00
parent 3096761623
commit 895199d9f8
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
14 changed files with 180 additions and 37 deletions

View file

@ -89,6 +89,15 @@ invoking methods with the following info:
* [x] Address of API (http/ipc)
* [ ] List of known accounts
* [ ] `account_signRawTransaction`
* [ ] `account_bulkSignTransactions([] transactions)` should
* only exist if enabled via config/flag
* only allow non-data-sending transactions
* all txs must use the same `from`-account
* let the user confirm, showing
* the total amount
* the number of unique recipients
* Geth todos
- The signer should pass the `Origin` header as call-info to the UI. As of right now, the way that info about the request is
@ -115,7 +124,7 @@ put together is a bit of a hack into the http server. This could probably be gre
### External API
The signer listens to HTTP requests on `rpcaddr`:`rpcport`. The messages are
The signer listens to HTTP requests on `rpcaddr`:`rpcport`, with the same JSONRPC standard as Geth. The messages are
expected to be JSON [jsonrpc 2.0 standard](http://www.jsonrpc.org/specification).
Some of these call can require user interaction. Clients must be aware that responses
@ -172,7 +181,7 @@ None
- url [string]: location of the keyfile
#### Sample call
```
```json
{
"id": 0,
"jsonrpc": "2.0",
@ -206,7 +215,7 @@ None
- account.url [string]: location of the account
#### Sample call
```
```json
{
"id": 1,
"jsonrpc": "2.0",
@ -253,7 +262,7 @@ None
- signed transaction in RLP encoded form [data]
#### Sample call
```
```json
{
"id": 2,
"jsonrpc": "2.0",
@ -270,7 +279,10 @@ None
}
]
}
```
Response
```json
{
"jsonrpc": "2.0",
"id": 67,
@ -283,7 +295,7 @@ None
#### Sample call with ABI-data
```
```json
{
"jsonrpc": "2.0",
"method": "account_signTransaction",
@ -301,7 +313,10 @@ None
],
"id": 67
}
```
Response
```json
{
"jsonrpc": "2.0",
"id": 67,
@ -344,7 +359,7 @@ Bash example:
- calculated signature [data]
#### Sample call
```
```json
{
"id": 3,
"jsonrpc": "2.0",
@ -354,7 +369,10 @@ Bash example:
"0xaabbccdd"
]
}
```
Response
```json
{
"id": 3,
"jsonrpc": "2.0",
@ -375,7 +393,7 @@ Bash example:
- derived account [address]
#### Sample call
```
```json
{
"id": 4,
"jsonrpc": "2.0",
@ -385,7 +403,10 @@ Bash example:
"0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c"
]
}
```
Response
```json
{
"id": 4,
"jsonrpc": "2.0",
@ -410,7 +431,7 @@ Bash example:
- key.url [string]: key URL
#### Sample call
```
```json
{
"id": 6,
"jsonrpc": "2.0",
@ -439,6 +460,10 @@ Bash example:
},
]
}
```
Response
```json
{
"id": 6,
"jsonrpc": "2.0",
@ -464,7 +489,7 @@ Bash example:
more information
#### Sample call
```
```json
{
"id": 5,
"jsonrpc": "2.0",
@ -473,6 +498,10 @@ Bash example:
"0xc7412fc59930fd90099c917a50e5f11d0934b2f5"
]
}
```
Response
```json
{
"id": 5,
"jsonrpc": "2.0",
@ -506,7 +535,6 @@ Bash example:
These methods needs to be implemented by a UI listener.
By starting the signer with the switch `--stdio-ui-test`, the signer will invoke all known methods, and expect the UI to respond with
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'.
@ -515,6 +543,10 @@ All methods in this API uses object-based parameters, so that there can be no mi
See the [ui api changelog](intapi_changelog.md) for information about changes to this API.
OBS! A slight deviation from `json` standard is in place: every request and response should be confined to a single line.
Whereas the `json` specification allows for linebreaks, linebreaks __should not__ be used in this communication channel, to make
things simpler for both parties.
### ApproveTx
Invoked when there's a transaction for approval.

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify

View file

@ -1,3 +1,19 @@
// Copyright 2018 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 <http://www.gnu.org/licenses/>.
//
package core
import (

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"golang.org/x/crypto/ssh/terminal"
"github.com/davecgh/go-spew/spew"
)
type CommandlineUI struct {
@ -233,7 +234,8 @@ func (ui *CommandlineUI) ShowInfo(message string) {
}
func (ui *CommandlineUI) OnApprovedTx(tx ethapi.SignTransactionResult) {
fmt.Printf("Transaction signed: %v", tx.Tx.String())
fmt.Printf("Transaction signed:\n ")
spew.Dump(tx.Tx)
}
func (ui *CommandlineUI) OnSignerStartup(info StartupInfo) {

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
@ -27,7 +27,6 @@ import (
"fmt"
"io"
"io/ioutil"
"net"
"os"
"os/user"
"path/filepath"
@ -45,6 +44,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/rpc"
"gopkg.in/urfave/cli.v1"
"os/signal"
)
// EXT_API_VERSION -- see extapi_changelog.md
@ -180,6 +180,9 @@ func init() {
utils.NoUSBFlag,
utils.RPCListenAddrFlag,
utils.RPCVirtualHostsFlag,
utils.IPCDisabledFlag,
utils.IPCPathFlag,
utils.RPCEnabledFlag,
rpcPortFlag,
signerSecretFlag,
dBFlag,
@ -330,8 +333,6 @@ func signer(c *cli.Context) error {
var (
api core.ExternalAPI
listener net.Listener
server = rpc.NewServer()
)
configDir := c.String(configdirFlag.Name)
@ -396,18 +397,56 @@ func signer(c *cli.Context) error {
log.Info("Audit logs configured", "file", logfile)
}
// register signer API with server
if err = server.RegisterName("account", api); err != nil {
utils.Fatalf("Could not register signer API: %v", err)
var (
extapiUrl = "n/a"
ipcApiUrl = "n/a"
)
rpcApi := []rpc.API{
rpc.API{
Namespace: "account",
Public: true,
Service: api,
Version: "1.0"},
}
if c.Bool(utils.RPCEnabledFlag.Name) {
vhosts := splitAndTrim(c.GlobalString(utils.RPCVirtualHostsFlag.Name))
//!TODO
cors := []string{"*"}
// start http server
endpoint := fmt.Sprintf("%s:%d", c.String(utils.RPCListenAddrFlag.Name), c.Int(rpcPortFlag.Name))
if listener, err = net.Listen("tcp", endpoint); err != nil {
utils.Fatalf("Could not start http listener: %v", err)
httpEndpoint := fmt.Sprintf("%s:%d", c.String(utils.RPCListenAddrFlag.Name), c.Int(rpcPortFlag.Name))
listener, _, err := node.StartHttpEndpoint(httpEndpoint, rpcApi, []string{"account"}, cors, vhosts)
if err != nil {
utils.Fatalf("Could not start RPC api: %v", err)
}
extapiUrl = fmt.Sprintf("http://%s", httpEndpoint)
log.Info("HTTP endpoint opened", "url", extapiUrl)
defer func() {
listener.Close()
log.Info("HTTP endpoint closed", "url", httpEndpoint)
}()
}
if !c.Bool(utils.IPCDisabledFlag.Name) {
if c.IsSet(utils.IPCPathFlag.Name) {
ipcApiUrl = c.String(utils.IPCPathFlag.Name)
} else {
ipcApiUrl = fmt.Sprintf("%s", filepath.Join(configDir, "signer.ipc"))
}
listener, _, err := node.StartIPCEndpoint(func() bool { return true }, ipcApiUrl, rpcApi)
if err != nil {
utils.Fatalf("Could not start IPC api: %v", err)
}
log.Info("IPC endpoint opened", "url", ipcApiUrl)
defer func() {
listener.Close()
log.Info("IPC endpoint closed", "url", ipcApiUrl)
}()
}
extapi_url := fmt.Sprintf("http://%s", endpoint)
log.Info("HTTP endpoint opened", "url", extapi_url)
cors := []string{"*"}
if c.Bool(testFlag.Name) {
log.Info("Performing UI test")
@ -417,12 +456,18 @@ func signer(c *cli.Context) error {
Info: map[string]interface{}{
"extapi_version": EXT_API_VERSION,
"intapi_version": INT_API_VERSION,
"extapi_http": extapi_url,
"extapi_ipc": nil,
"extapi_http": extapiUrl,
"extapi_ipc": ipcApiUrl,
},
})
vhosts := splitAndTrim(c.GlobalString(utils.RPCVirtualHostsFlag.Name))
rpc.NewHTTPServer(cors, vhosts, server).Serve(listener)
abortChan := make(chan os.Signal)
signal.Notify(abortChan, os.Interrupt)
select {
case sig := <-abortChan:
log.Info("Exiting...", "signal", sig)
}
return nil
}

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify

View file

@ -1,4 +1,4 @@
// Copyright 2017 The go-ethereum Authors
// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify

View file

@ -1,3 +1,19 @@
// Copyright 2018 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 <http://www.gnu.org/licenses/>.
//
package rules
import (

View file

@ -1,3 +1,19 @@
// Copyright 2018 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 <http://www.gnu.org/licenses/>.
//
package storage
import (

View file

@ -1,3 +1,19 @@
// Copyright 2018 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 <http://www.gnu.org/licenses/>.
//
package storage
import (