38 #include <boost/exception/errinfo_nested_exception.hpp> 39 #include <boost/filesystem.hpp> 44 namespace fs = boost::filesystem;
46 #define ETH_TIMED_IMPORTS 1 50 std::string
const c_chainStart{
"chainStart"};
51 db::Slice const c_sliceChainStart{c_chainStart};
57 _bc.m_blocksDB->forEach([&_out, &cmp](
db::Slice const& _key,
db::Slice const& _value) {
58 if (
string(_key.
data(), _key.
size()) !=
"best")
60 const string key(_key.
data(), _key.
size());
64 _out <<
toHex(key) <<
": " << d.number() <<
" @ " << d.parentHash()
65 << (cmp == key ?
" BEST" :
"") << std::endl;
69 cwarn <<
"Invalid DB entry:" <<
toHex(key) <<
" -> " 80 #if ALL_COMPILERS_ARE_CPP11_COMPLIANT 82 h[32] = (uint8_t)_sub;
85 static boost::thread_specific_ptr<FixedHash<33>> t_h;
89 (*t_h)[32] = (uint8_t)_sub;
91 #endif //ALL_COMPILERS_ARE_CPP11_COMPLIANT 96 #if ALL_COMPILERS_ARE_CPP11_COMPLIANT 99 h[32] = (uint8_t)_sub;
102 static boost::thread_specific_ptr<FixedHash<33>> t_h;
107 (*t_h)[32] = (uint8_t)_sub;
118 explicit LastBlockHashes(
BlockChain const& _bc): m_bc(_bc) {}
120 h256s precedingHashes(
h256 const& _mostRecentHash)
const override 122 Guard l(m_lastHashesMutex);
123 if (m_lastHashes.empty() || m_lastHashes.front() != _mostRecentHash)
125 m_lastHashes.resize(256);
126 m_lastHashes[0] = _mostRecentHash;
127 for (
unsigned i = 0; i < 255; ++i)
128 m_lastHashes[i + 1] = m_lastHashes[i] ? m_bc.info(m_lastHashes[i]).parentHash() :
h256();
133 void clear()
override 135 Guard l(m_lastHashesMutex);
136 m_lastHashes.clear();
142 mutable Mutex m_lastHashesMutex;
143 mutable h256s m_lastHashes;
160 static const chrono::system_clock::duration c_collectionDuration = chrono::seconds(60);
163 static const unsigned c_collectionQueueSize = 20;
166 static const unsigned c_maxCacheSize = 1024 * 1024 * 64;
169 static const unsigned c_minCacheSize = 1024 * 1024 * 32;
173 m_lastBlockHashes(new LastBlockHashes(*this)),
177 open(_dbPath, _we, _pc);
194 m_genesisHash = m_genesis.
hash();
202 m_cacheUsage.resize(c_collectionQueueSize);
203 m_lastCollection = chrono::system_clock::now();
212 unsigned BlockChain::open(fs::path
const& _path,
WithExisting _we)
215 fs::path chainPath = path / fs::path(
toHex(m_genesisHash.
ref().
cropped(0, 4)));
221 fs::create_directories(extrasPath);
231 fs::rename(extrasPath / fs::path(
"extras"), extrasPath / fs::path(
"extras.old"));
232 fs::remove_all(extrasPath / fs::path(
"state"));
234 lastMinor = (unsigned)
RLP(status);
239 cnote <<
"Killing blockchain & extras database (WithExisting::Kill).";
240 fs::remove_all(chainPath / fs::path(
"blocks"));
241 fs::remove_all(extrasPath / fs::path(
"extras"));
250 catch (db::DatabaseError
const& ex)
258 if (fs::space(chainPath / fs::path(
"blocks")).available < 1024)
260 cwarn <<
"Not enough available space found on hard drive. Please free some up and then re-run. Bailing.";
261 BOOST_THROW_EXCEPTION(NotEnoughAvailableSpace());
267 (chainPath / fs::path(
"blocks")) <<
269 (extrasPath / fs::path(
"extras")) <<
270 "already open. You appear to have another instance of ethereum running. Bailing.";
271 BOOST_THROW_EXCEPTION(DatabaseAlreadyOpen());
276 cwarn <<
"Unknown database error occurred during in-memory database creation";
286 auto r = m_details[m_genesisHash].
rlp();
296 auto const l = m_extrasDB->lookup(
db::Slice(
"best"));
299 m_lastBlockNumber =
number(m_lastBlockHash);
315 open(m_dbPath, _we, _pc);
318 void BlockChain::close()
320 ctrace <<
"Closing blockchain DB";
326 m_lastBlockHash = m_genesisHash;
327 m_lastBlockNumber = 0;
333 m_transactionAddresses.clear();
334 m_blockHashes.clear();
335 m_blocksBlooms.clear();
336 m_cacheUsage.clear();
338 m_lastBlockHashes->clear();
345 cwarn <<
"In-memory database detected, skipping rebuild (since there's no existing database to rebuild)";
350 fs::path chainPath = path / fs::path(
toHex(m_genesisHash.
ref().
cropped(0, 4)));
353 unsigned originalNumber = m_lastBlockNumber;
363 fs::rename(extrasPath / fs::path(
"extras"), extrasPath / fs::path(
"extras.old"));
364 std::unique_ptr<db::DatabaseFace> oldExtrasDB(
db::DBFactory::create(extrasPath / fs::path(
"extras.old")));
374 m_transactionAddresses.clear();
375 m_blockHashes.clear();
376 m_blocksBlooms.clear();
377 m_lastBlockHashes->clear();
379 m_lastBlockNumber = 0;
381 m_details[m_lastBlockHash].totalDifficulty = s.
info().
difficulty();
386 h256 lastHash = m_lastBlockHash;
388 for (
unsigned d = 1; d <= originalNumber; ++d)
392 cerr <<
"\n1000 blocks in " << t.
elapsed() <<
"s = " << (1000.0 / t.
elapsed()) <<
"b/s" << endl;
397 bytes b =
block(queryExtras<BlockHash, uint64_t, ExtraBlockHash>(
398 d, m_blockHashes, x_blockHashes, NullBlockHash, oldExtrasDB.get())
405 cwarn <<
"DISJOINT CHAIN DETECTED; " << bi.
hash() <<
"#" << d <<
" -> parent is" << bi.
parentHash() <<
"; expected" << lastHash <<
"#" << (d - 1);
408 lastHash = bi.
hash();
409 import(b, s.
db(), 0);
418 _progress(d, originalNumber);
421 fs::remove_all(path / fs::path(
"extras.old"));
427 oss << m_lastBlockHash <<
'\n';
431 std::map<std::string, std::string> dbData;
437 for (
auto const& it : dbData)
438 oss <<
toHex(it.first) <<
"/" <<
toHex(it.second) <<
'\n';
448 _bq.
drain(blocks, _max);
466 goodTransactions.reserve(goodTransactions.size() + r.
goodTranactions.size());
470 catch (dev::eth::AlreadyHaveBlock
const&)
472 cwarn <<
"ODD: Import queue contains already imported block";
475 catch (dev::eth::UnknownParent
const&)
477 cwarn <<
"ODD: Import queue contains block with unknown parent.";
480 badBlocks.push_back(
block.verified.info.hash());
482 catch (dev::eth::FutureTime
const&)
484 cwarn <<
"ODD: Import queue contains a block with future time.";
485 this_thread::sleep_for(chrono::seconds(1));
488 catch (dev::eth::TransientError
const&)
490 this_thread::sleep_for(chrono::milliseconds(100));
500 badBlocks.push_back(
block.verified.info.hash());
517 catch (AlreadyHaveBlock&)
537 return import(
block, _db, _mustBeNew);
551 checkBlockIsNew(_block);
563 for (
auto i:
RLP(_receipts))
568 LOG(m_logger) << _block.
info.
hash() <<
" : Invalid receipts root " 571 BOOST_THROW_EXCEPTION(InvalidReceiptsStateRoot());
577 auto pdata = pd.
rlp();
578 LOG(m_loggerError) <<
"Details is returning false despite block known: " <<
RLP(pdata);
581 LOG(m_loggerError) <<
"last/number: " << m_lastBlockNumber <<
" " << m_lastBlockHash <<
" " 584 LOG(m_loggerError) <<
"RLP: " <<
RLP(parentBlock);
585 LOG(m_loggerError) <<
"DATABASE CORRUPTION: CRITICAL FAILURE";
590 checkBlockTimestamp(_block.
info);
596 std::unique_ptr<db::WriteBatchFace> blocksWriteBatch = m_blocksDB->createWriteBatch();
597 std::unique_ptr<db::WriteBatchFace> extrasWriteBatch = m_extrasDB->createWriteBatch();
600 for (
auto i:
RLP(_receipts))
621 extrasWriteBatch->insert(
623 extrasWriteBatch->insert(
629 m_blocksDB->commit(std::move(blocksWriteBatch));
631 catch (boost::exception
const& ex)
633 cwarn <<
"Error writing to blockchain database: " << boost::diagnostic_information(ex);
634 cwarn <<
"Fail writing to blockchain database. Bombing out.";
640 m_extrasDB->commit(std::move(extrasWriteBatch));
642 catch (boost::exception
const& ex)
644 cwarn <<
"Error writing to extras database: " << boost::diagnostic_information(ex);
645 cwarn <<
"Fail writing to extras database. Bombing out.";
658 checkBlockIsNew(_block);
671 auto pdata = pd.
rlp();
672 LOG(m_loggerError) <<
"Details is returning false despite block known: " <<
RLP(pdata);
675 LOG(m_loggerError) <<
"last/number: " << m_lastBlockNumber <<
" " << m_lastBlockHash <<
" " 678 LOG(m_loggerError) <<
"RLP: " <<
RLP(parentBlock);
679 LOG(m_loggerError) <<
"DATABASE CORRUPTION: CRITICAL FAILURE";
683 checkBlockTimestamp(_block.
info);
688 LOG(m_loggerDetail) <<
"Attempting import of " << _block.
info.
hash() <<
" ...";
699 auto tdIncrease = s.
enactOn(_block, *
this);
701 for (
unsigned i = 0; i < s.
pending().size(); ++i)
706 td = pd.totalDifficulty + tdIncrease;
712 #endif // ETH_PARANOIA 716 cwarn <<
"*** BadRoot error! Trying to import" << _block.
info.
hash() <<
"needed root" 717 << *boost::get_error_info<errinfo_hash256>(ex);
720 BOOST_THROW_EXCEPTION(TransientError());
730 return insertBlockAndExtras(_block,
ref(
receipts), td, performanceLogger);
738 checkBlockIsNew(
block);
740 checkBlockTimestamp(
block.info);
743 return insertBlockAndExtras(
block, _receipts, _totalDifficulty, performanceLogger);
750 LOG(m_logger) << _block.
info.
hash() <<
" : Not new.";
755 void BlockChain::checkBlockTimestamp(
BlockHeader const& _header)
const 760 LOG(m_loggerDetail) << _header.
hash() <<
" : Future time " << _header.
timestamp()
761 <<
" (now at " <<
utcTime() <<
")";
763 BOOST_THROW_EXCEPTION(FutureTime());
769 std::unique_ptr<db::WriteBatchFace> blocksWriteBatch = m_blocksDB->createWriteBatch();
770 std::unique_ptr<db::WriteBatchFace> extrasWriteBatch = m_extrasDB->createWriteBatch();
772 unsigned newLastBlockNumber =
number();
793 extrasWriteBatch->insert(
797 for (
auto i:
RLP(_receipts))
799 extrasWriteBatch->insert(
814 bool isImportedAndBest =
false;
817 if (_totalDifficulty >
details(last).totalDifficulty || (m_sealEngine->chainParams().tieBreakingGas &&
822 unsigned commonIndex;
824 route.push_back(_block.
info.
hash());
829 clearCachesDuringChainReversion(
number(common) + 1);
833 for (
auto i = route.rbegin(); i != route.rend() && *i != common; ++i)
848 for (
unsigned level = 0, index = (
unsigned)tbi.
number(); level < c_bloomIndexLevels; level++, index /= c_bloomIndexSize)
852 for (
unsigned level = 0, index = (
unsigned)tbi.
number(); level < c_bloomIndexLevels; level++, index /= c_bloomIndexSize)
854 unsigned i = index / c_bloomIndexSize;
855 unsigned o = index % c_bloomIndexSize;
856 alteredBlooms.push_back(chunkId(level, i));
857 m_blocksBlooms[alteredBlooms.back()].blooms[o] |=
blockBloom;
868 extrasWriteBatch->insert(
875 for (
auto const& h: alteredBlooms)
876 extrasWriteBatch->insert(
884 newLastBlockHash = _block.
info.
hash();
885 newLastBlockNumber = (unsigned)_block.
info.
number();
886 isImportedAndBest =
true;
889 LOG(m_logger) <<
" Imported and best " << _totalDifficulty <<
" (#" 892 <<
" siblings. Route: " << route;
897 <<
" > TD: " << _totalDifficulty <<
"; " <<
details(last).
number <<
".." 903 m_blocksDB->commit(std::move(blocksWriteBatch));
905 catch (boost::exception& ex)
907 cwarn <<
"Error writing to blockchain database: " << boost::diagnostic_information(ex);
908 cwarn <<
"Fail writing to blockchain database. Bombing out.";
914 m_extrasDB->commit(std::move(extrasWriteBatch));
916 catch (boost::exception& ex)
918 cwarn <<
"Error writing to extras database: " << boost::diagnostic_information(ex);
919 cwarn <<
"Fail writing to extras database. Bombing out.";
926 LOG(m_loggerError) <<
"Known block just inserted has no details.";
927 LOG(m_loggerError) <<
"Block: " << _block.
info;
928 LOG(m_loggerError) <<
"DATABASE CORRUPTION: CRITICAL FAILURE";
935 canary.populateFromChain(*
this, _block.
info.
hash());
939 LOG(m_loggerError) <<
"Failed to initialise State object form imported block.";
940 LOG(m_loggerError) <<
"Block: " << _block.
info;
941 LOG(m_loggerError) <<
"DATABASE CORRUPTION: CRITICAL FAILURE";
944 #endif // ETH_PARANOIA 946 if (m_lastBlockHash != newLastBlockHash)
949 m_lastBlockHash = newLastBlockHash;
950 m_lastBlockNumber = newLastBlockNumber;
955 catch (boost::exception
const& ex)
957 cwarn <<
"Error writing to extras database: " << boost::diagnostic_information(ex);
960 cwarn <<
"Fail writing to extras database. Bombing out.";
967 #endif // ETH_PARANOIA 971 unsigned const gasPerSecond =
static_cast<double>(_block.
info.
gasUsed()) / _performanceLogger.
stageDuration(
"enactment");
975 {
"gasPerSecond",
toString(gasPerSecond)},
983 if (isImportedAndBest && m_onBlockImport)
984 m_onBlockImport(_block.
info);
989 for (
auto const& h: route)
999 void BlockChain::clearBlockBlooms(
unsigned _begin,
unsigned _end)
1017 unsigned beginDirty = _begin;
1018 unsigned endDirty = _end;
1019 for (
unsigned level = 0; level < c_bloomIndexLevels; level++, beginDirty /= c_bloomIndexSize, endDirty = (endDirty - 1) / c_bloomIndexSize + 1)
1022 for (
unsigned item = beginDirty; item != endDirty; ++item)
1024 unsigned bunch = item / c_bloomIndexSize;
1025 unsigned offset = item % c_bloomIndexSize;
1026 auto id = chunkId(level, bunch);
1031 auto lowerChunkId = chunkId(level - 1, item);
1036 m_blocksBlooms[id].blooms[offset] = acc;
1043 cout <<
"Rescuing database..." << endl;
1060 cout <<
"Finding last likely block number..." << endl;
1063 unsigned m = (u + l) / 2;
1064 cout <<
" " << m << flush;
1070 cout <<
" lowest is " << l << endl;
1074 cout <<
"Checking validity of " << l <<
" (" << h <<
")..." << flush;
1077 cout <<
"block..." << flush;
1079 cout <<
"extras..." << flush;
1081 cout <<
"state..." << flush;
1087 cout <<
"OK." << endl;
1095 if (_newHead >= m_lastBlockNumber)
1097 clearCachesDuringChainReversion(_newHead + 1);
1099 m_lastBlockNumber = _newHead;
1104 catch (boost::exception
const& ex)
1106 cwarn <<
"Error writing to extras database: " << boost::diagnostic_information(ex);
1109 cwarn <<
"Fail writing to extras database. Bombing out.";
1127 unsigned fn = fromDetails.
number;
1128 unsigned tn = toDetails.
number;
1134 ret.push_back(from);
1150 if (_pre && (from != to || _common))
1151 ret.push_back(from);
1152 if (_post && (from != to || (!_pre && _common)))
1162 ret.reserve(ret.size() + back.size());
1163 unsigned i = ret.size() - (int)(_common && !ret.empty() && !back.empty());
1164 for (
auto it = back.rbegin(); it != back.rend(); ++it)
1166 return make_tuple(ret, from, i);
1169 void BlockChain::noteUsed(
h256 const& _h,
unsigned _extra)
const 1171 auto id = CacheID(_h, _extra);
1172 Guard l(x_cacheUsage);
1173 m_cacheUsage[0].insert(
id);
1174 if (m_cacheUsage[1].count(
id))
1175 m_cacheUsage[1].erase(
id);
1180 template <
class K,
class T>
static unsigned getHashSize(unordered_map<K, T>
const& _map)
1183 for (
auto const& i: _map)
1184 ret += i.second.size + 64;
1188 void BlockChain::updateStats()
const 1192 for (
auto const& i: m_blocks)
1193 m_lastStats.
memBlocks += i.second.size() + 64;
1195 m_lastStats.
memDetails = getHashSize(m_details);
1196 size_t logBloomsSize = 0;
1197 size_t blocksBloomsSize = 0;
1199 logBloomsSize = getHashSize(m_logBlooms);
1201 blocksBloomsSize = getHashSize(m_blocksBlooms);
1202 m_lastStats.
memLogBlooms = logBloomsSize + blocksBloomsSize;
1204 m_lastStats.
memReceipts = getHashSize(m_receipts);
1215 if (!_force && chrono::system_clock::now() < m_lastCollection + c_collectionDuration && m_lastStats.
memTotal() < c_maxCacheSize)
1217 if (m_lastStats.
memTotal() < c_minCacheSize)
1220 m_lastCollection = chrono::system_clock::now();
1222 Guard l(x_cacheUsage);
1223 for (CacheID
const&
id: m_cacheUsage.back())
1232 m_blocks.erase(
id.first);
1238 m_details.erase(
id.first);
1250 m_receipts.erase(
id.first);
1256 m_logBlooms.erase(
id.first);
1262 m_transactionAddresses.erase(
id.first);
1268 m_blocksBlooms.erase(
id.first);
1273 m_cacheUsage.pop_back();
1274 m_cacheUsage.push_front(std::unordered_set<CacheID>{});
1277 void BlockChain::checkConsistency()
1282 if (_key.
size() == 32)
1287 if (p !=
h256() && p != m_genesisHash)
1293 cnote <<
"Apparently the database is corrupt. Not much we can do at this " 1296 cnote <<
"Apparently the database is corrupt. Not much we can do at this " 1304 void BlockChain::clearCachesDuringChainReversion(
unsigned _firstInvalid)
1306 unsigned end = m_lastBlockNumber + 1;
1308 for (
auto i = _firstInvalid; i < end; ++i)
1309 m_blockHashes.erase(i);
1311 m_transactionAddresses.clear();
1315 clearBlockBlooms(_firstInvalid, end);
1318 static inline unsigned upow(
unsigned a,
unsigned b) {
if (!b)
return 1;
while (--b > 0) a *= a;
return a; }
1319 static inline unsigned ceilDiv(
unsigned n,
unsigned d) {
return (n + d - 1) / d; }
1336 vector<unsigned> ret;
1339 unsigned u = upow(c_bloomIndexSize, c_bloomIndexLevels);
1342 for (
unsigned index = _earliest / u; index <= ceilDiv(_latest, u); ++index)
1343 ret +=
withBlockBloom(_b, _earliest, _latest, c_bloomIndexLevels - 1, index);
1355 vector<unsigned> ret;
1357 unsigned uCourse = upow(c_bloomIndexSize, _level + 1);
1360 unsigned uFine = upow(c_bloomIndexSize, _level);
1364 unsigned obegin = _index == _earliest / uCourse ? _earliest / uFine % c_bloomIndexSize : 0;
1369 unsigned oend = _index == _latest / uCourse ? (_latest / uFine) % c_bloomIndexSize + 1 : c_bloomIndexSize;
1376 for (
unsigned o = obegin; o < oend; ++o)
1377 if (bb.blooms[o].contains(_b))
1381 ret +=
withBlockBloom(_b, _earliest, _latest, _level - 1, o + _index * c_bloomIndexSize);
1383 ret.push_back(o + _index * c_bloomIndexSize);
1394 for (
unsigned i = 0; i < _generations && p != m_genesisHash; ++i, p =
details(p).
parent)
1396 ret.insert(
details(p).parent);
1398 for (
auto i:
RLP(b)[2])
1399 ret.insert(
sha3(i.data()));
1406 if (_hash == m_genesisHash)
1410 if (!m_blocks.count(_hash) && !m_blocksDB->exists(
toSlice(_hash)))
1420 return !_isCurrent ||
details(_hash).
number <= m_lastBlockNumber;
1425 if (_hash == m_genesisHash)
1430 auto it = m_blocks.find(_hash);
1431 if (it != m_blocks.end())
1435 string const d = m_blocksDB->lookup(
toSlice(_hash));
1438 cwarn <<
"Couldn't find requested block:" << _hash;
1445 m_blocks[_hash].resize(d.size());
1446 memcpy(m_blocks[_hash].data(), d.data(), d.size());
1448 return m_blocks[_hash];
1453 if (_hash == m_genesisHash)
1454 return m_genesisHeaderBytes;
1458 auto it = m_blocks.find(_hash);
1459 if (it != m_blocks.end())
1463 string const d = m_blocksDB->lookup(
toSlice(_hash));
1466 cwarn <<
"Couldn't find requested block:" << _hash;
1473 m_blocks[_hash].resize(d.size());
1474 memcpy(m_blocks[_hash].data(), d.data(), d.size());
1490 cwarn <<
"Hinted genesis block's state root hash is incorrect!";
1515 if (parentHeader.empty())
1525 addBlockInfo(ex, h, _block.
toBytes());
1534 for (
auto const& uncle: r[2])
1543 if (parentHeader.empty())
1553 addBlockInfo(ex, uh, _block.
toBytes());
1562 for (
RLP const& tr: r[1])
1568 m_sealEngine->verifyTransaction(_ir, t, h, 0);
1576 addBlockInfo(ex, h, _block.
toBytes());
1591 BOOST_THROW_EXCEPTION(UnknownBlockNumber());
1598 catch (boost::exception
const& ex)
1600 BOOST_THROW_EXCEPTION(FailedToWriteChainStart()
1602 << boost::errinfo_nested_exception(boost::copy_exception(ex)));
1608 auto const value = m_extrasDB->lookup(c_sliceChainStart);
boost::error_info< struct tag_block, bytes > errinfo_block
vector_ref< _T > cropped(size_t _begin, size_t _count) const
vector_ref< _T const > ref(_T const &_t)
SealEngineFace * sealEngine() const
void drain(std::vector< VerifiedBlock > &o_out, unsigned _max)
BlocksBlooms blocksBlooms(unsigned _level, unsigned _index) const
int64_t utcTime()
Get the current time in seconds since the epoch in UTC.
bool doneDrain(h256s const &_knownBad=h256s())
void toBigEndian(T _val, Out &o_out)
boost::error_info< struct tag_uncleIndex, unsigned > errinfo_uncleIndex
Implements the blockchain database. All data this gives is disk-backed. .
ImportRoute insertWithoutParent(bytes const &_block, bytesConstRef _receipts, u256 const &_totalDifficulty)
Insert that doesn't require parent to be imported, useful when we don't have the full blockchain (lik...
bytes rlp(_T _t)
Export a single item in RLP format, returning a byte array.
bytes genesisBlock() const
Genesis block info.
Do all checks that cannot be done independently of prior blocks having been imported.
Check the basic structure of the uncles.
std::ostream & operator<<(std::ostream &_out, BlockHeader const &_bi)
std::vector< unsigned char > toBytes() const
void noteChain(BlockChain const &_bc)
boost::error_info< struct tag_transaction, bytes > errinfo_transaction
boost::error_info< struct tag_currentNumber, u256 > errinfo_currentNumber
TransactionReceipts receipts
void cleanup()
Returns back to a pristine state after having done a playback.
std::vector< Transaction > Transactions
Nice name for vector of Transaction.
Interface for getting a list of recent block hashes .
Transactions const & pending() const
Get the list of pending transactions.
boost::upgrade_to_unique_lock< boost::shared_mutex > UpgradeGuard
std::string toString(std::chrono::time_point< T > const &_e, std::string const &_format="%F %T")
boost::upgrade_lock< boost::shared_mutex > UpgradableGuard
std::string abridged() const
#define DEV_TIMED_ABOVE(S, MS)
unsigned memTransactionAddresses
FixedHash & shiftBloom(FixedHash< M > const &_h)
Verified block info, combines block data and verified info/transactions.
bytesConstRef block
Block data reference.
bool sha3(bytesConstRef _input, bytesRef o_output) noexcept
boost::error_info< struct tag_phase, unsigned > errinfo_phase
bytes contents(boost::filesystem::path const &_file)
u256 enactOn(VerifiedBlockRef const &_block, BlockChain const &_bc)
LogBloom blockBloom(unsigned _number) const
Check the basic structure of the transactions.
OverlayDB const & db() const
Open a DB - useful for passing into the constructor & keeping for other states that are necessary...
Active model of a block within the block chain. Keeps track of all transactions, receipts and state f...
boost::error_info< struct tag_hash, h256 > errinfo_hash256
#define assertsEqual(A, B)
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)...
TransactionReceipt const & receipt(unsigned _i) const
Get the transaction receipt for the transaction of the given index.
Base class for all exceptions.
vector_ref< byte > bytesRef
BlockReceipts receipts() const
std::lock_guard< std::mutex > Guard
bool contains(T const &_t, V const &_v)
BlockHeader const & genesis() const
#define DEV_WRITE_GUARDED(MUTEX)
Require block to be non-genesis.
bytesConstRef data() const
The bare data of the RLP.
Check the basic structure of the transactions.
void rewind(unsigned _newHead)
Alter the head of the chain to some prior block along it.
unsigned memTotal() const
Block genesisBlock(OverlayDB const &_db) const
Get a pre-made genesis State object.
boost::error_info< struct tag_required_h256, h256 > errinfo_required_h256
#define DEV_READ_GUARDED(MUTEX)
std::tuple< h256s, h256, unsigned > treeRoute(h256 const &_from, h256 const &_to, bool _common=true, bool _pre=true, bool _post=true) const
void resetCurrent(int64_t _timestamp=utcTime())
Check parent block header.
std::vector< byte > bytes
vector_ref< byte const > bytesConstRef
void rebuild(boost::filesystem::path const &_path, ProgressCallback const &_progress=std::function< void(unsigned, unsigned)>())
unsigned chainStartBlockNumber() const
static std::unique_ptr< DatabaseFace > create()
VerifiedBlockRef verifyBlock(bytesConstRef _block, std::function< void(Exception &)> const &_onBad, ImportRequirements::value _ir=ImportRequirements::OutOfOrderChecks) const
Verify block and prepare it for enactment.
A queue of blocks. Sits between network or other I/O and the BlockChain. Sorts them ready for blockch...
boost::error_info< struct tag_extraData, bytes > errinfo_extraData
void garbageCollect(bool _force=false)
Deallocate unused data.
h256 genesisHash() const
Get the hash of the genesis block. Thread-safe.
boost::shared_lock< boost::shared_mutex > ReadGuard
h256 currentHash() const
Get a given block (RLP format). Thread-safe.
Do all checks that can be done independently of prior blocks having been imported.
Encodes a transaction, ready to be exported to or freshly imported from RLP.
bool exists(h256 const &_h) const
boost::unique_lock< boost::shared_mutex > WriteGuard
void reopen(WithExisting _we=WithExisting::Trust, ProgressCallback const &_pc=ProgressCallback())
Reopen everything.
Check uncle parent block header.
void setChainStartBlockNumber(unsigned _number)
Change the chain start block.
ImportRoute import(bytes const &_block, OverlayDB const &_stateDB, bool _mustBeNew=true)
db::Slice toSlice(h256 const &_h, unsigned _sub=0)
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void > > u256
Verified block info, does not hold block data, but a reference instead.
BlockDetails details() const
std::string toBigEndianString(u256 _val)
Convenience functions for toBigEndian.
h256Hash allKinFrom(h256 const &_parent, unsigned _generations) const
const unsigned c_minorProtocolVersion
Current minor protocol version.
BlockHeader const & info() const
Get the header information on the present block.
boost::error_info< struct tag_now, unsigned > errinfo_now
std::string dumpDatabase() const
Gives a dump of the blockchain database. For debug/test use only.
std::vector< VerifiedBlock > VerifiedBlocks
std::string toString() const
std::vector< Transaction > transactions
Verified list of block transactions.
h256 rootHash() const
The hash of the root of our state tree.
std::unordered_set< h256 > h256Hash
h256 numberHash(unsigned _i) const
Get the hash for a given block's number.
const unsigned c_databaseVersion
Current database version.
void insert(bytes const &_block, bytesConstRef _receipts, bool _mustBeNew=true)
h256 orderedTrieRoot(std::vector< bytes > const &_data)
boost::error_info< struct tag_transactionIndex, unsigned > errinfo_transactionIndex
std::string toHex(Iterator _it, Iterator _end, std::string const &_prefix)
AddressHash commit(AccountMap const &_cache, SecureTrieDB< Address, DB > &_state)
std::vector< unsigned > withBlockBloom(LogBloom const &_b, unsigned _earliest, unsigned _latest) const
static OverlayDB openDB(boost::filesystem::path const &_path, h256 const &_genesisHash, WithExisting _we=WithExisting::Trust)
Open a DB - useful for passing into the constructor & keeping for other states that are necessary...
Check the basic structure of the uncles.
std::tuple< ImportRoute, bool, unsigned > sync(BlockQueue &_bq, OverlayDB const &_stateDB, unsigned _max)
boost::error_info< struct tag_uncleNumber, u256 > errinfo_uncleNumber
std::vector< Transaction > goodTranactions
std::vector< h256 > h256s
SealEngineFace * createSealEngine()
void writeFile(boost::filesystem::path const &_file, bytesConstRef _data, bool _writeDeleteRename)
virtual void verify(Strictness _s, BlockHeader const &_bi, BlockHeader const &_parent=BlockHeader(), bytesConstRef _block=bytesConstRef()) const
Don't forget to call Super::verify when subclassing & overriding.
void rescue(OverlayDB const &_db)
Rescue the database.
BlockHeader info
Prepopulated block info.
#define DEV_IGNORE_EXCEPTIONS(X)
vector_ref< char const > Slice
std::function< void(unsigned, unsigned)> ProgressCallback
LogBloom bloom(LogEntries const &_logs)
OverlayDB const & db() const
std::pair< ImportResult, ImportRoute > attemptImport(bytes const &_block, OverlayDB const &_stateDB, bool _mutBeNew=true) noexcept