Add mapSerials infrastructure to CCoinsView.
This adds the TXDB/CCoinsViewCache primitives necessary for writing consensus rules for mapSerials later.
This commit is contained in:
parent
9f25631d50
commit
45d6bee945
|
@ -41,6 +41,7 @@ bool CCoins::Spend(uint32_t nPos)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool CCoinsView::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return false; }
|
bool CCoinsView::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return false; }
|
||||||
|
bool CCoinsView::GetSerial(const uint256 &serial) const { return false; }
|
||||||
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
|
bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; }
|
||||||
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
|
bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; }
|
||||||
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
||||||
|
@ -48,13 +49,15 @@ uint256 CCoinsView::GetBestAnchor() const { return uint256(); };
|
||||||
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins,
|
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashAnchor,
|
const uint256 &hashAnchor,
|
||||||
CAnchorsMap &mapAnchors) { return false; }
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials) { return false; }
|
||||||
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
|
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
|
||||||
|
|
||||||
|
|
||||||
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
|
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
|
||||||
|
|
||||||
bool CCoinsViewBacked::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return base->GetAnchorAt(rt, tree); }
|
bool CCoinsViewBacked::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const { return base->GetAnchorAt(rt, tree); }
|
||||||
|
bool CCoinsViewBacked::GetSerial(const uint256 &serial) const { return base->GetSerial(serial); }
|
||||||
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
|
bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); }
|
||||||
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
|
bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); }
|
||||||
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
||||||
|
@ -63,7 +66,8 @@ void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||||
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins,
|
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashAnchor,
|
const uint256 &hashAnchor,
|
||||||
CAnchorsMap &mapAnchors) { return base->BatchWrite(mapCoins, hashBlock, hashAnchor, mapAnchors); }
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials) { return base->BatchWrite(mapCoins, hashBlock, hashAnchor, mapAnchors, mapSerials); }
|
||||||
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
|
bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); }
|
||||||
|
|
||||||
CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
|
CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {}
|
||||||
|
@ -121,6 +125,21 @@ bool CCoinsViewCache::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMer
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCoinsViewCache::GetSerial(const uint256 &serial) const {
|
||||||
|
CSerialsMap::iterator it = cacheSerials.find(serial);
|
||||||
|
if (it != cacheSerials.end())
|
||||||
|
return it->second.entered;
|
||||||
|
|
||||||
|
CSerialsCacheEntry entry;
|
||||||
|
bool tmp = base->GetSerial(serial);
|
||||||
|
entry.entered = tmp;
|
||||||
|
|
||||||
|
cacheSerials.insert(std::make_pair(serial, entry));
|
||||||
|
|
||||||
|
// TODO: cache usage
|
||||||
|
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
void CCoinsViewCache::PushAnchor(const libzerocash::IncrementalMerkleTree &tree) {
|
void CCoinsViewCache::PushAnchor(const libzerocash::IncrementalMerkleTree &tree) {
|
||||||
std::vector<unsigned char> newrt_v(32);
|
std::vector<unsigned char> newrt_v(32);
|
||||||
|
@ -161,6 +180,12 @@ void CCoinsViewCache::PopAnchor(const uint256 &newrt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCoinsViewCache::SetSerial(const uint256 &serial, bool spent) {
|
||||||
|
std::pair<CSerialsMap::iterator, bool> ret = cacheSerials.insert(std::make_pair(serial, CSerialsCacheEntry()));
|
||||||
|
ret.first->second.entered = spent;
|
||||||
|
ret.first->second.flags |= CSerialsCacheEntry::DIRTY;
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
|
bool CCoinsViewCache::GetCoins(const uint256 &txid, CCoins &coins) const {
|
||||||
CCoinsMap::const_iterator it = FetchCoins(txid);
|
CCoinsMap::const_iterator it = FetchCoins(txid);
|
||||||
if (it != cacheCoins.end()) {
|
if (it != cacheCoins.end()) {
|
||||||
|
@ -229,7 +254,8 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
|
||||||
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
|
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlockIn,
|
const uint256 &hashBlockIn,
|
||||||
const uint256 &hashAnchorIn,
|
const uint256 &hashAnchorIn,
|
||||||
CAnchorsMap &mapAnchors) {
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials) {
|
||||||
assert(!hasModifier);
|
assert(!hasModifier);
|
||||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
|
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end();) {
|
||||||
if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
|
if (it->second.flags & CCoinsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
|
||||||
|
@ -294,15 +320,44 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
|
||||||
CAnchorsMap::iterator itOld = child_it++;
|
CAnchorsMap::iterator itOld = child_it++;
|
||||||
mapAnchors.erase(itOld);
|
mapAnchors.erase(itOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (CSerialsMap::iterator child_it = mapSerials.begin(); child_it != mapSerials.end();)
|
||||||
|
{
|
||||||
|
if (child_it->second.flags & CSerialsCacheEntry::DIRTY) { // Ignore non-dirty entries (optimization).
|
||||||
|
CSerialsMap::iterator parent_it = cacheSerials.find(child_it->first);
|
||||||
|
|
||||||
|
if (parent_it == cacheSerials.end()) {
|
||||||
|
if (child_it->second.entered) {
|
||||||
|
// Parent doesn't have an entry, but child has a SPENT serial.
|
||||||
|
// Move the spent serial up.
|
||||||
|
|
||||||
|
CSerialsCacheEntry& entry = cacheSerials[child_it->first];
|
||||||
|
entry.entered = true;
|
||||||
|
entry.flags = CSerialsCacheEntry::DIRTY;
|
||||||
|
|
||||||
|
// TODO: cache usage
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (parent_it->second.entered != child_it->second.entered) {
|
||||||
|
parent_it->second.entered = child_it->second.entered;
|
||||||
|
parent_it->second.flags |= CSerialsCacheEntry::DIRTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CSerialsMap::iterator itOld = child_it++;
|
||||||
|
mapSerials.erase(itOld);
|
||||||
|
}
|
||||||
|
|
||||||
hashAnchor = hashAnchorIn;
|
hashAnchor = hashAnchorIn;
|
||||||
hashBlock = hashBlockIn;
|
hashBlock = hashBlockIn;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::Flush() {
|
bool CCoinsViewCache::Flush() {
|
||||||
bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashAnchor, cacheAnchors);
|
bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashAnchor, cacheAnchors, cacheSerials);
|
||||||
cacheCoins.clear();
|
cacheCoins.clear();
|
||||||
cacheAnchors.clear();
|
cacheAnchors.clear();
|
||||||
|
cacheSerials.clear();
|
||||||
cachedCoinsUsage = 0;
|
cachedCoinsUsage = 0;
|
||||||
return fOk;
|
return fOk;
|
||||||
}
|
}
|
||||||
|
|
31
src/coins.h
31
src/coins.h
|
@ -311,8 +311,21 @@ struct CAnchorsCacheEntry
|
||||||
CAnchorsCacheEntry() : entered(false), flags(0), tree(INCREMENTAL_MERKLE_TREE_DEPTH) {}
|
CAnchorsCacheEntry() : entered(false), flags(0), tree(INCREMENTAL_MERKLE_TREE_DEPTH) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CSerialsCacheEntry
|
||||||
|
{
|
||||||
|
bool entered; // If the serial is spent or not
|
||||||
|
unsigned char flags;
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
|
||||||
|
};
|
||||||
|
|
||||||
|
CSerialsCacheEntry() : entered(false), flags(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
|
typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
|
||||||
typedef boost::unordered_map<uint256, CAnchorsCacheEntry, CCoinsKeyHasher> CAnchorsMap;
|
typedef boost::unordered_map<uint256, CAnchorsCacheEntry, CCoinsKeyHasher> CAnchorsMap;
|
||||||
|
typedef boost::unordered_map<uint256, CSerialsCacheEntry, CCoinsKeyHasher> CSerialsMap;
|
||||||
|
|
||||||
struct CCoinsStats
|
struct CCoinsStats
|
||||||
{
|
{
|
||||||
|
@ -335,6 +348,9 @@ public:
|
||||||
//! Retrieve the tree at a particular anchored root in the chain
|
//! Retrieve the tree at a particular anchored root in the chain
|
||||||
virtual bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
virtual bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
||||||
|
|
||||||
|
//! Determine whether a serial is spent or not
|
||||||
|
virtual bool GetSerial(const uint256 &serial) const;
|
||||||
|
|
||||||
//! Retrieve the CCoins (unspent transaction outputs) for a given txid
|
//! Retrieve the CCoins (unspent transaction outputs) for a given txid
|
||||||
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
virtual bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||||
|
|
||||||
|
@ -353,7 +369,8 @@ public:
|
||||||
virtual bool BatchWrite(CCoinsMap &mapCoins,
|
virtual bool BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashAnchor,
|
const uint256 &hashAnchor,
|
||||||
CAnchorsMap &mapAnchors);
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials);
|
||||||
|
|
||||||
//! Calculate statistics about the unspent transaction output set
|
//! Calculate statistics about the unspent transaction output set
|
||||||
virtual bool GetStats(CCoinsStats &stats) const;
|
virtual bool GetStats(CCoinsStats &stats) const;
|
||||||
|
@ -372,6 +389,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
CCoinsViewBacked(CCoinsView *viewIn);
|
CCoinsViewBacked(CCoinsView *viewIn);
|
||||||
bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
||||||
|
bool GetSerial(const uint256 &serial) const;
|
||||||
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||||
bool HaveCoins(const uint256 &txid) const;
|
bool HaveCoins(const uint256 &txid) const;
|
||||||
uint256 GetBestBlock() const;
|
uint256 GetBestBlock() const;
|
||||||
|
@ -380,7 +398,8 @@ public:
|
||||||
bool BatchWrite(CCoinsMap &mapCoins,
|
bool BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashAnchor,
|
const uint256 &hashAnchor,
|
||||||
CAnchorsMap &mapAnchors);
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials);
|
||||||
bool GetStats(CCoinsStats &stats) const;
|
bool GetStats(CCoinsStats &stats) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -423,6 +442,7 @@ protected:
|
||||||
mutable CCoinsMap cacheCoins;
|
mutable CCoinsMap cacheCoins;
|
||||||
mutable uint256 hashAnchor;
|
mutable uint256 hashAnchor;
|
||||||
mutable CAnchorsMap cacheAnchors;
|
mutable CAnchorsMap cacheAnchors;
|
||||||
|
mutable CSerialsMap cacheSerials;
|
||||||
|
|
||||||
/* Cached dynamic memory usage for the inner CCoins objects. */
|
/* Cached dynamic memory usage for the inner CCoins objects. */
|
||||||
mutable size_t cachedCoinsUsage;
|
mutable size_t cachedCoinsUsage;
|
||||||
|
@ -433,6 +453,7 @@ public:
|
||||||
|
|
||||||
// Standard CCoinsView methods
|
// Standard CCoinsView methods
|
||||||
bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
||||||
|
bool GetSerial(const uint256 &serial) const;
|
||||||
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||||
bool HaveCoins(const uint256 &txid) const;
|
bool HaveCoins(const uint256 &txid) const;
|
||||||
uint256 GetBestBlock() const;
|
uint256 GetBestBlock() const;
|
||||||
|
@ -441,7 +462,8 @@ public:
|
||||||
bool BatchWrite(CCoinsMap &mapCoins,
|
bool BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashAnchor,
|
const uint256 &hashAnchor,
|
||||||
CAnchorsMap &mapAnchors);
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials);
|
||||||
|
|
||||||
|
|
||||||
// Adds the tree to mapAnchors and sets the current commitment
|
// Adds the tree to mapAnchors and sets the current commitment
|
||||||
|
@ -452,6 +474,9 @@ public:
|
||||||
// the new current root.
|
// the new current root.
|
||||||
void PopAnchor(const uint256 &rt);
|
void PopAnchor(const uint256 &rt);
|
||||||
|
|
||||||
|
// Marks a serial as spent or not.
|
||||||
|
void SetSerial(const uint256 &serial, bool spent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a pointer to CCoins in the cache, or NULL if not found. This is
|
* Return a pointer to CCoins in the cache, or NULL if not found. This is
|
||||||
* more efficient than GetCoins. Modifications to other cache entries are
|
* more efficient than GetCoins. Modifications to other cache entries are
|
||||||
|
|
|
@ -21,6 +21,7 @@ class CCoinsViewTest : public CCoinsView
|
||||||
uint256 hashBestAnchor_;
|
uint256 hashBestAnchor_;
|
||||||
std::map<uint256, CCoins> map_;
|
std::map<uint256, CCoins> map_;
|
||||||
std::map<uint256, libzerocash::IncrementalMerkleTree> mapAnchors_;
|
std::map<uint256, libzerocash::IncrementalMerkleTree> mapAnchors_;
|
||||||
|
std::map<uint256, bool> mapSerials_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool GetAnchorAt(const uint256& rt, libzerocash::IncrementalMerkleTree &tree) const {
|
bool GetAnchorAt(const uint256& rt, libzerocash::IncrementalMerkleTree &tree) const {
|
||||||
|
@ -39,6 +40,19 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetSerial(const uint256 &serial) const
|
||||||
|
{
|
||||||
|
std::map<uint256, bool>::const_iterator it = mapSerials_.find(serial);
|
||||||
|
|
||||||
|
if (it == mapSerials_.end()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// The map shouldn't contain any false entries.
|
||||||
|
assert(it->second);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint256 GetBestAnchor() const { return hashBestAnchor_; }
|
uint256 GetBestAnchor() const { return hashBestAnchor_; }
|
||||||
|
|
||||||
bool GetCoins(const uint256& txid, CCoins& coins) const
|
bool GetCoins(const uint256& txid, CCoins& coins) const
|
||||||
|
@ -66,7 +80,8 @@ public:
|
||||||
bool BatchWrite(CCoinsMap& mapCoins,
|
bool BatchWrite(CCoinsMap& mapCoins,
|
||||||
const uint256& hashBlock,
|
const uint256& hashBlock,
|
||||||
const uint256& hashAnchor,
|
const uint256& hashAnchor,
|
||||||
CAnchorsMap& mapAnchors)
|
CAnchorsMap& mapAnchors,
|
||||||
|
CSerialsMap& mapSerials)
|
||||||
{
|
{
|
||||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) {
|
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); ) {
|
||||||
map_[it->first] = it->second.coins;
|
map_[it->first] = it->second.coins;
|
||||||
|
@ -84,8 +99,17 @@ public:
|
||||||
}
|
}
|
||||||
mapAnchors.erase(it++);
|
mapAnchors.erase(it++);
|
||||||
}
|
}
|
||||||
|
for (CSerialsMap::iterator it = mapSerials.begin(); it != mapSerials.end(); ) {
|
||||||
|
if (it->second.entered) {
|
||||||
|
mapSerials_[it->first] = true;
|
||||||
|
} else {
|
||||||
|
mapSerials_.erase(it->first);
|
||||||
|
}
|
||||||
|
mapSerials.erase(it++);
|
||||||
|
}
|
||||||
mapCoins.clear();
|
mapCoins.clear();
|
||||||
mapAnchors.clear();
|
mapAnchors.clear();
|
||||||
|
mapSerials.clear();
|
||||||
hashBestBlock_ = hashBlock;
|
hashBestBlock_ = hashBlock;
|
||||||
hashBestAnchor_ = hashAnchor;
|
hashBestAnchor_ = hashAnchor;
|
||||||
return true;
|
return true;
|
||||||
|
@ -113,6 +137,30 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(serials_test)
|
||||||
|
{
|
||||||
|
CCoinsViewTest base;
|
||||||
|
CCoinsViewCacheTest cache(&base);
|
||||||
|
|
||||||
|
uint256 myserial = GetRandHash();
|
||||||
|
|
||||||
|
BOOST_CHECK(!cache.GetSerial(myserial));
|
||||||
|
cache.SetSerial(myserial, true);
|
||||||
|
BOOST_CHECK(cache.GetSerial(myserial));
|
||||||
|
cache.Flush();
|
||||||
|
|
||||||
|
CCoinsViewCacheTest cache2(&base);
|
||||||
|
|
||||||
|
BOOST_CHECK(cache2.GetSerial(myserial));
|
||||||
|
cache2.SetSerial(myserial, false);
|
||||||
|
BOOST_CHECK(!cache2.GetSerial(myserial));
|
||||||
|
cache2.Flush();
|
||||||
|
|
||||||
|
CCoinsViewCacheTest cache3(&base);
|
||||||
|
|
||||||
|
BOOST_CHECK(!cache3.GetSerial(myserial));
|
||||||
|
}
|
||||||
|
|
||||||
void appendRandomCommitment(IncrementalMerkleTree &tree)
|
void appendRandomCommitment(IncrementalMerkleTree &tree)
|
||||||
{
|
{
|
||||||
Address addr = Address::CreateNewRandomAddress();
|
Address addr = Address::CreateNewRandomAddress();
|
||||||
|
|
30
src/txdb.cpp
30
src/txdb.cpp
|
@ -18,6 +18,7 @@
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static const char DB_ANCHOR = 'A';
|
static const char DB_ANCHOR = 'A';
|
||||||
|
static const char DB_SERIAL = 's';
|
||||||
static const char DB_COINS = 'c';
|
static const char DB_COINS = 'c';
|
||||||
static const char DB_BLOCK_FILES = 'f';
|
static const char DB_BLOCK_FILES = 'f';
|
||||||
static const char DB_TXINDEX = 't';
|
static const char DB_TXINDEX = 't';
|
||||||
|
@ -42,6 +43,13 @@ void static BatchWriteAnchor(CLevelDBBatch &batch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static BatchWriteSerial(CLevelDBBatch &batch, const uint256 &serial, const bool &entered) {
|
||||||
|
if (!entered)
|
||||||
|
batch.Erase(make_pair(DB_SERIAL, serial));
|
||||||
|
else
|
||||||
|
batch.Write(make_pair(DB_SERIAL, serial), true);
|
||||||
|
}
|
||||||
|
|
||||||
void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
|
void static BatchWriteCoins(CLevelDBBatch &batch, const uint256 &hash, const CCoins &coins) {
|
||||||
if (coins.IsPruned())
|
if (coins.IsPruned())
|
||||||
batch.Erase(make_pair(DB_COINS, hash));
|
batch.Erase(make_pair(DB_COINS, hash));
|
||||||
|
@ -81,6 +89,16 @@ bool CCoinsViewDB::GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkle
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCoinsViewDB::GetSerial(const uint256 &serial) const {
|
||||||
|
bool spent = false;
|
||||||
|
bool read = db.Read(make_pair(DB_SERIAL, serial), spent);
|
||||||
|
|
||||||
|
// We should never read false from the database.
|
||||||
|
assert(spent != read);
|
||||||
|
|
||||||
|
return spent;
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
|
bool CCoinsViewDB::GetCoins(const uint256 &txid, CCoins &coins) const {
|
||||||
return db.Read(make_pair(DB_COINS, txid), coins);
|
return db.Read(make_pair(DB_COINS, txid), coins);
|
||||||
}
|
}
|
||||||
|
@ -106,7 +124,8 @@ uint256 CCoinsViewDB::GetBestAnchor() const {
|
||||||
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
|
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashAnchor,
|
const uint256 &hashAnchor,
|
||||||
CAnchorsMap &mapAnchors) {
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials) {
|
||||||
CLevelDBBatch batch;
|
CLevelDBBatch batch;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
size_t changed = 0;
|
size_t changed = 0;
|
||||||
|
@ -129,6 +148,15 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
|
||||||
mapAnchors.erase(itOld);
|
mapAnchors.erase(itOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (CSerialsMap::iterator it = mapSerials.begin(); it != mapSerials.end();) {
|
||||||
|
if (it->second.flags & CSerialsCacheEntry::DIRTY) {
|
||||||
|
BatchWriteSerial(batch, it->first, it->second.entered);
|
||||||
|
// TODO: changed++?
|
||||||
|
}
|
||||||
|
CSerialsMap::iterator itOld = it++;
|
||||||
|
mapSerials.erase(itOld);
|
||||||
|
}
|
||||||
|
|
||||||
if (!hashBlock.IsNull())
|
if (!hashBlock.IsNull())
|
||||||
BatchWriteHashBestChain(batch, hashBlock);
|
BatchWriteHashBestChain(batch, hashBlock);
|
||||||
if (!hashAnchor.IsNull())
|
if (!hashAnchor.IsNull())
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||||
|
|
||||||
bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
bool GetAnchorAt(const uint256 &rt, libzerocash::IncrementalMerkleTree &tree) const;
|
||||||
|
bool GetSerial(const uint256 &serial) const;
|
||||||
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
bool GetCoins(const uint256 &txid, CCoins &coins) const;
|
||||||
bool HaveCoins(const uint256 &txid) const;
|
bool HaveCoins(const uint256 &txid) const;
|
||||||
uint256 GetBestBlock() const;
|
uint256 GetBestBlock() const;
|
||||||
|
@ -44,7 +45,8 @@ public:
|
||||||
bool BatchWrite(CCoinsMap &mapCoins,
|
bool BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashAnchor,
|
const uint256 &hashAnchor,
|
||||||
CAnchorsMap &mapAnchors);
|
CAnchorsMap &mapAnchors,
|
||||||
|
CSerialsMap &mapSerials);
|
||||||
bool GetStats(CCoinsStats &stats) const;
|
bool GetStats(CCoinsStats &stats) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue