 |
Ethereum
PoC-8
The C++ Implementation of Ethereum
|
Go to the documentation of this file.
25 #include <boost/filesystem.hpp>
26 #include <boost/timer.hpp>
41 namespace fs = boost::filesystem;
43 #define ETH_TIMED_ENACTMENTS 0
45 static const unsigned c_maxSyncTransactions = 1024;
53 h256s precedingHashes(
h256 const& )
const override {
return {}; }
54 void clear()
override {}
66 m_previousBlock.
clear();
67 m_currentBlock.
clear();
78 m_previousBlock.
clear();
79 m_currentBlock.
clear();
85 m_transactions(_s.m_transactions),
86 m_receipts(_s.m_receipts),
87 m_transactionSet(_s.m_transactionSet),
88 m_precommit(_s.m_state),
89 m_previousBlock(_s.m_previousBlock),
90 m_currentBlock(_s.m_currentBlock),
91 m_currentBytes(_s.m_currentBytes),
92 m_author(_s.m_author),
93 m_sealEngine(_s.m_sealEngine)
95 m_committedToSeal =
false;
103 m_state = _s.m_state;
104 m_transactions = _s.m_transactions;
105 m_receipts = _s.m_receipts;
106 m_transactionSet = _s.m_transactionSet;
107 m_previousBlock = _s.m_previousBlock;
108 m_currentBlock = _s.m_currentBlock;
109 m_currentBytes = _s.m_currentBytes;
110 m_author = _s.m_author;
111 m_sealEngine = _s.m_sealEngine;
113 m_precommit = m_state;
114 m_committedToSeal =
false;
120 m_transactions.clear();
122 m_transactionSet.clear();
126 m_currentBytes.clear();
132 m_precommit = m_state;
133 m_committedToSeal =
false;
135 performIrregularModifications();
136 updateBlockhashContract();
142 BOOST_THROW_EXCEPTION(ChainOperationWithUnknownBlockChain());
165 cwarn <<
"Invalid block given for state population: " << _h;
169 auto b = _bc.
block(_h);
217 auto b = _bc.
block(_block);
224 cerr <<
"ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl;
225 cerr << diagnostic_information(_e) << endl;
227 catch (std::exception
const& _e)
230 cerr <<
"ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl;
231 cerr << _e.what() << endl;
235 if (bi == m_currentBlock)
239 m_previousBlock = m_currentBlock;
243 else if (bi == m_previousBlock)
256 cwarn <<
"Unable to sync to" << bi.
hash() <<
"; state root" << bi.
stateRoot() <<
"not found in database.";
257 cwarn <<
"Database corrupt: contains block without stateRoot:" << bi;
258 cwarn <<
"Try rescuing the database by running: eth --rescue";
259 BOOST_THROW_EXCEPTION(InvalidStateRoot() <<
errinfo_target(bi.stateRoot()));
261 m_previousBlock = bi;
272 std::vector<h256> chain;
275 chain.push_back(bi.
hash());
279 m_previousBlock = bi;
285 for (
auto it = chain.rbegin(); it != chain.rend(); ++it)
287 auto b = _bc.
block(*it);
295 cerr <<
"ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl;
296 cerr << boost::current_exception_diagnostic_information() << endl;
310 BOOST_THROW_EXCEPTION(InvalidOperationOnSealedBlock());
315 pair<TransactionReceipts, bool> ret;
318 ret.second = (transactions.size() == c_maxSyncTransactions);
322 auto deadline = chrono::steady_clock::now() + chrono::milliseconds(msTimeout);
324 for (
int goodTxs = max(0, (
int)transactions.size() - 1); goodTxs < (
int)transactions.size();)
327 for (
auto const& t : transactions)
328 if (!m_transactionSet.count(t.sha3()))
332 if (t.gasPrice() >= _gp.
ask(*
this))
336 ret.first.push_back(m_receipts.back());
340 else if (t.gasPrice() < _gp.
ask(*
this) * 9 / 10)
343 << t.sha3() <<
" Dropping El Cheapo transaction (<90% of ask price)";
349 bigint const& req = *boost::get_error_info<errinfo_required>(in);
350 bigint const& got = *boost::get_error_info<errinfo_got>(in);
355 LOG(m_logger) << t.sha3() <<
" Dropping old transaction (nonce too low)";
358 else if (got > req + _tq.
waiting(t.sender()))
362 << t.sha3() <<
" Dropping new transaction (too many nonces ahead)";
370 bigint const& got = *boost::get_error_info<errinfo_got>(e);
371 if (got > m_currentBlock.
gasLimit())
375 <<
" Dropping over-gassy transaction (gas > block's gas limit)";
377 <<
"got: " << got <<
" required: " << m_currentBlock.
gasLimit();
382 LOG(m_logger) << t.sha3()
383 <<
" Temporarily no gas left in current block (txs gas > "
384 "block's gas limit)";
394 LOG(m_logger) << t.sha3() <<
" Dropping invalid transaction: "
395 << diagnostic_information(_e);
398 catch (std::exception
const&)
402 cwarn << t.sha3() <<
"Transaction caused low-level exception :(";
405 if (chrono::steady_clock::now() > deadline)
418 #if ETH_TIMED_ENACTMENTS
420 double populateVerify;
421 double populateGrand;
430 #if ETH_TIMED_ENACTMENTS
439 #if ETH_TIMED_ENACTMENTS
447 #if ETH_TIMED_ENACTMENTS
452 m_previousBlock = biParent;
453 auto ret = enact(_block, _bc);
455 #if ETH_TIMED_ENACTMENTS
457 if (populateVerify + populateGrand + syncReset + enactment > 0.5)
458 LOG(m_logger) <<
"popVer/popGrand/syncReset/enactment = " << populateVerify <<
" / "
459 << populateGrand <<
" / " << syncReset <<
" / " << enactment;
476 BOOST_THROW_EXCEPTION(InvalidParentHash());
480 m_currentBlock = _block.
info;
487 vector<bytes> receipts;
508 m_receipts.back().streamRLP(receiptRLP);
509 receipts.push_back(receiptRLP.
out());
517 if (receiptsRoot != m_currentBlock.receiptsRoot())
519 InvalidReceiptsStateRoot ex;
523 BOOST_THROW_EXCEPTION(ex);
531 BOOST_THROW_EXCEPTION(ex);
538 if (
rlp[2].itemCount() > 2)
543 BOOST_THROW_EXCEPTION(ex);
546 vector<BlockHeader> rewarded;
549 excluded = _bc.allKinFrom(m_currentBlock.parentHash(), 6);
550 excluded.insert(m_currentBlock.hash());
554 for (auto const& i:
rlp[2])
558 auto h =
sha3(i.data());
559 if (excluded.count(h))
565 BOOST_THROW_EXCEPTION(ex);
573 if (!_bc.
isKnown(uncle.parentHash()))
591 BOOST_THROW_EXCEPTION(ex);
598 BOOST_THROW_EXCEPTION(ex);
610 for (
unsigned i = 1; i < depth; expectedUncleParent = _bc.
details(expectedUncleParent).parent, ++i) {}
611 if (expectedUncleParent != uncleParent.
hash())
613 UncleParentNotInChain ex;
616 BOOST_THROW_EXCEPTION(ex);
620 rewarded.push_back(uncle);
632 applyRewards(rewarded, _bc.sealEngine()->blockReward(m_currentBlock.number()));
635 bool removeEmptyAccounts = m_currentBlock.number() >= _bc.chainParams().EIP158ForkBlock;
637 m_state.
commit(removeEmptyAccounts ?
State::CommitBehaviour::RemoveEmptyAccounts :
State::CommitBehaviour::KeepEmptyAccounts);
640 if (m_currentBlock.stateRoot() != m_previousBlock.stateRoot() && m_currentBlock.stateRoot() !=
rootHash())
647 if (m_currentBlock.
gasUsed() != gasUsed())
660 BOOST_THROW_EXCEPTION(InvalidOperationOnSealedBlock());
666 std::pair<ExecutionResult, TransactionReceipt> resultReceipt = m_state.
execute(
EnvInfo(
info(), _lh, gasUsed()), *m_sealEngine, _t, _p, _onOp);
671 m_transactions.push_back(_t);
672 m_receipts.push_back(resultReceipt.second);
673 m_transactionSet.insert(_t.
sha3());
676 return resultReceipt.first;
679 void Block::applyRewards(vector<BlockHeader>
const& _uncleBlockHeaders,
u256 const& _blockReward)
681 u256 r = _blockReward;
682 for (
auto const& i: _uncleBlockHeaders)
684 m_state.
addBalance(i.author(), _blockReward * (8 + i.number() - m_currentBlock.
number()) / 8);
685 r += _blockReward / 32;
690 void Block::performIrregularModifications()
693 if (daoHardfork != 0 &&
info().number() == daoHardfork)
695 Address recipient(
"0xbf4ed7b27f1d666546e30d74d50d173d20bca754");
697 for (
Address const& dao: allDAOs)
703 void Block::updateBlockhashContract()
708 if (blockNumber == forkBlock)
715 if (blockNumber >= forkBlock)
717 DummyLastBlockHashes lastBlockHashes;
719 h256 const parentHash = m_previousBlock.
hash();
731 BOOST_THROW_EXCEPTION(InvalidOperationOnSealedBlock());
735 if (m_committedToSeal)
738 m_precommit = m_state;
740 vector<BlockHeader> uncleBlockHeaders;
743 unsigned unclesCount = 0;
744 if (m_previousBlock.
number() != 0)
747 LOG(m_loggerDetailed) <<
"Checking " << m_previousBlock.
hash()
748 <<
", parent = " << m_previousBlock.
parentHash();
751 for (
unsigned gen = 0; gen < 6 && p != _bc.
genesisHash() && unclesCount < 2; ++gen, p = _bc.
details(p).parent)
754 assert(us.size() >= 1);
755 for (
auto const& u: us)
756 if (!excluded.count(u))
758 uncleBlockHeaders.push_back(_bc.
info(u));
761 if (unclesCount == 2)
774 for (
unsigned i = 0; i < m_transactions.size(); ++i)
781 receiptsMap.insert(std::make_pair(k.
out(), receiptrlp.
out()));
784 m_transactions[i].streamRLP(txrlp);
785 transactionsMap.insert(std::make_pair(k.
out(), txrlp.
out()));
803 LOG(m_loggerDetailed) <<
"Post-reward stateRoot: " << m_state.
rootHash();
804 LOG(m_loggerDetailed) << m_state;
813 if (m_currentBlock.
extraData().size() > 32)
820 m_committedToSeal =
true;
823 void Block::uncommitToSeal()
825 if (m_committedToSeal)
827 m_state = m_precommit;
828 m_committedToSeal =
false;
834 if (!m_committedToSeal)
851 m_state = m_precommit;
860 _i = min<unsigned>(_i, m_transactions.size());
863 return (_i > 0 ?
receipt(_i - 1).stateRoot() : m_previousBlock.
stateRoot());
865 catch (TransactionReceiptVersionError
const&)
882 LOG(m_logger) <<
"Committing to disk: stateRoot " << m_currentBlock.
stateRoot() <<
" = "
890 catch (BadRoot
const&)
892 cwarn <<
"Trie corrupt! :-(";
901 m_previousBlock = m_currentBlock;
904 LOG(m_logger) <<
"finalising enactment. current -> previous, hash is "
905 << m_previousBlock.
hash();
Transactions topTransactions(unsigned _limit, h256Hash const &_avoid=h256Hash()) const
BlockHeader info(h256 const &_hash) const
Get the partial-header of a block (or the most recent mined if none given). Thread-safe.
h256 currentHash() const
Get a given block (RLP format). Thread-safe.
std::function< void(uint64_t, uint64_t, Instruction, bigint, bigint, bigint, VMFace const *, ExtVMFace const *)> OnOpFunc
virtual u256 ask(Block const &) const =0
bytes headerData(h256 const &_hash) const
Get a block (RLP format) for the given hash (or the most recent mined if none given)....
void commitToSeal(BlockChain const &_bc, bytes const &_extraData={})
h256 rootHash() const
The hash of the root of our state tree.
u256 const & accountStartNonce() const
Get the account start nonce. May be required.
Encodes a transaction, ready to be exported to or freshly imported from RLP.
std::vector< Transaction > Transactions
Nice name for vector of Transaction.
std::map< bytes, bytes > BytesMap
PopulationStatistics populateFromChain(BlockChain const &_bc, h256 const &_hash, ImportRequirements::value _ir=ImportRequirements::None)
Construct state object from arbitrary point in blockchain.
h256 rootHash() const
The hash of the root of our state tree.
bool sha3(bytesConstRef _input, bytesRef o_output) noexcept
u256 enactOn(VerifiedBlockRef const &_block, BlockChain const &_bc)
h256 genesisHash() const
Get the hash of the genesis block. Thread-safe.
h256 stateRootBeforeTx(unsigned _i) const
boost::error_info< struct tag_hash, h256 > errinfo_hash256
u256 experimentalForkBlock
bool isKnown(h256 const &_hash, bool _isCurrent=true) const
Returns true if the given block is known (though not necessarily a part of the canon chain).
h256 orderedTrieRoot(std::vector< bytes > const &_data)
void noteAccountStartNonce(u256 const &_actual)
bytes const & out() const
Read the byte stream.
bytesConstRef block
Block data reference.
AddressHash commit(AccountMap const &_cache, SecureTrieDB< Address, DB > &_state)
void streamRLP(RLPStream &_s) const
void commit(CommitBehaviour _commitBehaviour)
ChainOperationParams const & chainParams() const
SealEngineFace * sealEngine() const
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
h160s Addresses
A vector of Ethereum addresses.
LogBloom logBloom() const
Get the bloom filter of all logs that happened in the block.
void noteChain(BlockChain const &_bc)
#define DEV_TIMED_ABOVE(S, MS)
void addBalance(Address const &_id, u256 const &_amount)
Base class for all exceptions.
h256 hash256(BytesMap const &_s)
BlockDetails details(h256 const &_hash) const
Get the familial details concerning a block (or the most recent mined if none given)....
boost::error_info< struct tag_target, h256 > errinfo_target
ChainParams const & chainParams() const
virtual u256 blockReward(u256 const &_blockNumber) const =0
std::unordered_set< h256 > h256Hash
std::vector< h256 > h256s
Block(u256 const &_accountStartNonce)
Default constructor; creates with a blank database prepopulated with the genesis block.
boost::error_info< struct tag_got, bigint > errinfo_got
std::string lookup(h256 const &_h) const
const bytes c_blockhashContractCode
Code of the special contract for block hash storage defined in EIP96.
ExecutionResult execute(LastBlockHashesFace const &_lh, Transaction const &_t, Permanence _p=Permanence::Committed, OnOpFunc const &_onOp=OnOpFunc())
h256Hash allKinFrom(h256 const &_parent, unsigned _generations) const
boost::error_info< struct tag_transactionIndex, unsigned > errinfo_transactionIndex
void cleanup()
Returns back to a pristine state after having done a playback.
std::vector< byte > bytes
VerifiedBlockRef verifyBlock(bytesConstRef _block, std::function< void(Exception &)> const &_onBad, ImportRequirements::value _ir=ImportRequirements::OutOfOrderChecks) const
Verify block and prepare it for enactment.
boost::error_info< struct tag_uncleNumber, u256 > errinfo_uncleNumber
Message-call/contract-creation executor; useful for executing transactions.
Implements the blockchain database. All data this gives is disk-backed. @threadsafe.
LastBlockHashesFace const & lastBlockHashes() const
virtual void populateFromParent(BlockHeader &_bi, BlockHeader const &_parent) const
Don't forget to call Super::populateFromParent when subclassing & overriding.
h256 sha3(IncludeSignature _sig=WithSignature) const
const Address c_blockhashContractAddress(0xf0)
Address of the special contract for block hash storage defined in EIP96.
constexpr u256 Invalid256
boost::error_info< struct tag_uncleIndex, unsigned > errinfo_uncleIndex
A queue of Transactions, each stored as RLP. Maintains a transaction queue sorted by nonce diff and g...
Class for writing to an RLP bytestream.
void setFuture(h256 const &_t)
OverlayDB const & db() const
boost::multiprecision::number< boost::multiprecision::cpp_int_backend<> > bigint
void transferBalance(Address const &_from, Address const &_to, u256 const &_value)
Transfers "the balance _value between two accounts.
void resetCurrent(int64_t _timestamp=utcTime())
OverlayDB const & db() const
Open a DB - useful for passing into the constructor & keeping for other states that are necessary.
boost::error_info< struct tag_unclesExcluded, h256Hash > errinfo_unclesExcluded
boost::error_info< struct tag_max, bigint > errinfo_max
bytes asBytes(std::string const &_b)
Converts a string to a byte array containing the string's (byte) data.
TransactionReceipt const & receipt(unsigned _i) const
Get the transaction receipt for the transaction of the given index.
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
boost::error_info< struct tag_receipts, std::vector< bytes > > errinfo_receipts
bytes block(h256 const &_hash) const
Get a block (RLP format) for the given hash (or the most recent mined if none given)....
boost::error_info< struct tag_currentNumber, u256 > errinfo_currentNumber
Verified block info, does not hold block data, but a reference instead.
void swapOut(bytes &_dest)
Swap the contents of the output stream out for some other byte array.
void setRoot(h256 const &_root)
Resets any uncommitted changes to the cache.
bool sealBlock(bytes const &_header)
boost::tuple< errinfo_required_h256, errinfo_got_h256 > Hash256RequirementError
void setCode(Address const &_address, bytes &&_code)
Sets the code of the account. Must only be called during / after contract creation.
boost::tuple< errinfo_required, errinfo_got > RequirementError
u256 balance(Address const &_id) const
BlockHeader const & info() const
Get the header information on the present block.
Description of the result of executing a transaction.
unsigned waiting(Address const &_a) const
RLPStream & appendRaw(bytesConstRef _rlp, size_t _itemCount=1)
Appends raw (pre-serialised) RLP data. Use with caution.
dev::Addresses childDaos()
std::string toHex(Iterator _it, Iterator _end, std::string const &_prefix)
std::pair< ExecutionResult, TransactionReceipt > execute(EnvInfo const &_envInfo, SealEngineFace const &_sealEngine, Transaction const &_t, Permanence _p=Permanence::Committed, OnOpFunc const &_onOp=OnOpFunc())
void drop(h256 const &_txHash)
Address const SystemAddress
The SYSTEM address.
void createContract(Address const &_address)
Create a contract at the given address (with unset code and unchanged balance).
@ TransactionBasic
Check the basic structure of the transactions.
Interface for getting a list of recent block hashes @threadsafe.
Active model of a block within the block chain. Keeps track of all transactions, receipts and state f...
boost::tuple< errinfo_required_LogBloom, errinfo_got_LogBloom > LogBloomRequirementError
RLPStream & appendList(size_t _items)
Appends a list.
boost::error_info< struct tag_comment, std::string > errinfo_comment
std::pair< TransactionReceipts, bool > sync(BlockChain const &_bc, TransactionQueue &_tq, GasPricer const &_gp, unsigned _msTimeout=100)
BlockHeader info
Prepopulated block info.
#define DEV_TIMED_FUNCTION_ABOVE(MS)
Block & operator=(Block const &_s)
Copy state object.