-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create blockhash_refactoring.md #210
Changes from 9 commits
cff11da
600b28f
cebb3e2
9df24a3
ea4930e
14e8a35
f271d17
0fee545
2f8d0f5
4df6564
bce69eb
028099f
2243abb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
### Preamble | ||
|
||
EIP: <to be assigned> | ||
Title: Blockhash refactoring | ||
Author: Vitalik Buterin | ||
Type: Standard Track | ||
Category: Core | ||
Status: Draft | ||
Created: 2017-02-10 | ||
|
||
### Summary | ||
|
||
Stores blockhashes in the state, reducing the protocol complexity and the need for client implementation complexity in order to process the BLOCKHASH opcode. Also extends the range of how far back blockhash checking can go, with the side effect of creating direct links between blocks with very distant block numbers, facilitating much more efficient initial light client syncing. | ||
|
||
### Parameters | ||
|
||
* `METROPOLIS_FORK_BLKNUM`: TBD | ||
* `SUPER_USER`: 2**160 - 2 | ||
* `BLOCKHASH_CONTRACT_ADDR`: 0xf0 (ie. 240) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can this be a continuous address or is there a special reason for using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I asked about this before. The answer was this is not regular precompiled contract, because you deploy real bytecode. I think it make sense, because from EVM you don't need additional check "if precompiled" to use this contract. However, I'd use address of 0x100 to leave the lower byte for precompiled contracts only. |
||
* `BLOCKHASH_CONTRACT_CODE`: see below | ||
|
||
### Specification | ||
|
||
If `block.number == METROPOLIS_FORK_BLKNUM`, then when processing the block, before processing any transactions set the code of BLOCKHASH_CONTRACT_ADDR to BLOCKHASH_CONTRACT_CODE. | ||
|
||
If `block.number >= METROPOLIS_FORK_BLKNUM`, then when processing a block, before processing any transactions execute a call with the parameters: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should the gas consumption here be counted in the gas usage of the block? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this call increment the nonce? I feel ambiguous ethereum/aleth#4066 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the second last allcoredev call, I heard this should not increment the nonce. |
||
|
||
* `SENDER`: SUPER_USER | ||
* `GAS`: 1000000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the gas price and the nonce of this call transaction? |
||
* `TO`: BLOCKHASH_CONTRACT_ADDR | ||
* `VALUE`: 0 | ||
* `DATA`: <32 bytes corresponding to the block's prevhash> | ||
|
||
If `block.number >= METROPOLIS_FORK_BLKNUM + 256`, then the BLOCKHASH opcode instead returns the result of executing a call (NOT a transaction) with the parameters: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This part of the text needs to be updated. BLOCKHASH opcode should call the contract only about the most recent 256 blocks (#210 (comment)). |
||
|
||
* `SENDER`: <account from which the opcode was called> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Github Markdown renderer doesn't show this text in angle brackets for some reason |
||
* `GAS`: 1000000 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What happens when |
||
* `TO`: BLOCKHASH_CONTRACT_ADDR | ||
* `VALUE`: 0 | ||
* `DATA`: 32 byte zero-byte-leftpadded integer representing the stack argument with which the opcode was called | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
Also, for blocks where `block.number >= METROPOLIS_FORK_BLKNUM`, the gas cost is increased from 20 to 800 to reflect the higher costs of processing the algorithm in the contract code. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we charge the amount the contract will use. For this case, using a serpent contract the cost would be 700 of a call + ~400. The dominant cost is the CALL (700) and SLOAD (200), the rest should go down below 100 if optimized. So the final cost should not be higher than 1000. |
||
|
||
### BLOCKHASH_CONTRACT_CODE | ||
|
||
The Serpent source code is: | ||
|
||
```python | ||
with offset = 0: | ||
if msg.sender == 0xfffffffffffffffffffffffffffffffffffffffe: | ||
with bn = block.number - 1: | ||
while 1: | ||
~sstore(offset + ~mod(bn, 256), ~calldataload(0)) | ||
if ~mod(bn, 256): | ||
~stop() | ||
bn = ~div(bn, 256) | ||
offset += 256 | ||
elif ~calldataload(0) < block.number: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Still a bug there, this is signed comparison. |
||
with tbn = ~calldataload(0): | ||
with dist_minus_one = block.number - tbn - 1: | ||
while dist_minus_one >= 256 && ~mod(tbn, 256) == 0: | ||
offset += 256 | ||
tbn = ~div(tbn, 256) | ||
dist_minus_one = ~div(dist_minus_one, 256) | ||
if dist_minus_one >= 256: | ||
return(0) | ||
return(~sload(offset + ~mod(tbn, 256))) | ||
else: | ||
return(0) | ||
``` | ||
|
||
The EVM init code is: | ||
|
||
``` | ||
0x6100e28061000e6000396100f056600073fffffffffffffffffffffffffffffffffffffffe33141561005957600143035b60011561005357600035610100820683015561010081061561004057005b6101008104905061010082019150610022565b506100e0565b4360003512156100d4576000356001814303035b61010081121515610085576000610100830614610088565b60005b156100a75761010083019250610100820491506101008104905061006d565b610100811215156100bd57600060a052602060a0f35b610100820683015460c052602060c0f350506100df565b600060e052602060e0f35b5b505b6000f3 | ||
``` | ||
|
||
The EVM bytecode that the contract code should be set to is: | ||
|
||
``` | ||
0x600073fffffffffffffffffffffffffffffffffffffffe33141561005957600143035b60011561005357600035610100820683015561010081061561004057005b6101008104905061010082019150610022565b506100e0565b4360003512156100d4576000356001814303035b61010081121515610085576000610100830614610088565b60005b156100a75761010083019250610100820491506101008104905061006d565b610100811215156100bd57600060a052602060a0f35b610100820683015460c052602060c0f350506100df565b600060e052602060e0f35b5b50 | ||
``` | ||
|
||
### Rationale | ||
|
||
This removes the need for implementaitons to have an explicit way to look into historical block hashes, simplifying the protocol definition and removing a large component of the "implied state" (information that is technically state but is not part of the state tree) and thereby making the protocol more "pure". Additionally, it allows blocks to directly point to blocks far behind them, which enables extremely efficient and secure light client protocols. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, this should say
BYZANTIUM_FORK_BLKNUM
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, should say
CONSTANTINOPLE_FORK_BLNUM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, it has changed.