Added example RPC calls for account_signData and account_signTypedData

This commit is contained in:
Paul Berg 2018-11-05 17:54:58 +02:00 committed by Martin Holst Swende
parent 3be30e7101
commit 1a9cbe33bd
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
3 changed files with 117 additions and 28 deletions

View file

@ -189,7 +189,9 @@ None
"method": "account_new",
"params": []
}
```
Response
```
{
"id": 0,
"jsonrpc": "2.0",
@ -222,7 +224,9 @@ None
"jsonrpc": "2.0",
"method": "account_list"
}
```
Response
```
{
"id": 1,
"jsonrpc": "2.0",
@ -285,8 +289,8 @@ Response
```json
{
"id": 2,
"jsonrpc": "2.0",
"id": 67,
"error": {
"code": -32000,
"message": "Request denied"
@ -298,6 +302,7 @@ Response
```json
{
"id": 67,
"jsonrpc": "2.0",
"method": "account_signTransaction",
"params": [
@ -311,8 +316,7 @@ Response
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
},
"safeSend(address)"
],
"id": 67
]
}
```
Response
@ -346,16 +350,18 @@ Bash example:
{"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_signData
#### Sign data
Signs a chunk of data and returns the calculated signature.
#### Arguments
- content type [string]: type of data to sign
- content type [string]: type of signed data
- `text/validator`: hex data with custom validator defined in a contract
- `application/clique`: [clique](https://github.com/ethereum/EIPs/issues/225) headers
- `text/plain`: simple hex data validated by `account_ecRecover`
- account [address]: account to sign with
- data [data]: data to sign
- data [object]: data to sign
#### Result
- calculated signature [data]
@ -377,19 +383,115 @@ Response
```json
{
"id": 3,
"jsonrpc": "2.0",
"id": 3,
"result": "0x5b6693f153b48ec1c706ba4169960386dbaa6903e249cc79a8e6ddc434451d417e1e57327872c7f538beeb323c300afa9999a3d4a5de6caf3be0d5ef832b67ef1c"
}
```
### account_signTypedData
#### Sign data
Signs a chunk of structured data conformant to [EIP712]([EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md)) and returns the calculated signature.
#### Arguments
- account [address]: account to sign with
- data [object]: data to sign
#### Result
- calculated signature [data]
#### Sample call
```json
{
"id": 68,
"jsonrpc": "2.0",
"method": "account_signTypedData",
"params": [
"0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826",
{
"types": {
"EIP712Domain": [
{
"name": "name",
"type": "string"
},
{
"name": "version",
"type": "string"
},
{
"name": "chainId",
"type": "uint256"
},
{
"name": "verifyingContract",
"type": "address"
}
],
"Person": [
{
"name": "name",
"type": "string"
},
{
"name": "wallet",
"type": "address"
}
],
"Mail": [
{
"name": "from",
"type": "Person"
},
{
"name": "to",
"type": "Person"
},
{
"name": "contents",
"type": "string"
}
]
},
"primaryType": "Mail",
"domain": {
"name": "Ether Mail",
"version": "1",
"chainId": 1,
"verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
},
"message": {
"from": {
"name": "Cow",
"wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
},
"to": {
"name": "Bob",
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
},
"contents": "Hello, Bob!"
}
}
]
}
```
Response
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x4355c47d63924e8a72e509b65029052eb6c299d53a04e167c5775fd466751c9d07299936d304c153f6443dfa05f40ff007d72911b6f72307f996231605b915621c"
}
```
### account_ecRecover
#### Sign data
Derive the address from the account that was used to sign data from the data and signature.
Derive the address from the account that was used to sign data with content type `text/plain` and the signature.
#### Arguments
- content type [string]: type of signed data
- data [data]: data that was signed
- signature [data]: the signature to verify
@ -461,7 +563,7 @@ Response
},
"id": "09bccb61-b8d3-4e93-bf4f-205a8194f0b9",
"version": 3
},
}
]
}
```

View file

@ -8,7 +8,7 @@ The addition of `contentType` makes it possible to use the method for different
* signing data with an intended validator (not yet implemented)
* signing clique headers,
* signing plain personal messages,
* The external method `account_signTypedData` [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) and makes it possible to sign typed data.
* The external method `account_signTypedData` implements [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) and makes it possible to sign typed data.
#### 4.0.0

View file

@ -175,7 +175,6 @@ func (api *SignerAPI) determineSignatureFormat(contentType string, addr common.M
}
sighash, msg := SignTextValidator(validatorData)
req = &SignDataRequest{Rawdata: validatorData, Message: msg, Hash: sighash, ContentType: mediaType}
break
case ApplicationClique.Mime:
// Clique is the Ethereum PoA standard
cliqueData, err := hexutil.Decode(data.(string))
@ -192,7 +191,6 @@ func (api *SignerAPI) determineSignatureFormat(contentType string, addr common.M
}
msg := fmt.Sprintf("clique block %d [0x%x]", header.Number, header.Hash())
req = &SignDataRequest{Rawdata: cliqueData, Message: msg, Hash: sighash, ContentType: mediaType}
break
case TextPlain.Mime:
// Calculates an Ethereum ECDSA signature for:
// hash = keccak256("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}")
@ -202,7 +200,6 @@ func (api *SignerAPI) determineSignatureFormat(contentType string, addr common.M
}
sighash, msg := SignTextPlain(plainData)
req = &SignDataRequest{Rawdata: plainData, Message: msg, Hash: sighash, ContentType: mediaType}
break
default:
return nil, fmt.Errorf("content type '%s' not implemented for signing", contentType)
}
@ -382,7 +379,6 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
bytesValue = append(bytesValue, _byte)
}
primitiveEncValue = bytesValue
break
case "bool":
primitiveEncType = "uint256"
var int64Val int64
@ -390,11 +386,9 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
int64Val = 1
}
primitiveEncValue = abi.U256(big.NewInt(int64Val))
break
case "bytes", "string":
primitiveEncType = "bytes32"
primitiveEncValue = crypto.Keccak256(bytesValueOf(encValue))
break
default:
if strings.HasPrefix(encType, "bytes") {
encTypes = append(encTypes, "bytes32")
@ -404,15 +398,12 @@ func (typedData *TypedData) EncodeData(primaryType string, data map[string]inter
for i := 0; i < 32-size; i++ {
bytesValue = append(bytesValue, 0)
}
for _, _byte := range encValue.(hexutil.Bytes) {
bytesValue = append(bytesValue, _byte)
}
bytesValue = append(bytesValue, encValue.(hexutil.Bytes)...)
primitiveEncValue = bytesValue
} else if strings.HasPrefix(encType, "uint") || strings.HasPrefix(encType, "int") {
primitiveEncType = "uint256"
primitiveEncValue = abi.U256(encValue.(*big.Int))
}
break
}
return primitiveEncType, primitiveEncValue
}
@ -600,11 +591,7 @@ func isStandardTypeStr(encType string) bool {
}
// Reference types
if encType[len(encType)-1] == ']' {
return true
}
return false
return encType[len(encType)-1] == ']'
}
// IsValid checks if the given domain is valid, i.e. contains at least