mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-14 00:58:09 +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; }
|
||||
uint256 CCoinsView::GetBestBlock() const { return 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; }
|
||||
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); }
|
||||
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
||||
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; }
|
||||
bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) { return base->BatchWrite(mapCoins, hashBlock); }
|
||||
CCoinsViewCursor *CCoinsViewBacked::Cursor() const { return base->Cursor(); }
|
||||
@ -142,6 +146,96 @@ void CCoinsViewCache::SetBestBlock(const uint256 &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) {
|
||||
for (CCoinsMap::iterator it = mapCoins.begin(); it != mapCoins.end(); it = mapCoins.erase(it)) {
|
||||
// Ignore non-dirty entries (optimization).
|
||||
|
18
src/coins.h
18
src/coins.h
@ -11,6 +11,7 @@
|
||||
#include <core_memusage.h>
|
||||
#include <hash.h>
|
||||
#include <memusage.h>
|
||||
#include <keva/common.h>
|
||||
#include <serialize.h>
|
||||
#include <uint256.h>
|
||||
|
||||
@ -163,6 +164,12 @@ public:
|
||||
//! the old block hash, in that order.
|
||||
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).
|
||||
//! The passed mapCoins can be modified.
|
||||
virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock);
|
||||
@ -190,6 +197,8 @@ public:
|
||||
bool HaveCoin(const COutPoint &outpoint) const override;
|
||||
uint256 GetBestBlock() 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);
|
||||
bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock) override;
|
||||
CCoinsViewCursor *Cursor() const override;
|
||||
@ -211,6 +220,9 @@ protected:
|
||||
/* Cached dynamic memory usage for the inner Coin objects. */
|
||||
mutable size_t cachedCoinsUsage;
|
||||
|
||||
/** Name changes cache. */
|
||||
CKevaCache cacheNames;
|
||||
|
||||
public:
|
||||
CCoinsViewCache(CCoinsView *baseIn);
|
||||
|
||||
@ -224,11 +236,17 @@ public:
|
||||
bool HaveCoin(const COutPoint &outpoint) const override;
|
||||
uint256 GetBestBlock() const override;
|
||||
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;
|
||||
CCoinsViewCursor* Cursor() const override {
|
||||
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.
|
||||
* The semantics are the same as HaveCoin(), but no calls to
|
||||
|
@ -38,7 +38,7 @@ CNameIterator::~CNameIterator ()
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* CNameCacheNameIterator. */
|
||||
/* CKevaCacheNameIterator. */
|
||||
|
||||
class CCacheNameIterator : public CNameIterator
|
||||
{
|
||||
@ -46,7 +46,7 @@ class CCacheNameIterator : public CNameIterator
|
||||
private:
|
||||
|
||||
/** Reference to cache object that is used. */
|
||||
const CNameCache& cache;
|
||||
const CKevaCache& cache;
|
||||
|
||||
/** Base iterator to combine with the cache. */
|
||||
CNameIterator* base;
|
||||
@ -59,7 +59,7 @@ private:
|
||||
CKevaData baseData;
|
||||
|
||||
/** 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
|
||||
"cache" for the next entry. This already skips entries that are
|
||||
@ -73,7 +73,7 @@ public:
|
||||
* @param c The cache object to use.
|
||||
* @param b The base iterator.
|
||||
*/
|
||||
CCacheNameIterator (const CNameCache& c, CNameIterator* b);
|
||||
CCacheNameIterator (const CKevaCache& c, CNameIterator* b);
|
||||
|
||||
/* Destruct, this deletes also the base iterator. */
|
||||
~CCacheNameIterator ();
|
||||
@ -84,7 +84,7 @@ public:
|
||||
|
||||
};
|
||||
|
||||
CCacheNameIterator::CCacheNameIterator (const CNameCache& c, CNameIterator* b)
|
||||
CCacheNameIterator::CCacheNameIterator (const CKevaCache& c, CNameIterator* b)
|
||||
: cache(c), base(b)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
CNameCache::NameComparator cmp;
|
||||
CKevaCache::NameComparator cmp;
|
||||
useBase = cmp (baseName, cacheIter->first);
|
||||
}
|
||||
}
|
||||
@ -170,11 +170,12 @@ CCacheNameIterator::next (valtype& name, CKevaData& data)
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* CNameCache. */
|
||||
/* CKevaCache. */
|
||||
|
||||
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);
|
||||
if (i == entries.end ())
|
||||
return false;
|
||||
@ -184,8 +185,9 @@ CNameCache::get (const valtype& name, CKevaData& data) const
|
||||
}
|
||||
|
||||
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);
|
||||
if (di != deleted.end ())
|
||||
deleted.erase (di);
|
||||
@ -198,8 +200,9 @@ CNameCache::set (const valtype& name, const CKevaData& data)
|
||||
}
|
||||
|
||||
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);
|
||||
if (ei != entries.end ())
|
||||
entries.erase (ei);
|
||||
@ -208,13 +211,14 @@ CNameCache::remove (const valtype& name)
|
||||
}
|
||||
|
||||
CNameIterator*
|
||||
CNameCache::iterateNames (CNameIterator* base) const
|
||||
CKevaCache::iterateNames (CNameIterator* base) const
|
||||
{
|
||||
return new CCacheNameIterator (*this, base);
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool
|
||||
CNameCache::getHistory (const valtype& name, CNameHistory& res) const
|
||||
CKevaCache::getHistory (const valtype& name, CNameHistory& res) const
|
||||
{
|
||||
assert (fNameHistory);
|
||||
|
||||
@ -227,7 +231,7 @@ CNameCache::getHistory (const valtype& name, CNameHistory& res) const
|
||||
}
|
||||
|
||||
void
|
||||
CNameCache::setHistory (const valtype& name, const CNameHistory& data)
|
||||
CKevaCache::setHistory (const valtype& name, const CNameHistory& data)
|
||||
{
|
||||
assert (fNameHistory);
|
||||
|
||||
@ -237,9 +241,10 @@ CNameCache::setHistory (const valtype& name, const CNameHistory& data)
|
||||
else
|
||||
history.insert (std::make_pair (name, data));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CNameCache::updateNamesForHeight (unsigned nHeight,
|
||||
CKevaCache::updateNamesForHeight (unsigned nHeight,
|
||||
std::set<valtype>& names) const
|
||||
{
|
||||
/* Seek in the map of cached entries to the first one corresponding
|
||||
@ -263,21 +268,21 @@ CNameCache::updateNamesForHeight (unsigned nHeight,
|
||||
}
|
||||
|
||||
void
|
||||
CNameCache::addExpireIndex (const valtype& name, unsigned height)
|
||||
CKevaCache::addExpireIndex (const valtype& name, unsigned height)
|
||||
{
|
||||
const ExpireEntry entry(height, name);
|
||||
expireIndex[entry] = true;
|
||||
}
|
||||
|
||||
void
|
||||
CNameCache::removeExpireIndex (const valtype& name, unsigned height)
|
||||
CKevaCache::removeExpireIndex (const valtype& name, unsigned height)
|
||||
{
|
||||
const ExpireEntry entry(height, name);
|
||||
expireIndex[entry] = false;
|
||||
}
|
||||
|
||||
void
|
||||
CNameCache::apply (const CNameCache& cache)
|
||||
CKevaCache::apply (const CKevaCache& cache)
|
||||
{
|
||||
for (EntryMap::const_iterator i = cache.entries.begin ();
|
||||
i != cache.entries.end (); ++i)
|
||||
|
@ -274,7 +274,7 @@ public:
|
||||
* new names (or updates to them), this also keeps track of deleted names
|
||||
* (when rolling back changes).
|
||||
*/
|
||||
class CNameCache
|
||||
class CKevaCache
|
||||
{
|
||||
|
||||
private:
|
||||
@ -306,6 +306,7 @@ public:
|
||||
* the height is serialised as byte-array with little-endian order,
|
||||
* which does not correspond to the ordering by actual value.
|
||||
*/
|
||||
#if 0
|
||||
class ExpireEntry
|
||||
{
|
||||
public:
|
||||
@ -369,6 +370,7 @@ public:
|
||||
}
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Type of name entry map. This is public because it is also used
|
||||
@ -383,17 +385,21 @@ private:
|
||||
/** Deleted names. */
|
||||
std::set<valtype> deleted;
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* New or updated history stacks. If they are empty, the corresponding
|
||||
* database entry is deleted instead.
|
||||
*/
|
||||
std::map<valtype, CNameHistory> history;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Changes to be performed to the expire index. The entry is mapped
|
||||
* to either "true" (meaning to add it) or "false" (delete).
|
||||
*/
|
||||
std::map<ExpireEntry, bool> expireIndex;
|
||||
#endif
|
||||
|
||||
friend class CCacheNameIterator;
|
||||
|
||||
@ -404,8 +410,10 @@ public:
|
||||
{
|
||||
entries.clear ();
|
||||
deleted.clear ();
|
||||
#if 0
|
||||
history.clear ();
|
||||
expireIndex.clear ();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -417,38 +425,40 @@ public:
|
||||
inline bool
|
||||
empty () const
|
||||
{
|
||||
if (entries.empty () && deleted.empty ())
|
||||
{
|
||||
assert (history.empty () && expireIndex.empty ());
|
||||
return true;
|
||||
}
|
||||
if (entries.empty () && deleted.empty ()) {
|
||||
#if 0
|
||||
assert (history.empty () && expireIndex.empty ());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See if the given name is marked as deleted. */
|
||||
inline bool
|
||||
isDeleted (const valtype& name) const
|
||||
isDeleted (const valtype& nameSpace, const valtype& key) const
|
||||
{
|
||||
return (deleted.count (name) > 0);
|
||||
}
|
||||
|
||||
/* Try to get a name's associated data. This looks only
|
||||
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
|
||||
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. */
|
||||
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
|
||||
made to it according to the cache. The base iterator is taken
|
||||
ownership of. */
|
||||
CNameIterator* iterateNames (CNameIterator* base) const;
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Query for an history entry.
|
||||
* @param name The name to look up.
|
||||
@ -463,6 +473,7 @@ public:
|
||||
* @param data The new history entry.
|
||||
*/
|
||||
void setHistory (const valtype& name, const CNameHistory& data);
|
||||
#endif
|
||||
|
||||
/* Query the cached changes to the expire index. In particular,
|
||||
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. */
|
||||
void updateNamesForHeight (unsigned nHeight, std::set<valtype>& names) const;
|
||||
|
||||
#if 0
|
||||
/* Add an expire-index entry. */
|
||||
void addExpireIndex (const valtype& name, unsigned height);
|
||||
|
||||
/* Remove an expire-index entry. */
|
||||
void removeExpireIndex (const valtype& name, unsigned height);
|
||||
#endif
|
||||
|
||||
/* 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. */
|
||||
void writeBatch (CDBBatch& batch) const;
|
||||
|
@ -26,19 +26,20 @@
|
||||
/* CKevaTxUndo. */
|
||||
|
||||
void
|
||||
CKevaTxUndo::fromOldState(const valtype& nm, const CCoinsView& view)
|
||||
CKevaTxUndo::fromOldState(const valtype& nameSpace, const valtype& key, const CCoinsView& view)
|
||||
{
|
||||
name = nm;
|
||||
isNew = !view.GetName(name, oldData);
|
||||
this->nameSpace = nameSpace;
|
||||
this->key = key;
|
||||
isNew = !view.GetName(nameSpace, key, oldData);
|
||||
}
|
||||
|
||||
void
|
||||
CKevaTxUndo::apply (CCoinsViewCache& view) const
|
||||
CKevaTxUndo::apply(CCoinsViewCache& view) const
|
||||
{
|
||||
if (isNew)
|
||||
view.DeleteName(name);
|
||||
view.DeleteName(nameSpace, key);
|
||||
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);
|
||||
|
||||
#if 0
|
||||
/* Handle historic bugs that should *not* be applied. Names that are
|
||||
outputs should be marked as unspendable in this case. Otherwise,
|
||||
we get an inconsistency between the UTXO set and the name database. */
|
||||
@ -521,34 +523,34 @@ ApplyNameTransaction (const CTransaction& tx, unsigned nHeight,
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This check must be done *after* the historic bug fixing above! Some
|
||||
of the names that must be handled above are actually produced by
|
||||
transactions *not* marked as Namecoin tx. */
|
||||
if (!tx.IsNamecoin ())
|
||||
if (!tx.IsKevacoin ())
|
||||
return;
|
||||
|
||||
/* Changes are encoded in the outputs. We don't have to do any checks,
|
||||
so simply apply all these. */
|
||||
|
||||
for (unsigned i = 0; i < tx.vout.size (); ++i)
|
||||
{
|
||||
const CNameScript op(tx.vout[i].scriptPubKey);
|
||||
if (op.isNameOp () && op.isAnyUpdate ())
|
||||
{
|
||||
const valtype& name = op.getOpName ();
|
||||
LogPrint (BCLog::NAMES, "Updating name at height %d: %s\n",
|
||||
nHeight, ValtypeToString (name).c_str ());
|
||||
for (unsigned i = 0; i < tx.vout.size (); ++i) {
|
||||
const CKevaScript op(tx.vout[i].scriptPubKey);
|
||||
if (op.isKevaOp () && op.isAnyUpdate ()) {
|
||||
const valtype& nameSpace = op.getOpNamespace();
|
||||
const valtype& key = op.getOpKey();
|
||||
LogPrint (BCLog::KEVA, "Updating name at height %d: %s\n",
|
||||
nHeight, ValtypeToString (nameSpace).c_str ());
|
||||
|
||||
CKevaTxUndo opUndo;
|
||||
opUndo.fromOldState (name, view);
|
||||
undo.vnameundo.push_back (opUndo);
|
||||
CKevaTxUndo opUndo;
|
||||
opUndo.fromOldState(nameSpace, key, view);
|
||||
undo.vkevaundo.push_back(opUndo);
|
||||
|
||||
CNameData data;
|
||||
data.fromScript (nHeight, COutPoint (tx.GetHash (), i), op);
|
||||
view.SetName (name, data, false);
|
||||
}
|
||||
CKevaData data;
|
||||
data.fromScript (nHeight, COutPoint (tx.GetHash (), i), op);
|
||||
view.SetName (nameSpace, key, data, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -51,8 +51,11 @@ class CKevaTxUndo
|
||||
|
||||
private:
|
||||
|
||||
/** The name this concerns. */
|
||||
valtype name;
|
||||
/** The namespace this concerns. */
|
||||
valtype nameSpace;
|
||||
|
||||
/** The key this concerns. */
|
||||
valtype key;
|
||||
|
||||
/** Whether this was an entirely new name (no update). */
|
||||
bool isNew;
|
||||
@ -79,7 +82,7 @@ public:
|
||||
* @param nm The name that is being updated.
|
||||
* @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.
|
||||
|
@ -62,6 +62,12 @@ uint256 CMutableTransaction::GetHash() const
|
||||
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
|
||||
{
|
||||
return SerializeHash(*this, SER_GETHASH, SERIALIZE_TRANSACTION_NO_WITNESS);
|
||||
|
@ -266,6 +266,7 @@ class CTransaction
|
||||
public:
|
||||
// Default transaction version.
|
||||
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
|
||||
// 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());
|
||||
}
|
||||
|
||||
bool IsKevacoin() const
|
||||
{
|
||||
return nVersion == KEVACOIN_VERSION;
|
||||
}
|
||||
|
||||
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
||||
{
|
||||
return a.hash == b.hash;
|
||||
@ -404,6 +410,12 @@ struct CMutableTransaction
|
||||
}
|
||||
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;
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
* @return True iff this is a name operation.
|
||||
*/
|
||||
inline bool
|
||||
isNameOp () const
|
||||
isKevaOp () const
|
||||
{
|
||||
switch (op) {
|
||||
case OP_KEVA_PUT:
|
||||
@ -80,10 +80,10 @@ public:
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
inline opcodetype getNameOp() const
|
||||
inline opcodetype getKevaOp() const
|
||||
{
|
||||
switch (op) {
|
||||
case OP_KEVA_PUT:
|
||||
@ -119,9 +119,9 @@ public:
|
||||
/**
|
||||
* Return the name operation name. This call is only valid for
|
||||
* 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) {
|
||||
case OP_KEVA_PUT:
|
||||
@ -140,7 +140,7 @@ public:
|
||||
* OP_KEVA_PUT.
|
||||
* @return The name operation's value.
|
||||
*/
|
||||
inline const valtype& getOpValue () const
|
||||
inline const valtype& getOpNamespaceValue() const
|
||||
{
|
||||
switch (op) {
|
||||
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.
|
||||
* @return True iff it is a name script.
|
||||
*/
|
||||
static inline bool
|
||||
isNameScript (const CScript& script)
|
||||
isKevaScript (const CScript& 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.
|
||||
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
|
||||
|
||||
typedef std::vector<unsigned char> valtype;
|
||||
|
||||
template <typename T>
|
||||
std::vector<unsigned char> ToByteVector(const T& in)
|
||||
{
|
||||
|
@ -101,6 +101,9 @@ class CBlockUndo
|
||||
public:
|
||||
std::vector<CTxUndo> vtxundo; // for all but the coinbase
|
||||
|
||||
/** Stack of operations done to the keva database. */
|
||||
std::vector<CKevaTxUndo> vkevaundo;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
|
@ -104,6 +104,7 @@ namespace BCLog {
|
||||
COINDB = (1 << 18),
|
||||
QT = (1 << 19),
|
||||
LEVELDB = (1 << 20),
|
||||
KEVA = (1 << 21),
|
||||
ALL = ~(uint32_t)0,
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user