Browse Source

Cleaned up code - removed dead code from namecoin.

Removed lots of legacy checks from namecoin.
cn
Jianping Wu 6 years ago
parent
commit
11c740f549
  1. 389
      src/keva/main.cpp
  2. 76
      src/keva/main.h
  3. 18
      src/txmempool.h
  4. 29
      src/wallet/rpckeva.cpp

389
src/keva/main.cpp

@ -51,15 +51,11 @@ CKevaMemPool::addUnchecked (const uint256& hash, const CTxMemPoolEntry& entry) @@ -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) @@ -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) @@ -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) @@ -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 @@ -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 @@ -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 @@ -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, @@ -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
that are keva scripts. At most one input and output should be
a keva operation. */
/*
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.
*/
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, @@ -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). */
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));
/*
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",
__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, @@ -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, @@ -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));
}
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"));
return state.Invalid(error("%s: KEVA_PUT namespace mismatch to prev tx found in %s", __func__, txid));
}
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, @@ -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)
{

76
src/keva/main.h

@ -111,31 +111,6 @@ private: @@ -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: @@ -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: @@ -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.

18
src/txmempool.h

@ -675,24 +675,6 @@ public: @@ -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

29
src/wallet/rpckeva.cpp

@ -244,33 +244,16 @@ UniValue keva_put(const JSONRPCRequest& request) @@ -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");
}
}
EnsureWalletIsUnlocked(pwallet);
CKevaData oldData;
{
LOCK (cs_main);
if (!pcoinsTip->GetNamespace(nameSpace, oldData)) {
throw JSONRPCError (RPC_TRANSACTION_ERROR,
"this name can not be updated");
}
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 = oldData.getUpdateOutpoint();
const COutPoint outp(output.tx->GetHash(), output.i);
const CTxIn txIn(outp);
/* No more locking required, similarly to name_new. */
EnsureWalletIsUnlocked(pwallet);
CReserveKey keyName(pwallet);
CPubKey pubKeyReserve;
const bool ok = keyName.GetReservedKey(pubKeyReserve, true);

Loading…
Cancel
Save