aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.cpp40
-rw-r--r--src/main.h10
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/wallet.cpp5
-rw-r--r--src/wallet.h2
5 files changed, 32 insertions, 27 deletions
diff --git a/src/main.cpp b/src/main.cpp
index c23aae3206..a4f90dda71 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -111,10 +111,10 @@ void static EraseFromWallets(uint256 hash)
}
// make sure all wallets know about the given transaction, in the given block
-void SyncWithWallets(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
+void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{
BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->AddToWalletIfInvolvingMe(tx, pblock, fUpdate);
+ pwallet->AddToWalletIfInvolvingMe(hash, tx, pblock, fUpdate);
}
// notify wallets about a new best chain
@@ -1197,10 +1197,8 @@ unsigned int CTransaction::GetP2SHSigOpCount(CCoinsView& inputs) const
return nSigOps;
}
-bool CTransaction::UpdateCoins(CCoinsView &inputs, CTxUndo &txundo, int nHeight) const
+bool CTransaction::UpdateCoins(CCoinsView &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash) const
{
- uint256 hash = GetHash();
-
// mark inputs spent
if (!IsCoinBase()) {
BOOST_FOREACH(const CTxIn &txin, vin) {
@@ -1217,7 +1215,7 @@ bool CTransaction::UpdateCoins(CCoinsView &inputs, CTxUndo &txundo, int nHeight)
}
// add outputs
- if (!inputs.SetCoins(hash, CCoins(*this, nHeight)))
+ if (!inputs.SetCoins(txhash, CCoins(*this, nHeight)))
return error("UpdateCoins() : cannot update output");
return true;
@@ -1467,8 +1465,8 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsView &view, bool fJustCheck
bool fEnforceBIP30 = !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
if (fEnforceBIP30) {
- BOOST_FOREACH(CTransaction& tx, vtx) {
- uint256 hash = tx.GetHash();
+ for (unsigned int i=0; i<vtx.size(); i++) {
+ uint256 hash = GetTxHash(i);
CCoins coins;
if (view.GetCoins(hash, coins) && !coins.IsPruned())
return error("ConnectBlock() : tried to overwrite transaction");
@@ -1483,8 +1481,10 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsView &view, bool fJustCheck
int64 nFees = 0;
unsigned int nSigOps = 0;
- BOOST_FOREACH(CTransaction& tx, vtx)
+ for (unsigned int i=0; i<vtx.size(); i++)
{
+ const CTransaction &tx = vtx[i];
+
nSigOps += tx.GetLegacySigOpCount();
if (nSigOps > MAX_BLOCK_SIGOPS)
return DoS(100, error("ConnectBlock() : too many sigops"));
@@ -1511,7 +1511,7 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsView &view, bool fJustCheck
}
CTxUndo txundo;
- if (!tx.UpdateCoins(view, txundo, pindex->nHeight))
+ if (!tx.UpdateCoins(view, txundo, pindex->nHeight, GetTxHash(i)))
return error("ConnectBlock() : UpdateInputs failed");
if (!tx.IsCoinBase())
blockundo.vtxundo.push_back(txundo);
@@ -1542,8 +1542,8 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsView &view, bool fJustCheck
return false;
// Watch for transactions paying to me
- BOOST_FOREACH(CTransaction& tx, vtx)
- SyncWithWallets(tx, this, true);
+ for (unsigned int i=0; i<vtx.size(); i++)
+ SyncWithWallets(GetTxHash(i), vtx[i], this, true);
return true;
}
@@ -1755,7 +1755,7 @@ bool CBlock::AddToBlockIndex(const CDiskBlockPos &pos)
// Notify UI to display prev block's coinbase if it was ours
static uint256 hashPrevBestCoinBase;
UpdatedTransaction(hashPrevBestCoinBase);
- hashPrevBestCoinBase = vtx[0].GetHash();
+ hashPrevBestCoinBase = GetTxHash(0);
}
uiInterface.NotifyBlocksChanged();
@@ -1876,10 +1876,10 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot) const
// Check for duplicate txids. This is caught by ConnectInputs(),
// but catching it earlier avoids a potential DoS attack:
+ BuildMerkleTree();
set<uint256> uniqueTx;
- BOOST_FOREACH(const CTransaction& tx, vtx)
- {
- uniqueTx.insert(tx.GetHash());
+ for (unsigned int i=0; i<vtx.size(); i++) {
+ uniqueTx.insert(GetTxHash(i));
}
if (uniqueTx.size() != vtx.size())
return DoS(100, error("CheckBlock() : duplicate transaction"));
@@ -2914,7 +2914,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
bool fMissingInputs = false;
if (tx.AcceptToMemoryPool(true, &fMissingInputs))
{
- SyncWithWallets(tx, NULL, true);
+ SyncWithWallets(inv.hash, tx, NULL, true);
RelayMessage(inv, vMsg);
mapAlreadyAskedFor.erase(inv);
vWorkQueue.push_back(inv.hash);
@@ -2937,7 +2937,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if (tx.AcceptToMemoryPool(true, &fMissingInputs2))
{
printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,10).c_str());
- SyncWithWallets(tx, NULL, true);
+ SyncWithWallets(inv.hash, tx, NULL, true);
RelayMessage(inv, vMsg);
mapAlreadyAskedFor.erase(inv);
vWorkQueue.push_back(inv.hash);
@@ -3729,7 +3729,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
continue;
CTxUndo txundo;
- if (!tx.UpdateCoins(viewTemp, txundo, pindexPrev->nHeight+1))
+ uint256 hash = tx.GetHash();
+ if (!tx.UpdateCoins(viewTemp, txundo, pindexPrev->nHeight+1, hash))
continue;
// push changes from the second layer cache to the first one
@@ -3749,7 +3750,6 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
}
// Add transactions that depend on this one to the priority queue
- uint256 hash = tx.GetHash();
if (mapDependers.count(hash))
{
BOOST_FOREACH(COrphan* porphan, mapDependers[hash])
diff --git a/src/main.h b/src/main.h
index 0ec68b612b..3ee0108f46 100644
--- a/src/main.h
+++ b/src/main.h
@@ -91,7 +91,7 @@ class CCoinsView;
void RegisterWallet(CWallet* pwalletIn);
void UnregisterWallet(CWallet* pwalletIn);
-void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false);
+void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false);
bool ProcessBlock(CNode* pfrom, CBlock* pblock);
bool CheckDiskSpace(uint64 nAdditionalBytes=0);
FILE* OpenBlockFile(const CDiskBlockPos &pos, bool fReadOnly = false);
@@ -577,7 +577,7 @@ public:
bool CheckInputs(CCoinsView &view, enum CheckSig_mode csmode, bool fStrictPayToScriptHash=true, bool fStrictEncodings=true) const;
// Apply the effects of this transaction on the UTXO set represented by view
- bool UpdateCoins(CCoinsView &view, CTxUndo &txundo, int nHeight) const;
+ bool UpdateCoins(CCoinsView &view, CTxUndo &txundo, int nHeight, const uint256 &txhash) const;
// Context-independent validity checks
bool CheckTransaction() const;
@@ -1111,6 +1111,12 @@ public:
return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
}
+ const uint256 &GetTxHash(unsigned int nIndex) const {
+ assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
+ assert(nIndex < vtx.size());
+ return vMerkleTree[nIndex];
+ }
+
std::vector<uint256> GetMerkleBranch(int nIndex) const
{
if (vMerkleTree.empty())
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 647384f333..72a89c08c1 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -517,7 +517,7 @@ Value sendrawtransaction(const Array& params, bool fHelp)
// Not in block, but already in the memory pool; will drop
// through to re-relay it.
} else {
- SyncWithWallets(tx, NULL, true);
+ SyncWithWallets(hashTx, tx, NULL, true);
}
RelayMessage(CInv(MSG_TX, hashTx), tx);
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 5b32034696..1498ff28b7 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -479,9 +479,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn)
// Add a transaction to the wallet, or update it.
// pblock is optional, but should be provided if the transaction is known to be in a block.
// If fUpdate is true, existing transactions will be updated.
-bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
+bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
{
- uint256 hash = tx.GetHash();
{
LOCK(cs_wallet);
bool fExisted = mapWallet.count(hash);
@@ -756,7 +755,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
block.ReadFromDisk(pindex, true);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
- if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
+ if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
ret++;
}
pindex = pindex->pnext;
diff --git a/src/wallet.h b/src/wallet.h
index 8c98f34a5a..43b695c597 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -162,7 +162,7 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn);
- bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
+ bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
bool EraseFromWallet(uint256 hash);
void WalletUpdateSpent(const CTransaction& prevout);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);