diff --git a/src/Makefile.am b/src/Makefile.am --- a/src/Makefile.am +++ b/src/Makefile.am @@ -169,6 +169,7 @@ util.h \ utilmoneystr.h \ utiltime.h \ + utxocommit.cpp \ validation.h \ validationinterface.h \ versionbits.h \ @@ -233,7 +234,6 @@ txdb.cpp \ txmempool.cpp \ ui_interface.cpp \ - utxocommit.cpp \ validation.cpp \ validationinterface.cpp \ versionbits.cpp \ diff --git a/src/coins.h b/src/coins.h --- a/src/coins.h +++ b/src/coins.h @@ -12,11 +12,14 @@ #include "memusage.h" #include "serialize.h" #include "uint256.h" +#include "utxocommit.h" #include #include #include +class CUtxoCommit; + /** * A UTXO entry. * @@ -166,7 +169,8 @@ //! Do a bulk modification (multiple Coin changes + BestBlock change). //! The passed mapCoins can be modified. - virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock); + virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta); //! Get a cursor to iterate over the whole state virtual CCoinsViewCursor *Cursor() const; @@ -176,6 +180,8 @@ //! Estimate database size (0 if not implemented) virtual size_t EstimateSize() const { return 0; } + + virtual CUtxoCommit GetCommitment() const; }; /** CCoinsView backed by another CCoinsView */ @@ -190,9 +196,11 @@ uint256 GetBestBlock() const override; std::vector GetHeadBlocks() const override; void SetBackend(CCoinsView &viewIn); - bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override; + bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta) override; CCoinsViewCursor *Cursor() const override; size_t EstimateSize() const override; + CUtxoCommit GetCommitment() const override; }; /** @@ -210,6 +218,8 @@ /* Cached dynamic memory usage for the inner Coin objects. */ mutable size_t cachedCoinsUsage; + CUtxoCommit cacheUtxoCommitDelta; + public: CCoinsViewCache(CCoinsView *baseIn); @@ -218,7 +228,8 @@ bool HaveCoin(const COutPoint &outpoint) const override; uint256 GetBestBlock() const override; void SetBestBlock(const uint256 &hashBlock); - bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override; + bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta) override; /** * Check if we have the given utxo already loaded in this cache. @@ -256,6 +267,12 @@ */ bool Flush(); + /** + * Returns the UTXO commitment from the current full set + * This is the combination of the backed commitment and the commitment delta + */ + CUtxoCommit GetCommitment() const; + /** * Removes the UTXO with the given outpoint from the cache, if it is not * modified. diff --git a/src/coins.cpp b/src/coins.cpp --- a/src/coins.cpp +++ b/src/coins.cpp @@ -22,13 +22,18 @@ std::vector CCoinsView::GetHeadBlocks() const { return std::vector(); } -bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { +bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta) { return false; } CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; } +CUtxoCommit CCoinsView::GetCommitment() const { + return CUtxoCommit(); +} + CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) {} bool CCoinsViewBacked::GetCoin(const COutPoint &outpoint, Coin &coin) const { return base->GetCoin(outpoint, coin); @@ -45,9 +50,9 @@ void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } -bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, - const uint256 &hashBlock) { - return base->BatchWrite(mapCoins, hashBlock); +bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta) { + return base->BatchWrite(mapCoins, hashBlock, commitDelta); } CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); @@ -56,6 +61,10 @@ return base->EstimateSize(); } +CUtxoCommit CCoinsViewBacked::GetCommitment() const { + return base->GetCommitment(); +} + SaltedOutpointHasher::SaltedOutpointHasher() : k0(GetRand(std::numeric_limits::max())), k1(GetRand(std::numeric_limits::max())) {} @@ -126,6 +135,8 @@ it->second.flags |= CCoinsCacheEntry::DIRTY | (fresh ? CCoinsCacheEntry::FRESH : 0); cachedCoinsUsage += it->second.coin.DynamicMemoryUsage(); + + cacheUtxoCommitDelta.Add(outpoint, coin); } void AddCoins(CCoinsViewCache &cache, const CTransaction &tx, int nHeight, @@ -147,6 +158,8 @@ if (it == cacheCoins.end()) { return false; } + cacheUtxoCommitDelta.Remove(outpoint, it->second.coin); + cachedCoinsUsage -= it->second.coin.DynamicMemoryUsage(); if (moveout) { *moveout = std::move(it->second.coin); @@ -192,7 +205,9 @@ } bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, - const uint256 &hashBlockIn) { + const uint256 &hashBlockIn, + CUtxoCommit &commitDelta) { + // TODO: Kill this function; it's not used apart from a test for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { // Ignore non-dirty entries (optimization). if (it->second.flags & CCoinsCacheEntry::DIRTY) { @@ -255,12 +270,17 @@ } bool CCoinsViewCache::Flush() { - bool fOk = base->BatchWrite(cacheCoins, hashBlock); + bool fOk = base->BatchWrite(cacheCoins, hashBlock, cacheUtxoCommitDelta); cacheCoins.clear(); cachedCoinsUsage = 0; return fOk; } +CUtxoCommit CCoinsViewCache::GetCommitment() const { + CUtxoCommit combined(this->cacheUtxoCommitDelta, base->GetCommitment()); + return combined; +} + void CCoinsViewCache::Uncache(const COutPoint &outpoint) { CCoinsMap::iterator it = cacheCoins.find(outpoint); if (it != cacheCoins.end() && it->second.flags == 0) { diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -54,7 +54,8 @@ uint256 GetBestBlock() const override { return hashBestBlock_; } - bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override { + bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta) override { for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) { if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Same optimization used in CCoinsViewDB is to only write dirty @@ -610,7 +611,9 @@ void WriteCoinViewEntry(CCoinsView &view, const Amount value, char flags) { CCoinsMap map; InsertCoinMapEntry(map, value, flags); - view.BatchWrite(map, {}); + CUtxoCommit commit; + commit.Add(map.begin()->first, map.begin()->second.coin); + view.BatchWrite(map, {}, commit); } class SingleEntryCacheTest { diff --git a/src/test/utxocommit_tests.cpp b/src/test/utxocommit_tests.cpp --- a/src/test/utxocommit_tests.cpp +++ b/src/test/utxocommit_tests.cpp @@ -131,7 +131,8 @@ // This simulates the initial upgrade where the commitment stored in // LevelDB must be generated from the existing UTXO set. - const int count = 50000; + const int count = 1000000; + fPrintToConsole = true; // We use the pcoinviewdb provided by the test fixture's TestingSetup CCoinsViewCache cache(pcoinsdbview); diff --git a/src/txdb.h b/src/txdb.h --- a/src/txdb.h +++ b/src/txdb.h @@ -73,7 +73,8 @@ bool HaveCoin(const COutPoint &outpoint) const override; uint256 GetBestBlock() const override; std::vector GetHeadBlocks() const override; - bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override; + bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta) override; CCoinsViewCursor *Cursor() const override; //! Attempt to update from an older database format. diff --git a/src/txdb.cpp b/src/txdb.cpp --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -78,7 +78,8 @@ return vhashHeadBlocks; } -bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { +bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, + CUtxoCommit &commitDelta) { CDBBatch batch(db); size_t count = 0; size_t changed = 0; diff --git a/src/utxocommit.h b/src/utxocommit.h --- a/src/utxocommit.h +++ b/src/utxocommit.h @@ -5,12 +5,12 @@ #ifndef BITCOIN_UTXOCOMMIT_H #define BITCOIN_UTXOCOMMIT_H -#include "coins.h" #include "hash.h" #include "secp256k1/include/secp256k1_multiset.h" #include "streams.h" #include +class COutPoint; class Coin; class CCoinsViewCursor; diff --git a/src/utxocommit.cpp b/src/utxocommit.cpp --- a/src/utxocommit.cpp +++ b/src/utxocommit.cpp @@ -3,7 +3,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "utxocommit.h" - +#include "coins.h" #include "util.h" namespace {