Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAbstraction of transaction origin and signature.md #208
Conversation
This comment has been minimized.
This comment has been minimized.
|
Can we make the title more descriptive? How about something like "Abstraction of transaction origin and signature" |
This was referenced Mar 1, 2017
This comment has been minimized.
This comment has been minimized.
|
I see a change about nonce increment in https://github.com/ethcore/parity/pull/4697 (line: https://github.com/ethcore/parity/blob/027b0446efa48622ce166a561dd274332dac96a0/ethcore/src/executive.rs#L178 ) but not in this PR. |
This comment has been minimized.
This comment has been minimized.
|
@yann300 is also working on this. |
pirapira
reviewed
Mar 2, 2017
| If `block.number >= METROPOLIS_FORK_BLKNUM`, then: | ||
| 1. If the signature of a transaction is `(CHAIN_ID, 0, 0)` (ie. `r = s = 0`, `v = CHAIN_ID`), then treat it as valid and set the sender address to `NULL_SENDER` | ||
| 2. Set the address of any contract created through a creation transaction to equal `sha3(NULL_SENDER + sha3(init code)) % 2**160`, where `+` represents concatenation, replacing the earlier address formula of `sha3(rlp.encode([sender, nonce]))` | ||
| 3. Create a new opcode at `0xfb`, `CREATE_P2SH`, which sets the creation address to `sha3(sender + sha3(init code)) % 2**160`. If a contract at that address already exists, fails and returns 0 as if the init code had run out of gas. |
This comment has been minimized.
This comment has been minimized.
pirapira
Mar 2, 2017
Member
Does the last sentence ("If a contract at that address already exists,...") apply to CREATE opcode and creation by external accounts?
This comment has been minimized.
This comment has been minimized.
Yes, absolutely. We'll also have to make it work with the dust protection EIP. |
gumb0
reviewed
Mar 13, 2017
| ### Specification | ||
|
|
||
| If `block.number >= METROPOLIS_FORK_BLKNUM`, then: | ||
| 1. If the signature of a transaction is `(CHAIN_ID, 0, 0)` (ie. `r = s = 0`, `v = CHAIN_ID`), then treat it as valid and set the sender address to `NULL_SENDER` |
This comment has been minimized.
This comment has been minimized.
gumb0
Mar 13, 2017
Member
Was v = CHAIN_ID really the intention here?
Currently according to #155 v = CHAIN_ID * 2 + 35 or v = CHAIN_ID * 2 + 36
(implemented only as v = CHAIN_ID * 2 + 35 in cpp-ethereum)
So do we really need additional v rule for zero signature instead of following EIP155 here, too?
This comment has been minimized.
This comment has been minimized.
vbuterin
Apr 28, 2017
Author
Collaborator
There are two ways in which v is set in EIP 155. The first is the v value which appears in the actual transaction. This is set according to that formula. The second is the value which is put into the v slot when computing the hash. This is set to equal the CHAIN_ID, just as here.
This comment has been minimized.
This comment has been minimized.
gumb0
Apr 28, 2017
•
Member
So v here in this EIP refers not to the actual value in Tx RLP, but to the one extracted from it using EIP155 formula, right?
This comment has been minimized.
This comment has been minimized.
vbuterin
Apr 28, 2017
Author
Collaborator
Aah! I see what you mean, sorry I take back my previous comment. I would still prefer v in the transaction being equal to the chain ID, as that's the easiest thing to do. There is no need to set the v value to 35 + chain_id * 2 here.
This comment has been minimized.
This comment has been minimized.
|
Some questions about zero-sig transaction: what should be the standart transaction fields (gas, gasPrice, nonce) encoded in RLP? |
chriseth
reviewed
Mar 21, 2017
| ### Specification | ||
|
|
||
| If `block.number >= METROPOLIS_FORK_BLKNUM`, then: | ||
| 1. If the signature of a transaction is `(CHAIN_ID, 0, 0)` (ie. `r = s = 0`, `v = CHAIN_ID`), then treat it as valid and set the sender address to `NULL_SENDER` |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
pirapira
Apr 25, 2017
Member
How? I'm not seeing anything wrongly formatted https://github.com/ethereum/EIPs/blob/4120d2180a1cf62151066d9fb16742867315d649/EIPS/abstraction.md#specification
|
|
||
| If `block.number >= METROPOLIS_FORK_BLKNUM`, then: | ||
| 1. If the signature of a transaction is `(CHAIN_ID, 0, 0)` (ie. `r = s = 0`, `v = CHAIN_ID`), then treat it as valid and set the sender address to `NULL_SENDER` | ||
| 2. Set the address of any contract created through a creation transaction to equal `sha3(NULL_SENDER + sha3(init code)) % 2**160`, where `+` represents concatenation, replacing the earlier address formula of `sha3(rlp.encode([sender, nonce]))` |
This comment has been minimized.
This comment has been minimized.
chriseth
Mar 21, 2017
Contributor
I assume this only applies to transactions with r = s = 0. Is that correct? So we have:
If such a transaction has a to value of zero (i.e is a creation transaction), set the address of the created contract to sha3(NULL_SENDER + sha3(txdata)) % 2**160, .... If an account at that address already exists (TODO correctly specify existence), the transaction is considered invalid.
This comment has been minimized.
This comment has been minimized.
pirapira
Mar 21, 2017
Member
- I understood that this applies to all contract creations.
- I think we should keep allowing creating contracts on existing accounts (e.g. with positive balance).
This comment has been minimized.
This comment has been minimized.
|
Do we want to lower the gas costs for such transactions (i.e. the transaction itself) since ecrecover does not have to be called to check the signature. |
This comment has been minimized.
This comment has been minimized.
|
So there are two paths to resolving this:
EIP 86 transactions can create new contracts if the "to" field is empty. This looks ugly in either case, as we have useless vestigial fields that hang around like an appendix, but IMO we should make a future HF which modifies TX formats more substantially and makes them more logical, for example including a proper field for the network ID and the transaction version number, and past the HF making old-style transactions no longer valid. IMO we have to do this eventually, as if we do not, then every time we make new tx formats or change tx formats we incur more and more technical debt. If we really feel daring, I can make an EIP for doing this now, so we can just not do EIP 86 at all. |
This comment has been minimized.
This comment has been minimized.
|
@winsvega miners can, for example, whitelist contracts that pay the current miner (by calling |
This comment has been minimized.
This comment has been minimized.
|
if it has gasprice of 0 and can create contracts would not it mean that such transaction could spam contracts? lets define YP rules for zero sig transactions so we could define the concrete tests for that |
This comment has been minimized.
This comment has been minimized.
|
It is not the gas price that limits the spam, it is the block gas limit. |
This comment has been minimized.
This comment has been minimized.
|
So anyone will be able to create contracts for free? |
This comment has been minimized.
This comment has been minimized.
|
@winsvega That's already the case before this EIP if you mine a block that includes your transactions with gas price being zero. |
This comment has been minimized.
This comment has been minimized.
|
right. but miniers would most likely refuse such transactions. |
This comment has been minimized.
This comment has been minimized.
|
@winsvega it is the same thing. If the zero-sig transaction does not send money to the miner, miners will likely refuse to include it. |
This comment has been minimized.
This comment has been minimized.
|
I am confused. so the gasPrice needs to be > 0 ? |
This comment has been minimized.
This comment has been minimized.
|
zero-sig transactions send money to the miner as part of their execution and not as part of the surrounding framework, so gas price should be zero. |
This comment has been minimized.
This comment has been minimized.
|
@winsvega When a miner is constructing a block, the miner can freely exclude transactions. One strategy is doing nothing special about EIP86 transactions (then For somebody sending an EIP86 transaction, it does not make much sense to set When this kind of coordination takes place between the transaction senders and the miners, we will see EIP86 transactions in blocks. This coordination between the senders and the miners is not part of the protocol. Even local agreements can exist. |
This comment has been minimized.
This comment has been minimized.
|
so the actual payment for the transaction will be done by a contract that decode data of the zero sig transaction, is that right? we still have the nonce problem that Andrei mentioned if we do not implement nonce = 0 rule.
or like we already did we could just drop nonce checking for zero sig transactions. what I mean by YP rules is that we have to define for zero sig transaction
|
This comment has been minimized.
This comment has been minimized.
|
1 and 2: I think Vitalik's two options both work (but the first option with never-increasing nonce) 3 Disallowing the value transfer would enable an undesired course of events. The null sender receives some large amount by accident, but nobody can send it anywhere, so everyone starts using the null sender's wealth to pay for gas. That's undesired. I prefer allowing value transfer from the null sender because the null sender's wealth will be there only for a short period. I think the point of this EIP is to specify less and less in the protocol and let the transaction senders and the miners decide. |
This comment has been minimized.
This comment has been minimized.
|
Here's my EIP for fully "cleaning house" and making new tx types. It's much more work, but in the long run IMO something like this will be necessary. |
This comment has been minimized.
This comment has been minimized.
tomusdrw
commented
Mar 23, 2017
•
|
What if the transaction goes OOG or uses EDIT: |
jimpo
reviewed
Sep 20, 2017
| If `block.number >= METROPOLIS_FORK_BLKNUM`, then: | ||
| 1. If the signature of a transaction is `(CHAIN_ID, 0, 0)` (ie. `r = s = 0`, `v = CHAIN_ID`), then treat it as valid and set the sender address to `NULL_SENDER` | ||
| 2. Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account NULL_SENDER. | ||
| 3. Create a new opcode at `0xfb`, `CREATE2`, with 4 stack arguments (value, salt, mem_start, mem_size) which sets the creation address to `sha3(sender + salt + sha3(init code)) % 2**160`, where `salt` is always represented as a 32-byte value. |
This comment has been minimized.
This comment has been minimized.
MicahZoltu
referenced this pull request
Sep 28, 2017
Closed
Design Security: Do not constrain users to non-contracts or freeze tokens for extended periods of time. #9
jamesray1
reviewed
Oct 6, 2017
| tx_nonce = ~calldataload(96) | ||
| tx_to = ~calldataload(128) | ||
| tx_value = ~calldataload(160) | ||
| tx_gasprice = ~calldataload(192) |
This comment has been minimized.
This comment has been minimized.
jamesray1
Oct 6, 2017
•
Contributor
There's no gas limit included like in the yellow paper. What's the rationale for that? Rather the gas limit is fixed below as 50000, which doesn't seem right given we vary the gas limit.
Another thing that confuses me is that the yellow paper instructions don't look like they take variable arguments, e.g. all instructions take an operand starting from the first item then if there are more items consecutively going up the items in the stack, memory, or other data. But this code uses e.g. sload(-1), and mstore(signing data). So it might be helpful to revise the yellow paper to point out that the opcodes can take variable arguments (provided they are within the data that is called), not just, for example, having to work first with the first item in storage or memory.
From the above screenshot it looks like calldataload just loads the first input data item to the first word in memory. But given that they are known as opcodes, thus implying operators, it makes sense that they take at least one or more operands.
This comment has been minimized.
This comment has been minimized.
holiman
Oct 6, 2017
Contributor
In the YP, on the image above, the CALLDATALOAD 1 1 : that means it pops one off the stack and pushes one off the stack. So it takes one operand/parameter and returns one.
The CALLDATALOAD just places the data on the stack, does nothing with memory. The CALLDATACOPY is the one to use for getting it into memory.
This comment has been minimized.
This comment has been minimized.
jamesray1
Oct 6, 2017
•
Contributor
OK, my mistake, obviously I didn't read it carefully, didn't check and think carefully about what I was writing was valid, and maybe was getting it mixed up with other opcodes that do involve memory. Thanks for clarifying.
jamesray1
reviewed
Oct 6, 2017
|
|
||
| ```python | ||
| # Get signature from tx data | ||
| sig_v = ~calldataload(0) |
This comment has been minimized.
This comment has been minimized.
jamesray1
Oct 6, 2017
Contributor
When I first read this with the ~ I found it confusing as it is used to invert all the bits in Python, which is equivalent to ~x = -x - 1.
jamesray1
reviewed
Oct 6, 2017
| ~calldataload(signing_data + 32, 96, ~calldatasize() - 96) | ||
| signing_hash = sha3(signing_data:str) | ||
| # Perform usual checks | ||
| prev_nonce = ~sload(-1) |
This comment has been minimized.
This comment has been minimized.
jamesray1
Oct 6, 2017
•
Contributor
~sload(-1) reads the last word in storage, which is presumably where the nonce is stored. I'm not sure where this is defined in the current version of the yellow paper. The prev_nonce would be the nonce of the sender account. In the yellow paper the account nonce is the first item in the state.
| Word # in stack/ stack item no. | initial stack | bytes |
|---|---|---|
| 1 | v | 0 |
| 2 | r | 32 |
| 3 | s | 64 |
| 4 | nonce | 96 |
| 5 | to | 128 |
| 6 | value | 160 |
| 7 | gasprice | 192 |
| 8 | data | 224 |
Addresses are 160 bits, but above it sets aside 32 bytes, but I guess it does that for efficiency with extracting it, rather than performing bitwise operation on a word, where other data is stored in the word.
This comment has been minimized.
This comment has been minimized.
holiman
Oct 6, 2017
Contributor
In the context of this EIP, the nonce is not the same nonce as the YP talks about. The EVM has a 'native' nonce per account, whereas in the context of this EIP, the nonce is counter within the state.
This comment has been minimized.
This comment has been minimized.
jamesray1
Oct 6, 2017
Contributor
Ah OK, it's like the sequence number that Vitalik referred to in EIP 101. #28
jamesray1
reviewed
Oct 6, 2017
| tx_data = string(~calldatasize() - 224) | ||
| ~calldataload(tx_data, 224, ~calldatasize()) | ||
| # Get signing hash | ||
| signing_data = string(~calldatasize() - 64) |
This comment has been minimized.
This comment has been minimized.
jamesray1
Oct 6, 2017
•
Contributor
Just trying to understand this line with why it uses - 64. Signing data is passed into SHA3 below, which takes an arbitrary byte array loaded from a tuple of the first item in memory to the sum of the first and second items, minus 1, as follows:
~calldatasize() returns in this case a byte array of minimum length 224 bytes, plus the arbitrary length input data field.
So for signing the data I presume that there are two words that aren't needed from the input data fields, although it's not clear to me immediately from reading what they are. The purpose is to abstract out the security model, so v, r, and s then don't seem to be needed; i.e. leave the security model to be defined externally.
However, ~calldatasize just returns the size of the input data, rather than copying it. So this line doesn't seem to make sense when the variable it evaluates to, signing_data, is passed into SHA3. You could have two input data that are the same size with different data that when passed into SHA3 will return the same hash.
So wouldn't it make more sense to copy the input data, except for v, r and s (presuming that these are the three fields, rather than two as specified, that don't need to be copied) into signing_data?
jamesray1
reviewed
Oct 6, 2017
| prev_nonce = ~sload(-1) | ||
| assert tx_nonce == prev_nonce + 1 | ||
| assert self.balance >= tx_value + tx_gasprice * tx.startgas | ||
| assert ~ecrecover(signing_hash, sig_v, sig_r, sig_s) == <pubkey hash here> |
This comment has been minimized.
This comment has been minimized.
jamesray1
Oct 6, 2017
•
Contributor
Should we also abstract the pubkey verification? It could even be abstracted internally, by having a number of precompile contracts where you can call one with an opcode sigVerify. The opcode could even have a default option (where you can call it without any argument). However, I guess that there is not as much benefit to abstract the signature verification algorithm compared to abstracting the signature generation algorithm.
This comment has been minimized.
This comment has been minimized.
|
Should we include EIP 86 in the title? |
catageek
referenced this pull request
Nov 28, 2017
Open
Add web3.eth.encrypt method for RPC & web3 #130
This comment has been minimized.
This comment has been minimized.
|
Discussion of account abstraction proposals has continued here https://ethresear.ch/t/tradeoffs-in-account-abstraction-proposals/263 |
MitchK
referenced this pull request
Jan 5, 2018
Open
Idea: Making transaction nonce checking more flexible #822
spalladino
referenced this pull request
Jan 31, 2018
Open
Scheduler feature idea: gas-free token transactions #12
This comment has been minimized.
This comment has been minimized.
|
This EIP is mentioned as an example EIP in EIP-1. Can we merge it as a draft? @vbuterin, can you add the copyright assignment clause, please? |
Arachnid
added
the
needs-merge
label
Mar 23, 2018
Arachnid
and others
added some commits
Mar 25, 2018
Arachnid
approved these changes
Mar 27, 2018
Arachnid
merged commit 64f6248
into
master
Mar 27, 2018
Arachnid
deleted the
vbuterin-patch-3
branch
Mar 27, 2018
This comment has been minimized.
This comment has been minimized.
|
This is a courtesy notice to let you know that the format for EIPs has been modified slightly. If you want your draft merged, you will need to make some small changes to how your EIP is formatted:
If your PR is editing an existing EIP rather than creating a new one, this has already been done for you, and you need only rebase your PR. In addition, a continuous build has been setup, which will check your PR against the rules for EIP formatting automatically once you update your PR. This build ensures all required headers are present, as well as performing a number of other checks. Please rebase your PR against the latest master, and edit your PR to use the above format for frontmatter. For convenience, here's a sample header you can copy and adapt:
|


vbuterin commentedFeb 10, 2017
Implements a set of changes that serve the combined purpose of "abstracting out" signature verification and nonce checking, allowing users to create "account contracts" that perform any desired signature/nonce checks instead of using the mechanism that is currently hard-coded into transaction processing.