-
Notifications
You must be signed in to change notification settings - Fork 2.2k
EIP98 - Remove state root hash from transaction receipt #4035
Conversation
414a057
to
a693d63
Compare
Codecov Report
@@ Coverage Diff @@
## develop #4035 +/- ##
===========================================
- Coverage 65.89% 65.86% -0.03%
===========================================
Files 308 308
Lines 22876 22897 +21
===========================================
+ Hits 15075 15082 +7
- Misses 7801 7815 +14
|
87c7661
to
29df14f
Compare
4f9d148
to
83c5f61
Compare
…eAt, admin_eth_vmTrace RPC methods work even when intermediate state root hash is not available in receipts (this going to be the case after Metropolis). In this case execute all previous transactions in the block to get the intermediate state.
…it with zero hash
@@ -775,28 +775,6 @@ Block Client::block(h256 const& _blockHash, PopulationStatistics* o_stats) const | |||
} | |||
} | |||
|
|||
State Client::state(unsigned _txi, h256 const& _blockHash) const |
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.
These were not used
libethereum/Block.h
Outdated
@@ -202,10 +202,11 @@ class Block | |||
/// Get the bloom filter of a particular transaction that happened in the block. | |||
LogBloom const& logBloom(unsigned _i) const { return receipt(_i).bloom(); } | |||
|
|||
/// Get the State immediately after the given number of pending transactions have been applied. | |||
/// Get the State root hash immediately before after all previous transactions before transaction @a _i have been applied. |
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.
"before after" reads strange.
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.
Thanks, fixed
libethereum/Executive.cpp
Outdated
namespace | ||
{ | ||
|
||
State& initIntermediateState(State& _s, Block const& _block, unsigned _txIndex, BlockChain const& _bc) |
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.
Can you name this o_s
to signal that it will be modified?
libethereum/Executive.cpp
Outdated
@@ -158,7 +177,7 @@ Executive::Executive(Block& _s, LastHashes const& _lh, unsigned _level): | |||
} | |||
|
|||
Executive::Executive(State& _s, Block const& _block, unsigned _txIndex, BlockChain const& _bc, unsigned _level): |
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.
Also here, this should be named o_s
- but I see this is not part of the PR.
{ | ||
u256 gasUsed = 0; | ||
for (unsigned i = 0; i < _txCount; ++i) | ||
{ |
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.
The whole for-loop body should be a helper function also used elsewhere - or are the cases there more complicated?
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.
Yeah, the other case - State::execute
needs to get gas, logs, and return value from Executive
...
But I've moved the common part (initialize-execute-go-finalize) to separate helper method
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.
I wanted to move it to a separate function for a long time.
@@ -44,7 +54,13 @@ TransactionReceipt::TransactionReceipt(h256 _root, u256 _gasUsed, LogEntries con | |||
|
|||
void TransactionReceipt::streamRLP(RLPStream& _s) const | |||
{ | |||
_s.appendList(4) << m_stateRoot << m_gasUsed << m_bloom; | |||
if (m_stateRoot) |
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.
Can you document this is the header? Perhaps best to put that into the class description.
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.
Added a comment
libweb3jsonrpc/Debug.cpp
Outdated
State state = block.fromPending(i); | ||
State state(block.state()); | ||
u256 const rootHash = block.stateRootBeforeTx(_txIndex); | ||
if (rootHash) |
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.
I have seen this block of code before :-)
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.
Extracted this to common function dev::eth::createIntermediateState
in State.cpp
aa1dce9
to
ea91ddd
Compare
else | ||
{ | ||
o_s.setRoot(_block.stateRootBeforeTx(0)); | ||
o_s.executeBlockTransactions(_block, _txIndex, _bc.lastHashes(_block.info().parentHash()), *_bc.sealEngine()); |
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.
Do we need a check for dereferencing sealEngine here?
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.
I don't think so. I've spot it before, it should not be a pointer type.
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.
Yeah, it's always non-null in practice
libethereum/Executive.cpp
Outdated
@@ -157,8 +157,8 @@ Executive::Executive(Block& _s, LastHashes const& _lh, unsigned _level): | |||
{ | |||
} | |||
|
|||
Executive::Executive(State& _s, Block const& _block, unsigned _txIndex, BlockChain const& _bc, unsigned _level): | |||
m_s(_s = _block.fromPending(_txIndex)), | |||
Executive::Executive(State& o_s, Block const& _block, unsigned _txIndex, BlockChain const& _bc, unsigned _level): |
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.
I guess the convention is io_s
, however I'm not big fun of it.
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.
In some sense it's not really used as input, it is assigned immediately another State in createIntermediateState
. On the other hand it initializes m_state
member... Ok, I think I'll rename it
{ | ||
u256 gasUsed = 0; | ||
for (unsigned i = 0; i < _txCount; ++i) | ||
{ |
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.
I wanted to move it to a separate function for a long time.
libethereum/State.cpp
Outdated
return make_pair(res, receipt); | ||
} | ||
|
||
void State::executeTransaction(Executive& _e, Transaction const& _t, OnOpFunc const& _onOp) |
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.
It does not depend on State, can we make it a free function somewhere in Executive.h?
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.
Maybe better internal in Executive.cpp then?
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.
If possible, yes.
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.
I meant here in State.cpp, sorry, moved it now.
else | ||
{ | ||
o_s.setRoot(_block.stateRootBeforeTx(0)); | ||
o_s.executeBlockTransactions(_block, _txIndex, _bc.lastHashes(_block.info().parentHash()), *_bc.sealEngine()); |
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.
I don't think so. I've spot it before, it should not be a pointer type.
test/unittests/libethereum/Block.cpp
Outdated
@@ -59,7 +59,7 @@ BOOST_AUTO_TEST_CASE(bStates) | |||
OverlayDB const& genesisDB = genesisBlock.state().db(); | |||
BlockChain const& blockchain = testBlockchain.interface(); | |||
|
|||
State stateBofore = testBlockchain.topBlock().state(); | |||
h256 stateBefore = testBlockchain.topBlock().state().rootHash(); |
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.
Rename to stateRootBefore
?
test/unittests/libethereum/Block.cpp
Outdated
State stateAfterInsert = block2.fromPending(0); //get the state of blockchain on previous block | ||
BOOST_REQUIRE(ImportTest::compareStates(stateBofore, stateAfterInsert) == 0); | ||
h256 stateAfterInsert = block2.stateRootBeforeTx(0); //get the state of blockchain on previous block | ||
BOOST_REQUIRE_EQUAL(stateBefore, stateAfterInsert); |
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.
Just a notice, BOOST_REQUIRE
is overused in tests. I think BOOST_CHECK
is usually better.
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.
I'd say finer-grained tests with a single BOOST_REQUIRE in each one is better than large tests with a series of BOOST_CHECKs
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.
Always use CHECK if it is possible to continue the test in case it fails, and only REQUIRE if it would not make sense to continue the test.
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.
I think @gumb0 understand the difference. His point is that in case of failure in CHECK boost will output a long list of errors instead of single one per test.
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.
Yeah, here it doesn't make sense to proceed with other checks when the first check fails, they are dependent
Great job, as usual! |
I was asked to review this, and I intend to read the Metropolis changes in all major clients. I added this to my pending list with priority H and deadline June 15. |
Implementing Option 1 of EIP - removing state root hash from Receipt RLP
#3613
ethereum/EIPs#98