cmd/signer: rename fromaccount, update pythonpoc with new json encoding format

This commit is contained in:
Martin Holst Swende 2017-12-22 23:47:14 +01:00
parent c55fd329ae
commit f743cdd437
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
4 changed files with 238 additions and 37 deletions

View file

@ -377,7 +377,175 @@ None
These methods needs to be implemented by a UI listener.
still work in progress
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'.
**work in progress**
### ApproveTx
Invoked when there's a transaction for approval.
#### Sample call
```json
{
"jsonrpc": "2.0",
"method": "ApproveTx",
"params": [{
"transaction": {
"to": "0xae967917c465db8578ca9024c205720b1a3651A9",
"gas": "0x333",
"gasPrice": "0x123",
"value": "0x10",
"data": "0xd7a5865800000000000000000000000000000000000000000000000000000000000000ff",
"nonce": "0x0"
},
"fromaccount": "0xAe967917c465db8578ca9024c205720b1a3651A9",
"call_info": "Warning! Could not validate ABI-data against calldata\nSupplied ABI spec does not contain method signature in data: 0xd7a58658",
"meta": {
"remote": "127.0.0.1:34572",
"local": "localhost:8550",
"scheme": "HTTP/1.1"
}
}],
"id": 1
}
```
### ApproveExport
Invoked when a request to export an account has been made.
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 7,
"method": "ApproveExport",
"params": [
{
"address": "0x0000000000000000000000000000000000000000",
"meta": {
"remote": "signer binary",
"local": "main",
"scheme": "in-proc"
}
}
]
}
```
### ApproveListing
Invoked when a request for account listing has been made.
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 5,
"method": "ApproveListing",
"params": [
{
"accounts": [
{
"type": "Account",
"url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-20T14-44-54.089682944Z--123409812340981234098123409812deadbeef42",
"address": "0x123409812340981234098123409812deadbeef42"
},
{
"type": "Account",
"url": "keystore:///home/bazonk/.ethereum/keystore/UTC--2017-11-23T21-59-03.199240693Z--cafebabedeadbeef34098123409812deadbeef42",
"address": "0xcafebabedeadbeef34098123409812deadbeef42"
}
],
"meta": {
"remote": "signer binary",
"local": "main",
"scheme": "in-proc"
}
}
]
}
```
### ApproveSignData
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 4,
"method": "ApproveSignData",
"params": [
{
"address": "0x123409812340981234098123409812deadbeef42",
"raw_data": "0x01020304",
"message": "\u0019Ethereum Signed Message:\n4\u0001\u0002\u0003\u0004",
"hash": "0x7e3a4e7a9d1744bc5c675c25e1234ca8ed9162bd17f78b9085e48047c15ac310",
"meta": {
"remote": "signer binary",
"local": "main",
"scheme": "in-proc"
}
}
]
}
```
### ShowInfo
The UI should show the info to the user. Does not expect response.
#### Sample call
```json
{
"jsonrpc": "2.0",
"id": 9,
"method": "ShowInfo",
"params": [
{
"text": "Tests completed"
}
]
}
```
### ShowError
The UI should show the info to the user. Does not expect response.
```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "ShowError",
"params": [
{
"text": "Testing 'ShowError'"
}
]
}
```
### Rules for UI apis
@ -398,6 +566,9 @@ A UI should conform to the following rules.
along with the UI.
## TODOs
Some snags and todos

View file

@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"regexp"
"reflect"
)
type decodedArgument struct {
@ -82,18 +83,29 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {
if method == nil {
return nil, fmt.Errorf("Supplied ABI spec does not contain method signature in data: 0x%x", sigdata)
}
var v interface{}
method.Inputs.Unpack(v, argdata)
ref := reflect.ValueOf(v)
values := make([]interface{}, ref.NumField())
for i := 0; i < ref.NumField(); i++ {
values[i] = ref.Field(i).Interface()
}
fmt.Println(values)
decoded := decodedCallData{signature: method.Sig(), name: method.Name}
/*
for n, argument := range method.Inputs {
value, err := abi.ToGoType(n*32, argument.Type, argdata)
if err != nil {
return nil, fmt.Errorf("Failed to decode argument %d (signature %v): %v", n, method.Sig(), err)
} else {
decodedArg := decodedArgument{
soltype: argument,
value: value,
value: reflect.ValueOf(v,) ,
}
decoded.inputs = append(decoded.inputs, decodedArg)
}
@ -103,20 +115,19 @@ func parseCallData(calldata []byte, abidata string) (*decodedCallData, error) {
// original data. If we didn't do that, it would e.g. be possible to stuff extra data into the arguments, which
// is not detected by merely decoding the data.
var (
gotypedArguments = make([]interface{}, len(decoded.inputs))
encoded []byte
)
for i, arg := range decoded.inputs {
gotypedArguments[i] = arg.value
}
encoded, err = abispec.Pack(method.Name, gotypedArguments...)
encoded, err = method.Inputs.Pack(v)
if !bytes.Equal(encoded, calldata) {
exp := common.Bytes2Hex(encoded)
was := common.Bytes2Hex(calldata)
return nil, fmt.Errorf("WARNING: Supplied data is stuffed with extra data. \nWant %s\nHave %s\nfor method %v", exp, was, method.Sig())
}
*/
return &decoded, nil
}

View file

@ -26,6 +26,8 @@ import (
"bytes"
"reflect"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/accounts/usbwallet"
@ -56,7 +58,7 @@ type (
// SignTxRequest contains info about a Transaction to sign
SignTxRequest struct {
Transaction TransactionArg `json:"transaction"`
From common.MixedcaseAddress `json:"fromaccount"`
From common.MixedcaseAddress `json:"from"`
Callinfo string `json:"call_info"`
Meta Metadata `json:"meta"`
}
@ -64,7 +66,7 @@ type (
SignTxResponse struct {
//The UI may make changes to the TX
Transaction TransactionArg `json:"transaction"`
From common.MixedcaseAddress `json:"fromaccount"`
From common.MixedcaseAddress `json:"from"`
Approved bool `json:"approved"`
Password string `json:"password"`
}
@ -260,7 +262,7 @@ func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
modified = true
log.Info("Sender-account changed by UI", "was", f0, "is", f1)
}
if t0, t1 := original.Transaction.To, new.Transaction.To; t0 != t1 {
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
}

View file

@ -48,71 +48,87 @@ class StdIOHandler():
pass
@public
def ApproveTx(self,transaction = None, fromaccount = None, call_info = None, meta = None):
def ApproveTx(self,req):
"""
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": "0xae967917c465db8578ca9024c205720b1a3651A9",
"gas": "0x333",
"gasPrice": "0x123",
"value": "0x10",
"data": "0xd7a5865800000000000000000000000000000000000000000000000000000000000000ff",
"nonce": "0x0"
},
"from": "0xAe967917c465db8578ca9024c205720b1a3651A9",
"call_info": "Warning! Could not validate ABI-data against calldata\nSupplied ABI spec does not contain method signature in data: 0xd7a58658",
"meta": {
"remote": "127.0.0.1:34572",
"local": "localhost:8550",
"scheme": "HTTP/1.1"
}
}],
"id": 1
}
:param transaction: transaction info
:param call_info: info abou the call, e.g. if ABI info could not be
:param meta: metadata about the request, e.g. where the call comes from
:return:
"""
transaction = req.get('transaction')
_from = req.get('from')
call_info = req.get('call_info')
meta = req.get('meta')
return {
"approved" : False,
"transaction" : None,
#"fromaccount" : fromaccount,
"password" : None,
"transaction" : transaction,
"from" : _from,
# "password" : None,
}
@public
def ApproveSignData(self,address=None, raw_data = None, message = None, hash = None, meta = None):
def ApproveSignData(self, req):
""" Example request
{"jsonrpc":"2.0","method":"ApproveSignData","params":{"address":"0x0000000000000000000000000000000000000000","raw_data":"0x01020304","message":"\u0019Ethereum Signed Message:\n4\u0001\u0002\u0003\u0004","hash":"0x7e3a4e7a9d1744bc5c675c25e1234ca8ed9162bd17f78b9085e48047c15ac310","meta":{"remote":"signer binary","local":"main","scheme":"in-proc"}},"id":3}
"""
return {"approved": False,
"password" : None}
return {"approved": False, "password" : None}
@public
def ApproveExport(self,address = None, meta = None):
def ApproveExport(self, req):
""" Example request
{"jsonrpc":"2.0","method":"ApproveExport","params":{"address":"0x0000000000000000000000000000000000000000","meta":{"remote":"signer binary","local":"main","scheme":"in-proc"}},"id":5}
"""
return {"approved" : False}
@public
def ApproveImport(self,meta = None):
def ApproveImport(self, req):
""" Example request
{"jsonrpc":"2.0","method":"ApproveImport","params":{"Meta":{}},"id":4}
"""
return {"approved" : False, "old_password": "", "new_password": ""}
return { "approved" : False, "old_password": "", "new_password": ""}
@public
def ApproveListing(self,accounts=None, meta = None):
def ApproveListing(self, req):
""" Example request
{"jsonrpc":"2.0","method":"ApproveListing","params":{"accounts":[{"type":"Account","url":"keystore:///home/user/ethereum/keystore/file","address":"0x010101010101010010101010101abcdef0001337"}],"Meta":{}},"id":2}
"""
return {'accounts': []}
@public
def ApproveNewAccount(self,meta = None):
def ApproveNewAccount(self, req):
"""
Example request
{"jsonrpc":"2.0","method":"ApproveNewAccount","params":{"meta":{"remote":"signer binary","local":"main","scheme":"in-proc"}},"id":5}
:return:
"""
return {"approved": False, "password": ""}
return {"approved": False,
#"password": ""
}
@public
def ShowError(self,message = {}):
@ -137,6 +153,7 @@ class StdIOHandler():
:param message: to display
:return:nothing
"""
if 'text' in message.keys():
sys.stdout.write("Error: {}\n".format( message['text']))
return