mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 09:53:48 +00:00
cmd/signer: rework json communication
This commit is contained in:
parent
92ba02a8d5
commit
2ccae4ffec
4 changed files with 74 additions and 20 deletions
|
|
@ -404,17 +404,11 @@ Some snags and todos
|
||||||
checksum, since the addresses are common.Address, and not String. This should be changed upstream,
|
checksum, since the addresses are common.Address, and not String. This should be changed upstream,
|
||||||
so that they are some more complex form with both common.Address and the original string (?)
|
so that they are some more complex form with both common.Address and the original string (?)
|
||||||
|
|
||||||
* The JSON communication relies on an external library, which has not been vendored in. We could probably
|
|
||||||
reuse the jsoncodec by adding some fields for clientcodec, but it's a bit messy.
|
|
||||||
|
|
||||||
* The audit-log perhaps leave some things to be desired. I have not found a perfect way to save an audit log of events.
|
* The audit-log perhaps leave some things to be desired. I have not found a perfect way to save an audit log of events.
|
||||||
|
|
||||||
* Some more fields should be added to calldata, e.g http-header `Origin`.
|
* Some more fields should be added to calldata, e.g http-header `Origin`.
|
||||||
|
|
||||||
* The signer should also generate the identicon for the addresses, and pass to the UI as a base64 string.
|
|
||||||
* based on https://github.com/ethereum/blockies
|
|
||||||
* Maybe actually need to be in the UI, at least in UI:s allowing the user to change the address
|
|
||||||
|
|
||||||
* The signer should take a startup param "--no-change", for UI:s that do not contain the capability
|
* The signer should take a startup param "--no-change", for UI:s that do not contain the capability
|
||||||
to perform changes to things, only approve/deny. Such a UI should be able to start the signer in
|
to perform changes to things, only approve/deny. Such a UI should be able to start the signer in
|
||||||
a more secure mode by telling it that it only wants approve/deny capabilities.
|
a more secure mode by telling it that it only wants approve/deny capabilities.
|
||||||
|
|
@ -438,4 +432,13 @@ invoking methods with the following info:
|
||||||
* 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
|
* 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
|
||||||
put together is a bit of a hack into the http server. This could probably be greatly improved
|
put together is a bit of a hack into the http server. This could probably be greatly improved
|
||||||
|
|
||||||
* The signer
|
* Geth relay
|
||||||
|
- Geth should be started in `geth --external_signer localhost:8550`.
|
||||||
|
|
||||||
|
* Wallets / accounts. Add API methods for wallets.
|
||||||
|
|
||||||
|
* Rules. In the future, it should be possible to specify rules, e.g. "Allow sending up to 1 eth per day to contract Y". Two problems:
|
||||||
|
* There needs to be a very good structure around rules. Either a full language (lua/js) or a limited but flexible syntax based on e.g. json/yaml. Kind of like a firewall ruleset.
|
||||||
|
* This implies that the signer would remember passwords, which is very problematic. However, a good UI implementation will want these things,
|
||||||
|
and it would be better to implement it once in the signer, than having UI:s develop their own remember-password logic.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ def ApproveTx(transaction = None, fromaccount = None, call_info = None, meta = N
|
||||||
"""
|
"""
|
||||||
Example request:
|
Example request:
|
||||||
|
|
||||||
{"jsonrpc":"2.0","method":"ApproveTx","params":{"transaction":{"to":null,"gas":null,"gasPrice":null,"value":null,"data":"0x","nonce":null},"from":"0x0000000000000000000000000000000000000000","call_info":null,"meta":{"remote":"signer binary","local":"main","scheme":"in-proc"}},"id":2}
|
{"jsonrpc":"2.0","method":"ApproveTx","params":{"transaction":{"to":null,"gas":null,"gasPrice":null,"value":null,"data":"0x","nonce":null},"fromaccount":"0x0000000000000000000000000000000000000000","call_info":null,"meta":{"remote":"signer binary","local":"main","scheme":"in-proc"}},"id":2}
|
||||||
|
|
||||||
:param transaction: transaction info
|
:param transaction: transaction info
|
||||||
:param call_info: info abou the call, e.g. if ABI info could not be
|
:param call_info: info abou the call, e.g. if ABI info could not be
|
||||||
|
|
@ -59,7 +59,7 @@ def ApproveTx(transaction = None, fromaccount = None, call_info = None, meta = N
|
||||||
return {
|
return {
|
||||||
"approved" : False,
|
"approved" : False,
|
||||||
"transaction" : None,
|
"transaction" : None,
|
||||||
"fromaccount" : fromaccount,
|
# "fromaccount" : fromaccount,
|
||||||
"password" : None,
|
"password" : None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -154,4 +154,4 @@ def main(args):
|
||||||
rpc_server.serve_forever()
|
rpc_server.serve_forever()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
||||||
|
|
|
||||||
|
|
@ -18,26 +18,32 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/powerman/rpc-codec/jsonrpc2"
|
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"context"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StdIOUI struct {
|
type StdIOUI struct {
|
||||||
client *jsonrpc2.Client
|
//client *jsonrpc2.Client
|
||||||
|
client rpc.Client
|
||||||
// codec rpc.ClientCodec
|
// codec rpc.ClientCodec
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStdIOUI() *StdIOUI {
|
func NewStdIOUI() *StdIOUI {
|
||||||
in, out := bufio.NewReader(os.Stdin), os.Stdout
|
// in, out := bufio.NewReader(os.Stdin), os.Stdout
|
||||||
|
client, err := rpc.DialContext(context.Background(), "stdio://")
|
||||||
|
if err != nil {
|
||||||
|
log.Crit("Could not create stdio client", "err", err)
|
||||||
|
}
|
||||||
|
return &StdIOUI{client: *client}
|
||||||
|
//return &StdIOUI{client: jsonrpc2.NewClient(&rwc{in, out})}
|
||||||
|
|
||||||
//codec := rpc2.NewJSONCodec()
|
|
||||||
return &StdIOUI{client: jsonrpc2.NewClient(&rwc{in, out})}
|
|
||||||
//return &StdIOUI{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui StdIOUI) dispatch(serviceMethod string, args interface{}, reply interface{}) error {
|
func (ui StdIOUI) dispatch(serviceMethod string, args interface{}, reply interface{}) error {
|
||||||
|
|
@ -50,10 +56,12 @@ func (ui StdIOUI) dispatch(serviceMethod string, args interface{}, reply interfa
|
||||||
// in, out := bufio.NewReader(os.Stdin), os.Stdout
|
// in, out := bufio.NewReader(os.Stdin), os.Stdout
|
||||||
// codec := jsonrpc.NewClientCodec(&rwc{in, out})
|
// codec := jsonrpc.NewClientCodec(&rwc{in, out})
|
||||||
|
|
||||||
// c := rpc.NewClientWithCodec(codec)
|
// c := rpc.NewClientWithCodec(codec)
|
||||||
// return c.Call(serviceMethod, args, &reply)
|
// return c.Call(serviceMethod, args, &reply)
|
||||||
|
log.Info("Writing to client")
|
||||||
err := ui.client.Call(serviceMethod, args, &reply)
|
err := ui.client.Call(&reply, serviceMethod, args)
|
||||||
|
log.Info("Writing to client done")
|
||||||
|
// err := ui.client.Call(serviceMethod, args, &reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Info("Error", "exc", err.Error())
|
log.Info("Error", "exc", err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -171,6 +172,8 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) {
|
||||||
return DialHTTP(rawurl)
|
return DialHTTP(rawurl)
|
||||||
case "ws", "wss":
|
case "ws", "wss":
|
||||||
return DialWebsocket(ctx, rawurl, "")
|
return DialWebsocket(ctx, rawurl, "")
|
||||||
|
case "stdio":
|
||||||
|
return DialStdIO(ctx)
|
||||||
case "":
|
case "":
|
||||||
return DialIPC(ctx, rawurl)
|
return DialIPC(ctx, rawurl)
|
||||||
default:
|
default:
|
||||||
|
|
@ -178,6 +181,46 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StdIOConn struct{}
|
||||||
|
|
||||||
|
func (io StdIOConn) Read(b []byte) (n int, err error) {
|
||||||
|
return os.Stdin.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (io StdIOConn) Write(b []byte) (n int, err error) {
|
||||||
|
return os.Stdout.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (io StdIOConn) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (io StdIOConn) LocalAddr() net.Addr {
|
||||||
|
return &net.UnixAddr{Name: "stdio", Net: "stdio"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (io StdIOConn) RemoteAddr() net.Addr {
|
||||||
|
return &net.UnixAddr{Name: "stdio", Net: "stdio"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (io StdIOConn) SetDeadline(t time.Time) error {
|
||||||
|
return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (io StdIOConn) SetReadDeadline(t time.Time) error {
|
||||||
|
return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (io StdIOConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return &net.OpError{Op: "set", Net: "stdio", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
|
}
|
||||||
|
func DialStdIO(ctx context.Context) (*Client, error) {
|
||||||
|
|
||||||
|
return newClient(ctx, func(_ context.Context) (net.Conn, error) {
|
||||||
|
return StdIOConn{}, nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func newClient(initctx context.Context, connectFunc func(context.Context) (net.Conn, error)) (*Client, error) {
|
func newClient(initctx context.Context, connectFunc func(context.Context) (net.Conn, error)) (*Client, error) {
|
||||||
conn, err := connectFunc(initctx)
|
conn, err := connectFunc(initctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue