EIPs/EIPS/eip-191.md

83 lines
3.6 KiB
Markdown
Raw Normal View History

2018-04-05 16:04:47 +00:00
---
eip: 191
title: Signed Data Standard
2018-04-09 10:10:06 +00:00
author: Martin Holst Swende (@holiman), Nick Johnson <arachnid@notdot.net>
status: Draft
type: Standards Track
category: ERC
created: 2016-01-20
2018-04-05 16:04:47 +00:00
---
# Abstract
This ERC proposes a specification about how to handle signed data in Ethereum contracts.
2018-04-05 16:04:47 +00:00
# Motivation
Several multisignature wallet implementations have been created which accepts `presigned` transactions. A `presigned` transaction is a chunk of binary `signed_data`, along with signature (`r`, `s` and `v`). The interpretation of the `signed_data` has not been specified, leading to several problems:
* Standard Ethereum transactions can be submitted as `signed_data`. An Ethereum transaction can be unpacked, into the following components: `RLP<nonce, gasPrice, startGas, to, value, data>` (hereby called `RLPdata`), `r`, `s` and `v`. If there are no syntactical constraints on `signed_data`, this means that `RLPdata` can be used as a syntactically valid `presigned` transaction.
* Multisignature wallets have also had the problem that a `presigned` transaction has not been tied to a particular `validator`, i.e a specific wallet. Example:
1. Users `A`, `B` and `C` have the `2/3`-wallet `X`
2. Users `A`, `B` and `D` have the `2/3`-wallet `Y`
3. User `A` and `B` submites `presigned` transaction to `X`.
4. Attacker can now reuse their presigned transactions to `X`, and submit to `Y`.
## Specification
We propose the following format for `signed_data`
```
0x19 <1 byte version> <version specific data> <data to sign>.
```
Version `0` has `<20 byte address>` for the version specific data, and the `address` is the intended validator. In the case of a Multisig wallet, that is the wallet's own address .
The initial `0x19` byte is intended to ensure that the `signed_data` is not valid [RLP](https://github.com/ethereum/wiki/wiki/RLP)
> For a single byte whose value is in the [0x00, 0x7f] range, that byte is its own RLP encoding.
That means that any `signed_data` cannot be one RLP-structure, but a 1-byte `RLP` payload followed by something else. Thus, any ERC-191 `signed_data` can never be an Ethereum transaction.
Additionally, `0x19` has been chosen because since ethereum/go-ethereum#2940 , the following is prepended before hashing in personal_sign:
```
"\x19Ethereum Signed Message:\n" + len(message).
```
Using `0x19` thus makes it possible to extend the scheme by defining a version `0x45` (`E`) to handle these kinds of signatures.
[WIP] Add eth_signTypedData as a standard for machine-verifiable and human-readable typed data signing with Ethereum keys (#712) * Add eip-signTypedData * Change namespace from personal to eth * Change a way schema hash is combined together with data as proposed by @MicahZoltu * Add a note about it being implemented in MetaMask as an experimental feature * Add signerAddress as a parameter * Add test vectors * Fix an example * Missing commas, periods * Address the feedback * Add a missing signerAddress parameter in the example * Change the order of parameters to have an address as a second arg * Wrote motivation * WIP * First draft of specification * Fixes * Update to new EIP format * Assign EIP number * Clarify encoding of short static byte arrays * Removed Solidity changes * Fixup * Fix typos * WIP EIP191 * WIP TODO * WIP Replay attacks * Fixes the sorted by name example encoding * Remove Solidity hash * Added note on replay protection * Redesign domain separator * Include images and simple motivation * Fix up EIP metadata formatting * Add domain separator * Remove replay attacks from todo list * Add Jacob Evans to authors * Clarify encodeData * Rename Message example to Mail * Update mock signing screen * Rework EIP712Domain * Update Solidity example * Update Javascript example * Relocate files * Rename DomainSeparator to EIP712Domain (fix) * Move examples to separate files * Remove httpOrigin domain parameter * Update JSON-Schema * Add registery of version bytes * Add eip712 to eip191 registery * Add requires header * Set correct language on all snipets * GitHub highlighting for Solidity files * Update Web3 API specification * Use abi.encode where possible * Update JSON-RPC specification * Asset path repo is ethereums * Correctly spelling of registry
2018-06-09 19:19:15 +00:00
### Registry of version bytes
| Version byte | EIP | Description
| ------------ | -------------- | -----------
| `0x00` | [191][eip-191] | Data with intended validator
| `0x01` | [712][eip-712] | Structured data
| `0x45` | [191][eip-191] | `personal_sign` messages
[eip-191]: https://eips.ethereum.org/EIPS/eip-191
[eip-712]: https://eips.ethereum.org/EIPS/eip-712
2018-04-05 16:04:47 +00:00
### Example
The following snippet has been written in Solidity 0.5.0.
```solidity
function submitTransactionPreSigned(address destination, uint value, bytes data, uint nonce, uint8 v, bytes32 r, bytes32 s)
public
returns (bytes32 transactionHash)
{
// Arguments when calculating hash to validate
// 1: byte(0x19) - the initial 0x19 byte
// 2: byte(0) - the version byte
// 3: this - the validator address
// 4-7 : Application specific data
transactionHash = keccak256(abi.encodePacked(byte(0x19),byte(0),address(this),destination, value, data, nonce));
sender = ecrecover(transactionHash, v, r, s);
// ...
}
```
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).