From 57092ed9e7edb3c60adc75823dd922ad67ddec62 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 22 Oct 2014 09:25:08 +0200 Subject: rpc: make `gettxoutsettinfo` run lock-free For leveldb "An iterator operates on a snapshot of the database taken when the iterator is created". This means that it is unnecessary to lock out other threads while computing statistics, and neither to hold cs_main for the whole time. Let the thread run free. --- src/txdb.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index df9ff8d8c..935b78467 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -147,7 +147,10 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { return error("%s: Deserialize or I/O error - %s", __func__, e.what()); } } - stats.nHeight = mapBlockIndex.find(GetBestBlock())->second->nHeight; + { + LOCK(cs_main); + stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + } stats.hashSerialized = ss.GetHash(); stats.nTotalAmount = nTotalAmount; return true; -- cgit v1.2.3 From 9dd793f499254600efa468938cef9baa28ac81b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Sun, 5 Jul 2015 14:17:46 +0200 Subject: TRIVIAL: Missing includes --- src/txdb.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 935b78467..21ecd6523 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -5,6 +5,7 @@ #include "txdb.h" +#include "chain.h" #include "chainparams.h" #include "hash.h" #include "main.h" -- cgit v1.2.3 From 42cb388167ef78f47a3a440eb651b6938c10f508 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Mon, 7 Sep 2015 15:22:23 -0700 Subject: Add chainstate obfuscation to avoid spurious antivirus detection Adds an `obfuscate` parameter to `CLevelDBWrapper` and makes use of it for all new chainstate stores built via `CCoinsViewDB`. Also adds an `Xor` method to `CDataStream`. Thanks to @sipa @laanwj @pstratem @dexX7 @KyrosKrane @gmaxwell. --- src/txdb.cpp | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 21ecd6523..9738dea03 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -29,18 +29,8 @@ static const char DB_REINDEX_FLAG = 'R'; static const char DB_LAST_BLOCK = 'l'; -void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) { - if (coins.IsPruned()) - batch.Erase(make_pair(DB_COINS, hash)); - else - batch.Write(make_pair(DB_COINS, hash), coins); -} - -void static BatchWriteHashBestChain(CLevelDBBatch &batch, const uint256 &hash) { - batch.Write(DB_BEST_BLOCK, hash); -} - -CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe) { +CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(GetDataDir() / "chainstate", nCacheSize, fMemory, fWipe, true) +{ } bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const { @@ -59,12 +49,15 @@ uint256 CCoinsViewDB::GetBestBlock() const { } bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { - CLevelDBBatch batch; + CLevelDBBatch batch(db.GetObfuscateKey()); size_t count = 0; size_t changed = 0; for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { - BatchWriteCoins(batch, it->first, it->second.coins); + if (it->second.coins.IsPruned()) + batch.Erase(make_pair(DB_COINS, it->first)); + else + batch.Write(make_pair(DB_COINS, it->first), it->second.coins); changed++; } count++; @@ -72,7 +65,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { mapCoins.erase(itOld); } if (!hashBlock.IsNull()) - BatchWriteHashBestChain(batch, hashBlock); + batch.Write(DB_BEST_BLOCK, hashBlock); LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count); return db.WriteBatch(batch); @@ -158,7 +151,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { - CLevelDBBatch batch; + CLevelDBBatch batch(GetObfuscateKey()); for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); } @@ -174,7 +167,7 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { } bool CBlockTreeDB::WriteTxIndex(const std::vector >&vect) { - CLevelDBBatch batch; + CLevelDBBatch batch(GetObfuscateKey()); for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) batch.Write(make_pair(DB_TXINDEX, it->first), it->second); return WriteBatch(batch); -- cgit v1.2.3 From 3499ce1e1ad87a86598d00b7124072c91ddad833 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 7 Oct 2015 17:12:24 -0700 Subject: Encapsulate CLevelDB iterators cleanly Conflicts: src/leveldb.cpp src/leveldb.h src/txdb.cpp --- src/txdb.cpp | 59 ++++++++++++++++++++--------------------------------------- 1 file changed, 20 insertions(+), 39 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 9738dea03..3d2050891 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -98,8 +98,8 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { /* It seems that there are no "const iterators" for LevelDB. Since we only need read operations on it, use a const-cast to get around that restriction. */ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->SeekToFirst(); + boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + pcursor->Seek('c'); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = GetBestBlock(); @@ -107,22 +107,10 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { CAmount nTotalAmount = 0; while (pcursor->Valid()) { boost::this_thread::interruption_point(); - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == DB_COINS) { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); - CCoins coins; - ssValue >> coins; - uint256 txhash; - ssKey >> txhash; - ss << txhash; - ss << VARINT(coins.nVersion); - ss << (coins.fCoinBase ? 'c' : 'n'); - ss << VARINT(coins.nHeight); + std::pair key; + CCoins coins; + if (pcursor->GetKey(key) && key.first == 'c') { + if (pcursor->GetValue(coins)) { stats.nTransactions++; for (unsigned int i=0; iGetKeySize(); ss << VARINT(0); + } else { + return error("CCoinsViewDB::GetStats() : unable to read value"); } - pcursor->Next(); - } catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } else { + break; } + pcursor->Next(); } { LOCK(cs_main); @@ -189,24 +179,15 @@ bool CBlockTreeDB::LoadBlockIndexGuts() { boost::scoped_ptr pcursor(NewIterator()); - CDataStream ssKeySet(SER_DISK, CLIENT_VERSION); - ssKeySet << make_pair(DB_BLOCK_INDEX, uint256()); - pcursor->Seek(ssKeySet.str()); + pcursor->Seek(make_pair('b', uint256(0))); // Load mapBlockIndex while (pcursor->Valid()) { boost::this_thread::interruption_point(); - try { - leveldb::Slice slKey = pcursor->key(); - CDataStream ssKey(slKey.data(), slKey.data()+slKey.size(), SER_DISK, CLIENT_VERSION); - char chType; - ssKey >> chType; - if (chType == DB_BLOCK_INDEX) { - leveldb::Slice slValue = pcursor->value(); - CDataStream ssValue(slValue.data(), slValue.data()+slValue.size(), SER_DISK, CLIENT_VERSION); - CDiskBlockIndex diskindex; - ssValue >> diskindex; - + std::pair key; + if (pcursor->GetKey(key) && key.first == 'b') { + CDiskBlockIndex diskindex; + if (pcursor->GetValue(diskindex)) { // Construct block index object CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); @@ -227,10 +208,10 @@ bool CBlockTreeDB::LoadBlockIndexGuts() pcursor->Next(); } else { - break; // if shutdown requested or finished loading block index + return error("LoadBlockIndex() : failed to read value"); } - } catch (const std::exception& e) { - return error("%s: Deserialize or I/O error - %s", __func__, e.what()); + } else { + break; } } -- cgit v1.2.3 From 0fdf8c80ee322ab747321d61faf9c72af4a51445 Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Thu, 8 Oct 2015 00:44:10 -0700 Subject: Handle obfuscation in CLevelDBIterator --- src/txdb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 3d2050891..4d7ec27aa 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -98,7 +98,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { /* It seems that there are no "const iterators" for LevelDB. Since we only need read operations on it, use a const-cast to get around that restriction. */ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); pcursor->Seek('c'); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); @@ -177,9 +177,9 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { bool CBlockTreeDB::LoadBlockIndexGuts() { - boost::scoped_ptr pcursor(NewIterator()); + boost::scoped_ptr pcursor(NewIterator()); - pcursor->Seek(make_pair('b', uint256(0))); + pcursor->Seek(make_pair('b', uint256())); // Load mapBlockIndex while (pcursor->Valid()) { -- cgit v1.2.3 From dcd8e27c65de0d2cb972588a6e811ca7ccd1b3bd Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Fri, 9 Oct 2015 10:55:27 -0700 Subject: Refer to obfuscate_key via pointer in peripheral CLevelDB classes cc @sipa --- src/txdb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 4d7ec27aa..5723c9244 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -49,7 +49,7 @@ uint256 CCoinsViewDB::GetBestBlock() const { } bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { - CLevelDBBatch batch(db.GetObfuscateKey()); + CLevelDBBatch batch(&db.GetObfuscateKey()); size_t count = 0; size_t changed = 0; for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { @@ -141,7 +141,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { - CLevelDBBatch batch(GetObfuscateKey()); + CLevelDBBatch batch(&GetObfuscateKey()); for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); } @@ -157,7 +157,7 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { } bool CBlockTreeDB::WriteTxIndex(const std::vector >&vect) { - CLevelDBBatch batch(GetObfuscateKey()); + CLevelDBBatch batch(&GetObfuscateKey()); for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) batch.Write(make_pair(DB_TXINDEX, it->first), it->second); return WriteBatch(batch); -- cgit v1.2.3 From f8f2aceadd5f406f8bc6f6029b032d00828e6256 Mon Sep 17 00:00:00 2001 From: Daniel Kraft Date: Tue, 13 Oct 2015 20:25:57 +0200 Subject: trivial: use constants for db keys Replace literal occurances of the key "prefixes" 'c' and 'b' in txdb.cpp by the respective constants. --- src/txdb.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 5723c9244..a441aea68 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -99,7 +99,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { only need read operations on it, use a const-cast to get around that restriction. */ boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->Seek('c'); + pcursor->Seek(DB_COINS); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); stats.hashBlock = GetBestBlock(); @@ -109,7 +109,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { boost::this_thread::interruption_point(); std::pair key; CCoins coins; - if (pcursor->GetKey(key) && key.first == 'c') { + if (pcursor->GetKey(key) && key.first == DB_COINS) { if (pcursor->GetValue(coins)) { stats.nTransactions++; for (unsigned int i=0; i pcursor(NewIterator()); - pcursor->Seek(make_pair('b', uint256())); + pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); // Load mapBlockIndex while (pcursor->Valid()) { boost::this_thread::interruption_point(); std::pair key; - if (pcursor->GetKey(key) && key.first == 'b') { + if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) { CDiskBlockIndex diskindex; if (pcursor->GetValue(diskindex)) { // Construct block index object -- cgit v1.2.3 From 8587b23038b88340ec64253ea4282afe90187a69 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 22 Oct 2015 21:02:20 -0400 Subject: leveldbwrapper symbol rename: Remove "Level" from class, etc. names --- src/txdb.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index a441aea68..f0868a1eb 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -49,7 +49,7 @@ uint256 CCoinsViewDB::GetBestBlock() const { } bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { - CLevelDBBatch batch(&db.GetObfuscateKey()); + CDBBatch batch(&db.GetObfuscateKey()); size_t count = 0; size_t changed = 0; for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { @@ -71,7 +71,7 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return db.WriteBatch(batch); } -CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CLevelDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) { +CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWrapper(GetDataDir() / "blocks" / "index", nCacheSize, fMemory, fWipe) { } bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { @@ -98,7 +98,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { /* It seems that there are no "const iterators" for LevelDB. Since we only need read operations on it, use a const-cast to get around that restriction. */ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); + boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); pcursor->Seek(DB_COINS); CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); @@ -141,7 +141,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { - CLevelDBBatch batch(&GetObfuscateKey()); + CDBBatch batch(&GetObfuscateKey()); for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); } @@ -157,7 +157,7 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { } bool CBlockTreeDB::WriteTxIndex(const std::vector >&vect) { - CLevelDBBatch batch(&GetObfuscateKey()); + CDBBatch batch(&GetObfuscateKey()); for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) batch.Write(make_pair(DB_TXINDEX, it->first), it->second); return WriteBatch(batch); @@ -177,7 +177,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { bool CBlockTreeDB::LoadBlockIndexGuts() { - boost::scoped_ptr pcursor(NewIterator()); + boost::scoped_ptr pcursor(NewIterator()); pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); -- cgit v1.2.3 From 298e040bca0aad62b616a1d3e66e1e44d2b9bd3a Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Wed, 21 Oct 2015 23:23:59 +0200 Subject: Fix chainstate serialized_size computation --- src/txdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index f0868a1eb..cd76c0155 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -121,7 +121,7 @@ bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { nTotalAmount += out.nValue; } } - stats.nSerializedSize += 32 + pcursor->GetKeySize(); + stats.nSerializedSize += 32 + pcursor->GetValueSize(); ss << VARINT(0); } else { return error("CCoinsViewDB::GetStats() : unable to read value"); -- cgit v1.2.3 From fa24439ff3d8ab5b9efaf66ef4dae6713b88cb35 Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Sun, 13 Dec 2015 17:58:29 +0100 Subject: Bump copyright headers to 2015 --- src/txdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index cd76c0155..f99e11f26 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers +// Copyright (c) 2009-2015 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -- cgit v1.2.3 From 509cb006d514cece5ab7680094f033c8dc8a2318 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 28 Mar 2016 18:18:30 +0200 Subject: txdb: Add Cursor() method to CCoinsView to iterate over UTXO set Add a method Cursor() to CCoinsView that returns a cursor which can be used to iterate over the whole UTXO set. - rpc: Change gettxoutsetinfo to use new Cursor method - txdb: Remove GetStats method - Now that GetStats is implemented in terms of Cursor, remove it. --- src/txdb.cpp | 78 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 40 insertions(+), 38 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index f99e11f26..be86cceeb 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -94,50 +94,52 @@ bool CBlockTreeDB::ReadLastBlockFile(int &nFile) { return Read(DB_LAST_BLOCK, nFile); } -bool CCoinsViewDB::GetStats(CCoinsStats &stats) const { +CCoinsViewCursor *CCoinsViewDB::Cursor() const +{ + CCoinsViewDBCursor *i = new CCoinsViewDBCursor(const_cast(&db)->NewIterator(), GetBestBlock()); /* It seems that there are no "const iterators" for LevelDB. Since we only need read operations on it, use a const-cast to get around that restriction. */ - boost::scoped_ptr pcursor(const_cast(&db)->NewIterator()); - pcursor->Seek(DB_COINS); + i->pcursor->Seek(DB_COINS); + // Cache key of first record + i->pcursor->GetKey(i->keyTmp); + return i; +} - CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); - stats.hashBlock = GetBestBlock(); - ss << stats.hashBlock; - CAmount nTotalAmount = 0; - while (pcursor->Valid()) { - boost::this_thread::interruption_point(); - std::pair key; - CCoins coins; - if (pcursor->GetKey(key) && key.first == DB_COINS) { - if (pcursor->GetValue(coins)) { - stats.nTransactions++; - for (unsigned int i=0; iGetValueSize(); - ss << VARINT(0); - } else { - return error("CCoinsViewDB::GetStats() : unable to read value"); - } - } else { - break; - } - pcursor->Next(); +bool CCoinsViewDBCursor::GetKey(uint256 &key) const +{ + // Return cached key + if (keyTmp.first == DB_COINS) { + key = keyTmp.second; + return true; } - { - LOCK(cs_main); - stats.nHeight = mapBlockIndex.find(stats.hashBlock)->second->nHeight; + return false; +} + +bool CCoinsViewDBCursor::GetValue(CCoins &coins) const +{ + return pcursor->GetValue(coins); +} + +unsigned int CCoinsViewDBCursor::GetValueSize() const +{ + return pcursor->GetValueSize(); +} + +bool CCoinsViewDBCursor::Valid() const +{ + return keyTmp.first == DB_COINS; +} + +void CCoinsViewDBCursor::Next() +{ + pcursor->Next(); + if (pcursor->Valid()) { + bool ok = pcursor->GetKey(keyTmp); + assert(ok); // If GetKey fails here something must be wrong with underlying database, we cannot handle that here + } else { + keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false } - stats.hashSerialized = ss.GetHash(); - stats.nTotalAmount = nTotalAmount; - return true; } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { -- cgit v1.2.3 From 99e70751f23aa59ac297f6746dd8f09a140d48ae Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 5 Apr 2016 15:14:48 +0200 Subject: =?UTF-8?q?Break=20circular=20dependency=20main=20=E2=86=94=20txdb?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break the circular dependency between main and txdb by: - Moving `CBlockFileInfo` from `main.h` to `chain.h`. I think this makes sense, as the other block-file stuff is there too. - Moving `CDiskTxPos` from `main.h` to `txdb.h`. This type seems specific to txdb. - Pass a functor `insertBlockIndex` to `LoadBlockIndexGuts`. This leaves it up to the caller how to insert block indices. --- src/txdb.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index be86cceeb..caa6bde38 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -5,10 +5,8 @@ #include "txdb.h" -#include "chain.h" #include "chainparams.h" #include "hash.h" -#include "main.h" #include "pow.h" #include "uint256.h" @@ -177,7 +175,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { return true; } -bool CBlockTreeDB::LoadBlockIndexGuts() +bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) { boost::scoped_ptr pcursor(NewIterator()); @@ -191,8 +189,8 @@ bool CBlockTreeDB::LoadBlockIndexGuts() CDiskBlockIndex diskindex; if (pcursor->GetValue(diskindex)) { // Construct block index object - CBlockIndex* pindexNew = InsertBlockIndex(diskindex.GetBlockHash()); - pindexNew->pprev = InsertBlockIndex(diskindex.hashPrev); + CBlockIndex* pindexNew = insertBlockIndex(diskindex.GetBlockHash()); + pindexNew->pprev = insertBlockIndex(diskindex.hashPrev); pindexNew->nHeight = diskindex.nHeight; pindexNew->nFile = diskindex.nFile; pindexNew->nDataPos = diskindex.nDataPos; -- cgit v1.2.3 From a3310b4d485b1510c240f1db882530590b6fd7c9 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Mon, 18 Apr 2016 12:05:32 +0200 Subject: txdb: Fix assert crash in new UTXO set cursor Remove the mistaken assumption that GetKey returning false signifies an internal database issue. It will return false when the key cannot be deserialized into the (char,uint256) stanza, which indicates that the cursor has reached a different kind of key. Fixes bug #7890 introduced in #7756. --- src/txdb.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index be86cceeb..19ca17865 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -134,12 +134,8 @@ bool CCoinsViewDBCursor::Valid() const void CCoinsViewDBCursor::Next() { pcursor->Next(); - if (pcursor->Valid()) { - bool ok = pcursor->GetKey(keyTmp); - assert(ok); // If GetKey fails here something must be wrong with underlying database, we cannot handle that here - } else { + if (!pcursor->Valid() || !pcursor->GetKey(keyTmp)) keyTmp.first = 0; // Invalidate cached key after last record so that Valid() and GetKey() return false - } } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { -- cgit v1.2.3 From b69836d6ff2bd7dc9568ad4af8235662bb4f1826 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Wed, 20 Apr 2016 11:46:01 +0200 Subject: dbwrapper: Pass parent CDBWrapper into CDBBatch and CDBIterator Pass parent wrapper directly instead of obfuscation key. This makes it possible for other databases which re-use this code to use other properties from the database. Add a namespace dbwrapper_private for private functions to be used only in dbwrapper.h/cpp and dbwrapper_tests. --- src/txdb.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 19ca17865..5fbaeb608 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -49,7 +49,7 @@ uint256 CCoinsViewDB::GetBestBlock() const { } bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { - CDBBatch batch(&db.GetObfuscateKey()); + CDBBatch batch(db); size_t count = 0; size_t changed = 0; for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { @@ -139,7 +139,7 @@ void CCoinsViewDBCursor::Next() } bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { - CDBBatch batch(&GetObfuscateKey()); + CDBBatch batch(*this); for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); } @@ -155,7 +155,7 @@ bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { } bool CBlockTreeDB::WriteTxIndex(const std::vector >&vect) { - CDBBatch batch(&GetObfuscateKey()); + CDBBatch batch(*this); for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) batch.Write(make_pair(DB_TXINDEX, it->first), it->second); return WriteBatch(batch); -- cgit v1.2.3 From cdd79eb70fe163a92531a6f11c72bce6d228dac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Tue, 30 Aug 2016 22:41:56 +0200 Subject: C++11: s/boost::scoped_ptr/std::unique_ptr/ --- src/txdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 078c29def..4f11c7b95 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -173,7 +173,7 @@ bool CBlockTreeDB::ReadFlag(const std::string &name, bool &fValue) { bool CBlockTreeDB::LoadBlockIndexGuts(boost::function insertBlockIndex) { - boost::scoped_ptr pcursor(NewIterator()); + std::unique_ptr pcursor(NewIterator()); pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); -- cgit v1.2.3 From 27765b6403cece54320374b37afb01a0cfe571c3 Mon Sep 17 00:00:00 2001 From: isle2983 Date: Sat, 31 Dec 2016 11:01:21 -0700 Subject: Increment MIT Licence copyright header year on files modified in 2016 Edited via: $ contrib/devtools/copyright_header.py update . --- src/txdb.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 4f11c7b95..c223abd59 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2015 The Bitcoin Core developers +// Copyright (c) 2009-2016 The Bitcoin Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -- cgit v1.2.3 From b7b48c8bbdf7a90861610b035d8b0a247ef78c45 Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Fri, 27 Jan 2017 17:43:41 +0900 Subject: Refactor: Remove using namespace from src/*.cpp. --- src/txdb.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index c223abd59..1a30bb58a 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -14,8 +14,6 @@ #include -using namespace std; - static const char DB_COINS = 'c'; static const char DB_BLOCK_FILES = 'f'; static const char DB_TXINDEX = 't'; @@ -32,11 +30,11 @@ CCoinsViewDB::CCoinsViewDB(size_t nCacheSize, bool fMemory, bool fWipe) : db(Get } bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const { - return db.Read(make_pair(DB_COINS, txid), coins); + return db.Read(std::make_pair(DB_COINS, txid), coins); } bool CCoinsViewDB::HaveCoins(const uint256 &txid) const { - return db.Exists(make_pair(DB_COINS, txid)); + return db.Exists(std::make_pair(DB_COINS, txid)); } uint256 CCoinsViewDB::GetBestBlock() const { @@ -53,9 +51,9 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { if (it->second.coins.IsPruned()) - batch.Erase(make_pair(DB_COINS, it->first)); + batch.Erase(std::make_pair(DB_COINS, it->first)); else - batch.Write(make_pair(DB_COINS, it->first), it->second.coins); + batch.Write(std::make_pair(DB_COINS, it->first), it->second.coins); changed++; } count++; @@ -73,7 +71,7 @@ CBlockTreeDB::CBlockTreeDB(size_t nCacheSize, bool fMemory, bool fWipe) : CDBWra } bool CBlockTreeDB::ReadBlockFileInfo(int nFile, CBlockFileInfo &info) { - return Read(make_pair(DB_BLOCK_FILES, nFile), info); + return Read(std::make_pair(DB_BLOCK_FILES, nFile), info); } bool CBlockTreeDB::WriteReindexing(bool fReindexing) { @@ -139,23 +137,23 @@ void CCoinsViewDBCursor::Next() bool CBlockTreeDB::WriteBatchSync(const std::vector >& fileInfo, int nLastFile, const std::vector& blockinfo) { CDBBatch batch(*this); for (std::vector >::const_iterator it=fileInfo.begin(); it != fileInfo.end(); it++) { - batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second); + batch.Write(std::make_pair(DB_BLOCK_FILES, it->first), *it->second); } batch.Write(DB_LAST_BLOCK, nLastFile); for (std::vector::const_iterator it=blockinfo.begin(); it != blockinfo.end(); it++) { - batch.Write(make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it)); + batch.Write(std::make_pair(DB_BLOCK_INDEX, (*it)->GetBlockHash()), CDiskBlockIndex(*it)); } return WriteBatch(batch, true); } bool CBlockTreeDB::ReadTxIndex(const uint256 &txid, CDiskTxPos &pos) { - return Read(make_pair(DB_TXINDEX, txid), pos); + return Read(std::make_pair(DB_TXINDEX, txid), pos); } bool CBlockTreeDB::WriteTxIndex(const std::vector >&vect) { CDBBatch batch(*this); for (std::vector >::const_iterator it=vect.begin(); it!=vect.end(); it++) - batch.Write(make_pair(DB_TXINDEX, it->first), it->second); + batch.Write(std::make_pair(DB_TXINDEX, it->first), it->second); return WriteBatch(batch); } @@ -175,7 +173,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::function pcursor(NewIterator()); - pcursor->Seek(make_pair(DB_BLOCK_INDEX, uint256())); + pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256())); // Load mapBlockIndex while (pcursor->Valid()) { -- cgit v1.2.3 From 87a21d5922f3cdc7a7e21090dc7078e0774c1c1f Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Tue, 23 May 2017 10:04:14 -0700 Subject: Fix: make CCoinsViewDbCursor::Seek work for missing keys Thanks to Suhas Daftuar for figuring this out. Github-Pull: #10445 Rebased-From: 822755a424d0abfa408dc34313f4aca4b816f54f --- src/txdb.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 1a30bb58a..662e7cb06 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -98,7 +98,11 @@ CCoinsViewCursor *CCoinsViewDB::Cursor() const that restriction. */ i->pcursor->Seek(DB_COINS); // Cache key of first record - i->pcursor->GetKey(i->keyTmp); + if (i->pcursor->Valid()) { + i->pcursor->GetKey(i->keyTmp); + } else { + i->keyTmp.first = 0; // Make sure Valid() and GetKey() return false + } return i; } -- cgit v1.2.3 From b506efbe747ba31ee1f41be14cdbc0c30dfcf67f Mon Sep 17 00:00:00 2001 From: Warren Togami Date: Wed, 21 May 2014 20:24:15 +0100 Subject: Litecoin: Scrypt n=1024 Pow hash based upon Colin Percival's Tarnsnap (2009) Modified by Artforz, coblee, pooler, wtogami, Nikolay Belikov, Adrian Gallagher --- src/txdb.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 662e7cb06..0f11b5f0c 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -200,8 +200,9 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::functionnNonce = diskindex.nNonce; pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; + pindexNew->hashBlockPoW = diskindex.hashBlockPoW; - if (!CheckProofOfWork(pindexNew->GetBlockHash(), pindexNew->nBits, Params().GetConsensus())) + if (!CheckProofOfWork(pindexNew->GetBlockPoWHash(), pindexNew->nBits, Params().GetConsensus())) return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString()); pcursor->Next(); -- cgit v1.2.3 From bc8cca48968dfa3f60b5eae6a2b92bdd2870eee3 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Sun, 13 Aug 2017 13:31:12 +0100 Subject: Merge AuxPoW support from Namecore Changes are as below: Wrap CBlockHeader::nVersion into a new class (CBlockVersion). This allows to take care of interpreting the field into a base version, auxpow flag and the chain ID. Update getauxblock.py for new 'generate' RPC call. Add 'auxpow' to block JSON. Accept auxpow as PoW verification. Add unit tests for auxpow verification. Add check for memory-layout of CBlockVersion. Weaken auxpow chain ID checks for the testnet. Allow Params() to overrule when to check the auxpow chain ID and for legacy blocks. Use this to disable the checks on testnet. Introduce CPureBlockHeader. Split the block header part that is used by auxpow and the "real" block header (that uses auxpow) to resolve the cyclic dependency between the two. Differentiate between uint256 and arith_uint256. This change was done upstream, modify the auxpow code. Add missing lock in auxpow_tests. Fix REST header check for auxpow headers. Those can be longer, thus take that into account. Also perform the check actually on an auxpow header. Correctly set the coinbase for getauxblock results. Call IncrementExtraNonce in getauxblock so that the coinbase is actually initialised with the stuff it should be. (BIP30 block height and COINBASE_FLAGS.) Implement getauxblock plus regression test. Turn auxpow test into FIXTURE test. This allows using of the Params() calls. Move CMerkleTx code to auxpow.cpp. Otherwise we get linker errors when building without wallet. Fix rebase with BIP66. Update the code to handle BIP66's nVersion=3. Enforce that auxpow parent blocks have no auxpow block version. This is for compatibility with namecoind. See also https://github.com/namecoin/namecoin/pull/199. Move auxpow-related parameters to Consensus::Params. --- src/txdb.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/txdb.cpp') diff --git a/src/txdb.cpp b/src/txdb.cpp index 0f11b5f0c..b27ad8010 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -200,10 +200,11 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::functionnNonce = diskindex.nNonce; pindexNew->nStatus = diskindex.nStatus; pindexNew->nTx = diskindex.nTx; - pindexNew->hashBlockPoW = diskindex.hashBlockPoW; - if (!CheckProofOfWork(pindexNew->GetBlockPoWHash(), pindexNew->nBits, Params().GetConsensus())) - return error("LoadBlockIndex(): CheckProofOfWork failed: %s", pindexNew->ToString()); + /* Bitcoin checks the PoW here. We don't do this because + the CDiskBlockIndex does not contain the auxpow. + This check isn't important, since the data on disk should + already be valid and can be trusted. */ pcursor->Next(); } else { -- cgit v1.2.3