Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 3 additions & 22 deletions src/assets/assets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,28 +281,9 @@ bool CNewAsset::IsValid(std::string& strError, CAssetsCache& assetCache, bool fC
}

if (fCheckMempool) {
for (const CTxMemPoolEntry &entry : mempool.mapTx) {
CTransaction tx = entry.GetTx();

bool fIsNewAsset = tx.IsNewAsset();
bool fIsNewUniqueAsset = false;
if (!fIsNewAsset)
fIsNewUniqueAsset = tx.IsNewUniqueAsset();

if (fIsNewAsset || fIsNewUniqueAsset) {
CNewAsset asset;
std::string address;

if (fIsNewAsset)
AssetFromTransaction(tx, asset, address);
else
UniqueAssetFromTransaction(tx, asset, address);

if (asset.strName == strName) {
strError = _("Asset with this name is already in the mempool");
return false;
}
}
if (mempool.mapAssetToHash.count(strName)) {
strError = _("Asset with this name is already in the mempool");
return false;
}
}

Expand Down
49 changes: 49 additions & 0 deletions src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,12 @@ void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason)
mapReissuedTx.erase(hash);
}
}

// Erase from the asset mempool maps if they match txid
if (mapHashToAsset.count(hash)) {
mapAssetToHash.erase(mapHashToAsset.at(hash));
mapHashToAsset.erase(hash);
}
/** RVN END */
}

Expand Down Expand Up @@ -724,10 +730,20 @@ void CTxMemPool::removeConflicts(const CTransaction &tx)
}
}


/**
* Called when a block is connected. Removes from mempool and updates the miner fee estimator.
*/
void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight)
{
std::set<CAssetCacheNewAsset> set;
removeForBlock(vtx, nBlockHeight, set);
}

/**
* Called when a block is connected. Removes from mempool and updates the miner fee estimator.
*/
void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight, std::set<CAssetCacheNewAsset>& setNewAssets)
{
LOCK(cs);
std::vector<const CTxMemPoolEntry*> entries;
Expand All @@ -739,6 +755,21 @@ void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigne
if (i != mapTx.end())
entries.push_back(&*i);
}

/** RVN START */
// Get the newly added assets, and make sure they are in the entries
std::vector<CTransaction> trans;
for (auto it : setNewAssets) {
if (mapAssetToHash.count(it.asset.strName)) {
indexed_transaction_set::iterator i = mapTx.find(mapAssetToHash.at(it.asset.strName));
if (i != mapTx.end()) {
entries.push_back(&*i);
trans.emplace_back(i->GetTx());
}
}
}
/** RVN END */

// Before the txs in the new block have been removed from the mempool, update policy estimates
if (minerPolicyEstimator) {minerPolicyEstimator->processBlock(nBlockHeight, entries);}
for (const auto& tx : vtx)
Expand All @@ -752,6 +783,22 @@ void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigne
removeConflicts(*tx);
ClearPrioritisation(tx->GetHash());
}

/** RVN START */
// Remove newly added asset issue transactions from the mempool if they haven't been removed already
for (auto tx : trans)
{
txiter it = mapTx.find(tx.GetHash());
if (it != mapTx.end()) {
setEntries stage;
stage.insert(it);
RemoveStaged(stage, true, MemPoolRemovalReason::BLOCK);
}
removeConflicts(tx);
ClearPrioritisation(tx.GetHash());
}
/** RVN END */

lastRollingFeeUpdate = GetTime();
blockSinceLastRollingFeeBump = true;
}
Expand All @@ -767,6 +814,8 @@ void CTxMemPool::_clear()
blockSinceLastRollingFeeBump = false;
rollingMinimumFeeRate = 0;
++nTransactionsUpdated;
mapAssetToHash.clear();
mapHashToAsset.clear();
}

void CTxMemPool::clear()
Expand Down
4 changes: 4 additions & 0 deletions src/txmempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,9 @@ class CTxMemPool
mutable CCriticalSection cs;
indexed_transaction_set mapTx;

std::map<std::string, uint256> mapAssetToHash;
std::map<uint256, std::string> mapHashToAsset;

typedef indexed_transaction_set::nth_index<0>::type::iterator txiter;
std::vector<std::pair<uint256, txiter> > vTxHashes; //!< All tx witness hashes/entries in mapTx, in random order

Expand Down Expand Up @@ -543,6 +546,7 @@ class CTxMemPool
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason = MemPoolRemovalReason::UNKNOWN);
void removeForReorg(const CCoinsViewCache *pcoins, unsigned int nMemPoolHeight, int flags);
void removeConflicts(const CTransaction &tx);
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight, std::set<CAssetCacheNewAsset>& setNewAssets );
void removeForBlock(const std::vector<CTransactionRef>& vtx, unsigned int nBlockHeight);

void clear();
Expand Down
38 changes: 37 additions & 1 deletion src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,20 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
mapReissuedAssets.insert(out);
mapReissuedTx.insert(std::make_pair(out.second, out.first));
}

if (AreAssetsDeployed()) {
for (auto out : tx.vout) {
if (out.scriptPubKey.IsAssetScript()) {
CAssetOutputEntry data;
if (!GetAssetData(out.scriptPubKey, data))
continue;
if (data.type == TX_NEW_ASSET && !IsAssetNameAnOwner(data.assetName)) {
pool.mapAssetToHash[data.assetName] = hash;
pool.mapHashToAsset[hash] = data.assetName;
}
}
}
}
}

GetMainSignals().TransactionAddedToMempool(ptx);
Expand Down Expand Up @@ -2802,10 +2816,20 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1;
int64_t nTime3;
LogPrint(BCLog::BENCH, " - Load block from disk: %.2fms [%.2fs]\n", (nTime2 - nTime1) * MILLI, nTimeReadFromDisk * MICRO);

/** RVN START */
// Initialize sets used from removing asset entries from the mempool
std::set<CAssetCacheNewAsset> prevNewAssets;
std::set<CAssetCacheNewAsset> afterNewAsset;
/** RVN END */

{
CCoinsViewCache view(pcoinsTip);

/** RVN START */
CAssetsCache assetCache(*passets);
prevNewAssets = assetCache.setNewAssetsToAdd; // List of newly cached assets before block is connected
/** RVN END */

bool rv = ConnectBlock(blockConnecting, state, pindexNew, view, chainparams, &assetCache);
GetMainSignals().BlockChecked(blockConnecting, state);
Expand All @@ -2815,20 +2839,32 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
return error("ConnectTip(): ConnectBlock %s failed", pindexNew->GetBlockHash().ToString());
}

/** RVN START */
// Get the newly created assets, from the connectblock assetCache
afterNewAsset = assetCache.setNewAssetsToAdd;
for (auto it : prevNewAssets) {
if (afterNewAsset.count(it))
afterNewAsset.erase(it);
}

for (auto tx : blockConnecting.vtx) {
uint256 txHash = tx->GetHash();
if (mapReissuedTx.count(txHash)) {
mapReissuedAssets.erase(mapReissuedTx.at(txHash));
mapReissuedTx.erase(txHash);
}
}
/** RVN END */

nTime3 = GetTimeMicros(); nTimeConnectTotal += nTime3 - nTime2;
LogPrint(BCLog::BENCH, " - Connect total: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime3 - nTime2) * MILLI, nTimeConnectTotal * MICRO, nTimeConnectTotal * MILLI / nBlocksTotal);
bool flushed = view.Flush();
assert(flushed);

/** RVN START */
bool assetFlushed = assetCache.Flush(true);
assert(assetFlushed);
/** RVN END */
}
int64_t nTime4 = GetTimeMicros(); nTimeFlush += nTime4 - nTime3;
LogPrint(BCLog::BENCH, " - Flush: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime4 - nTime3) * MILLI, nTimeFlush * MICRO, nTimeFlush * MILLI / nBlocksTotal);
Expand All @@ -2838,7 +2874,7 @@ bool static ConnectTip(CValidationState& state, const CChainParams& chainparams,
int64_t nTime5 = GetTimeMicros(); nTimeChainState += nTime5 - nTime4;
LogPrint(BCLog::BENCH, " - Writing chainstate: %.2fms [%.2fs (%.2fms/blk)]\n", (nTime5 - nTime4) * MILLI, nTimeChainState * MICRO, nTimeChainState * MILLI / nBlocksTotal);
// Remove conflicting transactions from the mempool.;
mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight);
mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight, afterNewAsset);
disconnectpool.removeForBlock(blockConnecting.vtx);
// Update chainActive & related variables.
UpdateTip(pindexNew, chainparams);
Expand Down
61 changes: 61 additions & 0 deletions test/functional/feature_assets_mempool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
# Copyright (c) 2017 The Bitcoin Core developers
# Copyright (c) 2017-2018 The Raven Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Testing asset mempool use cases

"""
from test_framework.test_framework import RavenTestFramework
from test_framework.util import *


import string

class AssetMempoolTest(RavenTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 2


def activate_assets(self):
self.log.info("Generating RVN and activating assets...")
n0, n1 = self.nodes[0], self.nodes[1]

n0.generate(1)
self.sync_all()
n0.generate(216)
self.sync_all()
n1.generate(216)
self.sync_all()
assert_equal("active", n0.getblockchaininfo()['bip9_softforks']['assets']['status'])


def issue_mempool_test(self):
self.log.info("Testing issue mempool...")

n0, n1 = self.nodes[0], self.nodes[1]

disconnect_all_nodes(self.nodes)

asset_name = "MEMPOOL"

# Issue asset on chain 1 and mine it into the blocks
n0.issue(asset_name)
n0.generate(15)

# Issue asset on chain 2 but keep it in the mempool. No mining
txid = n1.issue(asset_name)
print(txid)

connect_all_nodes_bi(self.nodes)

assert_equal(n0.getblockcount(), n1.getblockcount())
assert_equal(n0.getbestblockhash(), n1.getbestblockhash())

def run_test(self):
self.activate_assets()
self.issue_mempool_test()

if __name__ == '__main__':
AssetMempoolTest().main()