Browse Source

1. Fixed pending information containing other people's information.

2. Fixed keva undo.
cn
Jianping Wu 5 years ago
parent
commit
37dfb034a6
  1. 3
      src/keva/common.cpp
  2. 30
      src/keva/main.cpp
  3. 13
      src/keva/main.h
  4. 1
      src/txmempool.cpp
  5. 6
      src/txmempool.h
  6. 1
      src/undo.h
  7. 3
      src/wallet/rpckeva.cpp
  8. 14
      src/wallet/wallet.cpp
  9. 89
      test/functional/feature_keva.py

3
src/keva/common.cpp

@ -226,8 +226,9 @@ CKevaCache::remove(const valtype& nameSpace, const valtype& key) @@ -226,8 +226,9 @@ CKevaCache::remove(const valtype& nameSpace, const valtype& key)
{
auto name = std::make_tuple(nameSpace, key);
const EntryMap::iterator ei = entries.find(name);
if (ei != entries.end())
if (ei != entries.end()) {
entries.erase(ei);
}
deleted.insert(name);
}

30
src/keva/main.cpp

@ -36,33 +36,35 @@ CKevaTxUndo::fromOldState(const valtype& nameSpace, const valtype& key, const CC @@ -36,33 +36,35 @@ CKevaTxUndo::fromOldState(const valtype& nameSpace, const valtype& key, const CC
void
CKevaTxUndo::apply(CCoinsViewCache& view) const
{
if (isNew)
if (isNew) {
view.DeleteName(nameSpace, key);
else
}
else {
view.SetName(nameSpace, key, oldData, true);
}
}
/* ************************************************************************** */
/* CKevaMemPool. */
void
CKevaMemPool::addUnchecked (const uint256& hash, const CTxMemPoolEntry& entry)
CKevaMemPool::addUnchecked(const uint256& hash, const CKevaScript& kevaOp)
{
AssertLockHeld (pool.cs);
if (entry.isNamespaceRegistration()) {
const valtype& nameSpace = entry.getNamespace();
listUnconfirmedNamespaces.push_back(std::make_tuple(hash, nameSpace, entry.getDisplayName()));
if (kevaOp.isNamespaceRegistration()) {
const valtype& nameSpace = kevaOp.getOpNamespace();
listUnconfirmedNamespaces.push_back(std::make_tuple(hash, nameSpace, kevaOp.getOpNamespaceDisplayName()));
}
if (entry.isKeyUpdate()) {
const valtype& nameSpace = entry.getNamespace();
listUnconfirmedKeyValues.push_back(std::make_tuple(hash, nameSpace, entry.getKey(), entry.getValue()));
if (kevaOp.getKevaOp() == OP_KEVA_PUT) {
const valtype& nameSpace = kevaOp.getOpNamespace();
listUnconfirmedKeyValues.push_back(std::make_tuple(hash, nameSpace, kevaOp.getOpKey(), kevaOp.getOpValue()));
}
if (entry.isKeyDelete()) {
const valtype& nameSpace = entry.getNamespace();
if (kevaOp.getKevaOp() == OP_KEVA_DELETE) {
const valtype& nameSpace = kevaOp.getOpNamespace();
const valtype& empty = ValtypeFromString("");
listUnconfirmedKeyValues.push_back(std::make_tuple(hash, nameSpace, entry.getKey(), empty));
listUnconfirmedKeyValues.push_back(std::make_tuple(hash, nameSpace, kevaOp.getOpKey(), empty));
}
}
@ -375,8 +377,8 @@ void ApplyKevaTransaction(const CTransaction& tx, unsigned nHeight, @@ -375,8 +377,8 @@ void ApplyKevaTransaction(const CTransaction& tx, unsigned nHeight,
} else if (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 ());
LogPrint (BCLog::KEVA, "Updating key at height %d: %s %s\n",
nHeight, ValtypeToString(nameSpace).c_str(), ValtypeToString(key).c_str());
CKevaTxUndo opUndo;
opUndo.fromOldState(nameSpace, key, view);

13
src/keva/main.h

@ -147,18 +147,17 @@ public: @@ -147,18 +147,17 @@ public:
}
/**
* Add an entry without checking it. It should have been checked
* already. If this conflicts with the mempool, it may throw.
* Added unconfirmed keva values.
* @param hash The tx hash.
* @param entry The new mempool entry.
* @param entry The new keva entry.
*/
void addUnchecked (const uint256& hash, const CTxMemPoolEntry& entry);
void addUnchecked(const uint256& hash, const CKevaScript& kevaOp);
/**
* Remove the given mempool entry. It is assumed that it is present.
* @param entry The entry to remove.
*/
void remove (const CTxMemPoolEntry& entry);
void remove(const CTxMemPoolEntry& entry);
/**
* Remove conflicts for the given tx, based on name operations. I. e.,
@ -167,7 +166,7 @@ public: @@ -167,7 +166,7 @@ public:
* @param tx The transaction for which we look for conflicts.
* @param removed Put removed tx here.
*/
void removeConflicts (const CTransaction& tx);
void removeConflicts(const CTransaction& tx);
/**
* Check if a tx can be added (based on name criteria) without
@ -175,7 +174,7 @@ public: @@ -175,7 +174,7 @@ public:
* @param tx The transaction to check.
* @return True if it doesn't conflict.
*/
bool checkTx (const CTransaction& tx) const;
bool checkTx(const CTransaction& tx) const;
/** Keva get unconfirmed namespaces. */
void getUnconfirmedNamespaceList(std::vector<std::tuple<valtype, valtype, uint256>>& nameSpaces) const;

1
src/txmempool.cpp

@ -423,7 +423,6 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry, @@ -423,7 +423,6 @@ bool CTxMemPool::addUnchecked(const uint256& hash, const CTxMemPoolEntry &entry,
nTransactionsUpdated++;
totalTxSize += entry.GetTxSize();
if (minerPolicyEstimator) {minerPolicyEstimator->processTransaction(entry, validFeeEstimate);}
kevaMemPool.addUnchecked (hash, entry);
vTxHashes.emplace_back(tx.GetWitnessHash(), newit);
newit->vTxHashesIdx = vTxHashes.size() - 1;

6
src/txmempool.h

@ -693,6 +693,12 @@ public: @@ -693,6 +693,12 @@ public:
return kevaMemPool.checkTx(tx);
}
inline void addKevaUnchecked(const uint256& hash, const CKevaScript& kevaOp)
{
AssertLockHeld(cs);
kevaMemPool.addUnchecked(hash, kevaOp);
}
/** Keva get unconfirmed key values. */
bool getUnconfirmedKeyValue(const valtype& nameSpace, const valtype& key, valtype& value) const;

1
src/undo.h

@ -110,6 +110,7 @@ public: @@ -110,6 +110,7 @@ public:
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(vtxundo);
READWRITE(vkevaundo);
}
};

3
src/wallet/rpckeva.cpp

@ -184,7 +184,8 @@ UniValue keva_list_namespaces(const JSONRPCRequest& request) @@ -184,7 +184,8 @@ UniValue keva_list_namespaces(const JSONRPCRequest& request)
UniValue res(UniValue::VARR);
for (const auto& item : mapObjects) {
UniValue obj(UniValue::VOBJ);
obj.pushKV(item.first, item.second);
obj.pushKV("namespaceId", item.first);
obj.pushKV("displayName", item.second);
res.push_back(obj);
}

14
src/wallet/wallet.cpp

@ -3176,6 +3176,20 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon @@ -3176,6 +3176,20 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
return false;
}
} else {
CKevaScript kevaOp;
auto _tx = wtx.tx;
if (_tx->IsKevacoin()) {
for (const auto& txOut : _tx->vout) {
const CKevaScript curKevaOp(txOut.scriptPubKey);
if (!curKevaOp.isKevaOp()) {
continue;
}
assert(!kevaOp.isKevaOp());
kevaOp = curKevaOp;
}
assert(kevaOp.isKevaOp());
mempool.addKevaUnchecked(wtx.GetHash(), kevaOp);
}
wtx.RelayWalletTransaction(connman);
}
}

89
test/functional/feature_keva.py

@ -16,15 +16,91 @@ import re @@ -16,15 +16,91 @@ import re
class KevaTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 3
self.num_nodes = 2
def setup_network(self):
super().setup_network()
connect_nodes(self.nodes[0], 2)
connect_nodes_bi(self.nodes, 0, 1)
self.sync_all()
def run_unconfirmed_namespaces(self):
self.sync_all()
response = self.nodes[1].keva_namespace('second_namespace')
namespaceId = response['namespaceId']
response = self.nodes[1].keva_list_namespaces()
# Node 0's unconfirmed namespace should not be here
assert(len(response) == 1)
# Node 0's unconfirmed operations should not be here
self.nodes[1].keva_put(namespaceId, 'second_key', 'second_value')
response = self.nodes[1].keva_pending()
# Pending namespace and put operation.
assert(len(response) == 2)
self.sync_all()
def run_test_disconnect_block(self, namespaceId):
key = 'This is the test key'
value = 'This is the test value'
self.nodes[0].keva_put(namespaceId, key, value)
self.nodes[0].generate(1)
response = self.nodes[0].keva_get(namespaceId, key)
assert(response['value'] == value)
# Disconnect the block
self.sync_all()
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
self.nodes[1].invalidateblock(self.nodes[1].getbestblockhash())
self.sync_all()
response = self.nodes[0].keva_get(namespaceId, key)
assert(response['value'] == '')
self.log.info("Test undeleting after disconnecting blocks")
keyToDelete = 'This is the test key to delete'
valueToDelete = 'This is the test value of the key'
self.nodes[0].keva_put(namespaceId, keyToDelete, valueToDelete)
self.nodes[0].generate(1)
response = self.nodes[0].keva_get(namespaceId, keyToDelete)
assert(response['value'] == valueToDelete)
# Now delete the key
self.nodes[0].keva_delete(namespaceId, keyToDelete)
self.nodes[0].generate(1)
response = self.nodes[0].keva_get(namespaceId, keyToDelete)
assert(response['value'] == '')
# Disconnect the block
self.sync_all()
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
self.nodes[1].invalidateblock(self.nodes[1].getbestblockhash())
self.sync_all()
response = self.nodes[0].keva_get(namespaceId, keyToDelete)
# The value should be undeleted.
assert(response['value'] == valueToDelete)
self.log.info("Test namespace after disconnecting blocks")
displayName = 'A new namspace'
response = self.nodes[0].keva_namespace(displayName)
newNamespaceId = response['namespaceId']
self.nodes[0].generate(1)
response = self.nodes[0].keva_list_namespaces()
found = False
print(response)
for ns in response:
if (ns['namespaceId'] == newNamespaceId):
found = True
assert(found)
# Now disconnect the block and the namespace should be gone.
self.sync_all()
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
self.nodes[1].invalidateblock(self.nodes[1].getbestblockhash())
self.sync_all()
found = False
for ns in response:
if (ns['namespaceId'] == newNamespaceId):
found = True
assert(not found)
def run_test(self):
self.nodes[0].generate(161) #block 161
self.nodes[0].generate(105)
self.nodes[1].generate(105)
response = self.nodes[0].keva_namespace('first_namespace')
namespaceId = response['namespaceId']
@ -38,6 +114,9 @@ class KevaTest(BitcoinTestFramework): @@ -38,6 +114,9 @@ class KevaTest(BitcoinTestFramework):
response = self.nodes[0].keva_get(namespaceId, key)
assert(response['value'] == value)
self.log.info("Test other wallet's unconfirmed namespaces do not show up in ours")
self.run_unconfirmed_namespaces()
self.nodes[0].generate(1)
response = self.nodes[0].keva_pending()
assert(len(response) == 0)
@ -99,5 +178,9 @@ class KevaTest(BitcoinTestFramework): @@ -99,5 +178,9 @@ class KevaTest(BitcoinTestFramework):
response = self.nodes[0].keva_get(namespaceId, keyToDelete)
assert(response['value'] == newValue)
self.log.info("Test disconnecting blocks")
self.run_test_disconnect_block(namespaceId)
if __name__ == '__main__':
KevaTest().main()

Loading…
Cancel
Save