mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-02-05 03:34:24 +00:00
WIP: tried to compile keva/main.cpp.
This commit is contained in:
parent
c56fb50b55
commit
d05ab948e2
@ -46,25 +46,25 @@ CKevaTxUndo::apply(CCoinsViewCache& view) const
|
|||||||
/* CKevaMemPool. */
|
/* CKevaMemPool. */
|
||||||
|
|
||||||
uint256
|
uint256
|
||||||
CKevaMemPool::getTxForName(const valtype& name) const
|
CKevaMemPool::getTxForNamespace(const valtype& nameSpace) const
|
||||||
{
|
{
|
||||||
NameTxMap::const_iterator mi;
|
#if 0
|
||||||
|
// JWU TODO: implement this!
|
||||||
|
NamespaceTxMap::const_iterator mi;
|
||||||
|
|
||||||
mi = mapNameRegs.find (name);
|
mi = mapNamespaceRegs.find(nameSpace);
|
||||||
if (mi != mapNameRegs.end ())
|
if (mi != mapNamespaceRegs.end()) {
|
||||||
{
|
assert(mapNamespaceKeyUpdates.count(name) == 0);
|
||||||
assert (mapNameUpdates.count (name) == 0);
|
return mi->second;
|
||||||
return mi->second;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mi = mapNameUpdates.find (name);
|
mi = mapNamespaceKeyUpdates.find(name);
|
||||||
if (mi != mapNameUpdates.end ())
|
if (mi != mapNameUpdates.end ()) {
|
||||||
{
|
assert (mapNameRegs.count (name) == 0);
|
||||||
assert (mapNameRegs.count (name) == 0);
|
return mi->second;
|
||||||
return mi->second;
|
}
|
||||||
}
|
#endif
|
||||||
|
return uint256();
|
||||||
return uint256 ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -72,29 +72,19 @@ CKevaMemPool::addUnchecked (const uint256& hash, const CTxMemPoolEntry& entry)
|
|||||||
{
|
{
|
||||||
AssertLockHeld (pool.cs);
|
AssertLockHeld (pool.cs);
|
||||||
|
|
||||||
if (entry.isNameNew ())
|
if (entry.isNamespaceRegistration()) {
|
||||||
{
|
const valtype& nameSpace = entry.getNamespace();
|
||||||
const valtype& newHash = entry.getNameNewHash ();
|
assert(mapNamespaceRegs.count(nameSpace) == 0);
|
||||||
const NameTxMap::const_iterator mit = mapNameNews.find (newHash);
|
mapNamespaceRegs.insert(std::make_pair (nameSpace, hash));
|
||||||
if (mit != mapNameNews.end ())
|
}
|
||||||
assert (mit->second == hash);
|
|
||||||
else
|
|
||||||
mapNameNews.insert (std::make_pair (newHash, hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.isNameRegistration ())
|
if (entry.isNamespaceKeyUpdate ()) {
|
||||||
{
|
const valtype& nameSpace = entry.getNamespace();
|
||||||
const valtype& name = entry.getName ();
|
const valtype& key = entry.getKey();
|
||||||
assert (mapNameRegs.count (name) == 0);
|
NamespaceKeyTuple tuple(nameSpace, key);
|
||||||
mapNameRegs.insert (std::make_pair (name, hash));
|
assert(mapNamespaceKeyUpdates.count(tuple) == 0);
|
||||||
}
|
mapNamespaceKeyUpdates.insert (std::make_pair (name, hash));
|
||||||
|
}
|
||||||
if (entry.isNameUpdate ())
|
|
||||||
{
|
|
||||||
const valtype& name = entry.getName ();
|
|
||||||
assert (mapNameUpdates.count (name) == 0);
|
|
||||||
mapNameUpdates.insert (std::make_pair (name, hash));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -102,18 +92,18 @@ CKevaMemPool::remove (const CTxMemPoolEntry& entry)
|
|||||||
{
|
{
|
||||||
AssertLockHeld (pool.cs);
|
AssertLockHeld (pool.cs);
|
||||||
|
|
||||||
if (entry.isNameRegistration ())
|
if (entry.isNamespaceRegistration ()) {
|
||||||
{
|
const NamespaceTxMap::iterator mit = mapNamespaceRegs.find (entry.getNamespace());
|
||||||
const NameTxMap::iterator mit = mapNameRegs.find (entry.getName ());
|
assert (mit != mapNamespaceRegs.end());
|
||||||
assert (mit != mapNameRegs.end ());
|
mapNamespaceRegs.erase (mit);
|
||||||
mapNameRegs.erase (mit);
|
}
|
||||||
}
|
|
||||||
if (entry.isNameUpdate ())
|
if (entry.isNamespaceKeyUpdate ()) {
|
||||||
{
|
NamespaceKeyTuple tuple(entry.getNamespace(), entry.getKey());
|
||||||
const NameTxMap::iterator mit = mapNameUpdates.find (entry.getName ());
|
const NamespaceKeyTxMap::iterator mit = mapNamespaceKeyUpdates.find(tuple);
|
||||||
assert (mit != mapNameUpdates.end ());
|
assert (mit != mapNamespaceKeyUpdates.end());
|
||||||
mapNameUpdates.erase (mit);
|
mapNamespaceKeyUpdates.erase (mit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -121,29 +111,27 @@ CKevaMemPool::removeConflicts (const CTransaction& tx)
|
|||||||
{
|
{
|
||||||
AssertLockHeld (pool.cs);
|
AssertLockHeld (pool.cs);
|
||||||
|
|
||||||
if (!tx.IsNamecoin ())
|
if (!tx.IsKevacoin ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const auto& txout : tx.vout)
|
for (const auto& txout : tx.vout)
|
||||||
{
|
{
|
||||||
const CNameScript nameOp(txout.scriptPubKey);
|
const CKevaScript nameOp(txout.scriptPubKey);
|
||||||
if (nameOp.isNameOp () && nameOp.getNameOp () == OP_NAME_FIRSTUPDATE)
|
if (nameOp.isKevaOp () && nameOp.getKevaOp () == OP_KEVA_PUT) {
|
||||||
{
|
const valtype& nameSpace = nameOp.getOpNamespace();
|
||||||
const valtype& name = nameOp.getOpName ();
|
const NamespaceTxMap::const_iterator mit = mapNamespaceRegs.find(nameSpace);
|
||||||
const NameTxMap::const_iterator mit = mapNameRegs.find (name);
|
if (mit != mapNamespaceRegs.end ()) {
|
||||||
if (mit != mapNameRegs.end ())
|
const CTxMemPool::txiter mit2 = pool.mapTx.find (mit->second);
|
||||||
{
|
assert (mit2 != pool.mapTx.end ());
|
||||||
const CTxMemPool::txiter mit2 = pool.mapTx.find (mit->second);
|
pool.removeRecursive (mit2->GetTx (),
|
||||||
assert (mit2 != pool.mapTx.end ());
|
MemPoolRemovalReason::KEVA_CONFLICT);
|
||||||
pool.removeRecursive (mit2->GetTx (),
|
|
||||||
MemPoolRemovalReason::NAME_CONFLICT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CKevaMemPool::check (const CCoinsView& coins) const
|
CKevaMemPool::check(const CCoinsView& coins) const
|
||||||
{
|
{
|
||||||
AssertLockHeld (pool.cs);
|
AssertLockHeld (pool.cs);
|
||||||
|
|
||||||
@ -156,56 +144,44 @@ CKevaMemPool::check (const CCoinsView& coins) const
|
|||||||
|
|
||||||
std::set<valtype> nameRegs;
|
std::set<valtype> nameRegs;
|
||||||
std::set<valtype> nameUpdates;
|
std::set<valtype> nameUpdates;
|
||||||
for (const auto& entry : pool.mapTx)
|
for (const auto& entry : pool.mapTx) {
|
||||||
{
|
const uint256 txHash = entry.GetTx ().GetHash ();
|
||||||
const uint256 txHash = entry.GetTx ().GetHash ();
|
if (entry.isNamespaceRegistration()) {
|
||||||
if (entry.isNameNew ())
|
const valtype& nameSpace = entry.getNamespace();
|
||||||
{
|
|
||||||
const valtype& newHash = entry.getNameNewHash ();
|
|
||||||
const NameTxMap::const_iterator mit = mapNameNews.find (newHash);
|
|
||||||
|
|
||||||
assert (mit != mapNameNews.end ());
|
const NamespaceTxMap::const_iterator mit = mapNamespaceRegs.find(nameSpace);
|
||||||
assert (mit->second == txHash);
|
assert (mit != mapNamespaceRegs.end());
|
||||||
}
|
assert (mit->second == txHash);
|
||||||
|
|
||||||
if (entry.isNameRegistration ())
|
assert (nameRegs.count(nameSpace) == 0);
|
||||||
{
|
nameRegs.insert(nameSpace);
|
||||||
const valtype& name = entry.getName ();
|
|
||||||
|
|
||||||
const NameTxMap::const_iterator mit = mapNameRegs.find (name);
|
/* The old name should be expired already. Note that we use
|
||||||
assert (mit != mapNameRegs.end ());
|
nHeight+1 for the check, because that's the height at which
|
||||||
assert (mit->second == txHash);
|
the mempool tx will actually be mined. */
|
||||||
|
CKevaData data;
|
||||||
assert (nameRegs.count (name) == 0);
|
if (coins.GetName(name, data))
|
||||||
nameRegs.insert (name);
|
assert (data.isExpired (nHeight + 1));
|
||||||
|
|
||||||
/* 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. */
|
|
||||||
CNameData data;
|
|
||||||
if (coins.GetName (name, data))
|
|
||||||
assert (data.isExpired (nHeight + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry.isNameUpdate ())
|
|
||||||
{
|
|
||||||
const valtype& name = entry.getName ();
|
|
||||||
|
|
||||||
const NameTxMap::const_iterator mit = mapNameUpdates.find (name);
|
|
||||||
assert (mit != mapNameUpdates.end ());
|
|
||||||
assert (mit->second == txHash);
|
|
||||||
|
|
||||||
assert (nameUpdates.count (name) == 0);
|
|
||||||
nameUpdates.insert (name);
|
|
||||||
|
|
||||||
/* As above, use nHeight+1 for the expiration check. */
|
|
||||||
CNameData data;
|
|
||||||
if (!coins.GetName (name, data))
|
|
||||||
assert (false);
|
|
||||||
assert (!data.isExpired (nHeight + 1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (entry.isNamespaceKeyUpdate()) {
|
||||||
|
const valtype& name = entry.getName ();
|
||||||
|
|
||||||
|
const NameTxMap::const_iterator mit = mapNameUpdates.find (name);
|
||||||
|
assert (mit != mapNameUpdates.end ());
|
||||||
|
assert (mit->second == txHash);
|
||||||
|
|
||||||
|
assert (nameUpdates.count (name) == 0);
|
||||||
|
nameUpdates.insert(name);
|
||||||
|
|
||||||
|
/* As above, use nHeight+1 for the expiration check. */
|
||||||
|
CKevaData data;
|
||||||
|
if (!coins.GetName(name, data))
|
||||||
|
assert (false);
|
||||||
|
assert (!data.isExpired (nHeight + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert (nameRegs.size () == mapNameRegs.size ());
|
assert (nameRegs.size () == mapNameRegs.size ());
|
||||||
assert (nameUpdates.size () == mapNameUpdates.size ());
|
assert (nameUpdates.size () == mapNameUpdates.size ());
|
||||||
|
|
||||||
@ -223,7 +199,7 @@ CKevaMemPool::checkTx (const CTransaction& tx) const
|
|||||||
{
|
{
|
||||||
AssertLockHeld (pool.cs);
|
AssertLockHeld (pool.cs);
|
||||||
|
|
||||||
if (!tx.IsNamecoin ())
|
if (!tx.IsKevacoin ())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* In principle, multiple name_updates could be performed within the
|
/* In principle, multiple name_updates could be performed within the
|
||||||
@ -231,44 +207,35 @@ CKevaMemPool::checkTx (const CTransaction& tx) const
|
|||||||
since the current mempool implementation does not like it. (We keep
|
since the current mempool implementation does not like it. (We keep
|
||||||
track of only a single update tx for each name.) */
|
track of only a single update tx for each name.) */
|
||||||
|
|
||||||
for (const auto& txout : tx.vout)
|
for (const auto& txout : tx.vout) {
|
||||||
{
|
const CKevaScript nameOp(txout.scriptPubKey);
|
||||||
const CNameScript nameOp(txout.scriptPubKey);
|
if (!nameOp.isKevaOp ())
|
||||||
if (!nameOp.isNameOp ())
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (nameOp.getNameOp ())
|
switch (nameOp.getKevaOp ()) {
|
||||||
{
|
case OP_KEVA_NAMESPACE:
|
||||||
case OP_NAME_NEW:
|
{
|
||||||
{
|
const valtype& nameSpace = nameOp.getOpNamespace();
|
||||||
const valtype& newHash = nameOp.getOpHash ();
|
std::map<valtype, uint256>::const_iterator mi;
|
||||||
std::map<valtype, uint256>::const_iterator mi;
|
mi = mapNamespaceRegs.find(nameSpace);
|
||||||
mi = mapNameNews.find (newHash);
|
if (mi != mapNamespaceRegs.end ())
|
||||||
if (mi != mapNameNews.end () && mi->second != tx.GetHash ())
|
return false;
|
||||||
return false;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case OP_NAME_FIRSTUPDATE:
|
case OP_KEVA_PUT:
|
||||||
{
|
{
|
||||||
const valtype& name = nameOp.getOpName ();
|
const valtype& nameSpace = nameOp.getOpNamespace();
|
||||||
if (registersName (name))
|
const valtype& key = nameOp.getOpKey();
|
||||||
return false;
|
if (updatesKey(nameSpace, key))
|
||||||
break;
|
return false;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case OP_NAME_UPDATE:
|
default:
|
||||||
{
|
assert (false);
|
||||||
const valtype& name = nameOp.getOpName ();
|
|
||||||
if (updatesName (name))
|
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
assert (false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -284,7 +251,7 @@ ConflictTrackerNotifyEntryRemoved (CNameConflictTracker* tracker,
|
|||||||
CTransactionRef txRemoved,
|
CTransactionRef txRemoved,
|
||||||
MemPoolRemovalReason reason)
|
MemPoolRemovalReason reason)
|
||||||
{
|
{
|
||||||
if (reason == MemPoolRemovalReason::NAME_CONFLICT)
|
if (reason == MemPoolRemovalReason::KEVA_CONFLICT)
|
||||||
tracker->AddConflictedEntry (txRemoved);
|
tracker->AddConflictedEntry (txRemoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,17 +287,19 @@ CheckNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
const char* txid = strTxid.c_str ();
|
const char* txid = strTxid.c_str ();
|
||||||
const bool fMempool = (flags & SCRIPT_VERIFY_NAMES_MEMPOOL);
|
const bool fMempool = (flags & SCRIPT_VERIFY_NAMES_MEMPOOL);
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Ignore historic bugs. */
|
/* Ignore historic bugs. */
|
||||||
CChainParams::BugType type;
|
CChainParams::BugType type;
|
||||||
if (Params ().IsHistoricBug (tx.GetHash (), nHeight, type))
|
if (Params ().IsHistoricBug (tx.GetHash (), nHeight, type))
|
||||||
return true;
|
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 name scripts. At most one input and output should be
|
that are name scripts. At most one input and output should be
|
||||||
a name operation. */
|
a name operation. */
|
||||||
|
|
||||||
int nameIn = -1;
|
int nameIn = -1;
|
||||||
CNameScript nameOpIn;
|
CKevaScript nameOpIn;
|
||||||
Coin coinIn;
|
Coin coinIn;
|
||||||
for (unsigned i = 0; i < tx.vin.size (); ++i)
|
for (unsigned i = 0; i < tx.vin.size (); ++i)
|
||||||
{
|
{
|
||||||
@ -339,51 +308,47 @@ CheckNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
if (!view.GetCoin (prevout, coin))
|
if (!view.GetCoin (prevout, coin))
|
||||||
return error ("%s: failed to fetch input coin for %s", __func__, txid);
|
return error ("%s: failed to fetch input coin for %s", __func__, txid);
|
||||||
|
|
||||||
const CNameScript op(coin.out.scriptPubKey);
|
const CKevaScript op(coin.out.scriptPubKey);
|
||||||
if (op.isNameOp ())
|
if (op.isKevaOp()) {
|
||||||
{
|
if (nameIn != -1)
|
||||||
if (nameIn != -1)
|
return state.Invalid (error ("%s: multiple name inputs into"
|
||||||
return state.Invalid (error ("%s: multiple name inputs into"
|
" transaction %s", __func__, txid));
|
||||||
" transaction %s", __func__, txid));
|
nameIn = i;
|
||||||
nameIn = i;
|
nameOpIn = op;
|
||||||
nameOpIn = op;
|
coinIn = coin;
|
||||||
coinIn = coin;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nameOut = -1;
|
int nameOut = -1;
|
||||||
CNameScript nameOpOut;
|
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);
|
||||||
const CNameScript op(tx.vout[i].scriptPubKey);
|
if (op.isKevaOp()) {
|
||||||
if (op.isNameOp ())
|
if (nameOut != -1)
|
||||||
{
|
return state.Invalid (error ("%s: multiple name outputs from"
|
||||||
if (nameOut != -1)
|
" transaction %s", __func__, txid));
|
||||||
return state.Invalid (error ("%s: multiple name outputs from"
|
nameOut = i;
|
||||||
" transaction %s", __func__, txid));
|
nameOpOut = op;
|
||||||
nameOut = i;
|
|
||||||
nameOpOut = op;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check that no name inputs/outputs are present for a non-Namecoin tx.
|
/* 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
|
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). */
|
should be at least an output (for NAME_NEW, no inputs are expected). */
|
||||||
|
|
||||||
if (!tx.IsNamecoin ())
|
if (!tx.IsKevacoin ()) {
|
||||||
{
|
if (nameIn != -1)
|
||||||
if (nameIn != -1)
|
return state.Invalid (error ("%s: non-Namecoin tx %s has name inputs",
|
||||||
return state.Invalid (error ("%s: non-Namecoin tx %s has name inputs",
|
__func__, txid));
|
||||||
__func__, txid));
|
if (nameOut != -1)
|
||||||
if (nameOut != -1)
|
return state.Invalid (error ("%s: non-Namecoin tx %s at height %u"
|
||||||
return state.Invalid (error ("%s: non-Namecoin tx %s at height %u"
|
" has name outputs",
|
||||||
" has name outputs",
|
__func__, txid, nHeight));
|
||||||
__func__, txid, nHeight));
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert (tx.IsNamecoin ());
|
assert(tx.IsKevacoin ());
|
||||||
if (nameOut == -1)
|
if (nameOut == -1)
|
||||||
return state.Invalid (error ("%s: Namecoin tx %s has no name outputs",
|
return state.Invalid (error ("%s: Namecoin tx %s has no name outputs",
|
||||||
__func__, txid));
|
__func__, txid));
|
||||||
@ -393,6 +358,7 @@ CheckNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
if (tx.vout[nameOut].nValue < params.rules->MinNameCoinAmount(nHeight))
|
if (tx.vout[nameOut].nValue < params.rules->MinNameCoinAmount(nHeight))
|
||||||
return state.Invalid (error ("%s: greedy name", __func__));
|
return state.Invalid (error ("%s: greedy name", __func__));
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Handle NAME_NEW now, since this is easy and different from the other
|
/* Handle NAME_NEW now, since this is easy and different from the other
|
||||||
operations. */
|
operations. */
|
||||||
|
|
||||||
@ -411,54 +377,65 @@ CheckNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
|
|
||||||
/* Now that we have ruled out NAME_NEW, check that we have a previous
|
/* Now that we have ruled out NAME_NEW, check that we have a previous
|
||||||
name input that is being updated. */
|
name input that is being updated. */
|
||||||
|
#endif
|
||||||
|
|
||||||
assert (nameOpOut.isAnyUpdate ());
|
assert (nameOpOut.isAnyUpdate());
|
||||||
if (nameIn == -1)
|
if (nameIn == -1) {
|
||||||
return state.Invalid (error ("CheckNameTransaction: update without"
|
return state.Invalid(error("CheckNameTransaction: update without"
|
||||||
" previous name input"));
|
" previous name input"));
|
||||||
const valtype& name = nameOpOut.getOpName ();
|
}
|
||||||
|
|
||||||
if (name.size () > MAX_NAME_LENGTH)
|
const valtype& key = nameOpOut.getOpKey();
|
||||||
return state.Invalid (error ("CheckNameTransaction: name too long"));
|
if (key.size() > MAX_KEY_LENGTH) {
|
||||||
if (nameOpOut.getOpValue ().size () > MAX_VALUE_LENGTH)
|
return state.Invalid (error ("CheckNameTransaction: key too long"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nameOpOut.getOpValue().size () > MAX_VALUE_LENGTH) {
|
||||||
return state.Invalid (error ("CheckNameTransaction: value too long"));
|
return state.Invalid (error ("CheckNameTransaction: value too long"));
|
||||||
|
}
|
||||||
|
|
||||||
/* Process NAME_UPDATE next. */
|
/* Process KEVA_PUT next. */
|
||||||
|
const valtype& nameSpace = nameOpOut.getOpNamespace();
|
||||||
|
if (nameOpOut.getKevaOp() == OP_KEVA_PUT) {
|
||||||
|
if (!nameOpIn.isAnyUpdate ()) {
|
||||||
|
return state.Invalid(error("CheckNameTransaction: KEVA_PUT with"
|
||||||
|
" prev input that is no update"));
|
||||||
|
}
|
||||||
|
|
||||||
if (nameOpOut.getNameOp () == OP_NAME_UPDATE)
|
if (nameSpace != nameOpIn.getOpNamespace()) {
|
||||||
{
|
return state.Invalid (error ("%s: KEVA_PUT namespace mismatch to prev tx"
|
||||||
if (!nameOpIn.isAnyUpdate ())
|
" found in %s", __func__, txid));
|
||||||
return state.Invalid (error ("CheckNameTransaction: NAME_UPDATE with"
|
}
|
||||||
" prev input that is no update"));
|
|
||||||
|
|
||||||
if (name != nameOpIn.getOpName ())
|
/* This is actually redundant, since expired names are removed
|
||||||
return state.Invalid (error ("%s: NAME_UPDATE name mismatch to prev tx"
|
from the UTXO set and thus not available to be spent anyway.
|
||||||
" found in %s", __func__, txid));
|
But it does not hurt to enforce this here, too. It is also
|
||||||
|
exercised by the unit tests. */
|
||||||
/* This is actually redundant, since expired names are removed
|
CKevaData oldName;
|
||||||
from the UTXO set and thus not available to be spent anyway.
|
const valtype& namespaceIn = nameOpIn.getOpNamespace();
|
||||||
But it does not hurt to enforce this here, too. It is also
|
const valtype& keyIn = nameOpIn.getOpKey();
|
||||||
exercised by the unit tests. */
|
if (!view.GetName(namespaceIn, keyIn, oldName)) {
|
||||||
CNameData oldName;
|
return state.Invalid (error ("%s: KEVA_PUT name does not exist",
|
||||||
if (!view.GetName (name, oldName))
|
__func__));
|
||||||
return state.Invalid (error ("%s: NAME_UPDATE 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 ());
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
if (oldName.isExpired (nHeight))
|
||||||
|
return state.Invalid (error ("%s: trying to update expired name",
|
||||||
|
__func__));
|
||||||
|
#endif
|
||||||
|
/* 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());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Finally, NAME_FIRSTUPDATE. */
|
/* Finally, NAME_FIRSTUPDATE. */
|
||||||
|
|
||||||
assert (nameOpOut.getNameOp () == OP_NAME_FIRSTUPDATE);
|
assert(nameOpOut.getNameOp () == OP_NAME_FIRSTUPDATE);
|
||||||
if (nameOpIn.getNameOp () != OP_NAME_NEW)
|
if (nameOpIn.getNameOp () != OP_NAME_NEW)
|
||||||
return state.Invalid (error ("CheckNameTransaction: NAME_FIRSTUPDATE"
|
return state.Invalid (error ("CheckNameTransaction: NAME_FIRSTUPDATE"
|
||||||
" with non-NAME_NEW prev tx"));
|
" with non-NAME_NEW prev tx"));
|
||||||
@ -495,7 +472,7 @@ CheckNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
/* We don't have to specifically check that miners don't create blocks with
|
/* We don't have to specifically check that miners don't create blocks with
|
||||||
conflicting NAME_FIRSTUPDATE's, since the mining's CCoinsViewCache
|
conflicting NAME_FIRSTUPDATE's, since the mining's CCoinsViewCache
|
||||||
takes care of this with the check above already. */
|
takes care of this with the check above already. */
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,6 +530,7 @@ ApplyNameTransaction (const CTransaction& tx, unsigned nHeight,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
bool
|
bool
|
||||||
ExpireNames (unsigned nHeight, CCoinsViewCache& view, CBlockUndo& undo,
|
ExpireNames (unsigned nHeight, CCoinsViewCache& view, CBlockUndo& undo,
|
||||||
std::set<valtype>& names)
|
std::set<valtype>& names)
|
||||||
@ -672,6 +650,7 @@ UnexpireNames (unsigned nHeight, CBlockUndo& undo, CCoinsViewCache& view,
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
CheckNameDB (bool disconnect)
|
CheckNameDB (bool disconnect)
|
||||||
|
@ -126,13 +126,13 @@ private:
|
|||||||
NamespaceTxMap mapNamespaceRegs;
|
NamespaceTxMap mapNamespaceRegs;
|
||||||
|
|
||||||
/** Map pending name updates to transaction IDs. */
|
/** Map pending name updates to transaction IDs. */
|
||||||
NamespaceTxMap mapNamespaceUpdates;
|
//NamespaceTxMap mapNamespaceUpdates;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep track of key that are registered by transactions in the pool.
|
* Keep track of key that are updated by transactions in the pool.
|
||||||
* Map key to registering transaction.
|
* Map key to registering transaction.
|
||||||
*/
|
*/
|
||||||
NamespaceKeyTxMap mapNamespaceKeyRegs;
|
NamespaceKeyTxMap mapNamespaceKeyUpdates;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -163,10 +163,10 @@ public:
|
|||||||
* @return True iff there's a matching name update in the pool.
|
* @return True iff there's a matching name update in the pool.
|
||||||
*/
|
*/
|
||||||
inline bool
|
inline bool
|
||||||
updatesName (const valtype& name) const
|
updatesKey (const valtype& nameSpace, const valtype& key) const
|
||||||
{
|
{
|
||||||
//return mapNameUpdates.count (name) > 0;
|
NamespaceKeyTuple tuple(nameSpace, key);
|
||||||
return true;
|
return mapNamespaceKeyUpdates.count(tuple) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -175,7 +175,9 @@ public:
|
|||||||
* @param name The name to check for.
|
* @param name The name to check for.
|
||||||
* @return The txid that registers/updates it. Null if none.
|
* @return The txid that registers/updates it. Null if none.
|
||||||
*/
|
*/
|
||||||
uint256 getTxForName (const valtype& name) const;
|
uint256 getTxForNamespace(const valtype& nameSpace) const;
|
||||||
|
|
||||||
|
uint256 getTxForNamespaceKey(const valtype& nameSpace, const valtype& key) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all data.
|
* Clear all data.
|
||||||
@ -183,11 +185,8 @@ public:
|
|||||||
inline void
|
inline void
|
||||||
clear ()
|
clear ()
|
||||||
{
|
{
|
||||||
/*
|
mapNamespaceRegs.clear();
|
||||||
mapNameRegs.clear ();
|
mapNamespaceKeyUpdates.clear();
|
||||||
mapNameUpdates.clear ();
|
|
||||||
mapNameNews.clear ();
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,6 +88,9 @@ private:
|
|||||||
CAmount nModFeesWithAncestors;
|
CAmount nModFeesWithAncestors;
|
||||||
int64_t nSigOpCostWithAncestors;
|
int64_t nSigOpCostWithAncestors;
|
||||||
|
|
||||||
|
/* Cache keva operation (if any) performed by this tx. */
|
||||||
|
CKevaScript kevaOp;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
|
CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
|
||||||
int64_t _nTime, unsigned int _entryHeight,
|
int64_t _nTime, unsigned int _entryHeight,
|
||||||
@ -127,6 +130,26 @@ public:
|
|||||||
CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
|
CAmount GetModFeesWithAncestors() const { return nModFeesWithAncestors; }
|
||||||
int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; }
|
int64_t GetSigOpCostWithAncestors() const { return nSigOpCostWithAncestors; }
|
||||||
|
|
||||||
|
inline bool isNamespaceRegistration() const
|
||||||
|
{
|
||||||
|
return kevaOp.isKevaOp() && kevaOp.getKevaOp() == OP_KEVA_NAMESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isNamespaceKeyUpdate() const
|
||||||
|
{
|
||||||
|
return kevaOp.isKevaOp() && kevaOp.getKevaOp() == OP_KEVA_PUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const valtype& getNamespace() const
|
||||||
|
{
|
||||||
|
return kevaOp.getOpNamespace();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const valtype& getKey() const
|
||||||
|
{
|
||||||
|
return kevaOp.getOpKey();
|
||||||
|
}
|
||||||
|
|
||||||
mutable size_t vTxHashesIdx; //!< Index in mempool's vTxHashes
|
mutable size_t vTxHashesIdx; //!< Index in mempool's vTxHashes
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -345,7 +368,8 @@ enum class MemPoolRemovalReason {
|
|||||||
REORG, //! Removed for reorganization
|
REORG, //! Removed for reorganization
|
||||||
BLOCK, //! Removed for block
|
BLOCK, //! Removed for block
|
||||||
CONFLICT, //! Removed for conflict with in-block transaction
|
CONFLICT, //! Removed for conflict with in-block transaction
|
||||||
REPLACED //! Removed for replacement
|
REPLACED, //! Removed for replacement,
|
||||||
|
KEVA_CONFLICT
|
||||||
};
|
};
|
||||||
|
|
||||||
class SaltedTxidHasher
|
class SaltedTxidHasher
|
||||||
|
Loading…
x
Reference in New Issue
Block a user