mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-14 09:08:11 +00:00
Cleaned up code - removed dead code from namecoin.
Removed lots of legacy checks from namecoin.
This commit is contained in:
parent
a875d1ca34
commit
11c740f549
@ -51,15 +51,11 @@ CKevaMemPool::addUnchecked (const uint256& hash, const CTxMemPoolEntry& entry)
|
||||
AssertLockHeld (pool.cs);
|
||||
if (entry.isNamespaceRegistration()) {
|
||||
const valtype& nameSpace = entry.getNamespace();
|
||||
assert(mapNamespaceRegs.count(nameSpace) == 0);
|
||||
mapNamespaceRegs.insert(std::make_pair(nameSpace, hash));
|
||||
listUnconfirmedNamespaces.push_back(std::make_tuple(hash, nameSpace, entry.getDisplayName()));
|
||||
}
|
||||
|
||||
if (entry.isNamespaceKeyUpdate ()) {
|
||||
const valtype& nameSpace = entry.getNamespace();
|
||||
assert(mapNamespaceUpdates.count(nameSpace) == 0);
|
||||
mapNamespaceUpdates.insert (std::make_pair(nameSpace, hash));
|
||||
listUnconfirmedKeyValues.push_back(std::make_tuple(hash, nameSpace, entry.getKey(), entry.getValue()));
|
||||
}
|
||||
}
|
||||
@ -94,9 +90,6 @@ void CKevaMemPool::remove(const CTxMemPoolEntry& entry)
|
||||
{
|
||||
AssertLockHeld (pool.cs);
|
||||
if (entry.isNamespaceRegistration()) {
|
||||
const NamespaceTxMap::iterator mit = mapNamespaceRegs.find(entry.getNamespace());
|
||||
assert (mit != mapNamespaceRegs.end());
|
||||
mapNamespaceRegs.erase(mit);
|
||||
auto hash = entry.GetTx().GetHash();
|
||||
for (auto iter = listUnconfirmedNamespaces.begin(); iter != listUnconfirmedNamespaces.end(); ++iter) {
|
||||
if (std::get<0>(*iter) == hash) {
|
||||
@ -107,9 +100,6 @@ void CKevaMemPool::remove(const CTxMemPoolEntry& entry)
|
||||
}
|
||||
|
||||
if (entry.isNamespaceKeyUpdate()) {
|
||||
const NamespaceTxMap::iterator mit = mapNamespaceUpdates.find(entry.getNamespace());
|
||||
assert (mit != mapNamespaceUpdates.end());
|
||||
mapNamespaceUpdates.erase(mit);
|
||||
auto hash = entry.GetTx().GetHash();
|
||||
for (auto iter = listUnconfirmedKeyValues.begin(); iter != listUnconfirmedKeyValues.end(); ++iter) {
|
||||
if (std::get<0>(*iter) == hash) {
|
||||
@ -146,79 +136,6 @@ CKevaMemPool::removeConflicts(const CTransaction& tx)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CKevaMemPool::check(const CCoinsView& coins) const
|
||||
{
|
||||
AssertLockHeld (pool.cs);
|
||||
|
||||
const uint256 blockHash = coins.GetBestBlock ();
|
||||
int nHeight;
|
||||
if (blockHash.IsNull())
|
||||
nHeight = 0;
|
||||
else
|
||||
nHeight = mapBlockIndex.find (blockHash)->second->nHeight;
|
||||
|
||||
std::set<valtype> nameRegs;
|
||||
std::set<valtype> namespaceKeyUpdates;
|
||||
for (const auto& entry : pool.mapTx) {
|
||||
const uint256 txHash = entry.GetTx ().GetHash ();
|
||||
if (entry.isNamespaceRegistration()) {
|
||||
const valtype& nameSpace = entry.getNamespace();
|
||||
|
||||
const NamespaceTxMap::const_iterator mit = mapNamespaceRegs.find(nameSpace);
|
||||
assert (mit != mapNamespaceRegs.end());
|
||||
assert (mit->second == txHash);
|
||||
|
||||
assert (nameRegs.count(nameSpace) == 0);
|
||||
nameRegs.insert(nameSpace);
|
||||
#if 0
|
||||
/* The old name should be expired already. Note that we use
|
||||
nHeight+1 for the check, because that's the height at which
|
||||
the mempool tx will actually be mined. */
|
||||
CKevaData data;
|
||||
if (coins.GetName(name, data))
|
||||
assert (data.isExpired (nHeight + 1));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (entry.isNamespaceKeyUpdate()) {
|
||||
const valtype& nameSpace = entry.getNamespace();
|
||||
const NamespaceTxMap::const_iterator mit = mapNamespaceUpdates.find(nameSpace);
|
||||
assert (mit != mapNamespaceUpdates.end ());
|
||||
assert (mit->second == txHash);
|
||||
|
||||
assert (namespaceKeyUpdates.count(nameSpace) == 0);
|
||||
namespaceKeyUpdates.insert(nameSpace);
|
||||
|
||||
#if 0
|
||||
/* As above, use nHeight+1 for the expiration check. */
|
||||
CKevaData data;
|
||||
if (!coins.GetName(name, data)) {
|
||||
assert (false);
|
||||
}
|
||||
assert (!data.isExpired (nHeight + 1));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
assert(nameRegs.size() == mapNamespaceRegs.size());
|
||||
assert(namespaceKeyUpdates.size() == mapNamespaceUpdates.size());
|
||||
|
||||
/* Check that nameRegs and nameUpdates are disjoint. They must be since
|
||||
a name can only be in either category, depending on whether it exists
|
||||
at the moment or not. */
|
||||
#if 0
|
||||
// Is this neccesary?
|
||||
for (const auto& nameSpace : nameRegs) {
|
||||
assert(namespaceKeyUpdates.count(name) == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (const auto& nameSpace : namespaceKeyUpdates) {
|
||||
assert(nameRegs.count(nameSpace) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool CKevaMemPool::validateNamespace(const CTransaction& tx, const valtype& nameSpace) const
|
||||
{
|
||||
valtype kevaNamespace = ToByteVector(Hash160(ToByteVector(tx.vin[0].prevout.hash)));
|
||||
@ -227,17 +144,14 @@ bool CKevaMemPool::validateNamespace(const CTransaction& tx, const valtype& name
|
||||
}
|
||||
|
||||
bool
|
||||
CKevaMemPool::checkTx (const CTransaction& tx) const
|
||||
CKevaMemPool::checkTx(const CTransaction& tx) const
|
||||
{
|
||||
AssertLockHeld (pool.cs);
|
||||
|
||||
if (!tx.IsKevacoin ())
|
||||
if (!tx.IsKevacoin ()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* In principle, multiple name_updates could be performed within the
|
||||
mempool at once (building upon each other). This is disallowed, though,
|
||||
since the current mempool implementation does not like it. (We keep
|
||||
track of only a single update tx for each name.) */
|
||||
for (const auto& txout : tx.vout) {
|
||||
const CKevaScript nameOp(txout.scriptPubKey);
|
||||
if (!nameOp.isKevaOp ())
|
||||
@ -247,10 +161,6 @@ CKevaMemPool::checkTx (const CTransaction& tx) const
|
||||
{
|
||||
const valtype& nameSpace = nameOp.getOpNamespace();
|
||||
std::map<valtype, uint256>::const_iterator mi;
|
||||
mi = mapNamespaceRegs.find(nameSpace);
|
||||
if (mi != mapNamespaceRegs.end ()) {
|
||||
return false;
|
||||
}
|
||||
if (!validateNamespace(tx, nameSpace)) {
|
||||
return false;
|
||||
}
|
||||
@ -259,11 +169,6 @@ CKevaMemPool::checkTx (const CTransaction& tx) const
|
||||
|
||||
case OP_KEVA_PUT:
|
||||
{
|
||||
const valtype& nameSpace = nameOp.getOpNamespace();
|
||||
const valtype& key = nameOp.getOpKey();
|
||||
if (updatesNamespace(nameSpace)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -320,33 +225,27 @@ CheckKevaTransaction (const CTransaction& tx, unsigned nHeight,
|
||||
{
|
||||
const std::string strTxid = tx.GetHash ().GetHex ();
|
||||
const char* txid = strTxid.c_str ();
|
||||
const bool fMempool = (flags & SCRIPT_VERIFY_KEVA_MEMPOOL);
|
||||
|
||||
#if 0
|
||||
/* Ignore historic bugs. */
|
||||
CChainParams::BugType type;
|
||||
if (Params ().IsHistoricBug (tx.GetHash (), nHeight, type))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
/* As a first step, try to locate inputs and outputs of the transaction
|
||||
/*
|
||||
As a first step, try to locate inputs and outputs of the transaction
|
||||
that are keva scripts. At most one input and output should be
|
||||
a keva operation. */
|
||||
a keva operation.
|
||||
*/
|
||||
|
||||
int nameIn = -1;
|
||||
CKevaScript nameOpIn;
|
||||
Coin coinIn;
|
||||
for (unsigned i = 0; i < tx.vin.size (); ++i) {
|
||||
for (unsigned i = 0; i < tx.vin.size(); ++i) {
|
||||
const COutPoint& prevout = tx.vin[i].prevout;
|
||||
Coin coin;
|
||||
if (!view.GetCoin (prevout, coin)) {
|
||||
return error ("%s: failed to fetch input coin for %s", __func__, txid);
|
||||
if (!view.GetCoin(prevout, coin)) {
|
||||
return error("%s: failed to fetch input coin for %s", __func__, txid);
|
||||
}
|
||||
|
||||
const CKevaScript op(coin.out.scriptPubKey);
|
||||
if (op.isKevaOp()) {
|
||||
if (nameIn != -1) {
|
||||
return state.Invalid (error ("%s: multiple name inputs into transaction %s", __func__, txid));
|
||||
return state.Invalid(error("%s: multiple name inputs into transaction %s", __func__, txid));
|
||||
}
|
||||
nameIn = i;
|
||||
nameOpIn = op;
|
||||
@ -356,71 +255,43 @@ CheckKevaTransaction (const CTransaction& tx, unsigned nHeight,
|
||||
|
||||
int nameOut = -1;
|
||||
CKevaScript nameOpOut;
|
||||
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);
|
||||
if (op.isKevaOp()) {
|
||||
if (nameOut != -1) {
|
||||
return state.Invalid (error ("%s: multiple name outputs from"
|
||||
" transaction %s", __func__, txid));
|
||||
return state.Invalid(error("%s: multiple name outputs from transaction %s", __func__, txid));
|
||||
}
|
||||
nameOut = i;
|
||||
nameOpOut = op;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that no name inputs/outputs are present for a non-Namecoin tx.
|
||||
If that's the case, all is fine. For a Namecoin tx instead, there
|
||||
should be at least an output (for NAME_NEW, no inputs are expected). */
|
||||
/*
|
||||
Check that no keva inputs/outputs are present for a non-Kevacoin tx.
|
||||
If that's the case, all is fine. For a kevacoin tx instead, there
|
||||
should be at least an output.
|
||||
*/
|
||||
|
||||
if (!tx.IsKevacoin ()) {
|
||||
if (nameIn != -1)
|
||||
return state.Invalid (error ("%s: non-Kevacoin tx %s has keva inputs",
|
||||
__func__, txid));
|
||||
if (nameOut != -1)
|
||||
return state.Invalid (error ("%s: non-Kevacoin tx %s at height %u"
|
||||
" has keva outputs",
|
||||
if (!tx.IsKevacoin()) {
|
||||
if (nameIn != -1) {
|
||||
return state.Invalid(error("%s: non-Kevacoin tx %s has keva inputs", __func__, txid));
|
||||
}
|
||||
if (nameOut != -1) {
|
||||
return state.Invalid (error ("%s: non-Kevacoin tx %s at height %u has keva outputs",
|
||||
__func__, txid, nHeight));
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(tx.IsKevacoin ());
|
||||
if (nameOut == -1)
|
||||
return state.Invalid (error ("%s: Kevacoin tx %s has no keva outputs",
|
||||
__func__, txid));
|
||||
if (nameOut == -1) {
|
||||
return state.Invalid (error ("%s: Kevacoin tx %s has no keva outputs", __func__, txid));
|
||||
}
|
||||
|
||||
/* Reject "greedy names". */
|
||||
#if 0
|
||||
const Consensus::Params& params = Params ().GetConsensus ();
|
||||
if (tx.vout[nameOut].nValue < params.rules->MinNameCoinAmount(nHeight)) {
|
||||
return state.Invalid (error ("%s: greedy name", __func__));
|
||||
}
|
||||
#else
|
||||
if (tx.vout[nameOut].nValue < KEVA_LOCKED_AMOUNT) {
|
||||
return state.Invalid (error ("%s: greedy name", __func__));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* Handle NAME_NEW now, since this is easy and different from the other
|
||||
operations. */
|
||||
|
||||
if (nameOpOut.getNameOp () == OP_NAME_NEW)
|
||||
{
|
||||
if (nameIn != -1)
|
||||
return state.Invalid (error ("CheckKevaTransaction: NAME_NEW with"
|
||||
" previous name input"));
|
||||
|
||||
if (nameOpOut.getOpHash ().size () != 20)
|
||||
return state.Invalid (error ("CheckKevaTransaction: NAME_NEW's hash"
|
||||
" has wrong size"));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Now that we have ruled out NAME_NEW, check that we have a previous
|
||||
name input that is being updated. */
|
||||
#endif
|
||||
|
||||
if (nameOpOut.isNamespaceRegistration()) {
|
||||
if (nameOpOut.getOpNamespaceDisplayName().size () > MAX_VALUE_LENGTH) {
|
||||
@ -429,7 +300,8 @@ CheckKevaTransaction (const CTransaction& tx, unsigned nHeight,
|
||||
return true;
|
||||
}
|
||||
|
||||
assert (nameOpOut.isAnyUpdate());
|
||||
assert(nameOpOut.isAnyUpdate());
|
||||
|
||||
if (nameIn == -1) {
|
||||
return state.Invalid(error("CheckKevaTransaction: update without previous keva input"));
|
||||
}
|
||||
@ -451,82 +323,9 @@ CheckKevaTransaction (const CTransaction& tx, unsigned nHeight,
|
||||
}
|
||||
|
||||
if (nameSpace != nameOpIn.getOpNamespace()) {
|
||||
return state.Invalid (error ("%s: KEVA_PUT namespace mismatch to prev tx"
|
||||
" found in %s", __func__, txid));
|
||||
return state.Invalid(error("%s: KEVA_PUT namespace mismatch to prev tx found in %s", __func__, txid));
|
||||
}
|
||||
|
||||
CKevaData oldName;
|
||||
const valtype& namespaceIn = nameOpIn.getOpNamespace();
|
||||
if (!view.GetNamespace(namespaceIn, oldName)) {
|
||||
return state.Invalid (error ("%s: Namespace not found", __func__));
|
||||
}
|
||||
assert (tx.vin[nameIn].prevout == oldName.getUpdateOutpoint());
|
||||
|
||||
#if 0
|
||||
/* This is actually redundant, since expired names are removed
|
||||
from the UTXO set and thus not available to be spent anyway.
|
||||
But it does not hurt to enforce this here, too. It is also
|
||||
exercised by the unit tests. */
|
||||
CKevaData oldName;
|
||||
const valtype& namespaceIn = nameOpIn.getOpNamespace();
|
||||
const valtype& keyIn = nameOpIn.getOpKey();
|
||||
if (!view.GetName(namespaceIn, keyIn, oldName)) {
|
||||
return state.Invalid (error ("%s: KEVA_PUT name does not exist",
|
||||
__func__));
|
||||
}
|
||||
if (oldName.isExpired (nHeight))
|
||||
return state.Invalid (error ("%s: trying to update expired name",
|
||||
__func__));
|
||||
/* This is an internal consistency check. If everything is fine,
|
||||
the input coins from the UTXO database should match the
|
||||
name database. */
|
||||
assert (static_cast<unsigned> (coinIn.nHeight) == oldName.getHeight());
|
||||
assert (tx.vin[nameIn].prevout == oldName.getUpdateOutpoint());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Finally, NAME_FIRSTUPDATE. */
|
||||
|
||||
assert(nameOpOut.getNameOp () == OP_NAME_FIRSTUPDATE);
|
||||
if (nameOpIn.getNameOp () != OP_NAME_NEW)
|
||||
return state.Invalid (error ("CheckKevaTransaction: NAME_FIRSTUPDATE"
|
||||
" with non-NAME_NEW prev tx"));
|
||||
|
||||
/* Maturity of NAME_NEW is checked only if we're not adding
|
||||
to the mempool. */
|
||||
if (!fMempool)
|
||||
{
|
||||
assert (static_cast<unsigned> (coinIn.nHeight) != MEMPOOL_HEIGHT);
|
||||
if (coinIn.nHeight + MIN_FIRSTUPDATE_DEPTH > nHeight)
|
||||
return state.Invalid (error ("CheckKevaTransaction: NAME_NEW"
|
||||
" is not mature for FIRST_UPDATE"));
|
||||
}
|
||||
|
||||
if (nameOpOut.getOpRand ().size () > 20)
|
||||
return state.Invalid (error ("CheckKevaTransaction: NAME_FIRSTUPDATE"
|
||||
" rand too large, %d bytes",
|
||||
nameOpOut.getOpRand ().size ()));
|
||||
|
||||
{
|
||||
valtype toHash(nameOpOut.getOpRand ());
|
||||
toHash.insert (toHash.end (), name.begin (), name.end ());
|
||||
const uint160 hash = Hash160 (toHash);
|
||||
if (hash != uint160 (nameOpIn.getOpHash ()))
|
||||
return state.Invalid (error ("CheckKevaTransaction: NAME_FIRSTUPDATE"
|
||||
" hash mismatch"));
|
||||
}
|
||||
|
||||
CNameData oldName;
|
||||
if (view.GetName (name, oldName) && !oldName.isExpired (nHeight))
|
||||
return state.Invalid (error ("CheckKevaTransaction: NAME_FIRSTUPDATE"
|
||||
" on an unexpired name"));
|
||||
|
||||
/* We don't have to specifically check that miners don't create blocks with
|
||||
conflicting NAME_FIRSTUPDATE's, since the mining's CCoinsViewCache
|
||||
takes care of this with the check above already. */
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -578,128 +377,6 @@ void ApplyNameTransaction(const CTransaction& tx, unsigned nHeight,
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool
|
||||
ExpireNames (unsigned nHeight, CCoinsViewCache& view, CBlockUndo& undo,
|
||||
std::set<valtype>& names)
|
||||
{
|
||||
names.clear ();
|
||||
|
||||
/* The genesis block contains no name expirations. */
|
||||
if (nHeight == 0)
|
||||
return true;
|
||||
|
||||
/* Otherwise, find out at which update heights names have expired
|
||||
since the last block. If the expiration depth changes, this could
|
||||
be multiple heights at once. */
|
||||
|
||||
const Consensus::Params& params = Params ().GetConsensus ();
|
||||
const unsigned expDepthOld = params.rules->NameExpirationDepth (nHeight - 1);
|
||||
const unsigned expDepthNow = params.rules->NameExpirationDepth (nHeight);
|
||||
|
||||
if (expDepthNow > nHeight)
|
||||
return true;
|
||||
|
||||
/* Both are inclusive! The last expireTo was nHeight - 1 - expDepthOld,
|
||||
now we start at this value + 1. */
|
||||
const unsigned expireFrom = nHeight - expDepthOld;
|
||||
const unsigned expireTo = nHeight - expDepthNow;
|
||||
|
||||
/* It is possible that expireFrom = expireTo + 1, in case that the
|
||||
expiration period is raised together with the block height. In this
|
||||
case, no names expire in the current step. This case means that
|
||||
the absolute expiration height "n - expirationDepth(n)" is
|
||||
flat -- which is fine. */
|
||||
assert (expireFrom <= expireTo + 1);
|
||||
|
||||
/* Find all names that expire at those depths. Note that GetNamesForHeight
|
||||
clears the output set, to we union all sets here. */
|
||||
for (unsigned h = expireFrom; h <= expireTo; ++h)
|
||||
{
|
||||
std::set<valtype> newNames;
|
||||
view.GetNamesForHeight (h, newNames);
|
||||
names.insert (newNames.begin (), newNames.end ());
|
||||
}
|
||||
|
||||
/* Expire all those names. */
|
||||
for (std::set<valtype>::const_iterator i = names.begin ();
|
||||
i != names.end (); ++i)
|
||||
{
|
||||
const std::string nameStr = ValtypeToString (*i);
|
||||
|
||||
CNameData data;
|
||||
if (!view.GetName (*i, data))
|
||||
return error ("%s : name '%s' not found in the database",
|
||||
__func__, nameStr.c_str ());
|
||||
if (!data.isExpired (nHeight))
|
||||
return error ("%s : name '%s' is not actually expired",
|
||||
__func__, nameStr.c_str ());
|
||||
|
||||
/* Special rule: When d/postmortem expires (the name used by
|
||||
libcoin in the name-stealing demonstration), it's coin
|
||||
is already spent. Ignore. */
|
||||
if (nHeight == 175868 && nameStr == "d/postmortem")
|
||||
continue;
|
||||
|
||||
const COutPoint& out = data.getUpdateOutpoint ();
|
||||
Coin coin;
|
||||
if (!view.GetCoin(out, coin))
|
||||
return error ("%s : name coin for '%s' is not available",
|
||||
__func__, nameStr.c_str ());
|
||||
const CNameScript nameOp(coin.out.scriptPubKey);
|
||||
if (!nameOp.isNameOp () || !nameOp.isAnyUpdate ()
|
||||
|| nameOp.getOpName () != *i)
|
||||
return error ("%s : name coin to be expired is wrong script", __func__);
|
||||
|
||||
if (!view.SpendCoin (out, &coin))
|
||||
return error ("%s : spending name coin failed", __func__);
|
||||
undo.vexpired.push_back (coin);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
UnexpireNames (unsigned nHeight, CBlockUndo& undo, CCoinsViewCache& view,
|
||||
std::set<valtype>& names)
|
||||
{
|
||||
names.clear ();
|
||||
|
||||
/* The genesis block contains no name expirations. */
|
||||
if (nHeight == 0)
|
||||
return true;
|
||||
|
||||
std::vector<Coin>::reverse_iterator i;
|
||||
for (i = undo.vexpired.rbegin (); i != undo.vexpired.rend (); ++i)
|
||||
{
|
||||
const CNameScript nameOp(i->out.scriptPubKey);
|
||||
if (!nameOp.isNameOp () || !nameOp.isAnyUpdate ())
|
||||
return error ("%s : wrong script to be unexpired", __func__);
|
||||
|
||||
const valtype& name = nameOp.getOpName ();
|
||||
if (names.count (name) > 0)
|
||||
return error ("%s : name '%s' unexpired twice",
|
||||
__func__, ValtypeToString (name).c_str ());
|
||||
names.insert (name);
|
||||
|
||||
CNameData data;
|
||||
if (!view.GetName (nameOp.getOpName (), data))
|
||||
return error ("%s : no data for name '%s' to be unexpired",
|
||||
__func__, ValtypeToString (name).c_str ());
|
||||
if (!data.isExpired (nHeight) || data.isExpired (nHeight - 1))
|
||||
return error ("%s : name '%s' to be unexpired is not expired in the DB"
|
||||
" or it was already expired before the current height",
|
||||
__func__, ValtypeToString (name).c_str ());
|
||||
|
||||
if (ApplyTxInUndo (std::move(*i), view,
|
||||
data.getUpdateOutpoint ()) != DISCONNECT_OK)
|
||||
return error ("%s : failed to undo name coin spending", __func__);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CheckNameDB (bool disconnect)
|
||||
{
|
||||
|
@ -111,31 +111,6 @@ private:
|
||||
/** The parent mempool object. Used to, e. g., remove conflicting tx. */
|
||||
CTxMemPool& pool;
|
||||
|
||||
/** Type used for internal indices. */
|
||||
typedef std::map<valtype, uint256> NamespaceTxMap;
|
||||
|
||||
/** Type used for indexing Tx */
|
||||
typedef std::tuple<valtype, valtype> NamespaceKeyTuple;
|
||||
|
||||
/** Type used for internal indices. */
|
||||
typedef std::map<NamespaceKeyTuple, uint256> NamespaceKeyTxMap;
|
||||
|
||||
|
||||
/**
|
||||
* Keep track of namespaces that are registered by transactions in the pool.
|
||||
* Map name to registering transaction.
|
||||
*/
|
||||
NamespaceTxMap mapNamespaceRegs;
|
||||
|
||||
/** Map pending name updates to transaction IDs. */
|
||||
//NamespaceTxMap mapNamespaceUpdates;
|
||||
|
||||
/**
|
||||
* Keep track of key that are updated by transactions in the pool.
|
||||
* Map key to registering transaction.
|
||||
*/
|
||||
NamespaceTxMap mapNamespaceUpdates;
|
||||
|
||||
/**
|
||||
* Pending/unconfirmed namespaces.
|
||||
* Tuple: txid, namespace, display name
|
||||
@ -159,52 +134,15 @@ public:
|
||||
* Construct with reference to parent mempool.
|
||||
* @param p The parent pool.
|
||||
*/
|
||||
explicit inline CKevaMemPool (CTxMemPool& p)
|
||||
: pool(p), mapNamespaceRegs()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Check whether a particular namespace is being registered by
|
||||
* some transaction in the mempool. Does not lock, this is
|
||||
* done by the parent mempool (which calls through afterwards).
|
||||
* @param name The name to check for.
|
||||
* @return True iff there's a matching namespace registration in the pool.
|
||||
*/
|
||||
inline bool
|
||||
registersNamespace (const valtype& nameSpace) const
|
||||
{
|
||||
return mapNamespaceRegs.count(nameSpace) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a particular namespace has a pending update. Does not lock.
|
||||
* @param name The namespace to check for.
|
||||
* @return True iff there's a matching namespace update in the pool.
|
||||
*/
|
||||
inline bool
|
||||
updatesNamespace(const valtype& nameSpace) const
|
||||
{
|
||||
return mapNamespaceUpdates.count(nameSpace) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return txid of transaction registering or updating a name. The returned
|
||||
* txid is null if no such tx exists.
|
||||
* @param name The name to check for.
|
||||
* @return The txid that registers/updates it. Null if none.
|
||||
*/
|
||||
uint256 getTxForNamespace(const valtype& nameSpace) const;
|
||||
|
||||
uint256 getTxForNamespaceKey(const valtype& nameSpace, const valtype& key) const;
|
||||
explicit inline CKevaMemPool (CTxMemPool& p) : pool(p) {}
|
||||
|
||||
/**
|
||||
* Clear all data.
|
||||
*/
|
||||
inline void
|
||||
clear ()
|
||||
inline void clear ()
|
||||
{
|
||||
mapNamespaceRegs.clear();
|
||||
mapNamespaceUpdates.clear();
|
||||
listUnconfirmedNamespaces.clear();
|
||||
listUnconfirmedKeyValues.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -230,12 +168,6 @@ public:
|
||||
*/
|
||||
void removeConflicts (const CTransaction& tx);
|
||||
|
||||
/**
|
||||
* Perform sanity checks. Throws if it fails.
|
||||
* @param coins The coins view this represents.
|
||||
*/
|
||||
void check (const CCoinsView& coins) const;
|
||||
|
||||
/**
|
||||
* Check if a tx can be added (based on name criteria) without
|
||||
* causing a conflict.
|
||||
|
@ -675,24 +675,6 @@ public:
|
||||
return (mapTx.count(hash) != 0);
|
||||
}
|
||||
|
||||
inline bool registersNamespace(const valtype& nameSpace) const
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
return kevaMemPool.registersNamespace(nameSpace);
|
||||
}
|
||||
|
||||
inline bool updatesNamespace(const valtype& nameSpace) const
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
return kevaMemPool.updatesNamespace(nameSpace);
|
||||
}
|
||||
|
||||
inline uint256 getTxForNamespace(const valtype& name) const
|
||||
{
|
||||
AssertLockHeld(cs);
|
||||
return kevaMemPool.getTxForNamespace(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a tx can be added to it according to name criteria.
|
||||
* (The non-name criteria are checked in main.cpp and not here, we
|
||||
|
@ -244,33 +244,16 @@ UniValue keva_put(const JSONRPCRequest& request)
|
||||
if (value.size () > MAX_VALUE_LENGTH)
|
||||
throw JSONRPCError (RPC_INVALID_PARAMETER, "the value is too long");
|
||||
|
||||
/* Reject updates to a name for which the mempool already has
|
||||
a pending update. This is not a hard rule enforced by network
|
||||
rules, but it is necessary with the current mempool implementation. */
|
||||
{
|
||||
LOCK (mempool.cs);
|
||||
if (mempool.updatesNamespace(nameSpace)) {
|
||||
throw JSONRPCError (RPC_TRANSACTION_ERROR,
|
||||
"there is already a pending update for this name");
|
||||
}
|
||||
}
|
||||
|
||||
CKevaData oldData;
|
||||
{
|
||||
LOCK (cs_main);
|
||||
if (!pcoinsTip->GetNamespace(nameSpace, oldData)) {
|
||||
throw JSONRPCError (RPC_TRANSACTION_ERROR,
|
||||
"this name can not be updated");
|
||||
}
|
||||
}
|
||||
|
||||
const COutPoint outp = oldData.getUpdateOutpoint();
|
||||
const CTxIn txIn(outp);
|
||||
|
||||
/* No more locking required, similarly to name_new. */
|
||||
|
||||
EnsureWalletIsUnlocked(pwallet);
|
||||
|
||||
COutput output;
|
||||
std::string kevaNamespce = namespaceStr;
|
||||
if (!pwallet->FindKevaCoin(output, kevaNamespce)) {
|
||||
throw JSONRPCError (RPC_TRANSACTION_ERROR, "this name can not be updated");
|
||||
}
|
||||
const COutPoint outp(output.tx->GetHash(), output.i);
|
||||
const CTxIn txIn(outp);
|
||||
|
||||
CReserveKey keyName(pwallet);
|
||||
CPubKey pubKeyReserve;
|
||||
const bool ok = keyName.GetReservedKey(pubKeyReserve, true);
|
||||
|
Loading…
Reference in New Issue
Block a user