aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp198
1 files changed, 64 insertions, 134 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 01a1babc7..875cd6734 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -49,7 +49,7 @@ int64 CTransaction::nMinTxFee = 10000; // Override with -mintxfee
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying) */
int64 CTransaction::nMinRelayTxFee = 10000;
-CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have
+static CMedianFilter<int> cPeerBlockCounts(8, 0); // Amount of blocks that other nodes claim to have
map<uint256, CBlock*> mapOrphanBlocks;
multimap<uint256, CBlock*> mapOrphanBlocksByPrev;
@@ -74,93 +74,52 @@ int64 nTransactionFee = 0;
// These functions dispatch to one or all registered wallets
-
-void RegisterWallet(CWallet* pwalletIn)
-{
- {
- LOCK(cs_setpwalletRegistered);
- setpwalletRegistered.insert(pwalletIn);
- }
-}
-
-void UnregisterWallet(CWallet* pwalletIn)
-{
- {
- LOCK(cs_setpwalletRegistered);
- setpwalletRegistered.erase(pwalletIn);
- }
+namespace {
+struct CMainSignals {
+ // Notifies listeners of updated transaction data (passing hash, transaction, and optionally the block it is found in.
+ boost::signals2::signal<void (const uint256 &, const CTransaction &, const CBlock *)> SyncTransaction;
+ // Notifies listeners of an erased transaction (currently disabled, requires transaction replacement).
+ boost::signals2::signal<void (const uint256 &)> EraseTransaction;
+ // Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible).
+ boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
+ // Notifies listeners of a new active block chain.
+ boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
+ // Notifies listeners about an inventory item being seen on the network.
+ boost::signals2::signal<void (const uint256 &)> Inventory;
+ // Tells listeners to broadcast their data.
+ boost::signals2::signal<void ()> Broadcast;
+} g_signals;
}
-void UnregisterAllWallets()
-{
- LOCK(cs_setpwalletRegistered);
- setpwalletRegistered.clear();
+void RegisterWallet(CWalletInterface* pwalletIn) {
+ g_signals.SyncTransaction.connect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3));
+ g_signals.EraseTransaction.connect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
+ g_signals.UpdatedTransaction.connect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
+ g_signals.SetBestChain.connect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
+ g_signals.Inventory.connect(boost::bind(&CWalletInterface::Inventory, pwalletIn, _1));
+ g_signals.Broadcast.connect(boost::bind(&CWalletInterface::ResendWalletTransactions, pwalletIn));
}
-// get the wallet transaction with the given hash (if it exists)
-bool static GetTransaction(const uint256& hashTx, CWalletTx& wtx)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- if (pwallet->GetTransaction(hashTx,wtx))
- return true;
- return false;
+void UnregisterWallet(CWalletInterface* pwalletIn) {
+ g_signals.Broadcast.disconnect(boost::bind(&CWalletInterface::ResendWalletTransactions, pwalletIn));
+ g_signals.Inventory.disconnect(boost::bind(&CWalletInterface::Inventory, pwalletIn, _1));
+ g_signals.SetBestChain.disconnect(boost::bind(&CWalletInterface::SetBestChain, pwalletIn, _1));
+ g_signals.UpdatedTransaction.disconnect(boost::bind(&CWalletInterface::UpdatedTransaction, pwalletIn, _1));
+ g_signals.EraseTransaction.disconnect(boost::bind(&CWalletInterface::EraseFromWallet, pwalletIn, _1));
+ g_signals.SyncTransaction.disconnect(boost::bind(&CWalletInterface::SyncTransaction, pwalletIn, _1, _2, _3));
}
-// erases transaction with the given hash from all wallets
-void static EraseFromWallets(uint256 hash)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->EraseFromWallet(hash);
+void UnregisterAllWallets() {
+ g_signals.Broadcast.disconnect_all_slots();
+ g_signals.Inventory.disconnect_all_slots();
+ g_signals.SetBestChain.disconnect_all_slots();
+ g_signals.UpdatedTransaction.disconnect_all_slots();
+ g_signals.EraseTransaction.disconnect_all_slots();
+ g_signals.SyncTransaction.disconnect_all_slots();
}
-// make sure all wallets know about the given transaction, in the given block
-void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->AddToWalletIfInvolvingMe(hash, tx, pblock, fUpdate);
-}
-
-// notify wallets about a new best chain
-void static SetBestChain(const CBlockLocator& loc)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->SetBestChain(loc);
-}
-
-// notify wallets about an updated transaction
-void static UpdatedTransaction(const uint256& hashTx)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->UpdatedTransaction(hashTx);
-}
-
-// dump all wallets
-void static PrintWallets(const CBlock& block)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->PrintWallet(block);
-}
-
-// notify wallets about an incoming inventory (for request counts)
-void static Inventory(const uint256& hash)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->Inventory(hash);
-}
-
-// ask wallets to resend their transactions
-void static ResendWalletTransactions()
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->ResendWalletTransactions();
+void SyncWithWallets(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) {
+ g_signals.SyncTransaction(hash, tx, pblock);
}
//////////////////////////////////////////////////////////////////////////////
@@ -931,8 +890,8 @@ bool CTxMemPool::accept(CValidationState &state, const CTransaction &tx, bool fL
///// are we sure this is ok when loading transactions or restoring block txes
// If updated, erase old tx from wallet
if (ptxOld)
- EraseFromWallets(ptxOld->GetHash());
- SyncWithWallets(hash, tx, NULL, true);
+ g_signals.EraseTransaction(ptxOld->GetHash());
+ g_signals.SyncTransaction(hash, tx, NULL);
LogPrint("mempool", "CTxMemPool::accept() : accepted %s (poolsz %"PRIszu")\n",
hash.ToString().c_str(),
@@ -1095,27 +1054,6 @@ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree)
}
-
-bool CWalletTx::AcceptWalletTransaction()
-{
- {
- LOCK(mempool.cs);
- // Add previous supporting transactions first
- BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
- {
- if (!tx.IsCoinBase())
- {
- uint256 hash = tx.GetHash();
- if (!mempool.exists(hash) && pcoinsTip->HaveCoins(hash))
- tx.AcceptToMemoryPool(false);
- }
- }
- return AcceptToMemoryPool(false);
- }
- return false;
-}
-
-
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{
@@ -1750,12 +1688,12 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
const CTransaction &tx = block.vtx[i];
uint256 hash = tx.GetHash();
- // check that all outputs are available
- if (!view.HaveCoins(hash)) {
- fClean = fClean && error("DisconnectBlock() : outputs still spent? database corrupted");
- view.SetCoins(hash, CCoins());
- }
- CCoins &outs = view.GetCoins(hash);
+ // Check that all outputs are available and match the outputs in the block itself
+ // exactly. Note that transactions with only provably unspendable outputs won't
+ // have outputs available even in the block itself, so we handle that case
+ // specially with outsEmpty.
+ CCoins outsEmpty;
+ CCoins &outs = view.HaveCoins(hash) ? view.GetCoins(hash) : outsEmpty;
outs.ClearUnspendable();
CCoins outsBlock = CCoins(tx, pindex->nHeight);
@@ -1992,7 +1930,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
// Watch for transactions paying to me
for (unsigned int i = 0; i < block.vtx.size(); i++)
- SyncWithWallets(block.GetTxHash(i), block.vtx[i], &block, true);
+ g_signals.SyncTransaction(block.GetTxHash(i), block.vtx[i], &block);
return true;
}
@@ -2126,7 +2064,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// Update best block in wallet (so we can detect restored wallets)
if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
- ::SetBestChain(chainActive.GetLocator(pindexNew));
+ g_signals.SetBestChain(chainActive.GetLocator(pindexNew));
// New best block
nTimeBestReceived = GetTime();
@@ -2206,7 +2144,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
CheckForkWarningConditions();
// Notify UI to display prev block's coinbase if it was ours
static uint256 hashPrevBestCoinBase;
- UpdatedTransaction(hashPrevBestCoinBase);
+ g_signals.UpdatedTransaction(hashPrevBestCoinBase);
hashPrevBestCoinBase = block.GetTxHash(0);
} else
CheckForkWarningConditionsOnNewFork(pindexNew);
@@ -2355,7 +2293,7 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
uniqueTx.insert(block.GetTxHash(i));
}
if (uniqueTx.size() != block.vtx.size())
- return state.DoS(100, error("CheckBlock() : duplicate transaction"));
+ return state.DoS(100, error("CheckBlock() : duplicate transaction"), true);
unsigned int nSigOps = 0;
BOOST_FOREACH(const CTransaction& tx, block.vtx)
@@ -3041,8 +2979,6 @@ void PrintBlockTree()
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()).c_str(),
block.vtx.size());
- PrintWallets(block);
-
// put the main time-chain first
vector<CBlockIndex*>& vNext = mapNext[pindex];
for (unsigned int i = 0; i < vNext.size(); i++)
@@ -3331,7 +3267,7 @@ void static ProcessGetData(CNode* pfrom)
}
// Track requests for our stuff.
- Inventory(inv.hash);
+ g_signals.Inventory(inv.hash);
}
}
@@ -3460,8 +3396,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
LogPrintf("receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str());
- LOCK(cs_main);
AddTimeData(pfrom->addr, nTime);
+
+ LOCK(cs_main);
cPeerBlockCounts.input(pfrom->nStartingHeight);
}
@@ -3593,7 +3530,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
// Track requests for our stuff
- Inventory(inv.hash);
+ g_signals.Inventory(inv.hash);
}
}
@@ -3608,10 +3545,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return error("message getdata size() = %"PRIszu"", vInv.size());
}
- if (fDebugNet || (vInv.size() != 1))
+ if (fDebug || (vInv.size() != 1))
LogPrint("net", "received getdata (%"PRIszu" invsz)\n", vInv.size());
- if ((fDebugNet && vInv.size() > 0) || (vInv.size() == 1))
+ if ((fDebug && vInv.size() > 0) || (vInv.size() == 1))
LogPrint("net", "received getdata for: %s\n", vInv[0].ToString().c_str());
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
@@ -3783,7 +3720,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
LOCK(cs_main);
CValidationState state;
- if (ProcessBlock(state, pfrom, &block))
+ if (ProcessBlock(state, pfrom, &block) || state.CorruptionPossible())
mapAlreadyAskedFor.erase(inv);
int nDoS = 0;
if (state.IsInvalid(nDoS))
@@ -3814,8 +3751,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
if ((pfrom->pfilter && pfrom->pfilter->IsRelevantAndUpdate(mempool.lookup(hash), hash)) ||
(!pfrom->pfilter))
vInv.push_back(inv);
- if (vInv.size() == MAX_INV_SZ)
- break;
+ if (vInv.size() == MAX_INV_SZ) {
+ pfrom->PushMessage("inv", vInv);
+ vInv.clear();
+ }
}
if (vInv.size() > 0)
pfrom->PushMessage("inv", vInv);
@@ -4213,7 +4152,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// transactions become unconfirmed and spams other nodes.
if (!fReindex && !fImporting && !IsInitialBlockDownload())
{
- ResendWalletTransactions();
+ g_signals.Broadcast();
}
//
@@ -4241,15 +4180,6 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
hashRand = Hash(BEGIN(hashRand), END(hashRand));
bool fTrickleWait = ((hashRand & 3) != 0);
- // always trickle our own transactions
- if (!fTrickleWait)
- {
- CWalletTx wtx;
- if (GetTransaction(inv.hash, wtx))
- if (wtx.fFromMe)
- fTrickleWait = true;
- }
-
if (fTrickleWait)
{
vInvWait.push_back(inv);
@@ -4284,7 +4214,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
const CInv& inv = (*pto->mapAskFor.begin()).second;
if (!AlreadyHave(inv))
{
- if (fDebugNet)
+ if (fDebug)
LogPrint("net", "sending getdata: %s\n", inv.ToString().c_str());
vGetData.push_back(inv);
if (vGetData.size() >= 1000)