mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-14 17:17:58 +00:00
WIP: namespace/key
This commit is contained in:
parent
b112e0c795
commit
c56fb50b55
@ -10,6 +10,8 @@
|
|||||||
bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
|
bool CCoinsView::GetCoin(const COutPoint &outpoint, Coin &coin) const { return false; }
|
||||||
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
||||||
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
|
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
|
||||||
|
bool CCoinsView::GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const { return false; }
|
||||||
|
bool CCoinsView::GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const { return false; }
|
||||||
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
|
bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return false; }
|
||||||
CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; }
|
CCoinsViewCursor *CCoinsView::Cursor() const { return nullptr; }
|
||||||
|
|
||||||
@ -24,6 +26,8 @@ bool CCoinsViewBacked::GetCoin(const COutPoint &outpoint, Coin &coin) const { re
|
|||||||
bool CCoinsViewBacked::HaveCoin(const COutPoint &outpoint) const { return base->HaveCoin(outpoint); }
|
bool CCoinsViewBacked::HaveCoin(const COutPoint &outpoint) const { return base->HaveCoin(outpoint); }
|
||||||
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
||||||
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
|
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
|
||||||
|
bool CCoinsViewBacked::GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const { return false; }
|
||||||
|
bool CCoinsViewBacked::GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const { return false; }
|
||||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
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) { return base->BatchWrite(mapCoins, hashBlock); }
|
||||||
CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
|
CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
|
||||||
@ -142,6 +146,96 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
|
|||||||
hashBlock = hashBlockIn;
|
hashBlock = hashBlockIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CCoinsViewCache::GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const {
|
||||||
|
if (cacheNames.isDeleted(nameSpace, key))
|
||||||
|
return false;
|
||||||
|
if (cacheNames.get(nameSpace, key, data))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Note: This does not attempt to cache name queries. The cache
|
||||||
|
only keeps track of changes! */
|
||||||
|
|
||||||
|
return base->GetName(nameSpace, key, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CCoinsViewCache::GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const {
|
||||||
|
/* Query the base view first, and then apply the cached changes (if
|
||||||
|
there are any). */
|
||||||
|
|
||||||
|
if (!base->GetNamesForHeight(nHeight, names))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
cacheNames.updateNamesForHeight(nHeight, names);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
name history. */
|
||||||
|
void CCoinsViewCache::SetName(const valtype &nameSpace, const valtype &key, const CKevaData& data, bool undo) {
|
||||||
|
CKevaData oldData;
|
||||||
|
if (GetName(nameSpace, key, oldData))
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
cacheNames.removeExpireIndex(name, oldData.getHeight());
|
||||||
|
|
||||||
|
/* Update the name history. If we are undoing, we expect that
|
||||||
|
the top history item matches the data being set now. If we
|
||||||
|
are not undoing, push the overwritten data onto the history stack.
|
||||||
|
Note that we only have to do this if the name already existed
|
||||||
|
in the database. Otherwise, no special action is required
|
||||||
|
for the name history. */
|
||||||
|
if (fNameHistory)
|
||||||
|
{
|
||||||
|
CNameHistory history;
|
||||||
|
if (!GetNameHistory(name, history))
|
||||||
|
{
|
||||||
|
/* Ensure that the history stack is indeed (still) empty
|
||||||
|
and was not modified by the failing GetNameHistory call. */
|
||||||
|
assert(history.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (undo)
|
||||||
|
history.pop(data);
|
||||||
|
else
|
||||||
|
history.push(oldData);
|
||||||
|
|
||||||
|
cacheNames.setHistory(name, history);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else
|
||||||
|
assert (!undo);
|
||||||
|
|
||||||
|
cacheNames.set(nameSpace, key, data);
|
||||||
|
#if 0
|
||||||
|
cacheNames.addExpireIndex(name, data.getHeight());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCoinsViewCache::DeleteName(const valtype &nameSpace, const valtype &key) {
|
||||||
|
CKevaData oldData;
|
||||||
|
if (GetName(nameSpace, key, oldData)) {
|
||||||
|
#if 0
|
||||||
|
cacheNames.removeExpireIndex(name, oldData.getHeight());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (fNameHistory)
|
||||||
|
{
|
||||||
|
/* When deleting a name, the history should already be clean. */
|
||||||
|
CNameHistory history;
|
||||||
|
assert (!GetNameHistory(name, history) || history.empty());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
cacheNames.remove(nameSpace, key);
|
||||||
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
|
bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn) {
|
||||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) {
|
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) {
|
||||||
// Ignore non-dirty entries (optimization).
|
// Ignore non-dirty entries (optimization).
|
||||||
|
18
src/coins.h
18
src/coins.h
@ -11,6 +11,7 @@
|
|||||||
#include <core_memusage.h>
|
#include <core_memusage.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
#include <memusage.h>
|
#include <memusage.h>
|
||||||
|
#include <keva/common.h>
|
||||||
#include <serialize.h>
|
#include <serialize.h>
|
||||||
#include <uint256.h>
|
#include <uint256.h>
|
||||||
|
|
||||||
@ -163,6 +164,12 @@ public:
|
|||||||
//! the old block hash, in that order.
|
//! the old block hash, in that order.
|
||||||
virtual std::vector<uint256> GetHeadBlocks() const;
|
virtual std::vector<uint256> GetHeadBlocks() const;
|
||||||
|
|
||||||
|
// Get a name (if it exists)
|
||||||
|
virtual bool GetName(const valtype& nameSpace, const valtype& key, CKevaData& data) const;
|
||||||
|
|
||||||
|
// Query for names that were updated at the given height
|
||||||
|
virtual bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const;
|
||||||
|
|
||||||
//! Do a bulk modification (multiple Coin changes + BestBlock change).
|
//! Do a bulk modification (multiple Coin changes + BestBlock change).
|
||||||
//! The passed mapCoins can be modified.
|
//! The passed mapCoins can be modified.
|
||||||
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||||
@ -190,6 +197,8 @@ public:
|
|||||||
bool HaveCoin(const COutPoint &outpoint) const override;
|
bool HaveCoin(const COutPoint &outpoint) const override;
|
||||||
uint256 GetBestBlock() const override;
|
uint256 GetBestBlock() const override;
|
||||||
std::vector<uint256> GetHeadBlocks() const override;
|
std::vector<uint256> GetHeadBlocks() const override;
|
||||||
|
bool GetName(const valtype& nameSpace, const valtype& key, CKevaData& data) const override;
|
||||||
|
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
||||||
void SetBackend(CCoinsView &viewIn);
|
void SetBackend(CCoinsView &viewIn);
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
||||||
CCoinsViewCursor *Cursor() const override;
|
CCoinsViewCursor *Cursor() const override;
|
||||||
@ -211,6 +220,9 @@ protected:
|
|||||||
/* Cached dynamic memory usage for the inner Coin objects. */
|
/* Cached dynamic memory usage for the inner Coin objects. */
|
||||||
mutable size_t cachedCoinsUsage;
|
mutable size_t cachedCoinsUsage;
|
||||||
|
|
||||||
|
/** Name changes cache. */
|
||||||
|
CKevaCache cacheNames;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CCoinsViewCache(CCoinsView *baseIn);
|
CCoinsViewCache(CCoinsView *baseIn);
|
||||||
|
|
||||||
@ -224,11 +236,17 @@ public:
|
|||||||
bool HaveCoin(const COutPoint &outpoint) const override;
|
bool HaveCoin(const COutPoint &outpoint) const override;
|
||||||
uint256 GetBestBlock() const override;
|
uint256 GetBestBlock() const override;
|
||||||
void SetBestBlock(const uint256 &hashBlock);
|
void SetBestBlock(const uint256 &hashBlock);
|
||||||
|
bool GetName(const valtype &nameSpace, const valtype &key, CKevaData &data) const override;
|
||||||
|
bool GetNamesForHeight(unsigned nHeight, std::set<valtype>& names) const override;
|
||||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
||||||
CCoinsViewCursor* Cursor() const override {
|
CCoinsViewCursor* Cursor() const override {
|
||||||
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Changes to the name database. */
|
||||||
|
void SetName(const valtype &nameSpace, const valtype &key, const CKevaData &data, bool undo);
|
||||||
|
void DeleteName(const valtype &nameSpace, const valtype &key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if we have the given utxo already loaded in this cache.
|
* Check if we have the given utxo already loaded in this cache.
|
||||||
* The semantics are the same as HaveCoin(), but no calls to
|
* The semantics are the same as HaveCoin(), but no calls to
|
||||||
|
@ -38,7 +38,7 @@ CNameIterator::~CNameIterator ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
/* CNameCacheNameIterator. */
|
/* CKevaCacheNameIterator. */
|
||||||
|
|
||||||
class CCacheNameIterator : public CNameIterator
|
class CCacheNameIterator : public CNameIterator
|
||||||
{
|
{
|
||||||
@ -46,7 +46,7 @@ class CCacheNameIterator : public CNameIterator
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
/** Reference to cache object that is used. */
|
/** Reference to cache object that is used. */
|
||||||
const CNameCache& cache;
|
const CKevaCache& cache;
|
||||||
|
|
||||||
/** Base iterator to combine with the cache. */
|
/** Base iterator to combine with the cache. */
|
||||||
CNameIterator* base;
|
CNameIterator* base;
|
||||||
@ -59,7 +59,7 @@ private:
|
|||||||
CKevaData baseData;
|
CKevaData baseData;
|
||||||
|
|
||||||
/** Iterator of the cache's entries. */
|
/** Iterator of the cache's entries. */
|
||||||
CNameCache::EntryMap::const_iterator cacheIter;
|
CKevaCache::EntryMap::const_iterator cacheIter;
|
||||||
|
|
||||||
/* Call the base iterator's next() routine to fill in the internal
|
/* Call the base iterator's next() routine to fill in the internal
|
||||||
"cache" for the next entry. This already skips entries that are
|
"cache" for the next entry. This already skips entries that are
|
||||||
@ -73,7 +73,7 @@ public:
|
|||||||
* @param c The cache object to use.
|
* @param c The cache object to use.
|
||||||
* @param b The base iterator.
|
* @param b The base iterator.
|
||||||
*/
|
*/
|
||||||
CCacheNameIterator (const CNameCache& c, CNameIterator* b);
|
CCacheNameIterator (const CKevaCache& c, CNameIterator* b);
|
||||||
|
|
||||||
/* Destruct, this deletes also the base iterator. */
|
/* Destruct, this deletes also the base iterator. */
|
||||||
~CCacheNameIterator ();
|
~CCacheNameIterator ();
|
||||||
@ -84,7 +84,7 @@ public:
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CCacheNameIterator::CCacheNameIterator (const CNameCache& c, CNameIterator* b)
|
CCacheNameIterator::CCacheNameIterator (const CKevaCache& c, CNameIterator* b)
|
||||||
: cache(c), base(b)
|
: cache(c), base(b)
|
||||||
{
|
{
|
||||||
/* Add a seek-to-start to ensure that everything is consistent. This call
|
/* Add a seek-to-start to ensure that everything is consistent. This call
|
||||||
@ -147,7 +147,7 @@ CCacheNameIterator::next (valtype& name, CKevaData& data)
|
|||||||
{
|
{
|
||||||
assert (baseName != cacheIter->first);
|
assert (baseName != cacheIter->first);
|
||||||
|
|
||||||
CNameCache::NameComparator cmp;
|
CKevaCache::NameComparator cmp;
|
||||||
useBase = cmp (baseName, cacheIter->first);
|
useBase = cmp (baseName, cacheIter->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,11 +170,12 @@ CCacheNameIterator::next (valtype& name, CKevaData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
/* CNameCache. */
|
/* CKevaCache. */
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CNameCache::get (const valtype& name, CKevaData& data) const
|
CKevaCache::get (const valtype& nameSpace, const valtype& key, CKevaData& data) const
|
||||||
{
|
{
|
||||||
|
valtype name = nameSpace + key;
|
||||||
const EntryMap::const_iterator i = entries.find (name);
|
const EntryMap::const_iterator i = entries.find (name);
|
||||||
if (i == entries.end ())
|
if (i == entries.end ())
|
||||||
return false;
|
return false;
|
||||||
@ -184,8 +185,9 @@ CNameCache::get (const valtype& name, CKevaData& data) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CNameCache::set (const valtype& name, const CKevaData& data)
|
CKevaCache::set (const valtype& nameSpace, const valtype& key, const CKevaData& data)
|
||||||
{
|
{
|
||||||
|
valtype name = nameSpace + key;
|
||||||
const std::set<valtype>::iterator di = deleted.find (name);
|
const std::set<valtype>::iterator di = deleted.find (name);
|
||||||
if (di != deleted.end ())
|
if (di != deleted.end ())
|
||||||
deleted.erase (di);
|
deleted.erase (di);
|
||||||
@ -198,8 +200,9 @@ CNameCache::set (const valtype& name, const CKevaData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CNameCache::remove (const valtype& name)
|
CKevaCache::remove (const valtype& nameSpace, const valtype& key)
|
||||||
{
|
{
|
||||||
|
valtype name = nameSpace + key;
|
||||||
const EntryMap::iterator ei = entries.find (name);
|
const EntryMap::iterator ei = entries.find (name);
|
||||||
if (ei != entries.end ())
|
if (ei != entries.end ())
|
||||||
entries.erase (ei);
|
entries.erase (ei);
|
||||||
@ -208,13 +211,14 @@ CNameCache::remove (const valtype& name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CNameIterator*
|
CNameIterator*
|
||||||
CNameCache::iterateNames (CNameIterator* base) const
|
CKevaCache::iterateNames (CNameIterator* base) const
|
||||||
{
|
{
|
||||||
return new CCacheNameIterator (*this, base);
|
return new CCacheNameIterator (*this, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool
|
bool
|
||||||
CNameCache::getHistory (const valtype& name, CNameHistory& res) const
|
CKevaCache::getHistory (const valtype& name, CNameHistory& res) const
|
||||||
{
|
{
|
||||||
assert (fNameHistory);
|
assert (fNameHistory);
|
||||||
|
|
||||||
@ -227,7 +231,7 @@ CNameCache::getHistory (const valtype& name, CNameHistory& res) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CNameCache::setHistory (const valtype& name, const CNameHistory& data)
|
CKevaCache::setHistory (const valtype& name, const CNameHistory& data)
|
||||||
{
|
{
|
||||||
assert (fNameHistory);
|
assert (fNameHistory);
|
||||||
|
|
||||||
@ -237,9 +241,10 @@ CNameCache::setHistory (const valtype& name, const CNameHistory& data)
|
|||||||
else
|
else
|
||||||
history.insert (std::make_pair (name, data));
|
history.insert (std::make_pair (name, data));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
CNameCache::updateNamesForHeight (unsigned nHeight,
|
CKevaCache::updateNamesForHeight (unsigned nHeight,
|
||||||
std::set<valtype>& names) const
|
std::set<valtype>& names) const
|
||||||
{
|
{
|
||||||
/* Seek in the map of cached entries to the first one corresponding
|
/* Seek in the map of cached entries to the first one corresponding
|
||||||
@ -263,21 +268,21 @@ CNameCache::updateNamesForHeight (unsigned nHeight,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CNameCache::addExpireIndex (const valtype& name, unsigned height)
|
CKevaCache::addExpireIndex (const valtype& name, unsigned height)
|
||||||
{
|
{
|
||||||
const ExpireEntry entry(height, name);
|
const ExpireEntry entry(height, name);
|
||||||
expireIndex[entry] = true;
|
expireIndex[entry] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CNameCache::removeExpireIndex (const valtype& name, unsigned height)
|
CKevaCache::removeExpireIndex (const valtype& name, unsigned height)
|
||||||
{
|
{
|
||||||
const ExpireEntry entry(height, name);
|
const ExpireEntry entry(height, name);
|
||||||
expireIndex[entry] = false;
|
expireIndex[entry] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CNameCache::apply (const CNameCache& cache)
|
CKevaCache::apply (const CKevaCache& cache)
|
||||||
{
|
{
|
||||||
for (EntryMap::const_iterator i = cache.entries.begin ();
|
for (EntryMap::const_iterator i = cache.entries.begin ();
|
||||||
i != cache.entries.end (); ++i)
|
i != cache.entries.end (); ++i)
|
||||||
|
@ -274,7 +274,7 @@ public:
|
|||||||
* new names (or updates to them), this also keeps track of deleted names
|
* new names (or updates to them), this also keeps track of deleted names
|
||||||
* (when rolling back changes).
|
* (when rolling back changes).
|
||||||
*/
|
*/
|
||||||
class CNameCache
|
class CKevaCache
|
||||||
{
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -306,6 +306,7 @@ public:
|
|||||||
* the height is serialised as byte-array with little-endian order,
|
* the height is serialised as byte-array with little-endian order,
|
||||||
* which does not correspond to the ordering by actual value.
|
* which does not correspond to the ordering by actual value.
|
||||||
*/
|
*/
|
||||||
|
#if 0
|
||||||
class ExpireEntry
|
class ExpireEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -369,6 +370,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of name entry map. This is public because it is also used
|
* Type of name entry map. This is public because it is also used
|
||||||
@ -383,17 +385,21 @@ private:
|
|||||||
/** Deleted names. */
|
/** Deleted names. */
|
||||||
std::set<valtype> deleted;
|
std::set<valtype> deleted;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* New or updated history stacks. If they are empty, the corresponding
|
* New or updated history stacks. If they are empty, the corresponding
|
||||||
* database entry is deleted instead.
|
* database entry is deleted instead.
|
||||||
*/
|
*/
|
||||||
std::map<valtype, CNameHistory> history;
|
std::map<valtype, CNameHistory> history;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* Changes to be performed to the expire index. The entry is mapped
|
* Changes to be performed to the expire index. The entry is mapped
|
||||||
* to either "true" (meaning to add it) or "false" (delete).
|
* to either "true" (meaning to add it) or "false" (delete).
|
||||||
*/
|
*/
|
||||||
std::map<ExpireEntry, bool> expireIndex;
|
std::map<ExpireEntry, bool> expireIndex;
|
||||||
|
#endif
|
||||||
|
|
||||||
friend class CCacheNameIterator;
|
friend class CCacheNameIterator;
|
||||||
|
|
||||||
@ -404,8 +410,10 @@ public:
|
|||||||
{
|
{
|
||||||
entries.clear ();
|
entries.clear ();
|
||||||
deleted.clear ();
|
deleted.clear ();
|
||||||
|
#if 0
|
||||||
history.clear ();
|
history.clear ();
|
||||||
expireIndex.clear ();
|
expireIndex.clear ();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -417,38 +425,40 @@ public:
|
|||||||
inline bool
|
inline bool
|
||||||
empty () const
|
empty () const
|
||||||
{
|
{
|
||||||
if (entries.empty () && deleted.empty ())
|
if (entries.empty () && deleted.empty ()) {
|
||||||
{
|
#if 0
|
||||||
assert (history.empty () && expireIndex.empty ());
|
assert (history.empty () && expireIndex.empty ());
|
||||||
return true;
|
#endif
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See if the given name is marked as deleted. */
|
/* See if the given name is marked as deleted. */
|
||||||
inline bool
|
inline bool
|
||||||
isDeleted (const valtype& name) const
|
isDeleted (const valtype& nameSpace, const valtype& key) const
|
||||||
{
|
{
|
||||||
return (deleted.count (name) > 0);
|
return (deleted.count (name) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to get a name's associated data. This looks only
|
/* Try to get a name's associated data. This looks only
|
||||||
in entries, and doesn't care about deleted data. */
|
in entries, and doesn't care about deleted data. */
|
||||||
bool get (const valtype& name, CKevaData& data) const;
|
bool get (const valtype& nameSpace, const valtype& key, CKevaData& data) const;
|
||||||
|
|
||||||
/* Insert (or update) a name. If it is marked as "deleted", this also
|
/* Insert (or update) a name. If it is marked as "deleted", this also
|
||||||
removes the "deleted" mark. */
|
removes the "deleted" mark. */
|
||||||
void set (const valtype& name, const CKevaData& data);
|
void set (const valtype& nameSpace, const valtype& key, const CKevaData& data);
|
||||||
|
|
||||||
/* Delete a name. If it is in the "entries" set also, remove it there. */
|
/* Delete a name. If it is in the "entries" set also, remove it there. */
|
||||||
void remove (const valtype& name);
|
void remove (const valtype& nameSpace, const valtype& key);
|
||||||
|
|
||||||
/* Return a name iterator that combines a "base" iterator with the changes
|
/* Return a name iterator that combines a "base" iterator with the changes
|
||||||
made to it according to the cache. The base iterator is taken
|
made to it according to the cache. The base iterator is taken
|
||||||
ownership of. */
|
ownership of. */
|
||||||
CNameIterator* iterateNames (CNameIterator* base) const;
|
CNameIterator* iterateNames (CNameIterator* base) const;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* Query for an history entry.
|
* Query for an history entry.
|
||||||
* @param name The name to look up.
|
* @param name The name to look up.
|
||||||
@ -463,6 +473,7 @@ public:
|
|||||||
* @param data The new history entry.
|
* @param data The new history entry.
|
||||||
*/
|
*/
|
||||||
void setHistory (const valtype& name, const CNameHistory& data);
|
void setHistory (const valtype& name, const CNameHistory& data);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Query the cached changes to the expire index. In particular,
|
/* Query the cached changes to the expire index. In particular,
|
||||||
for a given height and a given set of names that were indexed to
|
for a given height and a given set of names that were indexed to
|
||||||
@ -470,14 +481,16 @@ public:
|
|||||||
are represented by the cached expire index changes. */
|
are represented by the cached expire index changes. */
|
||||||
void updateNamesForHeight (unsigned nHeight, std::set<valtype>& names) const;
|
void updateNamesForHeight (unsigned nHeight, std::set<valtype>& names) const;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Add an expire-index entry. */
|
/* Add an expire-index entry. */
|
||||||
void addExpireIndex (const valtype& name, unsigned height);
|
void addExpireIndex (const valtype& name, unsigned height);
|
||||||
|
|
||||||
/* Remove an expire-index entry. */
|
/* Remove an expire-index entry. */
|
||||||
void removeExpireIndex (const valtype& name, unsigned height);
|
void removeExpireIndex (const valtype& name, unsigned height);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Apply all the changes in the passed-in record on top of this one. */
|
/* Apply all the changes in the passed-in record on top of this one. */
|
||||||
void apply (const CNameCache& cache);
|
void apply (const CKevaCache& cache);
|
||||||
|
|
||||||
/* Write all cached changes to a database batch update object. */
|
/* Write all cached changes to a database batch update object. */
|
||||||
void writeBatch (CDBBatch& batch) const;
|
void writeBatch (CDBBatch& batch) const;
|
||||||
|
@ -26,19 +26,20 @@
|
|||||||
/* CKevaTxUndo. */
|
/* CKevaTxUndo. */
|
||||||
|
|
||||||
void
|
void
|
||||||
CKevaTxUndo::fromOldState(const valtype& nm, const CCoinsView& view)
|
CKevaTxUndo::fromOldState(const valtype& nameSpace, const valtype& key, const CCoinsView& view)
|
||||||
{
|
{
|
||||||
name = nm;
|
this->nameSpace = nameSpace;
|
||||||
isNew = !view.GetName(name, oldData);
|
this->key = key;
|
||||||
|
isNew = !view.GetName(nameSpace, key, oldData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CKevaTxUndo::apply (CCoinsViewCache& view) const
|
CKevaTxUndo::apply(CCoinsViewCache& view) const
|
||||||
{
|
{
|
||||||
if (isNew)
|
if (isNew)
|
||||||
view.DeleteName(name);
|
view.DeleteName(nameSpace, key);
|
||||||
else
|
else
|
||||||
view.SetName(name, oldData, true);
|
view.SetName(nameSpace, key, oldData, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
@ -504,6 +505,7 @@ ApplyNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
{
|
{
|
||||||
assert (nHeight != MEMPOOL_HEIGHT);
|
assert (nHeight != MEMPOOL_HEIGHT);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Handle historic bugs that should *not* be applied. Names that are
|
/* Handle historic bugs that should *not* be applied. Names that are
|
||||||
outputs should be marked as unspendable in this case. Otherwise,
|
outputs should be marked as unspendable in this case. Otherwise,
|
||||||
we get an inconsistency between the UTXO set and the name database. */
|
we get an inconsistency between the UTXO set and the name database. */
|
||||||
@ -521,34 +523,34 @@ ApplyNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This check must be done *after* the historic bug fixing above! Some
|
/* This check must be done *after* the historic bug fixing above! Some
|
||||||
of the names that must be handled above are actually produced by
|
of the names that must be handled above are actually produced by
|
||||||
transactions *not* marked as Namecoin tx. */
|
transactions *not* marked as Namecoin tx. */
|
||||||
if (!tx.IsNamecoin ())
|
if (!tx.IsKevacoin ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Changes are encoded in the outputs. We don't have to do any checks,
|
/* Changes are encoded in the outputs. We don't have to do any checks,
|
||||||
so simply apply all these. */
|
so simply apply all these. */
|
||||||
|
|
||||||
for (unsigned i = 0; i < tx.vout.size (); ++i)
|
for (unsigned i = 0; i < tx.vout.size (); ++i) {
|
||||||
{
|
const CKevaScript op(tx.vout[i].scriptPubKey);
|
||||||
const CNameScript op(tx.vout[i].scriptPubKey);
|
if (op.isKevaOp () && op.isAnyUpdate ()) {
|
||||||
if (op.isNameOp () && op.isAnyUpdate ())
|
const valtype& nameSpace = op.getOpNamespace();
|
||||||
{
|
const valtype& key = op.getOpKey();
|
||||||
const valtype& name = op.getOpName ();
|
LogPrint (BCLog::KEVA, "Updating name at height %d: %s\n",
|
||||||
LogPrint (BCLog::NAMES, "Updating name at height %d: %s\n",
|
nHeight, ValtypeToString (nameSpace).c_str ());
|
||||||
nHeight, ValtypeToString (name).c_str ());
|
|
||||||
|
|
||||||
CKevaTxUndo opUndo;
|
CKevaTxUndo opUndo;
|
||||||
opUndo.fromOldState (name, view);
|
opUndo.fromOldState(nameSpace, key, view);
|
||||||
undo.vnameundo.push_back (opUndo);
|
undo.vkevaundo.push_back(opUndo);
|
||||||
|
|
||||||
CNameData data;
|
CKevaData data;
|
||||||
data.fromScript (nHeight, COutPoint (tx.GetHash (), i), op);
|
data.fromScript (nHeight, COutPoint (tx.GetHash (), i), op);
|
||||||
view.SetName (name, data, false);
|
view.SetName (nameSpace, key, data, false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -51,8 +51,11 @@ class CKevaTxUndo
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** The name this concerns. */
|
/** The namespace this concerns. */
|
||||||
valtype name;
|
valtype nameSpace;
|
||||||
|
|
||||||
|
/** The key this concerns. */
|
||||||
|
valtype key;
|
||||||
|
|
||||||
/** Whether this was an entirely new name (no update). */
|
/** Whether this was an entirely new name (no update). */
|
||||||
bool isNew;
|
bool isNew;
|
||||||
@ -79,7 +82,7 @@ public:
|
|||||||
* @param nm The name that is being updated.
|
* @param nm The name that is being updated.
|
||||||
* @param view The (old!) chain state.
|
* @param view The (old!) chain state.
|
||||||
*/
|
*/
|
||||||
void fromOldState (const valtype& nm, const CCoinsView& view);
|
void fromOldState (const valtype& nameSpace, const valtype& key, const CCoinsView& view);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the undo to the chain state given.
|
* Apply the undo to the chain state given.
|
||||||
|
@ -62,6 +62,12 @@ uint256 CMutableTransaction::GetHash() const
|
|||||||
return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
|
return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMutableTransaction::SetKevacoin()
|
||||||
|
{
|
||||||
|
assert (nVersion == CTransaction::CURRENT_VERSION);
|
||||||
|
nVersion = CTransaction::KEVACOIN_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
uint256 CTransaction::ComputeHash() const
|
uint256 CTransaction::ComputeHash() const
|
||||||
{
|
{
|
||||||
return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
|
return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
|
||||||
|
@ -266,6 +266,7 @@ class CTransaction
|
|||||||
public:
|
public:
|
||||||
// Default transaction version.
|
// Default transaction version.
|
||||||
static const int32_t CURRENT_VERSION=2;
|
static const int32_t CURRENT_VERSION=2;
|
||||||
|
static const int32_t KEVACOIN_VERSION=0x7100;
|
||||||
|
|
||||||
// Changing the default transaction version requires a two step process: first
|
// Changing the default transaction version requires a two step process: first
|
||||||
// adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
|
// adapting relay policy by bumping MAX_STANDARD_VERSION, and then later date
|
||||||
@ -335,6 +336,11 @@ public:
|
|||||||
return (vin.size() == 1 && vin[0].prevout.IsNull());
|
return (vin.size() == 1 && vin[0].prevout.IsNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsKevacoin() const
|
||||||
|
{
|
||||||
|
return nVersion == KEVACOIN_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
||||||
{
|
{
|
||||||
return a.hash == b.hash;
|
return a.hash == b.hash;
|
||||||
@ -404,6 +410,12 @@ struct CMutableTransaction
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn this into a Kevacoin version transaction. It is assumed
|
||||||
|
* that it isn't already.
|
||||||
|
*/
|
||||||
|
void SetKevacoin();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<const CTransaction> CTransactionRef;
|
typedef std::shared_ptr<const CTransaction> CTransactionRef;
|
||||||
|
@ -52,7 +52,7 @@ public:
|
|||||||
* @return True iff this is a name operation.
|
* @return True iff this is a name operation.
|
||||||
*/
|
*/
|
||||||
inline bool
|
inline bool
|
||||||
isNameOp () const
|
isKevaOp () const
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_KEVA_PUT:
|
case OP_KEVA_PUT:
|
||||||
@ -80,10 +80,10 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the name operation. This returns OP_NAME_NEW, OP_NAME_FIRSTUPDATE
|
* Return the name operation. This returns OP_NAME_NEW, OP_NAME_FIRSTUPDATE
|
||||||
* or OP_NAME_UPDATE. Do not call if this is not a name script.
|
* or OP_NAME_UPDATE. Do not call if this is not a keva script.
|
||||||
* @return The name operation opcode.
|
* @return The name operation opcode.
|
||||||
*/
|
*/
|
||||||
inline opcodetype getNameOp() const
|
inline opcodetype getKevaOp() const
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_KEVA_PUT:
|
case OP_KEVA_PUT:
|
||||||
@ -119,9 +119,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Return the name operation name. This call is only valid for
|
* Return the name operation name. This call is only valid for
|
||||||
* OP_KEVA_NAMESPACE or OP_KEVA_PUT.
|
* OP_KEVA_NAMESPACE or OP_KEVA_PUT.
|
||||||
* @return The name operation's name.
|
* @return The keva operation's namespace.
|
||||||
*/
|
*/
|
||||||
inline const valtype& getOpName () const
|
inline const valtype& getOpNamespace() const
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_KEVA_PUT:
|
case OP_KEVA_PUT:
|
||||||
@ -140,7 +140,7 @@ public:
|
|||||||
* OP_KEVA_PUT.
|
* OP_KEVA_PUT.
|
||||||
* @return The name operation's value.
|
* @return The name operation's value.
|
||||||
*/
|
*/
|
||||||
inline const valtype& getOpValue () const
|
inline const valtype& getOpNamespaceValue() const
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_KEVA_PUT:
|
case OP_KEVA_PUT:
|
||||||
@ -153,15 +153,51 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the given script is a name script. This is a utility method.
|
* Return the keva operation key. This call is only valid for
|
||||||
|
* OP_KEVA_PUT.
|
||||||
|
* @return The keva operation's value.
|
||||||
|
*/
|
||||||
|
inline const valtype& getOpKey() const
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case OP_KEVA_PUT:
|
||||||
|
return args[0];
|
||||||
|
|
||||||
|
case OP_KEVA_NAMESPACE:
|
||||||
|
return args[0];
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the keva operation value. This call is only valid for
|
||||||
|
* OP_KEVA_PUT.
|
||||||
|
* @return The keva operation's value.
|
||||||
|
*/
|
||||||
|
inline const valtype& getOpValue() const
|
||||||
|
{
|
||||||
|
switch (op) {
|
||||||
|
case OP_KEVA_PUT:
|
||||||
|
// args[1] is namespace
|
||||||
|
return args[2];
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert (false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given script is a keva script. This is a utility method.
|
||||||
* @param script The script to parse.
|
* @param script The script to parse.
|
||||||
* @return True iff it is a name script.
|
* @return True iff it is a name script.
|
||||||
*/
|
*/
|
||||||
static inline bool
|
static inline bool
|
||||||
isNameScript (const CScript& script)
|
isKevaScript (const CScript& script)
|
||||||
{
|
{
|
||||||
const CKevaScript op(script);
|
const CKevaScript op(script);
|
||||||
return op.isNameOp ();
|
return op.isKevaOp ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,6 +38,8 @@ static const int MAX_STACK_SIZE = 1000;
|
|||||||
// otherwise as UNIX timestamp.
|
// otherwise as UNIX timestamp.
|
||||||
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
||||||
|
|
||||||
|
typedef std::vector<unsigned char> valtype;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<unsigned char> ToByteVector(const T& in)
|
std::vector<unsigned char> ToByteVector(const T& in)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +101,9 @@ class CBlockUndo
|
|||||||
public:
|
public:
|
||||||
std::vector<CTxUndo> vtxundo; // for all but the coinbase
|
std::vector<CTxUndo> vtxundo; // for all but the coinbase
|
||||||
|
|
||||||
|
/** Stack of operations done to the keva database. */
|
||||||
|
std::vector<CKevaTxUndo> vkevaundo;
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
template <typename Stream, typename Operation>
|
||||||
|
@ -104,6 +104,7 @@ namespace BCLog {
|
|||||||
COINDB = (1 << 18),
|
COINDB = (1 << 18),
|
||||||
QT = (1 << 19),
|
QT = (1 << 19),
|
||||||
LEVELDB = (1 << 20),
|
LEVELDB = (1 << 20),
|
||||||
|
KEVA = (1 << 21),
|
||||||
ALL = ~(uint32_t)0,
|
ALL = ~(uint32_t)0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user