Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

EIP98 - Remove state root hash from transaction receipt #4035

Merged
merged 7 commits into from
May 4, 2017
Merged

Conversation

gumb0
Copy link
Member

@gumb0 gumb0 commented Apr 11, 2017

Implementing Option 1 of EIP - removing state root hash from Receipt RLP

#3613
ethereum/EIPs#98

  • Save zero hash instead of root state hash
  • Remove root state hash instead of saving zero hash
  • Implement debug RPC methods (trace, storageRangeAt) without relying on state root in receipt
  • Fix tests relying on state root in receipts

@gumb0 gumb0 changed the title EIP98 = EIP98 - Remove state root hash from transaction receipt Apr 11, 2017
@gumb0 gumb0 added this to the Metropolis milestone Apr 11, 2017
@gumb0 gumb0 force-pushed the eip98 branch 2 times, most recently from 414a057 to a693d63 Compare April 11, 2017 14:29
@codecov-io
Copy link

codecov-io commented Apr 11, 2017

Codecov Report

Merging #4035 into develop will decrease coverage by 0.02%.
The diff coverage is 51.72%.

@@             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
Impacted Files Coverage Δ
libethereum/State.h 94.28% <ø> (ø) ⬆️
libethereum/Block.h 60.86% <ø> (ø) ⬆️
libethereum/Executive.h 66.66% <ø> (ø) ⬆️
libethereum/Client.cpp 24.55% <ø> (+0.47%) ⬆️
libethereum/Client.h 68.42% <ø> (ø) ⬆️
libethereum/Block.cpp 83.76% <0%> (+0.34%) ⬆️
test/unittests/libethereum/Block.cpp 69.71% <0%> (ø) ⬆️
libethereum/Executive.cpp 57.43% <0%> (ø) ⬆️
test/tools/libtesteth/BlockChainHelper.cpp 76.6% <100%> (-0.46%) ⬇️
libethereum/TransactionReceipt.h 27.27% <100%> (+7.27%) ⬆️
... and 11 more

@gumb0 gumb0 force-pushed the eip98 branch 3 times, most recently from 87c7661 to 29df14f Compare April 20, 2017 08:59
@gumb0 gumb0 force-pushed the eip98 branch 2 times, most recently from 4f9d148 to 83c5f61 Compare April 26, 2017 10:50
…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.
@@ -775,28 +775,6 @@ Block Client::block(h256 const& _blockHash, PopulationStatistics* o_stats) const
}
}

State Client::state(unsigned _txi, h256 const& _blockHash) const
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These were not used

@@ -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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"before after" reads strange.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed

namespace
{

State& initIntermediateState(State& _s, Block const& _block, unsigned _txIndex, BlockChain const& _bc)
Copy link
Contributor

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?

@@ -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):
Copy link
Contributor

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)
{
Copy link
Contributor

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?

Copy link
Member Author

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

Copy link
Member

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)
Copy link
Contributor

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment

State state = block.fromPending(i);
State state(block.state());
u256 const rootHash = block.stateRootBeforeTx(_txIndex);
if (rootHash)
Copy link
Contributor

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 :-)

Copy link
Member Author

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

@gumb0 gumb0 force-pushed the eip98 branch 2 times, most recently from aa1dce9 to ea91ddd Compare May 3, 2017 09:24
else
{
o_s.setRoot(_block.stateRootBeforeTx(0));
o_s.executeBlockTransactions(_block, _txIndex, _bc.lastHashes(_block.info().parentHash()), *_bc.sealEngine());
Copy link
Contributor

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?

Copy link
Member

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.

Copy link
Member Author

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

@@ -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):
Copy link
Member

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.

Copy link
Member Author

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)
{
Copy link
Member

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.

return make_pair(res, receipt);
}

void State::executeTransaction(Executive& _e, Transaction const& _t, OnOpFunc const& _onOp)
Copy link
Member

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?

Copy link
Member Author

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?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If possible, yes.

Copy link
Member Author

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());
Copy link
Member

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.

@@ -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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename to stateRootBefore?

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);
Copy link
Member

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.

Copy link
Member Author

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

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Member Author

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

@chfast
Copy link
Member

chfast commented May 4, 2017

Great job, as usual!

@pirapira pirapira deleted the eip98 branch May 4, 2017 19:48
@pirapira
Copy link
Member

pirapira commented May 4, 2017

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants