Skip to content

Commit

Permalink
Migrating to CTransationRef second round:
Browse files Browse the repository at this point in the history
 1) mempool: CTxMemPoolEntry migrated to receive CTransationRef as constructor argument.
 2) validation: ATMP and ATMPW migrated to receive CTransationRef.
 3) net_processing: ProcessMessage migrated TX message processing to use CTransactionRef.
 4) swiftx: ProcessMessage migrated IX message processing to use CTransactionRef.
 5) migrated mapOrphanTransactions to use CTransactionRef.
  • Loading branch information
furszy committed Oct 16, 2020
1 parent 2a89063 commit 80a94df
Show file tree
Hide file tree
Showing 12 changed files with 62 additions and 60 deletions.
33 changes: 17 additions & 16 deletions src/net_processing.cpp
Expand Up @@ -24,7 +24,7 @@ int64_t nTimeBestReceived = 0; // Used only to inform the wallet of when we las
static const uint64_t RANDOMIZER_ID_ADDRESS_RELAY = 0x3cac0035b5866b90ULL; // SHA256("main address relay")[0:8]

struct COrphanTx {
CTransaction tx;
CTransactionRef tx;
NodeId fromPeer;
};

Expand Down Expand Up @@ -511,9 +511,9 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals)
// mapOrphanTransactions
//

bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool AddOrphanTx(const CTransactionRef& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
uint256 hash = tx.GetHash();
const uint256& hash = tx->GetHash();
if (mapOrphanTransactions.count(hash))
return false;

Expand All @@ -524,15 +524,15 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(c
// have been mined or received.
// 10,000 orphans, each of which is at most 5,000 bytes big is
// at most 500 megabytes of orphans:
unsigned int sz = GetSerializeSize(tx, SER_NETWORK, CTransaction::CURRENT_VERSION);
unsigned int sz = GetSerializeSize(*tx, SER_NETWORK, CTransaction::CURRENT_VERSION);
if (sz > 5000) {
LogPrint(BCLog::MEMPOOL, "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
return false;
}

mapOrphanTransactions[hash].tx = tx;
mapOrphanTransactions[hash].fromPeer = peer;
for (const CTxIn& txin : tx.vin)
auto ret = mapOrphanTransactions.emplace(hash, COrphanTx{tx, peer});
assert(ret.second);
for (const CTxIn& txin : tx->vin)
mapOrphanTransactionsByPrev[txin.prevout.hash].insert(hash);

LogPrint(BCLog::MEMPOOL, "stored orphan tx %s (mapsz %u prevsz %u)\n", hash.ToString(),
Expand All @@ -545,7 +545,7 @@ void static EraseOrphanTx(uint256 hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.find(hash);
if (it == mapOrphanTransactions.end())
return;
for (const CTxIn& txin : it->second.tx.vin) {
for (const CTxIn& txin : it->second.tx->vin) {
std::map<uint256, std::set<uint256> >::iterator itPrev = mapOrphanTransactionsByPrev.find(txin.prevout.hash);
if (itPrev == mapOrphanTransactionsByPrev.end())
continue;
Expand All @@ -563,7 +563,7 @@ void EraseOrphansFor(NodeId peer) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
while (iter != mapOrphanTransactions.end()) {
std::map<uint256, COrphanTx>::iterator maybeErase = iter++; // increment to avoid iterator becoming invalid
if (maybeErase->second.fromPeer == peer) {
EraseOrphanTx(maybeErase->second.tx.GetHash());
EraseOrphanTx(maybeErase->second.tx->GetHash());
++nErased;
}
}
Expand Down Expand Up @@ -1401,8 +1401,9 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
else if (strCommand == NetMsgType::TX) {
std::vector<uint256> vWorkQueue;
std::vector<uint256> vEraseQueue;
CTransaction tx;
vRecv >> tx;
CTransactionRef ptx;
vRecv >> ptx;
const CTransaction& tx = *ptx;

CInv inv(MSG_TX, tx.GetHash());
pfrom->AddInventoryKnown(inv);
Expand All @@ -1416,7 +1417,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR

mapAlreadyAskedFor.erase(inv);

if (!tx.HasZerocoinSpendInputs() && AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs, false, ignoreFees)) {
if (!tx.HasZerocoinSpendInputs() && AcceptToMemoryPool(mempool, state, ptx, true, &fMissingInputs, false, ignoreFees)) {
mempool.check(pcoinsTip);
RelayTransaction(tx, connman);
vWorkQueue.push_back(inv.hash);
Expand All @@ -1435,7 +1436,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
mi != itByPrev->second.end();
++mi) {
const uint256 &orphanHash = *mi;
const CTransaction &orphanTx = mapOrphanTransactions[orphanHash].tx;
const auto &orphanTx = mapOrphanTransactions[orphanHash].tx;
NodeId fromPeer = mapOrphanTransactions[orphanHash].fromPeer;
bool fMissingInputs2 = false;
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan
Expand All @@ -1448,7 +1449,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
continue;
if(AcceptToMemoryPool(mempool, stateDummy, orphanTx, true, &fMissingInputs2)) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx, connman);
RelayTransaction(*orphanTx, connman);
vWorkQueue.push_back(orphanHash);
vEraseQueue.push_back(orphanHash);
} else if(!fMissingInputs2) {
Expand All @@ -1472,7 +1473,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR

for (uint256& hash : vEraseQueue) EraseOrphanTx(hash);

} else if (tx.HasZerocoinSpendInputs() && AcceptToMemoryPool(mempool, state, tx, true, &fMissingZerocoinInputs, false, false, ignoreFees)) {
} else if (tx.HasZerocoinSpendInputs() && AcceptToMemoryPool(mempool, state, ptx, true, &fMissingZerocoinInputs, false, false, ignoreFees)) {
//Presstab: ZCoin has a bunch of code commented out here. Is this something that should have more going on?
//Also there is nothing that handles fMissingZerocoinInputs. Does there need to be?
RelayTransaction(tx, connman);
Expand All @@ -1481,7 +1482,7 @@ bool static ProcessMessage(CNode* pfrom, std::string strCommand, CDataStream& vR
tx.GetHash().ToString(),
mempool.mapTx.size());
} else if (fMissingInputs) {
AddOrphanTx(tx, pfrom->GetId());
AddOrphanTx(ptx, pfrom->GetId());

// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS));
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/rawtransaction.cpp
Expand Up @@ -863,7 +863,7 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
}
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(mempool, state, tx, false, &fMissingInputs, false, !fOverrideFees)) {
if (!AcceptToMemoryPool(mempool, state, MakeTransactionRef(std::move(tx)), false, &fMissingInputs, false, !fOverrideFees)) {
if (state.IsInvalid()) {
throw JSONRPCError(RPC_TRANSACTION_REJECTED, strprintf("%i: %s", state.GetRejectCode(), state.GetRejectReason()));
} else {
Expand Down
11 changes: 6 additions & 5 deletions src/swifttx.cpp
Expand Up @@ -44,8 +44,9 @@ void ProcessMessageSwiftTX(CNode* pfrom, std::string& strCommand, CDataStream& v
if (strCommand == NetMsgType::IX) {
//LogPrintf("ProcessMessageSwiftTX::ix\n");
CDataStream vMsg(vRecv);
CTransaction tx;
vRecv >> tx;
CTransactionRef ptx;
vRecv >> ptx;
const CTransaction& tx = *ptx;

CInv inv(MSG_TXLOCK_REQUEST, tx.GetHash());
pfrom->AddInventoryKnown(inv);
Expand Down Expand Up @@ -75,7 +76,7 @@ void ProcessMessageSwiftTX(CNode* pfrom, std::string& strCommand, CDataStream& v
bool fAccepted = false;
{
LOCK(cs_main);
fAccepted = AcceptToMemoryPool(mempool, state, tx, true, &fMissingInputs);
fAccepted = AcceptToMemoryPool(mempool, state, ptx, true, &fMissingInputs);
}
if (fAccepted) {
g_connman->RelayInv(inv);
Expand Down Expand Up @@ -260,7 +261,7 @@ int64_t CreateNewLock(CTransaction tx)
}

// check if we need to vote on this transaction
void DoConsensusVote(CTransaction& tx, int64_t nBlockHeight)
void DoConsensusVote(const CTransaction& tx, int64_t nBlockHeight)
{
if (!fMasterNode) return;

Expand Down Expand Up @@ -400,7 +401,7 @@ bool ProcessConsensusVote(CNode* pnode, CConsensusVote& ctx)
return false;
}

bool CheckForConflictingLocks(CTransaction& tx)
bool CheckForConflictingLocks(const CTransaction& tx)
{
/*
It's possible (very unlikely though) to get 2 conflicting transaction locks approved by the network.
Expand Down
4 changes: 2 additions & 2 deletions src/swifttx.h
Expand Up @@ -45,12 +45,12 @@ int64_t CreateNewLock(CTransaction tx);
bool IsIXTXValid(const CTransaction& txCollateral);

// if two conflicting locks are approved by the network, they will cancel out
bool CheckForConflictingLocks(CTransaction& tx);
bool CheckForConflictingLocks(const CTransaction& tx);

void ProcessMessageSwiftTX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);

//check if we need to vote on this transaction
void DoConsensusVote(CTransaction& tx, int64_t nBlockHeight);
void DoConsensusVote(const CTransaction& tx, int64_t nBlockHeight);

//process consensus vote message
bool ProcessConsensusVote(CNode* pnode, CConsensusVote& ctx);
Expand Down
24 changes: 12 additions & 12 deletions src/test/DoS_tests.cpp
Expand Up @@ -25,11 +25,11 @@
#include <boost/test/unit_test.hpp>

// Tests this internal-to-validation.cpp method:
extern bool AddOrphanTx(const CTransaction& tx, NodeId peer);
extern bool AddOrphanTx(const CTransactionRef& tx, NodeId peer);
extern void EraseOrphansFor(NodeId peer);
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
struct COrphanTx {
CTransaction tx;
CTransactionRef tx;
NodeId fromPeer;
};
extern std::map<uint256, COrphanTx> mapOrphanTransactions;
Expand Down Expand Up @@ -132,7 +132,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
BOOST_CHECK(!connman->IsBanned(addr));
}

CTransaction RandomOrphan()
CTransactionRef RandomOrphan()
{
std::map<uint256, COrphanTx>::iterator it;
it = mapOrphanTransactions.lower_bound(InsecureRand256());
Expand Down Expand Up @@ -160,30 +160,30 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());

AddOrphanTx(tx, i);
AddOrphanTx(MakeTransactionRef(tx), i);
}

// ... and 50 that depend on other orphans:
for (int i = 0; i < 50; i++)
{
CTransaction txPrev = RandomOrphan();
CTransactionRef txPrev = RandomOrphan();

CMutableTransaction tx;
tx.vin.resize(1);
tx.vin[0].prevout.n = 0;
tx.vin[0].prevout.hash = txPrev.GetHash();
tx.vin[0].prevout.hash = txPrev->GetHash();
tx.vout.resize(1);
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL);
SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);

AddOrphanTx(tx, i);
AddOrphanTx(MakeTransactionRef(tx), i);
}

// This really-big orphan should be ignored:
for (int i = 0; i < 10; i++)
{
CTransaction txPrev = RandomOrphan();
CTransactionRef txPrev = RandomOrphan();

CMutableTransaction tx;
tx.vout.resize(1);
Expand All @@ -193,15 +193,15 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
for (unsigned int j = 0; j < tx.vin.size(); j++)
{
tx.vin[j].prevout.n = j;
tx.vin[j].prevout.hash = txPrev.GetHash();
tx.vin[j].prevout.hash = txPrev->GetHash();
}
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL);
SignSignature(keystore, *txPrev, tx, 0, SIGHASH_ALL);
// Re-use same signature for other inputs
// (they don't have to be valid for this test)
for (unsigned int j = 1; j < tx.vin.size(); j++)
tx.vin[j].scriptSig = tx.vin[0].scriptSig;

BOOST_CHECK(!AddOrphanTx(tx, i));
BOOST_CHECK(!AddOrphanTx(MakeTransactionRef(tx), i));
}

// Test EraseOrphansFor:
Expand Down
4 changes: 2 additions & 2 deletions src/test/test_pivx.cpp
Expand Up @@ -78,10 +78,10 @@ TestingSetup::~TestingSetup()
}

CTxMemPoolEntry TestMemPoolEntryHelper::FromTx(CMutableTransaction &tx, CTxMemPool *pool) {
CTransaction txn(tx);
const CTransactionRef txn = MakeTransactionRef(tx); // todo: move to the caller side..
bool hasNoDependencies = pool ? pool->HasNoInputsOf(tx) : hadNoDependencies;
// Hack to assume either its completely dependent on other mempool txs or not at all
CAmount inChainValue = hasNoDependencies ? txn.GetValueOut() : 0;
CAmount inChainValue = hasNoDependencies ? txn->GetValueOut() : 0;

return CTxMemPoolEntry(txn, nFee, nTime, dPriority, nHeight,
hasNoDependencies, inChainValue, spendsCoinbaseOrCoinstake, sigOpCount);
Expand Down
14 changes: 7 additions & 7 deletions src/txmempool.cpp
Expand Up @@ -19,22 +19,22 @@
#include <boost/foreach.hpp>


CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority,
unsigned int _entryHeight, bool poolHasNoInputsOf, CAmount _inChainInputValue,
bool _spendsCoinbaseOrCoinstake, unsigned int _sigOps) :
tx(MakeTransactionRef(_tx)), nFee(_nFee), nTime(_nTime), entryPriority(_entryPriority), entryHeight(_entryHeight), hadNoDependencies(poolHasNoInputsOf), inChainInputValue(_inChainInputValue), spendsCoinbaseOrCoinstake(_spendsCoinbaseOrCoinstake), sigOpCount(_sigOps)
{
nTxSize = ::GetSerializeSize(_tx, SER_NETWORK, PROTOCOL_VERSION);
nModSize = _tx.CalculateModifiedSize(nTxSize);
nUsageSize = _tx.DynamicMemoryUsage();
hasZerocoins = _tx.ContainsZerocoins();
m_isShielded = tx->hasSaplingData();
nTxSize = ::GetSerializeSize(*_tx, SER_NETWORK, PROTOCOL_VERSION);
nModSize = _tx->CalculateModifiedSize(nTxSize);
nUsageSize = _tx->DynamicMemoryUsage();
hasZerocoins = _tx->ContainsZerocoins();
m_isShielded = _tx->hasSaplingData();

nCountWithDescendants = 1;
nSizeWithDescendants = nTxSize;
nFeesWithDescendants = nFee;
CAmount nValueIn = _tx.GetValueOut()+nFee;
CAmount nValueIn = _tx->GetValueOut()+nFee;
assert(inChainInputValue <= nValueIn);

feeDelta = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/txmempool.h
Expand Up @@ -87,7 +87,7 @@ class CTxMemPoolEntry
CAmount nFeesWithDescendants; //! ... and total fees (all including us)

public:
CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
CTxMemPoolEntry(const CTransactionRef& _tx, const CAmount& _nFee,
int64_t _nTime, double _entryPriority, unsigned int _entryHeight,
bool poolHasNoInputsOf, CAmount _inChainInputValue, bool _spendsCoinbaseOrCoinstake,
unsigned int nSigOps);
Expand Down
18 changes: 9 additions & 9 deletions src/validation.cpp
Expand Up @@ -303,11 +303,12 @@ std::string FormatStateMessage(const CValidationState &state)
state.GetRejectCode());
}

bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const CTransactionRef& _tx, bool fLimitFree,
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee, bool ignoreFees,
std::vector<COutPoint>& coins_to_uncache)
{
AssertLockHeld(cs_main);
const CTransaction& tx = *_tx;
if (pfMissingInputs)
*pfMissingInputs = false;

Expand Down Expand Up @@ -469,7 +470,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
}
}

CTxMemPoolEntry entry(tx, nFees, GetTime(), dPriority, chainHeight, pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbaseOrCoinstake, nSigOps);
CTxMemPoolEntry entry(_tx, nFees, GetTime(), dPriority, chainHeight, pool.HasNoInputsOf(tx), inChainInputValue, fSpendsCoinbaseOrCoinstake, nSigOps);
unsigned int nSize = entry.GetTxSize();

// Don't accept it if it can't get into a block
Expand Down Expand Up @@ -581,7 +582,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
return true;
}

bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransaction &tx, bool fLimitFree,
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef& tx, bool fLimitFree,
bool* pfMissingInputs, bool fOverrideMempoolLimit, bool fRejectAbsurdFee, bool fIgnoreFees)
{
std::vector<COutPoint> coins_to_uncache;
Expand Down Expand Up @@ -1889,15 +1890,14 @@ bool static DisconnectTip(CValidationState& state)
return false;
// Resurrect mempool transactions from the disconnected block.
std::vector<uint256> vHashUpdate;
for (const auto& txIn : block.vtx) {
const CTransaction& tx = *txIn;
for (const auto& tx : block.vtx) {
// ignore validation errors in resurrected transactions
std::list<CTransactionRef> removed;
CValidationState stateDummy;
if (tx.IsCoinBase() || tx.IsCoinStake() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, nullptr, true)) {
mempool.remove(tx, removed, true);
} else if (mempool.exists(tx.GetHash())) {
vHashUpdate.push_back(tx.GetHash());
if (tx->IsCoinBase() || tx->IsCoinStake() || !AcceptToMemoryPool(mempool, stateDummy, tx, false, nullptr, true)) {
mempool.remove(*tx, removed, true);
} else if (mempool.exists(tx->GetHash())) {
vHashUpdate.push_back(tx->GetHash());
}
}
// AcceptToMemoryPool/addUnchecked all assume that new mempool entries have
Expand Down
2 changes: 1 addition & 1 deletion src/validation.h
Expand Up @@ -217,7 +217,7 @@ void FlushStateToDisk();


/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransaction& tx, bool fLimitFree, bool* pfMissingInputs, bool fOverrideMempoolLimit = false, bool fRejectInsaneFee = false, bool ignoreFees = false);
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState& state, const CTransactionRef& tx, bool fLimitFree, bool* pfMissingInputs, bool fOverrideMempoolLimit = false, bool fRejectInsaneFee = false, bool ignoreFees = false);

int GetIXConfirmations(uint256 nTXHash);

Expand Down
4 changes: 2 additions & 2 deletions src/wallet/test/wallet_tests.cpp
Expand Up @@ -337,7 +337,7 @@ CBlockIndex* SimpleFakeMine(CWalletTx& wtx, CBlockIndex* pprev = nullptr)
return fakeIndex;
}

void fakeMempoolInsertion(const CWalletTx& wtxCredit)
void fakeMempoolInsertion(const CTransactionRef& wtxCredit)
{
CTxMemPoolEntry entry(wtxCredit, 0, 0, 0, 0, false, 0, false, 0);
LOCK(mempool.cs);
Expand Down Expand Up @@ -435,7 +435,7 @@ BOOST_AUTO_TEST_CASE(cached_balances_tests)
);

// GetUnconfirmedBalance requires tx in mempool.
fakeMempoolInsertion(wtxCredit);
fakeMempoolInsertion(MakeTransactionRef(wtxCredit));
BOOST_CHECK_EQUAL(wallet.GetUnconfirmedBalance(), nCredit);

// 2) Confirm tx and verify
Expand Down

0 comments on commit 80a94df

Please sign in to comment.