aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bitcoind.cpp3
-rw-r--r--src/bitcoinrpc.cpp2
-rw-r--r--src/core.h3
-rw-r--r--src/init.h5
-rw-r--r--src/key.h7
-rw-r--r--src/main.cpp181
-rw-r--r--src/main.h34
-rw-r--r--src/net.cpp35
-rw-r--r--src/net.h10
-rw-r--r--src/qt/forms/receivecoinsdialog.ui27
-rw-r--r--src/qt/optionsmodel.cpp3
-rw-r--r--src/rpcdump.cpp1
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/serialize.h17
-rw-r--r--src/test/serialize_tests.cpp48
-rw-r--r--src/wallet.cpp66
-rw-r--r--src/wallet.h13
17 files changed, 247 insertions, 210 deletions
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index fbacbd2e24..4fd3296069 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -3,7 +3,10 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "ui_interface.h"
#include "init.h"
+#include "util.h"
+#include "main.h"
#include "bitcoinrpc.h"
#include <boost/algorithm/string/predicate.hpp>
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index f2a52e92ed..f3ea0adb40 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -4,6 +4,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chainparams.h"
+#include "main.h"
+#include "wallet.h"
#include "init.h"
#include "util.h"
#include "sync.h"
diff --git a/src/core.h b/src/core.h
index 9ee8b2edce..70e62716f3 100644
--- a/src/core.h
+++ b/src/core.h
@@ -421,6 +421,9 @@ public:
// equality test
friend bool operator==(const CCoins &a, const CCoins &b) {
+ // Empty CCoins objects are always equal.
+ if (a.IsPruned() && b.IsPruned())
+ return true;
return a.fCoinBase == b.fCoinBase &&
a.nHeight == b.nHeight &&
a.nVersion == b.nVersion &&
diff --git a/src/init.h b/src/init.h
index 785a6cdba1..8cb1bf52fc 100644
--- a/src/init.h
+++ b/src/init.h
@@ -5,7 +5,10 @@
#ifndef BITCOIN_INIT_H
#define BITCOIN_INIT_H
-#include "wallet.h"
+#include <string>
+#include <boost/thread.hpp>
+
+class CWallet;
extern std::string strWalletFile;
extern CWallet* pwalletMain;
diff --git a/src/key.h b/src/key.h
index ac050356f2..bbe64d6685 100644
--- a/src/key.h
+++ b/src/key.h
@@ -205,7 +205,8 @@ public:
}
friend bool operator==(const CKey &a, const CKey &b) {
- return a.fCompressed == b.fCompressed && memcmp(&a.vch[0], &b.vch[0], 32);
+ return a.fCompressed == b.fCompressed && a.size() == b.size() &&
+ memcmp(&a.vch[0], &b.vch[0], a.size()) == 0;
}
// Initialize using begin and end iterators to byte data.
@@ -261,9 +262,9 @@ public:
// Derive BIP32 child key.
bool Derive(CKey& keyChild, unsigned char ccChild[32], unsigned int nChild, const unsigned char cc[32]) const;
-
+
// Load private key and check that public key matches.
- bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck);
+ bool Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck);
};
struct CExtPubKey {
diff --git a/src/main.cpp b/src/main.cpp
index 6ffbc5a44e..3d339b4fdd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -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);
- }
-}
-
-void UnregisterAllWallets()
-{
- LOCK(cs_setpwalletRegistered);
- setpwalletRegistered.clear();
+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;
}
-// 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;
-}
-
-// 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 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));
}
-// 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);
+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));
}
-// notify wallets about an updated transaction
-void static UpdatedTransaction(const uint256& hashTx)
-{
- LOCK(cs_setpwalletRegistered);
- BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
- pwallet->UpdatedTransaction(hashTx);
+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();
}
-// 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);
}
}
@@ -3593,7 +3529,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
}
// Track requests for our stuff
- Inventory(inv.hash);
+ g_signals.Inventory(inv.hash);
}
}
@@ -3783,7 +3719,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))
@@ -4215,7 +4151,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
// transactions become unconfirmed and spams other nodes.
if (!fReindex && !fImporting && !IsInitialBlockDownload())
{
- ResendWalletTransactions();
+ g_signals.Broadcast();
}
//
@@ -4243,15 +4179,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);
diff --git a/src/main.h b/src/main.h
index 76de47071e..b56a4a5e19 100644
--- a/src/main.h
+++ b/src/main.h
@@ -17,7 +17,6 @@
#include <list>
-class CWallet;
class CBlock;
class CBlockIndex;
class CKeyItem;
@@ -81,8 +80,6 @@ extern uint64 nLastBlockTx;
extern uint64 nLastBlockSize;
extern const std::string strMessageMagic;
extern int64 nTimeBestReceived;
-extern CCriticalSection cs_setpwalletRegistered;
-extern std::set<CWallet*> setpwalletRegistered;
extern bool fImporting;
extern bool fReindex;
extern bool fBenchmark;
@@ -108,17 +105,18 @@ class CCoinsView;
class CCoinsViewCache;
class CScriptCheck;
class CValidationState;
+class CWalletInterface;
struct CBlockTemplate;
/** Register a wallet to receive updates from core */
-void RegisterWallet(CWallet* pwalletIn);
+void RegisterWallet(CWalletInterface* pwalletIn);
/** Unregister a wallet from core */
-void UnregisterWallet(CWallet* pwalletIn);
+void UnregisterWallet(CWalletInterface* pwalletIn);
/** Unregister all wallets from core */
void UnregisterAllWallets();
/** Push an updated transaction to all registered wallets */
-void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false);
+void SyncWithWallets(const uint256 &hash, const CTransaction& tx, const CBlock* pblock = NULL);
/** Register with a network node to receive its signals */
void RegisterNodeSignals(CNodeSignals& nodeSignals);
@@ -190,9 +188,6 @@ bool AbortNode(const std::string &msg);
-
-bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
-
struct CDiskBlockPos
{
int nFile;
@@ -946,13 +941,15 @@ private:
MODE_ERROR, // run-time error
} mode;
int nDoS;
+ bool corruptionPossible;
public:
CValidationState() : mode(MODE_VALID), nDoS(0) {}
- bool DoS(int level, bool ret = false) {
+ bool DoS(int level, bool ret = false, bool corruptionIn = false) {
if (mode == MODE_ERROR)
return ret;
nDoS += level;
mode = MODE_INVALID;
+ corruptionPossible = corruptionIn;
return ret;
}
bool Invalid(bool ret = false) {
@@ -982,6 +979,9 @@ public:
}
return false;
}
+ bool CorruptionPossible() {
+ return corruptionPossible;
+ }
};
/** An in-memory indexed chain of blocks. */
@@ -1256,4 +1256,18 @@ public:
)
};
+
+class CWalletInterface {
+protected:
+ virtual void SyncTransaction(const uint256 &hash, const CTransaction &tx, const CBlock *pblock) =0;
+ virtual void EraseFromWallet(const uint256 &hash) =0;
+ virtual void SetBestChain(const CBlockLocator &locator) =0;
+ virtual void UpdatedTransaction(const uint256 &hash) =0;
+ virtual void Inventory(const uint256 &hash) =0;
+ virtual void ResendWalletTransactions() =0;
+ friend void ::RegisterWallet(CWalletInterface*);
+ friend void ::UnregisterWallet(CWalletInterface*);
+ friend void ::UnregisterAllWallets();
+};
+
#endif
diff --git a/src/net.cpp b/src/net.cpp
index d223b3999e..de8543da59 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1894,3 +1894,38 @@ uint64 CNode::GetTotalBytesSent()
LOCK(cs_totalBytesSent);
return nTotalBytesSent;
}
+
+void CNode::Fuzz(int nChance)
+{
+ if (!fSuccessfullyConnected) return; // Don't fuzz initial handshake
+ if (GetRand(nChance) != 0) return; // Fuzz 1 of every nChance messages
+
+ switch (GetRand(3))
+ {
+ case 0:
+ // xor a random byte with a random value:
+ if (!ssSend.empty()) {
+ CDataStream::size_type pos = GetRand(ssSend.size());
+ ssSend[pos] ^= (unsigned char)(GetRand(256));
+ }
+ break;
+ case 1:
+ // delete a random byte:
+ if (!ssSend.empty()) {
+ CDataStream::size_type pos = GetRand(ssSend.size());
+ ssSend.erase(ssSend.begin()+pos);
+ }
+ break;
+ case 2:
+ // insert a random byte at a random position
+ {
+ CDataStream::size_type pos = GetRand(ssSend.size());
+ char ch = (char)GetRand(256);
+ ssSend.insert(ssSend.begin()+pos, ch);
+ }
+ break;
+ }
+ // Chance of more than one change half the time:
+ // (more changes exponentially less likely):
+ Fuzz(2);
+}
diff --git a/src/net.h b/src/net.h
index a1dc19df34..b32178ad41 100644
--- a/src/net.h
+++ b/src/net.h
@@ -218,6 +218,9 @@ protected:
static CCriticalSection cs_setBanned;
int nMisbehavior;
+ // Basic fuzz-testing
+ void Fuzz(int nChance); // modifies ssSend
+
public:
uint256 hashContinue;
CBlockIndex* pindexLastGetBlocksBegin;
@@ -434,12 +437,17 @@ public:
// TODO: Document the precondition of this function. Is cs_vSend locked?
void EndMessage() UNLOCK_FUNCTION(cs_vSend)
{
- if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
+ // The -*messagestest options are intentionally not documented in the help message,
+ // since they are only used during development to debug the networking code and are
+ // not intended for end-users.
+ if (mapArgs.count("-dropmessagestest") && GetRand(GetArg("-dropmessagestest", 2)) == 0)
{
LogPrint("net", "dropmessages DROPPING SEND MESSAGE\n");
AbortMessage();
return;
}
+ if (mapArgs.count("-fuzzmessagestest"))
+ Fuzz(GetArg("-fuzzmessagestest", 10));
if (ssSend.size() == 0)
return;
diff --git a/src/qt/forms/receivecoinsdialog.ui b/src/qt/forms/receivecoinsdialog.ui
index dbb19cff4d..6d1a72ecd2 100644
--- a/src/qt/forms/receivecoinsdialog.ui
+++ b/src/qt/forms/receivecoinsdialog.ui
@@ -12,15 +12,15 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <layout class="QFormLayout" name="formLayout">
- <property name="fieldGrowthPolicy">
- <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
- </property>
+ <layout class="QGridLayout" name="gridLayout">
<item row="3" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>&amp;Amount:</string>
</property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
<property name="buddy">
<cstring>reqAmount</cstring>
</property>
@@ -44,6 +44,9 @@
<property name="text">
<string>&amp;Label:</string>
</property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
<property name="buddy">
<cstring>reqLabel</cstring>
</property>
@@ -61,6 +64,9 @@
<property name="text">
<string>&amp;Message:</string>
</property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
<property name="buddy">
<cstring>reqMessage</cstring>
</property>
@@ -100,6 +106,19 @@
</layout>
</item>
<item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="clearButton">
diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp
index 95efc58320..4db048dcce 100644
--- a/src/qt/optionsmodel.cpp
+++ b/src/qt/optionsmodel.cpp
@@ -6,6 +6,9 @@
#include "bitcoinunits.h"
#include "init.h"
+#include "core.h"
+#include "wallet.h"
+#include "netbase.h"
#include "walletdb.h"
#include "guiutil.h"
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index 3589b45900..a5f7a542de 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -6,6 +6,7 @@
#include <fstream>
#include "init.h" // for pwalletMain
+#include "wallet.h"
#include "bitcoinrpc.h"
#include "ui_interface.h"
#include "base58.h"
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index d5bd39cb4d..4d1381bc20 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -560,7 +560,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(hashTx, tx, NULL, true);
+ SyncWithWallets(hashTx, tx, NULL);
}
RelayTransaction(tx, hashTx);
diff --git a/src/serialize.h b/src/serialize.h
index 4d9aec3426..115ea1d447 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -901,19 +901,6 @@ public:
iterator insert(iterator it, const char& x=char()) { return vch.insert(it, x); }
void insert(iterator it, size_type n, const char& x) { vch.insert(it, n, x); }
- void insert(iterator it, const_iterator first, const_iterator last)
- {
- assert(last - first >= 0);
- if (it == vch.begin() + nReadPos && (unsigned int)(last - first) <= nReadPos)
- {
- // special case for inserting at the front when there's room
- nReadPos -= (last - first);
- memcpy(&vch[nReadPos], &first[0], last - first);
- }
- else
- vch.insert(it, first, last);
- }
-
void insert(iterator it, std::vector<char>::const_iterator first, std::vector<char>::const_iterator last)
{
assert(last - first >= 0);
@@ -1104,8 +1091,8 @@ public:
}
void GetAndClear(CSerializeData &data) {
- vch.swap(data);
- CSerializeData().swap(vch);
+ data.insert(data.end(), begin(), end());
+ clear();
}
};
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 50139df09e..7e193c88ce 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -102,4 +102,52 @@ BOOST_AUTO_TEST_CASE(noncanonical)
BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
}
+BOOST_AUTO_TEST_CASE(insert_delete)
+{
+ // Test inserting/deleting bytes.
+ CDataStream ss(SER_DISK, 0);
+ BOOST_CHECK_EQUAL(ss.size(), 0);
+
+ ss.write("\x00\x01\x02\xff", 4);
+ BOOST_CHECK_EQUAL(ss.size(), 4);
+
+ char c = (char)11;
+
+ // Inserting at beginning/end/middle:
+ ss.insert(ss.begin(), c);
+ BOOST_CHECK_EQUAL(ss.size(), 5);
+ BOOST_CHECK_EQUAL(ss[0], c);
+ BOOST_CHECK_EQUAL(ss[1], 0);
+
+ ss.insert(ss.end(), c);
+ BOOST_CHECK_EQUAL(ss.size(), 6);
+ BOOST_CHECK_EQUAL(ss[4], (char)0xff);
+ BOOST_CHECK_EQUAL(ss[5], c);
+
+ ss.insert(ss.begin()+2, c);
+ BOOST_CHECK_EQUAL(ss.size(), 7);
+ BOOST_CHECK_EQUAL(ss[2], c);
+
+ // Delete at beginning/end/middle
+ ss.erase(ss.begin());
+ BOOST_CHECK_EQUAL(ss.size(), 6);
+ BOOST_CHECK_EQUAL(ss[0], 0);
+
+ ss.erase(ss.begin()+ss.size()-1);
+ BOOST_CHECK_EQUAL(ss.size(), 5);
+ BOOST_CHECK_EQUAL(ss[4], (char)0xff);
+
+ ss.erase(ss.begin()+1);
+ BOOST_CHECK_EQUAL(ss.size(), 4);
+ BOOST_CHECK_EQUAL(ss[0], 0);
+ BOOST_CHECK_EQUAL(ss[1], 1);
+ BOOST_CHECK_EQUAL(ss[2], 2);
+ BOOST_CHECK_EQUAL(ss[3], (char)0xff);
+
+ // Make sure GetAndClear does the right thing:
+ CSerializeData d;
+ ss.GetAndClear(d);
+ BOOST_CHECK_EQUAL(ss.size(), 0);
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet.cpp b/src/wallet.cpp
index a7a2992bb9..ea1e01e6e9 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -505,7 +505,7 @@ 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 uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
+bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate)
{
{
LOCK(cs_wallet);
@@ -525,16 +525,20 @@ bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction&
return false;
}
-bool CWallet::EraseFromWallet(uint256 hash)
+void CWallet::SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock) {
+ AddToWalletIfInvolvingMe(hash, tx, pblock, true);
+}
+
+void CWallet::EraseFromWallet(const uint256 &hash)
{
if (!fFileBacked)
- return false;
+ return;
{
LOCK(cs_wallet);
if (mapWallet.erase(hash))
CWalletDB(strWalletFile).EraseTx(hash);
}
- return true;
+ return;
}
@@ -773,6 +777,25 @@ void CWalletTx::AddSupportingTransactions()
reverse(vtxPrev.begin(), vtxPrev.end());
}
+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;
+}
+
bool CWalletTx::WriteToDisk()
{
return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
@@ -1485,33 +1508,6 @@ bool CWallet::DelAddressBook(const CTxDestination& address)
return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
}
-void CWallet::PrintWallet(const CBlock& block)
-{
- {
- LOCK(cs_wallet);
- if (mapWallet.count(block.vtx[0].GetHash()))
- {
- CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
- LogPrintf(" mine: %d %d %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
- }
- }
- LogPrintf("\n");
-}
-
-bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
-{
- {
- LOCK(cs_wallet);
- map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
- if (mi != mapWallet.end())
- {
- wtx = (*mi).second;
- return true;
- }
- }
- return false;
-}
-
bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
{
if (fFileBacked)
@@ -1523,14 +1519,6 @@ bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
return true;
}
-bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
-{
- if (!pwallet->fFileBacked)
- return false;
- strWalletFileOut = pwallet->strWalletFile;
- return true;
-}
-
//
// Mark old keypool keys as used,
// and generate all new keys
diff --git a/src/wallet.h b/src/wallet.h
index f87e9b08c4..21510f8c39 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -80,7 +80,7 @@ public:
/** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
* and provides the ability to create new transactions.
*/
-class CWallet : public CCryptoKeyStore
+class CWallet : public CCryptoKeyStore, public CWalletInterface
{
private:
bool SelectCoins(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
@@ -197,8 +197,9 @@ public:
void MarkDirty();
bool AddToWallet(const CWalletTx& wtxIn);
- bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
- bool EraseFromWallet(uint256 hash);
+ void SyncTransaction(const uint256 &hash, const CTransaction& tx, const CBlock* pblock);
+ bool AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate);
+ void EraseFromWallet(const uint256 &hash);
void WalletUpdateSpent(const CTransaction& prevout);
int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
void ReacceptWalletTransactions();
@@ -302,8 +303,6 @@ public:
void UpdatedTransaction(const uint256 &hashTx);
- void PrintWallet(const CBlock& block);
-
void Inventory(const uint256 &hash)
{
{
@@ -319,8 +318,6 @@ public:
return setKeyPool.size();
}
- bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
-
bool SetDefaultKey(const CPubKey &vchPubKey);
// signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
@@ -891,6 +888,4 @@ private:
std::vector<char> _ssExtra;
};
-bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
-
#endif