diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp index 4963d2742..ff505d5f2 100644 --- a/alethzero/MainWin.cpp +++ b/alethzero/MainWin.cpp @@ -1097,30 +1097,33 @@ void Main::refreshBlockChain() blockItem->setSelected(true); int n = 0; - auto b = bc.block(h); - for (auto const& i: RLP(b)[1]) - { - Transaction t(i.data(), CheckTransaction::Everything); - QString s = t.receiveAddress() ? - QString(" %2 %5> %3: %1 [%4]") - .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(t.receiveAddress())) - .arg((unsigned)t.nonce()) - .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : - QString(" %2 +> %3: %1 [%4]") - .arg(formatBalance(t.value()).c_str()) - .arg(render(t.safeSender())) - .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) - .arg((unsigned)t.nonce()); - QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks); - auto hba = QByteArray((char const*)h.data(), h.size); - txItem->setData(Qt::UserRole, hba); - txItem->setData(Qt::UserRole + 1, n); - if (oldSelected == hba) - txItem->setSelected(true); - n++; + try { + auto b = bc.block(h); + for (auto const& i: RLP(b)[1]) + { + Transaction t(i.data(), CheckTransaction::Everything); + QString s = t.receiveAddress() ? + QString(" %2 %5> %3: %1 [%4]") + .arg(formatBalance(t.value()).c_str()) + .arg(render(t.safeSender())) + .arg(render(t.receiveAddress())) + .arg((unsigned)t.nonce()) + .arg(ethereum()->codeAt(t.receiveAddress()).size() ? '*' : '-') : + QString(" %2 +> %3: %1 [%4]") + .arg(formatBalance(t.value()).c_str()) + .arg(render(t.safeSender())) + .arg(render(right160(sha3(rlpList(t.safeSender(), t.nonce()))))) + .arg((unsigned)t.nonce()); + QListWidgetItem* txItem = new QListWidgetItem(s, ui->blocks); + auto hba = QByteArray((char const*)h.data(), h.size); + txItem->setData(Qt::UserRole, hba); + txItem->setData(Qt::UserRole + 1, n); + if (oldSelected == hba) + txItem->setSelected(true); + n++; + } } + catch (...) {} }; if (filters.empty()) diff --git a/libdevcrypto/TrieDB.h b/libdevcrypto/TrieDB.h index a707c30f0..c609f4b43 100644 --- a/libdevcrypto/TrieDB.h +++ b/libdevcrypto/TrieDB.h @@ -47,6 +47,11 @@ struct InvalidTrie: virtual dev::Exception {}; extern const h256 c_shaNull; extern const h256 EmptyTrie; +enum class Verification { + Skip, + Normal +}; + /** * @brief Merkle Patricia Tree "Trie": a modifed base-16 Radix tree. * This version uses a database backend. @@ -69,23 +74,26 @@ public: using DB = _DB; GenericTrieDB(DB* _db = nullptr): m_db(_db) {} - GenericTrieDB(DB* _db, h256 _root) { open(_db, _root); } + GenericTrieDB(DB* _db, h256 const& _root, Verification _v = Verification::Normal) { open(_db, _root, _v); } ~GenericTrieDB() {} void open(DB* _db) { m_db = _db; } - void open(DB* _db, h256 _root) { m_db = _db; setRoot(_root); } + void open(DB* _db, h256 const& _root, Verification _v = Verification::Normal) { m_db = _db; setRoot(_root, _v); } void init() { setRoot(insertNode(&RLPNull)); assert(node(m_root).size()); } - void setRoot(h256 _root) + void setRoot(h256 const& _root, Verification _v = Verification::Normal) { m_root = _root; - if (m_root == c_shaNull && !m_db->exists(m_root)) - init(); + if (_v == Verification::Normal) + { + if (m_root == c_shaNull && !m_db->exists(m_root)) + init(); - /*std::cout << "Setting root to " << _root << " (patched to " << m_root << ")" << std::endl;*/ - if (!node(m_root).size()) - BOOST_THROW_EXCEPTION(RootNotFound()); + /*std::cout << "Setting root to " << _root << " (patched to " << m_root << ")" << std::endl;*/ + if (!node(m_root).size()) + BOOST_THROW_EXCEPTION(RootNotFound()); + } } /// True if the trie is uninitialised (i.e. that the DB doesn't contain the root node). @@ -93,7 +101,7 @@ public: /// True if the trie is initialised but empty (i.e. that the DB contains the root node which is empty). bool isEmpty() const { return m_root == c_shaNull && node(m_root).size(); } - h256 root() const { if (!node(m_root).size()) BOOST_THROW_EXCEPTION(BadRoot()); /*std::cout << "Returning root as " << ret << " (really " << m_root << ")" << std::endl;*/ return m_root; } // patch the root in the case of the empty trie. TODO: handle this properly. + h256 const& root() const { if (!node(m_root).size()) BOOST_THROW_EXCEPTION(BadRoot()); /*std::cout << "Returning root as " << ret << " (really " << m_root << ")" << std::endl;*/ return m_root; } // patch the root in the case of the empty trie. TODO: handle this properly. void debugPrint() {} @@ -301,7 +309,7 @@ public: using KeyType = _KeyType; SpecificTrieDB(DB* _db = nullptr): Generic(_db) {} - SpecificTrieDB(DB* _db, h256 _root): Generic(_db, _root) {} + SpecificTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal): Generic(_db, _root, _v) {} std::string operator[](KeyType _k) const { return at(_k); } @@ -349,7 +357,7 @@ public: using DB = _DB; HashedGenericTrieDB(DB* _db = nullptr): Super(_db) {} - HashedGenericTrieDB(DB* _db, h256 _root): Super(_db, _root) {} + HashedGenericTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal): Super(_db, _root, _v) {} using Super::open; using Super::init; @@ -402,20 +410,20 @@ class FatGenericTrieDB: public GenericTrieDB public: FatGenericTrieDB(DB* _db): Super(_db), m_secure(_db) {} - FatGenericTrieDB(DB* _db, h256 _root) { open(_db, _root); } + FatGenericTrieDB(DB* _db, h256 _root, Verification _v = Verification::Normal) { open(_db, _root, _v); } - void open(DB* _db, h256 _root) { Super::open(_db); m_secure.open(_db); setRoot(_root); } + void open(DB* _db, h256 _root, Verification _v = Verification::Normal) { Super::open(_db); m_secure.open(_db); setRoot(_root, _v); } void init() { Super::init(); m_secure.init(); syncRoot(); } - void setRoot(h256 _root) + void setRoot(h256 _root, Verification _v = Verification::Normal) { if (!m_secure.isNull()) Super::db()->removeAux(m_secure.root()); - m_secure.setRoot(_root); + m_secure.setRoot(_root, _v); auto rb = Super::db()->lookupAux(m_secure.root()); auto r = h256(rb); - Super::setRoot(r); + Super::setRoot(r, _v); } h256 root() const { return m_secure.root(); } diff --git a/libethereum/BlockChain.cpp b/libethereum/BlockChain.cpp index a4d070171..c0394db95 100644 --- a/libethereum/BlockChain.cpp +++ b/libethereum/BlockChain.cpp @@ -445,8 +445,8 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import ldb::WriteBatch blocksBatch; ldb::WriteBatch extrasBatch; - h256 newLastBlockHash; - unsigned newLastBlockNumber = 0; + h256 newLastBlockHash = currentHash(); + unsigned newLastBlockNumber = number(); u256 td; #if ETH_CATCH @@ -478,30 +478,27 @@ ImportRoute BlockChain::import(bytes const& _block, OverlayDB const& _db, Import #endif // All ok - insert into DB - { - // ensure parent is cached for later addition. - // TODO: this is a bit horrible would be better refactored into an enveloping UpgradableGuard - // together with an "ensureCachedWithUpdatableLock(l)" method. - // This is safe in practice since the caches don't get flushed nearly often enough to be - // done here. - details(bi.parentHash); - WriteGuard l(x_details); + + // ensure parent is cached for later addition. + // TODO: this is a bit horrible would be better refactored into an enveloping UpgradableGuard + // together with an "ensureCachedWithUpdatableLock(l)" method. + // This is safe in practice since the caches don't get flushed nearly often enough to be + // done here. + details(bi.parentHash); + ETH_WRITE_GUARDED(x_details) m_details[bi.parentHash].children.push_back(bi.hash()); - } #if ETH_TIMED_IMPORTS collation = t.elapsed(); t.restart(); #endif - { - ReadGuard l2(x_details); - extrasBatch.Put(toSlice(bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {}).rlp())); + blocksBatch.Put(toSlice(bi.hash()), (ldb::Slice)ref(_block)); + ETH_READ_GUARDED(x_details) extrasBatch.Put(toSlice(bi.parentHash, ExtraDetails), (ldb::Slice)dev::ref(m_details[bi.parentHash].rlp())); - extrasBatch.Put(toSlice(bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp())); - extrasBatch.Put(toSlice(bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp())); - blocksBatch.Put(toSlice(bi.hash()), (ldb::Slice)ref(_block)); - } + extrasBatch.Put(toSlice(bi.hash(), ExtraDetails), (ldb::Slice)dev::ref(BlockDetails((unsigned)pd.number + 1, td, bi.parentHash, {}).rlp())); + extrasBatch.Put(toSlice(bi.hash(), ExtraLogBlooms), (ldb::Slice)dev::ref(blb.rlp())); + extrasBatch.Put(toSlice(bi.hash(), ExtraReceipts), (ldb::Slice)dev::ref(br.rlp())); #if ETH_TIMED_IMPORTS writing = t.elapsed(); diff --git a/libethereum/State.cpp b/libethereum/State.cpp index d5a54985e..83a78e1e8 100644 --- a/libethereum/State.cpp +++ b/libethereum/State.cpp @@ -152,7 +152,7 @@ State::State(OverlayDB const& _db, BlockChain const& _bc, h256 _h): State::State(State const& _s): m_db(_s.m_db), - m_state(&m_db, _s.m_state.root()), + m_state(&m_db, _s.m_state.root(), Verification::Skip), m_transactions(_s.m_transactions), m_receipts(_s.m_receipts), m_transactionSet(_s.m_transactionSet), @@ -184,7 +184,7 @@ void State::paranoia(std::string const& _when, bool _enforceRefs) const State& State::operator=(State const& _s) { m_db = _s.m_db; - m_state.open(&m_db, _s.m_state.root()); + m_state.open(&m_db, _s.m_state.root(), Verification::Skip); m_transactions = _s.m_transactions; m_receipts = _s.m_receipts; m_transactionSet = _s.m_transactionSet;