Add support for Sapling anchors in coins/txdb.
This commit is contained in:
125
src/coins.cpp
125
src/coins.cpp
@@ -43,6 +43,7 @@ bool CCoins::Spend(uint32_t nPos)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool CCoinsView::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return false; }
|
bool CCoinsView::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return false; }
|
||||||
|
bool CCoinsView::GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const { return false; }
|
||||||
bool CCoinsView::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return false; }
|
bool CCoinsView::GetNullifier(const uint256 &nullifier, ShieldedType type) 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; }
|
||||||
@@ -53,6 +54,7 @@ bool CCoinsView::BatchWrite(CCoinsMap &mapCoins,
|
|||||||
const uint256 &hashSproutAnchor,
|
const uint256 &hashSproutAnchor,
|
||||||
const uint256 &hashSaplingAnchor,
|
const uint256 &hashSaplingAnchor,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers) { return false; }
|
CNullifiersMap &mapSaplingNullifiers) { return false; }
|
||||||
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
|
bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
|
||||||
@@ -61,6 +63,7 @@ bool CCoinsView::GetStats(CCoinsStats &stats) const { return false; }
|
|||||||
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
|
CCoinsViewBacked::CCoinsViewBacked(CCoinsView *viewIn) : base(viewIn) { }
|
||||||
|
|
||||||
bool CCoinsViewBacked::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return base->GetSproutAnchorAt(rt, tree); }
|
bool CCoinsViewBacked::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const { return base->GetSproutAnchorAt(rt, tree); }
|
||||||
|
bool CCoinsViewBacked::GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const { return base->GetSaplingAnchorAt(rt, tree); }
|
||||||
bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return base->GetNullifier(nullifier, type); }
|
bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier, ShieldedType type) const { return base->GetNullifier(nullifier, type); }
|
||||||
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); }
|
||||||
@@ -72,8 +75,9 @@ bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins,
|
|||||||
const uint256 &hashSproutAnchor,
|
const uint256 &hashSproutAnchor,
|
||||||
const uint256 &hashSaplingAnchor,
|
const uint256 &hashSaplingAnchor,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers) { return base->BatchWrite(mapCoins, hashBlock, hashSproutAnchor, hashSaplingAnchor, mapSproutAnchors, mapSproutNullifiers, mapSaplingNullifiers); }
|
CNullifiersMap &mapSaplingNullifiers) { return base->BatchWrite(mapCoins, hashBlock, hashSproutAnchor, hashSaplingAnchor, mapSproutAnchors, mapSaplingAnchors, mapSproutNullifiers, mapSaplingNullifiers); }
|
||||||
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()) {}
|
||||||
@@ -88,6 +92,7 @@ CCoinsViewCache::~CCoinsViewCache()
|
|||||||
size_t CCoinsViewCache::DynamicMemoryUsage() const {
|
size_t CCoinsViewCache::DynamicMemoryUsage() const {
|
||||||
return memusage::DynamicUsage(cacheCoins) +
|
return memusage::DynamicUsage(cacheCoins) +
|
||||||
memusage::DynamicUsage(cacheSproutAnchors) +
|
memusage::DynamicUsage(cacheSproutAnchors) +
|
||||||
|
memusage::DynamicUsage(cacheSaplingAnchors) +
|
||||||
memusage::DynamicUsage(cacheSproutNullifiers) +
|
memusage::DynamicUsage(cacheSproutNullifiers) +
|
||||||
memusage::DynamicUsage(cacheSaplingNullifiers) +
|
memusage::DynamicUsage(cacheSaplingNullifiers) +
|
||||||
cachedCoinsUsage;
|
cachedCoinsUsage;
|
||||||
@@ -135,6 +140,29 @@ bool CCoinsViewCache::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTr
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCoinsViewCache::GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const {
|
||||||
|
CAnchorsSaplingMap::const_iterator it = cacheSaplingAnchors.find(rt);
|
||||||
|
if (it != cacheSaplingAnchors.end()) {
|
||||||
|
if (it->second.entered) {
|
||||||
|
tree = it->second.tree;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!base->GetSaplingAnchorAt(rt, tree)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAnchorsSaplingMap::iterator ret = cacheSaplingAnchors.insert(std::make_pair(rt, CAnchorsSaplingCacheEntry())).first;
|
||||||
|
ret->second.entered = true;
|
||||||
|
ret->second.tree = tree;
|
||||||
|
cachedCoinsUsage += ret->second.tree.DynamicMemoryUsage();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::GetNullifier(const uint256 &nullifier, ShieldedType type) const {
|
bool CCoinsViewCache::GetNullifier(const uint256 &nullifier, ShieldedType type) const {
|
||||||
CNullifiersMap* cacheToUse;
|
CNullifiersMap* cacheToUse;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -203,6 +231,24 @@ void CCoinsViewCache::PushSproutAnchor(const ZCIncrementalMerkleTree &tree) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void CCoinsViewCache::BringBestAnchorIntoCache(
|
||||||
|
const uint256 ¤tRoot,
|
||||||
|
ZCIncrementalMerkleTree &tree
|
||||||
|
)
|
||||||
|
{
|
||||||
|
assert(GetSproutAnchorAt(currentRoot, tree));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void CCoinsViewCache::BringBestAnchorIntoCache(
|
||||||
|
const uint256 ¤tRoot,
|
||||||
|
ZCSaplingIncrementalMerkleTree &tree
|
||||||
|
)
|
||||||
|
{
|
||||||
|
assert(GetSaplingAnchorAt(currentRoot, tree));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Tree, typename Cache, typename CacheEntry>
|
template<typename Tree, typename Cache, typename CacheEntry>
|
||||||
void CCoinsViewCache::AbstractPopAnchor(
|
void CCoinsViewCache::AbstractPopAnchor(
|
||||||
const uint256 &newrt,
|
const uint256 &newrt,
|
||||||
@@ -221,17 +267,7 @@ void CCoinsViewCache::AbstractPopAnchor(
|
|||||||
// so that its tree exists in memory.
|
// so that its tree exists in memory.
|
||||||
{
|
{
|
||||||
Tree tree;
|
Tree tree;
|
||||||
switch (type) {
|
BringBestAnchorIntoCache(currentRoot, tree);
|
||||||
case SPROUT:
|
|
||||||
assert(GetSproutAnchorAt(currentRoot, tree));
|
|
||||||
break;
|
|
||||||
case SAPLING:
|
|
||||||
// TODO
|
|
||||||
assert(false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("Unknown shielded type " + type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the anchor as unentered, removing it from view
|
// Mark the anchor as unentered, removing it from view
|
||||||
@@ -367,11 +403,45 @@ void BatchWriteNullifiers(CNullifiersMap &mapNullifiers, CNullifiersMap &cacheNu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Map, typename MapIterator, typename MapEntry>
|
||||||
|
void BatchWriteAnchors(
|
||||||
|
Map &mapAnchors,
|
||||||
|
Map &cacheAnchors,
|
||||||
|
size_t &cachedCoinsUsage
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (MapIterator child_it = mapAnchors.begin(); child_it != mapAnchors.end();)
|
||||||
|
{
|
||||||
|
if (child_it->second.flags & MapEntry::DIRTY) {
|
||||||
|
MapIterator parent_it = cacheAnchors.find(child_it->first);
|
||||||
|
|
||||||
|
if (parent_it == cacheAnchors.end()) {
|
||||||
|
MapEntry& entry = cacheAnchors[child_it->first];
|
||||||
|
entry.entered = child_it->second.entered;
|
||||||
|
entry.tree = child_it->second.tree;
|
||||||
|
entry.flags = MapEntry::DIRTY;
|
||||||
|
|
||||||
|
cachedCoinsUsage += entry.tree.DynamicMemoryUsage();
|
||||||
|
} else {
|
||||||
|
if (parent_it->second.entered != child_it->second.entered) {
|
||||||
|
// The parent may have removed the entry.
|
||||||
|
parent_it->second.entered = child_it->second.entered;
|
||||||
|
parent_it->second.flags |= MapEntry::DIRTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MapIterator itOld = child_it++;
|
||||||
|
mapAnchors.erase(itOld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
|
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlockIn,
|
const uint256 &hashBlockIn,
|
||||||
const uint256 &hashSproutAnchorIn,
|
const uint256 &hashSproutAnchorIn,
|
||||||
const uint256 &hashSaplingAnchorIn,
|
const uint256 &hashSaplingAnchorIn,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers) {
|
CNullifiersMap &mapSaplingNullifiers) {
|
||||||
assert(!hasModifier);
|
assert(!hasModifier);
|
||||||
@@ -410,30 +480,8 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
|
|||||||
mapCoins.erase(itOld);
|
mapCoins.erase(itOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CAnchorsSproutMap::iterator child_it = mapSproutAnchors.begin(); child_it != mapSproutAnchors.end();)
|
::BatchWriteAnchors<CAnchorsSproutMap, CAnchorsSproutMap::iterator, CAnchorsSproutCacheEntry>(mapSproutAnchors, cacheSproutAnchors, cachedCoinsUsage);
|
||||||
{
|
::BatchWriteAnchors<CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry>(mapSaplingAnchors, cacheSaplingAnchors, cachedCoinsUsage);
|
||||||
if (child_it->second.flags & CAnchorsSproutCacheEntry::DIRTY) {
|
|
||||||
CAnchorsSproutMap::iterator parent_it = cacheSproutAnchors.find(child_it->first);
|
|
||||||
|
|
||||||
if (parent_it == cacheSproutAnchors.end()) {
|
|
||||||
CAnchorsSproutCacheEntry& entry = cacheSproutAnchors[child_it->first];
|
|
||||||
entry.entered = child_it->second.entered;
|
|
||||||
entry.tree = child_it->second.tree;
|
|
||||||
entry.flags = CAnchorsSproutCacheEntry::DIRTY;
|
|
||||||
|
|
||||||
cachedCoinsUsage += entry.tree.DynamicMemoryUsage();
|
|
||||||
} else {
|
|
||||||
if (parent_it->second.entered != child_it->second.entered) {
|
|
||||||
// The parent may have removed the entry.
|
|
||||||
parent_it->second.entered = child_it->second.entered;
|
|
||||||
parent_it->second.flags |= CAnchorsSproutCacheEntry::DIRTY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CAnchorsSproutMap::iterator itOld = child_it++;
|
|
||||||
mapSproutAnchors.erase(itOld);
|
|
||||||
}
|
|
||||||
|
|
||||||
::BatchWriteNullifiers(mapSproutNullifiers, cacheSproutNullifiers);
|
::BatchWriteNullifiers(mapSproutNullifiers, cacheSproutNullifiers);
|
||||||
::BatchWriteNullifiers(mapSaplingNullifiers, cacheSaplingNullifiers);
|
::BatchWriteNullifiers(mapSaplingNullifiers, cacheSaplingNullifiers);
|
||||||
@@ -445,9 +493,10 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::Flush() {
|
bool CCoinsViewCache::Flush() {
|
||||||
bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashSproutAnchor, hashSaplingAnchor, cacheSproutAnchors, cacheSproutNullifiers, cacheSaplingNullifiers);
|
bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashSproutAnchor, hashSaplingAnchor, cacheSproutAnchors, cacheSaplingAnchors, cacheSproutNullifiers, cacheSaplingNullifiers);
|
||||||
cacheCoins.clear();
|
cacheCoins.clear();
|
||||||
cacheSproutAnchors.clear();
|
cacheSproutAnchors.clear();
|
||||||
|
cacheSaplingAnchors.clear();
|
||||||
cacheSproutNullifiers.clear();
|
cacheSproutNullifiers.clear();
|
||||||
cacheSaplingNullifiers.clear();
|
cacheSaplingNullifiers.clear();
|
||||||
cachedCoinsUsage = 0;
|
cachedCoinsUsage = 0;
|
||||||
@@ -515,6 +564,8 @@ bool CCoinsViewCache::HaveJoinSplitRequirements(const CTransaction& tx) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Sapling anchor checks
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
32
src/coins.h
32
src/coins.h
@@ -286,6 +286,19 @@ struct CAnchorsSproutCacheEntry
|
|||||||
CAnchorsSproutCacheEntry() : entered(false), flags(0) {}
|
CAnchorsSproutCacheEntry() : entered(false), flags(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CAnchorsSaplingCacheEntry
|
||||||
|
{
|
||||||
|
bool entered; // This will be false if the anchor is removed from the cache
|
||||||
|
ZCSaplingIncrementalMerkleTree tree; // The tree itself
|
||||||
|
unsigned char flags;
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
DIRTY = (1 << 0), // This cache entry is potentially different from the version in the parent view.
|
||||||
|
};
|
||||||
|
|
||||||
|
CAnchorsSaplingCacheEntry() : entered(false), flags(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
struct CNullifiersCacheEntry
|
struct CNullifiersCacheEntry
|
||||||
{
|
{
|
||||||
bool entered; // If the nullifier is spent or not
|
bool entered; // If the nullifier is spent or not
|
||||||
@@ -306,6 +319,7 @@ enum ShieldedType
|
|||||||
|
|
||||||
typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
|
typedef boost::unordered_map<uint256, CCoinsCacheEntry, CCoinsKeyHasher> CCoinsMap;
|
||||||
typedef boost::unordered_map<uint256, CAnchorsSproutCacheEntry, CCoinsKeyHasher> CAnchorsSproutMap;
|
typedef boost::unordered_map<uint256, CAnchorsSproutCacheEntry, CCoinsKeyHasher> CAnchorsSproutMap;
|
||||||
|
typedef boost::unordered_map<uint256, CAnchorsSaplingCacheEntry, CCoinsKeyHasher> CAnchorsSaplingMap;
|
||||||
typedef boost::unordered_map<uint256, CNullifiersCacheEntry, CCoinsKeyHasher> CNullifiersMap;
|
typedef boost::unordered_map<uint256, CNullifiersCacheEntry, CCoinsKeyHasher> CNullifiersMap;
|
||||||
|
|
||||||
struct CCoinsStats
|
struct CCoinsStats
|
||||||
@@ -326,9 +340,12 @@ struct CCoinsStats
|
|||||||
class CCoinsView
|
class CCoinsView
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//! Retrieve the tree at a particular anchored root in the chain
|
//! Retrieve the tree (Sprout) at a particular anchored root in the chain
|
||||||
virtual bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
virtual bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
||||||
|
|
||||||
|
//! Retrieve the tree (Sapling) at a particular anchored root in the chain
|
||||||
|
virtual bool GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const;
|
||||||
|
|
||||||
//! Determine whether a nullifier is spent or not
|
//! Determine whether a nullifier is spent or not
|
||||||
virtual bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;
|
virtual bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;
|
||||||
|
|
||||||
@@ -352,6 +369,7 @@ public:
|
|||||||
const uint256 &hashSproutAnchor,
|
const uint256 &hashSproutAnchor,
|
||||||
const uint256 &hashSaplingAnchor,
|
const uint256 &hashSaplingAnchor,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers);
|
CNullifiersMap &mapSaplingNullifiers);
|
||||||
|
|
||||||
@@ -372,6 +390,7 @@ protected:
|
|||||||
public:
|
public:
|
||||||
CCoinsViewBacked(CCoinsView *viewIn);
|
CCoinsViewBacked(CCoinsView *viewIn);
|
||||||
bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
||||||
|
bool GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const;
|
||||||
bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;
|
bool GetNullifier(const uint256 &nullifier, ShieldedType type) 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;
|
||||||
@@ -383,6 +402,7 @@ public:
|
|||||||
const uint256 &hashSproutAnchor,
|
const uint256 &hashSproutAnchor,
|
||||||
const uint256 &hashSaplingAnchor,
|
const uint256 &hashSaplingAnchor,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers);
|
CNullifiersMap &mapSaplingNullifiers);
|
||||||
bool GetStats(CCoinsStats &stats) const;
|
bool GetStats(CCoinsStats &stats) const;
|
||||||
@@ -428,6 +448,7 @@ protected:
|
|||||||
mutable uint256 hashSproutAnchor;
|
mutable uint256 hashSproutAnchor;
|
||||||
mutable uint256 hashSaplingAnchor;
|
mutable uint256 hashSaplingAnchor;
|
||||||
mutable CAnchorsSproutMap cacheSproutAnchors;
|
mutable CAnchorsSproutMap cacheSproutAnchors;
|
||||||
|
mutable CAnchorsSaplingMap cacheSaplingAnchors;
|
||||||
mutable CNullifiersMap cacheSproutNullifiers;
|
mutable CNullifiersMap cacheSproutNullifiers;
|
||||||
mutable CNullifiersMap cacheSaplingNullifiers;
|
mutable CNullifiersMap cacheSaplingNullifiers;
|
||||||
|
|
||||||
@@ -440,6 +461,7 @@ public:
|
|||||||
|
|
||||||
// Standard CCoinsView methods
|
// Standard CCoinsView methods
|
||||||
bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
||||||
|
bool GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const;
|
||||||
bool GetNullifier(const uint256 &nullifier, ShieldedType type) const;
|
bool GetNullifier(const uint256 &nullifier, ShieldedType type) 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;
|
||||||
@@ -451,6 +473,7 @@ public:
|
|||||||
const uint256 &hashSproutAnchor,
|
const uint256 &hashSproutAnchor,
|
||||||
const uint256 &hashSaplingAnchor,
|
const uint256 &hashSaplingAnchor,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers);
|
CNullifiersMap &mapSaplingNullifiers);
|
||||||
|
|
||||||
@@ -542,6 +565,13 @@ private:
|
|||||||
Cache &cacheAnchors,
|
Cache &cacheAnchors,
|
||||||
uint256 &hash
|
uint256 &hash
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//! Interface for bringing an anchor into the cache.
|
||||||
|
template<typename Tree>
|
||||||
|
void BringBestAnchorIntoCache(
|
||||||
|
const uint256 ¤tRoot,
|
||||||
|
Tree &tree
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BITCOIN_COINS_H
|
#endif // BITCOIN_COINS_H
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool GetNullifier(const uint256 &nf, ShieldedType type) const {
|
bool GetNullifier(const uint256 &nf, ShieldedType type) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool GetNullifier(const uint256 &nf, ShieldedType type) const {
|
bool GetNullifier(const uint256 &nf, ShieldedType type) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
45
src/txdb.cpp
45
src/txdb.cpp
@@ -18,6 +18,7 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static const char DB_SPROUT_ANCHOR = 'A';
|
static const char DB_SPROUT_ANCHOR = 'A';
|
||||||
|
static const char DB_SAPLING_ANCHOR = 'X';
|
||||||
static const char DB_NULLIFIER = 's';
|
static const char DB_NULLIFIER = 's';
|
||||||
static const char DB_SAPLING_NULLIFIER = 'S';
|
static const char DB_SAPLING_NULLIFIER = 'S';
|
||||||
static const char DB_COINS = 'c';
|
static const char DB_COINS = 'c';
|
||||||
@@ -53,6 +54,18 @@ bool CCoinsViewDB::GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCoinsViewDB::GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const {
|
||||||
|
if (rt == ZCSaplingIncrementalMerkleTree::empty_root()) {
|
||||||
|
ZCSaplingIncrementalMerkleTree new_tree;
|
||||||
|
tree = new_tree;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool read = db.Read(make_pair(DB_SAPLING_ANCHOR, rt), tree);
|
||||||
|
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::GetNullifier(const uint256 &nf, ShieldedType type) const {
|
bool CCoinsViewDB::GetNullifier(const uint256 &nf, ShieldedType type) const {
|
||||||
bool spent = false;
|
bool spent = false;
|
||||||
char dbChar;
|
char dbChar;
|
||||||
@@ -118,11 +131,29 @@ void BatchWriteNullifiers(CDBBatch& batch, CNullifiersMap& mapToUse, const char&
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Map, typename MapIterator, typename MapEntry>
|
||||||
|
void BatchWriteAnchors(CDBBatch& batch, Map& mapToUse, const char& dbChar)
|
||||||
|
{
|
||||||
|
for (MapIterator it = mapToUse.begin(); it != mapToUse.end();) {
|
||||||
|
if (it->second.flags & MapEntry::DIRTY) {
|
||||||
|
if (!it->second.entered)
|
||||||
|
batch.Erase(make_pair(dbChar, it->first));
|
||||||
|
else {
|
||||||
|
batch.Write(make_pair(dbChar, it->first), it->second.tree);
|
||||||
|
}
|
||||||
|
// TODO: changed++?
|
||||||
|
}
|
||||||
|
MapIterator itOld = it++;
|
||||||
|
mapToUse.erase(itOld);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
|
bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
|
||||||
const uint256 &hashBlock,
|
const uint256 &hashBlock,
|
||||||
const uint256 &hashSproutAnchor,
|
const uint256 &hashSproutAnchor,
|
||||||
const uint256 &hashSaplingAnchor,
|
const uint256 &hashSaplingAnchor,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers) {
|
CNullifiersMap &mapSaplingNullifiers) {
|
||||||
CDBBatch batch(db);
|
CDBBatch batch(db);
|
||||||
@@ -141,18 +172,8 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins,
|
|||||||
mapCoins.erase(itOld);
|
mapCoins.erase(itOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (CAnchorsSproutMap::iterator it = mapSproutAnchors.begin(); it != mapSproutAnchors.end();) {
|
::BatchWriteAnchors<CAnchorsSproutMap, CAnchorsSproutMap::iterator, CAnchorsSproutCacheEntry>(batch, mapSproutAnchors, DB_SPROUT_ANCHOR);
|
||||||
if (it->second.flags & CAnchorsSproutCacheEntry::DIRTY) {
|
::BatchWriteAnchors<CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry>(batch, mapSaplingAnchors, DB_SAPLING_ANCHOR);
|
||||||
if (!it->second.entered)
|
|
||||||
batch.Erase(make_pair(DB_SPROUT_ANCHOR, it->first));
|
|
||||||
else {
|
|
||||||
batch.Write(make_pair(DB_SPROUT_ANCHOR, it->first), it->second.tree);
|
|
||||||
}
|
|
||||||
// TODO: changed++?
|
|
||||||
}
|
|
||||||
CAnchorsSproutMap::iterator itOld = it++;
|
|
||||||
mapSproutAnchors.erase(itOld);
|
|
||||||
}
|
|
||||||
|
|
||||||
::BatchWriteNullifiers(batch, mapSproutNullifiers, DB_NULLIFIER);
|
::BatchWriteNullifiers(batch, mapSproutNullifiers, DB_NULLIFIER);
|
||||||
::BatchWriteNullifiers(batch, mapSaplingNullifiers, DB_SAPLING_NULLIFIER);
|
::BatchWriteNullifiers(batch, mapSaplingNullifiers, DB_SAPLING_NULLIFIER);
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public:
|
|||||||
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
CCoinsViewDB(size_t nCacheSize, bool fMemory = false, bool fWipe = false);
|
||||||
|
|
||||||
bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
bool GetSproutAnchorAt(const uint256 &rt, ZCIncrementalMerkleTree &tree) const;
|
||||||
|
bool GetSaplingAnchorAt(const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) const;
|
||||||
bool GetNullifier(const uint256 &nf, ShieldedType type) const;
|
bool GetNullifier(const uint256 &nf, ShieldedType type) 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;
|
||||||
@@ -46,6 +47,7 @@ public:
|
|||||||
const uint256 &hashSproutAnchor,
|
const uint256 &hashSproutAnchor,
|
||||||
const uint256 &hashSaplingAnchor,
|
const uint256 &hashSaplingAnchor,
|
||||||
CAnchorsSproutMap &mapSproutAnchors,
|
CAnchorsSproutMap &mapSproutAnchors,
|
||||||
|
CAnchorsSaplingMap &mapSaplingAnchors,
|
||||||
CNullifiersMap &mapSproutNullifiers,
|
CNullifiersMap &mapSproutNullifiers,
|
||||||
CNullifiersMap &mapSaplingNullifiers);
|
CNullifiersMap &mapSaplingNullifiers);
|
||||||
bool GetStats(CCoinsStats &stats) const;
|
bool GetStats(CCoinsStats &stats) const;
|
||||||
|
|||||||
@@ -413,6 +413,7 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
|||||||
intermediates.insert(std::make_pair(tree.root(), tree));
|
intermediates.insert(std::make_pair(tree.root(), tree));
|
||||||
}
|
}
|
||||||
for (const SpendDescription &spendDescription : tx.vShieldedSpend) {
|
for (const SpendDescription &spendDescription : tx.vShieldedSpend) {
|
||||||
|
// TODO: anchor check
|
||||||
assert(!pcoins->GetNullifier(spendDescription.nullifier, SAPLING));
|
assert(!pcoins->GetNullifier(spendDescription.nullifier, SAPLING));
|
||||||
}
|
}
|
||||||
if (fDependsWait)
|
if (fDependsWait)
|
||||||
|
|||||||
Reference in New Issue
Block a user