diff --git a/src/coins.cpp b/src/coins.cpp index 1d62fd943..4ffd960c1 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -14,6 +14,7 @@ bool CCoinsView::GetNamespace(const valtype &nameSpace, CKevaData &data) const { bool CCoinsView::GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const { return false; } bool CCoinsView::GetNamesForHeight(unsigned nHeight, std::set& names) const { return false; } CKevaIterator* CCoinsView::IterateKeys(const valtype& nameSpace) const { assert (false); } +CKevaIterator* CCoinsView::IterateAssociatedNamespaces(const valtype& nameSpace) const { assert (false); } bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) { return false; } CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; } bool CCoinsView::ValidateKevaDB() const { @@ -43,6 +44,7 @@ bool CCoinsViewBacked::GetNamesForHeight(unsigned nHeight, std::set& na return base->GetNamesForHeight(nHeight, names); } CKevaIterator* CCoinsViewBacked::IterateKeys(const valtype& nameSpace) const { return base->IterateKeys(nameSpace); } +CKevaIterator* CCoinsViewBacked::IterateAssociatedNamespaces(const valtype& nameSpace) const { return base->IterateAssociatedNamespaces(nameSpace); } void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) { return base->BatchWrite(mapCoins, hashBlock, names); @@ -198,6 +200,10 @@ CKevaIterator* CCoinsViewCache::IterateKeys(const valtype& nameSpace) const { return cacheNames.iterateKeys(base->IterateKeys(nameSpace)); } +CKevaIterator* CCoinsViewCache::IterateAssociatedNamespaces(const valtype& nameSpace) const { + return cacheNames.IterateAssociatedNamespaces(base->IterateAssociatedNamespaces(nameSpace)); +} + /* undo is set if the change is due to disconnecting blocks / going back in time. The ordinary case (!undo) means that we update the name normally, going forward in time. This is important for keeping track of the @@ -210,6 +216,18 @@ void CCoinsViewCache::SetName(const valtype &nameSpace, const valtype &key, cons cacheNames.setNamespace(nameSpace, namespaceData); } cacheNames.set(nameSpace, key, data); + + // Handle namespace association. + valtype associdateNamespace; + if (!cacheNames.getAssociateNamespaces(data.getValue(), associdateNamespace)) { + return; + } + + CKevaData dummyData; + if (!GetNamespace(associdateNamespace, dummyData)) { + return; + } + cacheNames.associateNamespaces(nameSpace, associdateNamespace); } void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) { @@ -218,6 +236,18 @@ void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) { assert(false); } cacheNames.remove(nameSpace, key); + + // Handle namespace association. + valtype associdateNamespace; + if (!cacheNames.getAssociateNamespaces(oldData.getValue(), associdateNamespace)) { + return; + } + + CKevaData dummyData; + if (!GetNamespace(associdateNamespace, dummyData)) { + return; + } + cacheNames.disassociateNamespaces(nameSpace, associdateNamespace); } bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn, const CKevaCache &names) { diff --git a/src/coins.h b/src/coins.h index 7e69acf5a..2ea411009 100644 --- a/src/coins.h +++ b/src/coins.h @@ -176,6 +176,9 @@ public: // Get a key iterator. virtual CKevaIterator* IterateKeys(const valtype& nameSpace) const; + // Get the associated namespace iterator. + virtual CKevaIterator* IterateAssociatedNamespaces(const valtype& nameSpace) const; + //! Do a bulk modification (multiple Coin changes + BestBlock change). //! The passed mapCoins can be modified. virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names); @@ -210,6 +213,7 @@ public: bool GetName(const valtype& nameSpace, const valtype& key, CKevaData& data) const override; bool GetNamesForHeight(unsigned nHeight, std::set& names) const override; CKevaIterator* IterateKeys(const valtype& nameSpace) const override; + virtual CKevaIterator* IterateAssociatedNamespaces(const valtype& nameSpace) const override; void SetBackend(CCoinsView &viewIn); bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override; CCoinsViewCursor *Cursor() const override; @@ -252,6 +256,7 @@ public: bool GetName(const valtype &nameSpace, const valtype &key, CKevaData& data) const override; bool GetNamesForHeight(unsigned nHeight, std::set& names) const override; CKevaIterator* IterateKeys(const valtype& nameSpace) const override; + CKevaIterator* IterateAssociatedNamespaces(const valtype& nameSpace) const override; bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const CKevaCache &names) override; CCoinsViewCursor* Cursor() const override { throw std::logic_error("CCoinsViewCache cursor iteration not supported."); diff --git a/src/keva/common.cpp b/src/keva/common.cpp index 0d4406e37..1b4d613a8 100644 --- a/src/keva/common.cpp +++ b/src/keva/common.cpp @@ -7,7 +7,7 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include - +#include #include