aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/alert.h2
-rw-r--r--src/allocators.cpp3
-rw-r--r--src/allocators.h45
-rw-r--r--src/base58.h2
-rw-r--r--src/bignum.h2
-rw-r--r--src/bitcoind.cpp2
-rw-r--r--src/bitcoinrpc.cpp2
-rw-r--r--src/bitcoinrpc.h2
-rw-r--r--src/chainparams.cpp2
-rw-r--r--src/checkpoints.cpp2
-rw-r--r--src/checkpoints.h2
-rw-r--r--src/compat.h2
-rw-r--r--src/core.h34
-rw-r--r--src/crypter.cpp2
-rw-r--r--src/crypter.h10
-rw-r--r--src/db.cpp2
-rw-r--r--src/db.h4
-rw-r--r--src/hash.h2
-rw-r--r--src/init.cpp27
-rw-r--r--src/init.h2
-rw-r--r--src/key.cpp25
-rw-r--r--src/key.h3
-rw-r--r--src/keystore.cpp2
-rw-r--r--src/keystore.h2
-rw-r--r--src/main.cpp141
-rw-r--r--src/main.h61
-rw-r--r--src/miner.cpp18
-rw-r--r--src/miner.h2
-rw-r--r--src/net.cpp2
-rw-r--r--src/net.h2
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/netbase.h2
-rw-r--r--src/noui.cpp2
-rw-r--r--src/protocol.cpp2
-rw-r--r--src/protocol.h2
-rw-r--r--src/qt/Makefile.am6
-rw-r--r--src/qt/bitcoin.cpp4
-rw-r--r--src/qt/bitcoinamountfield.cpp5
-rw-r--r--src/qt/bitcoingui.cpp5
-rw-r--r--src/qt/bitcoingui.h8
-rw-r--r--src/qt/clientmodel.cpp4
-rw-r--r--src/qt/forms/sendcoinsentry.ui8
-rw-r--r--src/qt/paymentserver.cpp54
-rw-r--r--src/qt/paymentserver.h4
-rw-r--r--src/qt/sendcoinsentry.cpp24
-rw-r--r--src/qt/sendcoinsentry.h2
-rw-r--r--src/qt/walletframe.cpp117
-rw-r--r--src/qt/walletframe.h16
-rw-r--r--src/qt/walletmodel.cpp32
-rw-r--r--src/qt/walletstack.cpp174
-rw-r--r--src/qt/walletstack.h104
-rw-r--r--src/qt/walletview.cpp35
-rw-r--r--src/qt/walletview.h3
-rw-r--r--src/rpcblockchain.cpp2
-rw-r--r--src/rpcdump.cpp2
-rw-r--r--src/rpcmining.cpp2
-rw-r--r--src/rpcnet.cpp2
-rw-r--r--src/rpcrawtransaction.cpp2
-rw-r--r--src/rpcwallet.cpp6
-rw-r--r--src/script.cpp148
-rw-r--r--src/script.h2
-rw-r--r--src/serialize.h8
-rw-r--r--src/sync.cpp4
-rw-r--r--src/sync.h2
-rw-r--r--src/test/Makefile.am2
-rw-r--r--src/test/multisig_tests.cpp2
-rw-r--r--src/test/script_tests.cpp2
-rw-r--r--src/test/serialize_tests.cpp60
-rw-r--r--src/test/sighash_tests.cpp120
-rw-r--r--src/txdb.cpp2
-rw-r--r--src/txdb.h2
-rw-r--r--src/uint256.h2
-rw-r--r--src/util.cpp4
-rw-r--r--src/util.h2
-rw-r--r--src/wallet.cpp19
-rw-r--r--src/wallet.h2
-rw-r--r--src/walletdb.cpp40
-rw-r--r--src/walletdb.h12
78 files changed, 793 insertions, 682 deletions
diff --git a/src/alert.h b/src/alert.h
index 25e140f573..e4841f9c3f 100644
--- a/src/alert.h
+++ b/src/alert.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/allocators.cpp b/src/allocators.cpp
index b239b623d8..15f34aa2c8 100644
--- a/src/allocators.cpp
+++ b/src/allocators.cpp
@@ -24,6 +24,9 @@
#include <unistd.h> // for sysconf
#endif
+LockedPageManager* LockedPageManager::_instance = NULL;
+boost::once_flag LockedPageManager::init_flag = BOOST_ONCE_INIT;
+
/** Determine system page size in bytes */
static inline size_t GetSystemPageSize()
{
diff --git a/src/allocators.h b/src/allocators.h
index fd6f51b27e..a806780ad3 100644
--- a/src/allocators.h
+++ b/src/allocators.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_ALLOCATORS_H
@@ -8,6 +8,7 @@
#include <string.h>
#include <string>
#include <boost/thread/mutex.hpp>
+#include <boost/thread/once.hpp>
#include <map>
#include <openssl/crypto.h> // for OPENSSL_cleanse()
@@ -34,6 +35,12 @@ public:
page_mask = ~(page_size - 1);
}
+ ~LockedPageManagerBase()
+ {
+ assert(this->GetLockedPageCount() == 0);
+ }
+
+
// For all pages in affected range, increase lock count
void LockRange(void *p, size_t size)
{
@@ -117,13 +124,39 @@ public:
/**
* Singleton class to keep track of locked (ie, non-swappable) memory pages, for use in
* std::allocator templates.
+ *
+ * Some implementations of the STL allocate memory in some constructors (i.e., see
+ * MSVC's vector<T> implementation where it allocates 1 byte of memory in the allocator.)
+ * Due to the unpredictable order of static initializers, we have to make sure the
+ * LockedPageManager instance exists before any other STL-based objects that use
+ * secure_allocator are created. So instead of having LockedPageManager also be
+ * static-intialized, it is created on demand.
*/
class LockedPageManager: public LockedPageManagerBase<MemoryPageLocker>
{
public:
- static LockedPageManager instance; // instantiated in util.cpp
+ static LockedPageManager& Instance()
+ {
+ boost::call_once(LockedPageManager::CreateInstance, LockedPageManager::init_flag);
+ return *LockedPageManager::_instance;
+ }
+
private:
LockedPageManager();
+
+ static void CreateInstance()
+ {
+ // Using a local static instance guarantees that the object is initialized
+ // when it's first needed and also deinitialized after all objects that use
+ // it are done with it. I can think of one unlikely scenario where we may
+ // have a static deinitialization order/problem, but the check in
+ // LockedPageManagerBase's destructor helps us detect if that ever happens.
+ static LockedPageManager instance;
+ LockedPageManager::_instance = &instance;
+ }
+
+ static LockedPageManager* _instance;
+ static boost::once_flag init_flag;
};
//
@@ -131,12 +164,12 @@ private:
// Intended for non-dynamically allocated structures.
//
template<typename T> void LockObject(const T &t) {
- LockedPageManager::instance.LockRange((void*)(&t), sizeof(T));
+ LockedPageManager::Instance().LockRange((void*)(&t), sizeof(T));
}
template<typename T> void UnlockObject(const T &t) {
OPENSSL_cleanse((void*)(&t), sizeof(T));
- LockedPageManager::instance.UnlockRange((void*)(&t), sizeof(T));
+ LockedPageManager::Instance().UnlockRange((void*)(&t), sizeof(T));
}
//
@@ -168,7 +201,7 @@ struct secure_allocator : public std::allocator<T>
T *p;
p = std::allocator<T>::allocate(n, hint);
if (p != NULL)
- LockedPageManager::instance.LockRange(p, sizeof(T) * n);
+ LockedPageManager::Instance().LockRange(p, sizeof(T) * n);
return p;
}
@@ -177,7 +210,7 @@ struct secure_allocator : public std::allocator<T>
if (p != NULL)
{
OPENSSL_cleanse(p, sizeof(T) * n);
- LockedPageManager::instance.UnlockRange(p, sizeof(T) * n);
+ LockedPageManager::Instance().UnlockRange(p, sizeof(T) * n);
}
std::allocator<T>::deallocate(p, n);
}
diff --git a/src/base58.h b/src/base58.h
index aabae8de88..44bf5281e1 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin Developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bignum.h b/src/bignum.h
index 0881807d70..582e6f1517 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_BIGNUM_H
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index add3b4e1f0..1b40a868a1 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 798660dff3..29935d8f6c 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
index 1cad12f14a..275369ddd2 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index 0795f09765..82f41bcc50 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index bb551501f1..76ae911a5c 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/checkpoints.h b/src/checkpoints.h
index a49a908a38..4afd29326b 100644
--- a/src/checkpoints.h
+++ b/src/checkpoints.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_CHECKPOINT_H
diff --git a/src/compat.h b/src/compat.h
index b126df901a..c910f01cb4 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef _BITCOIN_COMPAT_H
diff --git a/src/core.h b/src/core.h
index ce21acd59e..9ee8b2edce 100644
--- a/src/core.h
+++ b/src/core.h
@@ -661,4 +661,38 @@ public:
void print() const;
};
+
+/** Describes a place in the block chain to another node such that if the
+ * other node doesn't have the same branch, it can find a recent common trunk.
+ * The further back it is, the further before the fork it may be.
+ */
+struct CBlockLocator
+{
+ std::vector<uint256> vHave;
+
+ CBlockLocator() {}
+
+ CBlockLocator(const std::vector<uint256>& vHaveIn)
+ {
+ vHave = vHaveIn;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ if (!(nType & SER_GETHASH))
+ READWRITE(nVersion);
+ READWRITE(vHave);
+ )
+
+ void SetNull()
+ {
+ vHave.clear();
+ }
+
+ bool IsNull()
+ {
+ return vHave.empty();
+ }
+};
+
#endif
diff --git a/src/crypter.cpp b/src/crypter.cpp
index 754de536a9..f3b9396dae 100644
--- a/src/crypter.cpp
+++ b/src/crypter.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 The Bitcoin Developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/crypter.h b/src/crypter.h
index 4134c1b49b..22187791e9 100644
--- a/src/crypter.h
+++ b/src/crypter.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 The Bitcoin Developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef __CRYPTER_H__
@@ -88,16 +88,16 @@ public:
// Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
// Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
// Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
- LockedPageManager::instance.LockRange(&chKey[0], sizeof chKey);
- LockedPageManager::instance.LockRange(&chIV[0], sizeof chIV);
+ LockedPageManager::Instance().LockRange(&chKey[0], sizeof chKey);
+ LockedPageManager::Instance().LockRange(&chIV[0], sizeof chIV);
}
~CCrypter()
{
CleanKey();
- LockedPageManager::instance.UnlockRange(&chKey[0], sizeof chKey);
- LockedPageManager::instance.UnlockRange(&chIV[0], sizeof chIV);
+ LockedPageManager::Instance().UnlockRange(&chKey[0], sizeof chKey);
+ LockedPageManager::Instance().UnlockRange(&chIV[0], sizeof chIV);
}
};
diff --git a/src/db.cpp b/src/db.cpp
index f722c52e93..7e58ff45fb 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/db.h b/src/db.h
index b3f269f3da..695e74ef2a 100644
--- a/src/db.h
+++ b/src/db.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_DB_H
@@ -16,7 +16,7 @@
#include <db_cxx.h>
class CAddrMan;
-class CBlockLocator;
+struct CBlockLocator;
class CDiskBlockIndex;
class CMasterKey;
class COutPoint;
diff --git a/src/hash.h b/src/hash.h
index 880468a2d2..ff7d57399a 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_HASH_H
diff --git a/src/init.cpp b/src/init.cpp
index dcd65198c3..2ac610b333 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -116,7 +116,7 @@ void Shutdown()
{
LOCK(cs_main);
if (pwalletMain)
- pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
if (pblocktree)
pblocktree->Flush();
if (pcoinsTip)
@@ -185,7 +185,7 @@ std::string HelpMessage()
strUsage += " -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n";
strUsage += " -proxy=<ip:port> " + _("Connect through socks proxy") + "\n";
strUsage += " -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n";
- strUsage += " -tor=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n";
+ strUsage += " -onion=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n";
strUsage += " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n";
strUsage += " -port=<port> " + _("Listen for connections on <port> (default: 8333 or testnet: 18333)") + "\n";
strUsage += " -maxconnections=<n> " + _("Maintain at most <n> connections to peers (default: 125)") + "\n";
@@ -642,15 +642,20 @@ bool AppInit2(boost::thread_group& threadGroup)
fProxy = true;
}
- // -tor can override normal proxy, -notor disables tor entirely
- if (!(mapArgs.count("-tor") && mapArgs["-tor"] == "0") && (fProxy || mapArgs.count("-tor"))) {
+ // -onion can override normal proxy, -noonion disables tor entirely
+ // -tor here is a temporary backwards compatibility measure
+ if (mapArgs.count("-tor"))
+ printf("Notice: option -tor has been replaced with -onion and will be removed in a later version.\n");
+ if (!(mapArgs.count("-onion") && mapArgs["-onion"] == "0") &&
+ !(mapArgs.count("-tor") && mapArgs["-tor"] == "0") &&
+ (fProxy || mapArgs.count("-onion") || mapArgs.count("-tor"))) {
CService addrOnion;
- if (!mapArgs.count("-tor"))
+ if (!mapArgs.count("-onion") && !mapArgs.count("-tor"))
addrOnion = addrProxy;
else
- addrOnion = CService(mapArgs["-tor"], 9050);
+ addrOnion = mapArgs.count("-onion")?CService(mapArgs["-onion"], 9050):CService(mapArgs["-tor"], 9050);
if (!addrOnion.IsValid())
- return InitError(strprintf(_("Invalid -tor address: '%s'"), mapArgs["-tor"].c_str()));
+ return InitError(strprintf(_("Invalid -onion address: '%s'"), mapArgs.count("-onion")?mapArgs["-onion"].c_str():mapArgs["-tor"].c_str()));
SetProxy(NET_TOR, addrOnion, 5);
SetReachable(NET_TOR);
}
@@ -912,7 +917,7 @@ bool AppInit2(boost::thread_group& threadGroup)
strErrors << _("Cannot write default address") << "\n";
}
- pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
}
LogPrintf("%s", strErrors.str().c_str());
@@ -928,7 +933,7 @@ bool AppInit2(boost::thread_group& threadGroup)
CWalletDB walletdb(strWalletFile);
CBlockLocator locator;
if (walletdb.ReadBestBlock(locator))
- pindexRescan = locator.GetBlockIndex();
+ pindexRescan = chainActive.FindFork(locator);
else
pindexRescan = chainActive.Genesis();
}
@@ -939,7 +944,7 @@ bool AppInit2(boost::thread_group& threadGroup)
nStart = GetTimeMillis();
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
LogPrintf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
- pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
+ pwalletMain->SetBestChain(chainActive.GetLocator());
nWalletDBUpdated++;
}
diff --git a/src/init.h b/src/init.h
index a4d5a67252..e5a2a69293 100644
--- a/src/init.h
+++ b/src/init.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_INIT_H
diff --git a/src/key.cpp b/src/key.cpp
index 8ef1c414c4..996539dca5 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -166,9 +166,12 @@ public:
assert(nSize == nSize2);
}
- bool SetPrivKey(const CPrivKey &privkey) {
+ bool SetPrivKey(const CPrivKey &privkey, bool fSkipCheck=false) {
const unsigned char* pbegin = &privkey[0];
if (d2i_ECPrivateKey(&pkey, &pbegin, privkey.size())) {
+ if(fSkipCheck)
+ return true;
+
// d2i_ECPrivateKey returns true if parsing succeeds.
// This doesn't necessarily mean the key is valid.
if (EC_KEY_check_key(pkey))
@@ -411,6 +414,24 @@ bool CKey::SignCompact(const uint256 &hash, std::vector<unsigned char>& vchSig)
return true;
}
+bool CKey::Load(CPrivKey &privkey, CPubKey &vchPubKey, bool fSkipCheck=false) {
+ CECKey key;
+ if (!key.SetPrivKey(privkey, fSkipCheck))
+ return false;
+
+ key.GetSecretBytes(vch);
+ fCompressed = vchPubKey.IsCompressed();
+ fValid = true;
+
+ if (fSkipCheck)
+ return true;
+
+ if (GetPubKey() != vchPubKey)
+ return false;
+
+ return true;
+}
+
bool CPubKey::Verify(const uint256 &hash, const std::vector<unsigned char>& vchSig) const {
if (!IsValid())
return false;
diff --git a/src/key.h b/src/key.h
index 75431e944f..ac050356f2 100644
--- a/src/key.h
+++ b/src/key.h
@@ -261,6 +261,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);
};
struct CExtPubKey {
diff --git a/src/keystore.cpp b/src/keystore.cpp
index 808f8c24ef..301180737f 100644
--- a/src/keystore.cpp
+++ b/src/keystore.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/keystore.h b/src/keystore.h
index 49a7bf569d..4f28fba91b 100644
--- a/src/keystore.h
+++ b/src/keystore.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_KEYSTORE_H
diff --git a/src/main.cpp b/src/main.cpp
index f2e6b67f8a..a5a0f031af 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -190,105 +190,61 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals)
//////////////////////////////////////////////////////////////////////////////
//
-// CBlockLocator implementation
+// CChain implementation
//
-CBlockLocator::CBlockLocator(uint256 hashBlock)
-{
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- Set((*mi).second);
+CBlockIndex *CChain::SetTip(CBlockIndex *pindex) {
+ if (pindex == NULL) {
+ vChain.clear();
+ return NULL;
+ }
+ vChain.resize(pindex->nHeight + 1);
+ while (pindex && vChain[pindex->nHeight] != pindex) {
+ vChain[pindex->nHeight] = pindex;
+ pindex = pindex->pprev;
+ }
+ return pindex;
}
-void CBlockLocator::Set(const CBlockIndex* pindex)
-{
- vHave.clear();
+CBlockLocator CChain::GetLocator(const CBlockIndex *pindex) const {
int nStep = 1;
- while (pindex)
- {
- vHave.push_back(pindex->GetBlockHash());
+ std::vector<uint256> vHave;
+ vHave.reserve(32);
- // Exponentially larger steps back
- for (int i = 0; pindex && i < nStep; i++)
+ if (!pindex)
+ pindex = Tip();
+ while (pindex) {
+ vHave.push_back(pindex->GetBlockHash());
+ // Stop when we have added the genesis block.
+ if (pindex->nHeight == 0)
+ break;
+ // Exponentially larger steps back, plus the genesis block.
+ int nHeight = std::max(pindex->nHeight - nStep, 0);
+ // In case pindex is not in this chain, iterate pindex->pprev to find blocks.
+ while (pindex->nHeight > nHeight && !Contains(pindex))
pindex = pindex->pprev;
+ // If pindex is in this chain, use direct height-based access.
+ if (pindex->nHeight > nHeight)
+ pindex = (*this)[nHeight];
if (vHave.size() > 10)
nStep *= 2;
}
- vHave.push_back(Params().HashGenesisBlock());
-}
-int CBlockLocator::GetDistanceBack()
-{
- // Retrace how far back it was in the sender's branch
- int nDistance = 0;
- int nStep = 1;
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (chainActive.Contains(pindex))
- return nDistance;
- }
- nDistance += nStep;
- if (nDistance > 10)
- nStep *= 2;
- }
- return nDistance;
+ return CBlockLocator(vHave);
}
-CBlockIndex *CBlockLocator::GetBlockIndex()
-{
+CBlockIndex *CChain::FindFork(const CBlockLocator &locator) const {
// Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
+ BOOST_FOREACH(const uint256& hash, locator.vHave) {
std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
if (mi != mapBlockIndex.end())
{
CBlockIndex* pindex = (*mi).second;
- if (chainActive.Contains(pindex))
+ if (Contains(pindex))
return pindex;
}
}
- return chainActive.Genesis();
-}
-
-uint256 CBlockLocator::GetBlockHash()
-{
- // Find the first block the caller has in the main chain
- BOOST_FOREACH(const uint256& hash, vHave)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
- if (mi != mapBlockIndex.end())
- {
- CBlockIndex* pindex = (*mi).second;
- if (chainActive.Contains(pindex))
- return hash;
- }
- }
- return Params().HashGenesisBlock();
-}
-
-int CBlockLocator::GetHeight()
-{
- CBlockIndex* pindex = GetBlockIndex();
- if (!pindex)
- return 0;
- return pindex->nHeight;
-}
-
-CBlockIndex *CChain::SetTip(CBlockIndex *pindex) {
- if (pindex == NULL) {
- std::vector<CBlockIndex*>().swap(vChain);
- return NULL;
- }
- vChain.resize(pindex->nHeight + 1);
- while (pindex && vChain[pindex->nHeight] != pindex) {
- vChain[pindex->nHeight] = pindex;
- pindex = pindex->pprev;
- }
- return pindex;
+ return Genesis();
}
//////////////////////////////////////////////////////////////////////////////
@@ -766,15 +722,18 @@ int64 GetMinFee(const CTransaction& tx, bool fAllowFree, enum GetMinFee_mode mod
{
// There is a free transaction area in blocks created by most miners,
// * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000
- // to be considered to fall into this category
- // * If we are creating a transaction we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 17000
- // (= 10000) to be considered safe and assume they can likely make it into this section
- if (nBytes < (mode == GMF_SEND ? (DEFAULT_BLOCK_PRIORITY_SIZE - 17000) : (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)))
+ // to be considered to fall into this category. We don't want to encourage sending
+ // multiple transactions instead of one big transaction to avoid fees.
+ // * If we are creating a transaction we allow transactions up to 1,000 bytes
+ // to be considered safe and assume they can likely make it into this section.
+ if (nBytes < (mode == GMF_SEND ? 1000 : (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)))
nMinFee = 0;
}
- // To limit dust spam, require base fee if any output is less than 0.01
- if (nMinFee < nBaseFee)
+ // This code can be removed after enough miners have upgraded to version 0.9.
+ // Until then, be safe when sending and require a fee if any output
+ // is less than CENT:
+ if (nMinFee < nBaseFee && mode == GMF_SEND)
{
BOOST_FOREACH(const CTxOut& txout, tx.vout)
if (txout.nValue < CENT)
@@ -2156,10 +2115,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))
- {
- const CBlockLocator locator(pindexNew);
- ::SetBestChain(locator);
- }
+ ::SetBestChain(chainActive.GetLocator(pindexNew));
// New best block
nTimeBestReceived = GetTime();
@@ -2525,7 +2481,7 @@ void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
pnode->pindexLastGetBlocksBegin = pindexBegin;
pnode->hashLastGetBlocksEnd = hashEnd;
- pnode->PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
+ pnode->PushMessage("getblocks", chainActive.GetLocator(pindexBegin), hashEnd);
}
bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp)
@@ -3661,7 +3617,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
LOCK(cs_main);
// Find the last block the caller has in the main chain
- CBlockIndex* pindex = locator.GetBlockIndex();
+ CBlockIndex* pindex = chainActive.FindFork(locator);
// Send the rest of the chain
if (pindex)
@@ -3708,7 +3664,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
else
{
// Find the last block the caller has in the main chain
- pindex = locator.GetBlockIndex();
+ pindex = chainActive.FindFork(locator);
if (pindex)
pindex = chainActive.Next(pindex);
}
@@ -3731,7 +3687,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
vector<uint256> vWorkQueue;
vector<uint256> vEraseQueue;
- CDataStream vMsg(vRecv);
CTransaction tx;
vRecv >> tx;
diff --git a/src/main.h b/src/main.h
index 46d629044a..76de47071e 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MAIN_H
@@ -1033,6 +1033,12 @@ public:
/** Set/initialize a chain with a given tip. Returns the forking point. */
CBlockIndex *SetTip(CBlockIndex *pindex);
+
+ /** Return a CBlockLocator that refers to a block in this chain (by default the tip). */
+ CBlockLocator GetLocator(const CBlockIndex *pindex = NULL) const;
+
+ /** Find the last common block between this chain and a locator. */
+ CBlockIndex *FindFork(const CBlockLocator &locator) const;
};
/** The currently-connected chain of blocks. */
@@ -1040,59 +1046,6 @@ extern CChain chainActive;
-/** Describes a place in the block chain to another node such that if the
- * other node doesn't have the same branch, it can find a recent common trunk.
- * The further back it is, the further before the fork it may be.
- */
-class CBlockLocator
-{
-protected:
- std::vector<uint256> vHave;
-public:
- CBlockLocator() {}
-
- explicit CBlockLocator(const CBlockIndex* pindex)
- {
- Set(pindex);
- }
-
- explicit CBlockLocator(uint256 hashBlock);
-
- CBlockLocator(const std::vector<uint256>& vHaveIn)
- {
- vHave = vHaveIn;
- }
-
- IMPLEMENT_SERIALIZE
- (
- if (!(nType & SER_GETHASH))
- READWRITE(nVersion);
- READWRITE(vHave);
- )
-
- void SetNull()
- {
- vHave.clear();
- }
-
- bool IsNull()
- {
- return vHave.empty();
- }
-
- /** Given a block initialises the locator to that point in the chain. */
- void Set(const CBlockIndex* pindex);
- /** Returns the distance in blocks this locator is from our chain head. */
- int GetDistanceBack();
- /** Returns the first best-chain block the locator contains. */
- CBlockIndex* GetBlockIndex();
- /** Returns the hash of the first best chain block the locator contains. */
- uint256 GetBlockHash();
- /** Returns the height of the first best chain block the locator has. */
- int GetHeight();
-};
-
-
diff --git a/src/miner.cpp b/src/miner.cpp
index e9c1d9aff9..dca8609e17 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -238,9 +238,21 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
}
if (fMissingInputs) continue;
- // Priority is sum(valuein * age) / txsize
+ // Priority is sum(valuein * age) / modified_txsize
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
- dPriority /= nTxSize;
+ unsigned int nTxSizeMod = nTxSize;
+ // In order to avoid disincentivizing cleaning up the UTXO set we don't count
+ // the constant overhead for each txin and up to 110 bytes of scriptSig (which
+ // is enough to cover a compressed pubkey p2sh redemption) for priority.
+ // Providing any more cleanup incentive than making additional inputs free would
+ // risk encouraging people to create junk outputs to redeem later.
+ BOOST_FOREACH(const CTxIn& txin, tx.vin)
+ {
+ unsigned int offset = 41U + min(110U, (unsigned int)txin.scriptSig.size());
+ if (nTxSizeMod > offset)
+ nTxSizeMod -= offset;
+ }
+ dPriority /= nTxSizeMod;
// This is a more accurate fee-per-kilobyte than is used by the client code, because the
// client code rounds up the size to the nearest 1K. That's good, because it gives an
diff --git a/src/miner.h b/src/miner.h
index 7e60b9e53b..a2800341d8 100644
--- a/src/miner.h
+++ b/src/miner.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MINER_H
diff --git a/src/net.cpp b/src/net.cpp
index e8baa8b383..dd7bf283a9 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/net.h b/src/net.h
index 9b76d1643d..2c2d3a768a 100644
--- a/src/net.h
+++ b/src/net.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_NET_H
diff --git a/src/netbase.cpp b/src/netbase.cpp
index 360ecdd959..36b90e0d4c 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/netbase.h b/src/netbase.h
index e1f80b4ee8..c14fa5075d 100644
--- a/src/netbase.h
+++ b/src/netbase.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_NETBASE_H
diff --git a/src/noui.cpp b/src/noui.cpp
index 67eac944c6..06c507d0e5 100644
--- a/src/noui.cpp
+++ b/src/noui.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/protocol.cpp b/src/protocol.cpp
index ba254be3e1..a841bbc14e 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/protocol.h b/src/protocol.h
index ae541dfdba..3d8eae55f9 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/qt/Makefile.am b/src/qt/Makefile.am
index e7ae0a905f..5892f6aca0 100644
--- a/src/qt/Makefile.am
+++ b/src/qt/Makefile.am
@@ -51,7 +51,7 @@ QT_MOC_CPP = moc_aboutdialog.cpp moc_addressbookpage.cpp \
moc_signverifymessagedialog.cpp moc_splashscreen.cpp moc_trafficgraphwidget.cpp moc_transactiondesc.cpp \
moc_transactiondescdialog.cpp moc_transactionfilterproxy.cpp \
moc_transactiontablemodel.cpp moc_transactionview.cpp moc_walletframe.cpp \
- moc_walletmodel.cpp moc_walletstack.cpp moc_walletview.cpp
+ moc_walletmodel.cpp moc_walletview.cpp
BITCOIN_MM = macdockiconhandler.mm macnotificationhandler.mm
QR_CPP = qrcodedialog.cpp
@@ -75,7 +75,7 @@ BITCOIN_QT_H = aboutdialog.h addressbookpage.h addresstablemodel.h \
sendcoinsdialog.h sendcoinsentry.h signverifymessagedialog.h splashscreen.h \
trafficgraphwidget.h transactiondescdialog.h transactiondesc.h transactionfilterproxy.h \
transactionrecord.h transactiontablemodel.h transactionview.h walletframe.h \
- walletmodel.h walletmodeltransaction.h walletstack.h walletview.h
+ walletmodel.h walletmodeltransaction.h walletview.h
RES_ICONS = res/icons/bitcoin.png res/icons/address-book.png \
res/icons/quit.png res/icons/send.png res/icons/toolbar.png \
@@ -105,7 +105,7 @@ BITCOIN_QT_CPP = aboutdialog.cpp addressbookpage.cpp \
signverifymessagedialog.cpp splashscreen.cpp trafficgraphwidget.cpp transactiondesc.cpp \
transactiondescdialog.cpp transactionfilterproxy.cpp transactionrecord.cpp \
transactiontablemodel.cpp transactionview.cpp walletframe.cpp \
- walletmodel.cpp walletmodeltransaction.cpp walletstack.cpp walletview.cpp
+ walletmodel.cpp walletmodeltransaction.cpp walletview.cpp
RES_IMAGES = res/images/about.png res/images/splash.png \
res/images/splash_testnet.png
diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp
index 78693971da..e73a82978a 100644
--- a/src/qt/bitcoin.cpp
+++ b/src/qt/bitcoin.cpp
@@ -333,8 +333,8 @@ int main(int argc, char *argv[])
paymentServer, SLOT(fetchPaymentACK(CWallet*,const SendCoinsRecipient&,QByteArray)));
QObject::connect(paymentServer, SIGNAL(receivedPaymentACK(QString)),
&window, SLOT(showPaymentACK(QString)));
- QObject::connect(paymentServer, SIGNAL(reportError(QString, QString, unsigned int)),
- guiref, SLOT(message(QString, QString, unsigned int)));
+ QObject::connect(paymentServer, SIGNAL(message(QString,QString,unsigned int)),
+ guiref, SLOT(message(QString,QString,unsigned int)));
QTimer::singleShot(100, paymentServer, SLOT(uiReady()));
app.exec();
diff --git a/src/qt/bitcoinamountfield.cpp b/src/qt/bitcoinamountfield.cpp
index d9d4e3b23d..37b8743eff 100644
--- a/src/qt/bitcoinamountfield.cpp
+++ b/src/qt/bitcoinamountfield.cpp
@@ -130,9 +130,10 @@ void BitcoinAmountField::setValue(qint64 value)
setText(BitcoinUnits::format(currentUnit, value));
}
-void BitcoinAmountField::setReadOnly(bool fReadeOnly)
+void BitcoinAmountField::setReadOnly(bool fReadOnly)
{
- // TODO ...
+ amount->setReadOnly(fReadOnly);
+ unit->setEnabled(!fReadOnly);
}
void BitcoinAmountField::unitChanged(int idx)
diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp
index 23a221120f..3336a8afd3 100644
--- a/src/qt/bitcoingui.cpp
+++ b/src/qt/bitcoingui.cpp
@@ -447,26 +447,31 @@ void BitcoinGUI::aboutClicked()
void BitcoinGUI::gotoOverviewPage()
{
+ overviewAction->setChecked(true);
if (walletFrame) walletFrame->gotoOverviewPage();
}
void BitcoinGUI::gotoHistoryPage()
{
+ historyAction->setChecked(true);
if (walletFrame) walletFrame->gotoHistoryPage();
}
void BitcoinGUI::gotoAddressBookPage()
{
+ addressBookAction->setChecked(true);
if (walletFrame) walletFrame->gotoAddressBookPage();
}
void BitcoinGUI::gotoReceiveCoinsPage()
{
+ receiveCoinsAction->setChecked(true);
if (walletFrame) walletFrame->gotoReceiveCoinsPage();
}
void BitcoinGUI::gotoSendCoinsPage(QString addr)
{
+ sendCoinsAction->setChecked(true);
if (walletFrame) walletFrame->gotoSendCoinsPage(addr);
}
diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h
index e2dd5dc6bc..e5a92fed93 100644
--- a/src/qt/bitcoingui.h
+++ b/src/qt/bitcoingui.h
@@ -61,14 +61,6 @@ public:
void removeAllWallets();
- /** Used by WalletView to allow access to needed QActions */
- // Todo: Use Qt signals for these
- QAction * getOverviewAction() { return overviewAction; }
- QAction * getHistoryAction() { return historyAction; }
- QAction * getAddressBookAction() { return addressBookAction; }
- QAction * getReceiveCoinsAction() { return receiveCoinsAction; }
- QAction * getSendCoinsAction() { return sendCoinsAction; }
-
protected:
void changeEvent(QEvent *e);
void closeEvent(QCloseEvent *event);
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index 2bab488135..212fa6974a 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -65,10 +65,8 @@ QDateTime ClientModel::getLastBlockDate() const
{
if (chainActive.Tip())
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
- else if(!isTestNet())
- return QDateTime::fromTime_t(1231006505); // Genesis block's time
else
- return QDateTime::fromTime_t(1296688602); // Genesis block's time (testnet)
+ return QDateTime::fromTime_t(Params().GenesisBlock().nTime); // Genesis block's time of current network
}
double ClientModel::getVerificationProgress() const
diff --git a/src/qt/forms/sendcoinsentry.ui b/src/qt/forms/sendcoinsentry.ui
index 2c1cec600c..5c6afd6c71 100644
--- a/src/qt/forms/sendcoinsentry.ui
+++ b/src/qt/forms/sendcoinsentry.ui
@@ -621,7 +621,7 @@
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
- <cstring>payAmount</cstring>
+ <cstring>payAmount_s</cstring>
</property>
</widget>
</item>
@@ -640,15 +640,9 @@
</item>
<item row="5" column="2">
<widget class="BitcoinAmountField" name="payAmount_s">
- <property name="enabled">
- <bool>false</bool>
- </property>
<property name="acceptDrops">
<bool>false</bool>
</property>
- <property name="readOnly">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="3" column="2">
diff --git a/src/qt/paymentserver.cpp b/src/qt/paymentserver.cpp
index 96ba997943..af75d6b4e5 100644
--- a/src/qt/paymentserver.cpp
+++ b/src/qt/paymentserver.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -189,7 +189,7 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[])
if (arg.startsWith("-"))
continue;
- if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin:
+ if (arg.startsWith(BITCOIN_IPC_PREFIX, Qt::CaseInsensitive)) // bitcoin: URI
{
savedPaymentRequests.append(arg);
@@ -220,9 +220,9 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[])
}
else
{
- qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << argv[i];
// Printing to debug.log is about the best we can do here, the
// GUI hasn't started yet so we can't pop up a message box.
+ qDebug() << "PaymentServer::ipcSendCommandLine : Payment request file does not exist: " << arg;
}
}
@@ -246,6 +246,7 @@ bool PaymentServer::ipcSendCommandLine(int argc, char* argv[])
delete socket;
fResult = true;
}
+
return fResult;
}
@@ -255,7 +256,9 @@ PaymentServer::PaymentServer(QObject* parent, bool startLocalServer) : QObject(p
// compatible with the version of the headers we compiled against.
GOOGLE_PROTOBUF_VERIFY_VERSION;
- // Install global event filter to catch QFileOpenEvents on the mac (sent when you click bitcoin: links)
+ // Install global event filter to catch QFileOpenEvents
+ // on Mac: sent when you click bitcoin: links
+ // other OSes: helpful when dealing with payment-request files (in the future)
if (parent)
parent->installEventFilter(this);
@@ -310,7 +313,7 @@ void PaymentServer::initNetManager()
if (netManager != NULL)
delete netManager;
- // netManager is used to fetch paymentrequests given in bitcoin: URI's
+ // netManager is used to fetch paymentrequests given in bitcoin: URIs
netManager = new QNetworkAccessManager(this);
// Use proxy settings from optionsModel:
@@ -360,7 +363,8 @@ void PaymentServer::handleURIOrFile(const QString& s)
#endif
if (uri.hasQueryItem("request"))
{
- QByteArray temp; temp.append(uri.queryItemValue("request"));
+ QByteArray temp;
+ temp.append(uri.queryItemValue("request"));
QString decoded = QUrl::fromPercentEncoding(temp);
QUrl fetchUrl(decoded, QUrl::StrictMode);
@@ -370,13 +374,17 @@ void PaymentServer::handleURIOrFile(const QString& s)
if (fetchUrl.isValid())
fetchRequest(fetchUrl);
else
- qDebug() << "PaymentServer::handleURIOrFile : Invalid url: " << fetchUrl;
+ qDebug() << "PaymentServer::handleURIOrFile : Invalid URL: " << fetchUrl;
return;
}
SendCoinsRecipient recipient;
if (GUIUtil::parseBitcoinURI(s, &recipient))
emit receivedPaymentRequest(recipient);
+ else
+ emit message(tr("URI handling"),
+ tr("URI can not be parsed! This can be caused by an invalid Bitcoin address or malformed URI parameters."),
+ CClientUIInterface::ICON_WARNING);
return;
}
@@ -408,10 +416,10 @@ void PaymentServer::handleURIConnection()
if (clientConnection->bytesAvailable() < (int)sizeof(quint16)) {
return;
}
- QString message;
- in >> message;
+ QString msg;
+ in >> msg;
- handleURIOrFile(message);
+ handleURIOrFile(msg);
}
bool PaymentServer::readPaymentRequest(const QString& filename, PaymentRequestPlus& request)
@@ -444,11 +452,11 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, QList<Sen
foreach(const PAIRTYPE(CScript, qint64)& sendingTo, sendingTos) {
CTxOut txOut(sendingTo.second, sendingTo.first);
if (txOut.IsDust(CTransaction::nMinRelayTxFee)) {
- QString message = QObject::tr("Requested payment amount (%1) too small")
+ QString msg = QObject::tr("Requested payment amount (%1) too small")
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second));
- qDebug() << "PaymentServer::processPaymentRequest : " << message;
- emit reportError(tr("Payment request error"), message, CClientUIInterface::MODAL);
+ qDebug() << "PaymentServer::processPaymentRequest : " << msg;
+ emit message(tr("Payment request error"), msg, CClientUIInterface::MSG_ERROR);
return false;
}
@@ -485,9 +493,9 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, QList<Sen
// Insecure payments to custom bitcoin addresses are not supported
// (there is no good way to tell the user where they are paying in a way
// they'd have a chance of understanding).
- emit reportError(tr("Payment request error"),
- tr("Insecure requests to custom payment scripts unsupported"),
- CClientUIInterface::MODAL);
+ emit message(tr("Payment request error"),
+ tr("Insecure requests to custom payment scripts unsupported"),
+ CClientUIInterface::MSG_ERROR);
return false;
}
}
@@ -566,11 +574,11 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply)
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError)
{
- QString message = QObject::tr("Error communicating with %1: %2")
+ QString msg = QObject::tr("Error communicating with %1: %2")
.arg(reply->request().url().toString())
.arg(reply->errorString());
- qDebug() << "PaymentServer::netRequestFinished : " << message;
- emit reportError(tr("Network request error"), message, CClientUIInterface::MODAL);
+ qDebug() << "PaymentServer::netRequestFinished : " << msg;
+ emit message(tr("Network request error"), msg, CClientUIInterface::MSG_ERROR);
return;
}
@@ -595,10 +603,10 @@ void PaymentServer::netRequestFinished(QNetworkReply* reply)
payments::PaymentACK paymentACK;
if (!paymentACK.ParseFromArray(data.data(), data.size()))
{
- QString message = QObject::tr("Bad response from server %1")
+ QString msg = QObject::tr("Bad response from server %1")
.arg(reply->request().url().toString());
- qDebug() << "PaymentServer::netRequestFinished : " << message;
- emit reportError(tr("Network request error"), message, CClientUIInterface::MODAL);
+ qDebug() << "PaymentServer::netRequestFinished : " << msg;
+ emit message(tr("Network request error"), msg, CClientUIInterface::MSG_ERROR);
}
else {
emit receivedPaymentACK(QString::fromStdString(paymentACK.memo()));
@@ -615,7 +623,7 @@ void PaymentServer::reportSslErrors(QNetworkReply* reply, const QList<QSslError>
qDebug() << "PaymentServer::reportSslErrors : " << err;
errString += err.errorString() + "\n";
}
- emit reportError(tr("Network request error"), errString, CClientUIInterface::MODAL);
+ emit message(tr("Network request error"), errString, CClientUIInterface::MSG_ERROR);
}
void PaymentServer::setOptionsModel(OptionsModel *optionsModel)
diff --git a/src/qt/paymentserver.h b/src/qt/paymentserver.h
index f9d827204b..042c41ef64 100644
--- a/src/qt/paymentserver.h
+++ b/src/qt/paymentserver.h
@@ -90,8 +90,8 @@ signals:
// Fired when a valid PaymentACK is received
void receivedPaymentACK(QString);
- // Fired when an error should be reported to the user
- void reportError(QString, QString, unsigned int);
+ // Fired when a message should be reported to the user
+ void message(const QString &title, const QString &message, unsigned int style);
public slots:
// Signal this when the main window's UI is ready
diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp
index 59724c94f4..188b8860a9 100644
--- a/src/qt/sendcoinsentry.cpp
+++ b/src/qt/sendcoinsentry.cpp
@@ -60,12 +60,7 @@ void SendCoinsEntry::on_addressBookButton_clicked()
void SendCoinsEntry::on_payTo_textChanged(const QString &address)
{
- if(!model)
- return;
- // Fill in label from address book, if address has an associated label
- QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
- if(!associatedLabel.isEmpty())
- ui->addAsLabel->setText(associatedLabel);
+ updateLabel(address);
}
void SendCoinsEntry::setModel(WalletModel *model)
@@ -174,6 +169,7 @@ void SendCoinsEntry::setValue(const SendCoinsRecipient &value)
ui->payTo_s->setText(recipient.authenticatedMerchant);
ui->memoTextLabel_s->setText(QString::fromStdString(details.memo()));
ui->payAmount_s->setValue(recipient.amount);
+ ui->payAmount_s->setReadOnly(true);
setCurrentWidget(ui->SendCoinsSecure);
}
}
@@ -203,3 +199,19 @@ void SendCoinsEntry::updateDisplayUnit()
ui->payAmount_s->setDisplayUnit(model->getOptionsModel()->getDisplayUnit());
}
}
+
+bool SendCoinsEntry::updateLabel(const QString &address)
+{
+ if(!model)
+ return false;
+
+ // Fill in label from address book, if address has an associated label
+ QString associatedLabel = model->getAddressTableModel()->labelForAddress(address);
+ if(!associatedLabel.isEmpty())
+ {
+ ui->addAsLabel->setText(associatedLabel);
+ return true;
+ }
+
+ return false;
+}
diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h
index 49e622daf1..66d9752909 100644
--- a/src/qt/sendcoinsentry.h
+++ b/src/qt/sendcoinsentry.h
@@ -58,6 +58,8 @@ private:
SendCoinsRecipient recipient;
Ui::SendCoinsEntry *ui;
WalletModel *model;
+
+ bool updateLabel(const QString &address);
};
#endif // SENDCOINSENTRY_H
diff --git a/src/qt/walletframe.cpp b/src/qt/walletframe.cpp
index 8d6a1b387e..f754bd5e71 100644
--- a/src/qt/walletframe.cpp
+++ b/src/qt/walletframe.cpp
@@ -5,20 +5,21 @@
* The Bitcoin Developers 2011-2013
*/
#include "walletframe.h"
+#include "walletview.h"
#include "bitcoingui.h"
-#include "walletstack.h"
#include <QHBoxLayout>
#include <QMessageBox>
+#include <QStackedWidget>
WalletFrame::WalletFrame(BitcoinGUI *_gui) :
- QFrame(_gui)
+ QFrame(_gui),
+ gui(_gui)
{
// Leave HBox hook for adding a list view later
QHBoxLayout *walletFrameLayout = new QHBoxLayout(this);
setContentsMargins(0,0,0,0);
- walletStack = new WalletStack(this);
- walletStack->setBitcoinGUI(_gui);
+ walletStack = new QStackedWidget(this);
walletFrameLayout->setContentsMargins(0,0,0,0);
walletFrameLayout->addWidget(walletStack);
}
@@ -29,95 +30,157 @@ WalletFrame::~WalletFrame()
void WalletFrame::setClientModel(ClientModel *clientModel)
{
- if (clientModel)
- walletStack->setClientModel(clientModel);
+ this->clientModel = clientModel;
}
bool WalletFrame::addWallet(const QString& name, WalletModel *walletModel)
{
- return walletStack->addWallet(name, walletModel);
+ if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0)
+ return false;
+
+ WalletView *walletView = new WalletView(this);
+ walletView->setBitcoinGUI(gui);
+ walletView->setClientModel(clientModel);
+ walletView->setWalletModel(walletModel);
+ walletView->showOutOfSyncWarning(bOutOfSync);
+
+ /* TODO we should goto the currently selected page once dynamically adding wallets is supported */
+ walletView->gotoOverviewPage();
+ walletStack->addWidget(walletView);
+ mapWalletViews[name] = walletView;
+
+ // Ensure a walletView is able to show the main window
+ connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));
+
+ return true;
}
bool WalletFrame::setCurrentWallet(const QString& name)
{
- // TODO: Check if valid name
- return walletStack->setCurrentWallet(name);
+ if (mapWalletViews.count(name) == 0)
+ return false;
+
+ WalletView *walletView = mapWalletViews.value(name);
+ walletStack->setCurrentWidget(walletView);
+ walletView->setEncryptionStatus();
+ return true;
+}
+
+bool WalletFrame::removeWallet(const QString &name)
+{
+ if (mapWalletViews.count(name) == 0)
+ return false;
+
+ WalletView *walletView = mapWalletViews.take(name);
+ walletStack->removeWidget(walletView);
+ return true;
}
void WalletFrame::removeAllWallets()
{
- walletStack->removeAllWallets();
+ QMap<QString, WalletView*>::const_iterator i;
+ for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
+ walletStack->removeWidget(i.value());
+ mapWalletViews.clear();
}
bool WalletFrame::handlePaymentRequest(const SendCoinsRecipient &recipient)
{
- return walletStack->handlePaymentRequest(recipient);
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (!walletView)
+ return false;
+
+ return walletView->handlePaymentRequest(recipient);
}
void WalletFrame::showOutOfSyncWarning(bool fShow)
{
- if (!walletStack)
- return;
-
- walletStack->showOutOfSyncWarning(fShow);
+ bOutOfSync = fShow;
+ QMap<QString, WalletView*>::const_iterator i;
+ for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
+ i.value()->showOutOfSyncWarning(fShow);
}
void WalletFrame::gotoOverviewPage()
{
- walletStack->gotoOverviewPage();
+ QMap<QString, WalletView*>::const_iterator i;
+ for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
+ i.value()->gotoOverviewPage();
}
void WalletFrame::gotoHistoryPage()
{
- walletStack->gotoHistoryPage();
+ QMap<QString, WalletView*>::const_iterator i;
+ for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
+ i.value()->gotoHistoryPage();
}
void WalletFrame::gotoAddressBookPage()
{
- walletStack->gotoAddressBookPage();
+ QMap<QString, WalletView*>::const_iterator i;
+ for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
+ i.value()->gotoAddressBookPage();
}
void WalletFrame::gotoReceiveCoinsPage()
{
- walletStack->gotoReceiveCoinsPage();
+ QMap<QString, WalletView*>::const_iterator i;
+ for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
+ i.value()->gotoReceiveCoinsPage();
}
void WalletFrame::gotoSendCoinsPage(QString addr)
{
- walletStack->gotoSendCoinsPage(addr);
+ QMap<QString, WalletView*>::const_iterator i;
+ for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
+ i.value()->gotoSendCoinsPage(addr);
}
void WalletFrame::gotoSignMessageTab(QString addr)
{
- walletStack->gotoSignMessageTab(addr);
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (walletView)
+ walletView->gotoSignMessageTab(addr);
}
void WalletFrame::gotoVerifyMessageTab(QString addr)
{
- walletStack->gotoSignMessageTab(addr);
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (walletView)
+ walletView->gotoVerifyMessageTab(addr);
}
void WalletFrame::encryptWallet(bool status)
{
- walletStack->encryptWallet(status);
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (walletView)
+ walletView->encryptWallet(status);
}
void WalletFrame::backupWallet()
{
- walletStack->backupWallet();
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (walletView)
+ walletView->backupWallet();
}
void WalletFrame::changePassphrase()
{
- walletStack->changePassphrase();
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (walletView)
+ walletView->changePassphrase();
}
void WalletFrame::unlockWallet()
{
- walletStack->unlockWallet();
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (walletView)
+ walletView->unlockWallet();
}
void WalletFrame::setEncryptionStatus()
{
- walletStack->setEncryptionStatus();
+ WalletView *walletView = (WalletView*)walletStack->currentWidget();
+ if (walletView)
+ walletView->setEncryptionStatus();
}
diff --git a/src/qt/walletframe.h b/src/qt/walletframe.h
index eaae053ccd..5011987963 100644
--- a/src/qt/walletframe.h
+++ b/src/qt/walletframe.h
@@ -8,12 +8,17 @@
#define WALLETFRAME_H
#include <QFrame>
+#include <QMap>
class BitcoinGUI;
class ClientModel;
class SendCoinsRecipient;
class WalletModel;
-class WalletStack;
+class WalletView;
+
+QT_BEGIN_NAMESPACE
+class QStackedWidget;
+QT_END_NAMESPACE
class WalletFrame : public QFrame
{
@@ -27,7 +32,7 @@ public:
bool addWallet(const QString& name, WalletModel *walletModel);
bool setCurrentWallet(const QString& name);
-
+ bool removeWallet(const QString &name);
void removeAllWallets();
bool handlePaymentRequest(const SendCoinsRecipient& recipient);
@@ -35,7 +40,12 @@ public:
void showOutOfSyncWarning(bool fShow);
private:
- WalletStack *walletStack;
+ QStackedWidget *walletStack;
+ BitcoinGUI *gui;
+ ClientModel *clientModel;
+ QMap<QString, WalletView*> mapWalletViews;
+
+ bool bOutOfSync;
public slots:
/** Switch to overview (home) page */
diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp
index 099fbe8dc3..417bac9928 100644
--- a/src/qt/walletmodel.cpp
+++ b/src/qt/walletmodel.cpp
@@ -258,22 +258,26 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(WalletModelTransaction &tran
// and emit coinsSent signal for each recipient
foreach(const SendCoinsRecipient &rcp, transaction.getRecipients())
{
- std::string strAddress = rcp.address.toStdString();
- CTxDestination dest = CBitcoinAddress(strAddress).Get();
- std::string strLabel = rcp.label.toStdString();
+ // Don't touch the address book when we have a secure payment-request
+ if (rcp.authenticatedMerchant.isEmpty())
{
- LOCK(wallet->cs_wallet);
-
- std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
-
- // Check if we have a new address or an updated label
- if (mi == wallet->mapAddressBook.end())
- {
- wallet->SetAddressBook(dest, strLabel, "send");
- }
- else if (mi->second.name != strLabel)
+ std::string strAddress = rcp.address.toStdString();
+ CTxDestination dest = CBitcoinAddress(strAddress).Get();
+ std::string strLabel = rcp.label.toStdString();
{
- wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
+ LOCK(wallet->cs_wallet);
+
+ std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest);
+
+ // Check if we have a new address or an updated label
+ if (mi == wallet->mapAddressBook.end())
+ {
+ wallet->SetAddressBook(dest, strLabel, "send");
+ }
+ else if (mi->second.name != strLabel)
+ {
+ wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose
+ }
}
}
emit coinsSent(wallet, rcp, transaction_array);
diff --git a/src/qt/walletstack.cpp b/src/qt/walletstack.cpp
deleted file mode 100644
index 4ef87aed52..0000000000
--- a/src/qt/walletstack.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Qt4 bitcoin GUI.
- *
- * W.J. van der Laan 2011-2012
- * The Bitcoin Developers 2011-2013
- */
-#include "walletstack.h"
-#include "walletview.h"
-#include "bitcoingui.h"
-
-#include <QMap>
-#include <QMessageBox>
-
-WalletStack::WalletStack(QWidget *parent) :
- QStackedWidget(parent),
- gui(0),
- clientModel(0),
- bOutOfSync(true)
-{
- setContentsMargins(0,0,0,0);
-}
-
-WalletStack::~WalletStack()
-{
-}
-
-bool WalletStack::addWallet(const QString& name, WalletModel *walletModel)
-{
- if (!gui || !clientModel || !walletModel || mapWalletViews.count(name) > 0)
- return false;
-
- WalletView *walletView = new WalletView(this, gui);
- walletView->setBitcoinGUI(gui);
- walletView->setClientModel(clientModel);
- walletView->setWalletModel(walletModel);
- walletView->showOutOfSyncWarning(bOutOfSync);
- addWidget(walletView);
- mapWalletViews[name] = walletView;
-
- // Ensure a walletView is able to show the main window
- connect(walletView, SIGNAL(showNormalIfMinimized()), gui, SLOT(showNormalIfMinimized()));
-
- return true;
-}
-
-bool WalletStack::removeWallet(const QString& name)
-{
- if (mapWalletViews.count(name) == 0)
- return false;
-
- WalletView *walletView = mapWalletViews.take(name);
- removeWidget(walletView);
- return true;
-}
-
-void WalletStack::removeAllWallets()
-{
- QMap<QString, WalletView*>::const_iterator i;
- for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
- removeWidget(i.value());
- mapWalletViews.clear();
-}
-
-bool WalletStack::handlePaymentRequest(const SendCoinsRecipient &recipient)
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (!walletView)
- return false;
-
- return walletView->handlePaymentRequest(recipient);
-}
-
-void WalletStack::showOutOfSyncWarning(bool fShow)
-{
- bOutOfSync = fShow;
- QMap<QString, WalletView*>::const_iterator i;
- for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
- i.value()->showOutOfSyncWarning(fShow);
-}
-
-void WalletStack::gotoOverviewPage()
-{
- QMap<QString, WalletView*>::const_iterator i;
- for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
- i.value()->gotoOverviewPage();
-}
-
-void WalletStack::gotoHistoryPage()
-{
- QMap<QString, WalletView*>::const_iterator i;
- for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
- i.value()->gotoHistoryPage();
-}
-
-void WalletStack::gotoAddressBookPage()
-{
- QMap<QString, WalletView*>::const_iterator i;
- for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
- i.value()->gotoAddressBookPage();
-}
-
-void WalletStack::gotoReceiveCoinsPage()
-{
- QMap<QString, WalletView*>::const_iterator i;
- for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
- i.value()->gotoReceiveCoinsPage();
-}
-
-void WalletStack::gotoSendCoinsPage(QString addr)
-{
- QMap<QString, WalletView*>::const_iterator i;
- for (i = mapWalletViews.constBegin(); i != mapWalletViews.constEnd(); ++i)
- i.value()->gotoSendCoinsPage(addr);
-}
-
-void WalletStack::gotoSignMessageTab(QString addr)
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (walletView)
- walletView->gotoSignMessageTab(addr);
-}
-
-void WalletStack::gotoVerifyMessageTab(QString addr)
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (walletView)
- walletView->gotoVerifyMessageTab(addr);
-}
-
-void WalletStack::encryptWallet(bool status)
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (walletView)
- walletView->encryptWallet(status);
-}
-
-void WalletStack::backupWallet()
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (walletView)
- walletView->backupWallet();
-}
-
-void WalletStack::changePassphrase()
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (walletView)
- walletView->changePassphrase();
-}
-
-void WalletStack::unlockWallet()
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (walletView)
- walletView->unlockWallet();
-}
-
-void WalletStack::setEncryptionStatus()
-{
- WalletView *walletView = (WalletView*)currentWidget();
- if (walletView)
- walletView->setEncryptionStatus();
-}
-
-bool WalletStack::setCurrentWallet(const QString& name)
-{
- if (mapWalletViews.count(name) == 0)
- return false;
-
- WalletView *walletView = mapWalletViews.value(name);
- setCurrentWidget(walletView);
- walletView->setEncryptionStatus();
- return true;
-}
diff --git a/src/qt/walletstack.h b/src/qt/walletstack.h
deleted file mode 100644
index 74b9f09081..0000000000
--- a/src/qt/walletstack.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Qt4 bitcoin GUI.
- *
- * W.J. van der Laan 2011-2012
- * The Bitcoin Developers 2011-2013
- */
-#ifndef WALLETSTACK_H
-#define WALLETSTACK_H
-
-#include <QStackedWidget>
-#include <QMap>
-#include <boost/shared_ptr.hpp>
-
-class BitcoinGUI;
-class TransactionTableModel;
-class ClientModel;
-class WalletModel;
-class WalletView;
-class TransactionView;
-class OverviewPage;
-class AddressBookPage;
-class SendCoinsDialog;
-class SendCoinsRecipient;
-class SignVerifyMessageDialog;
-class Notificator;
-class RPCConsole;
-
-class CWalletManager;
-
-QT_BEGIN_NAMESPACE
-class QLabel;
-class QModelIndex;
-QT_END_NAMESPACE
-
-/*
- WalletStack class. This class is a container for WalletView instances. It takes the place of centralWidget.
- It was added to support multiple wallet functionality. It communicates with both the client and the
- wallet models to give the user an up-to-date view of the current core state. It manages all the wallet views
- it contains and updates them accordingly.
- */
-class WalletStack : public QStackedWidget
-{
- Q_OBJECT
-
-public:
- explicit WalletStack(QWidget *parent = 0);
- ~WalletStack();
-
- void setBitcoinGUI(BitcoinGUI *gui) { this->gui = gui; }
-
- void setClientModel(ClientModel *clientModel) { this->clientModel = clientModel; }
-
- bool addWallet(const QString& name, WalletModel *walletModel);
- bool removeWallet(const QString& name);
-
- void removeAllWallets();
-
- bool handlePaymentRequest(const SendCoinsRecipient &recipient);
-
- void showOutOfSyncWarning(bool fShow);
-
-private:
- BitcoinGUI *gui;
- ClientModel *clientModel;
- QMap<QString, WalletView*> mapWalletViews;
-
- bool bOutOfSync;
-
-public slots:
- bool setCurrentWallet(const QString& name);
-
- /** Switch to overview (home) page */
- void gotoOverviewPage();
- /** Switch to history (transactions) page */
- void gotoHistoryPage();
- /** Switch to address book page */
- void gotoAddressBookPage();
- /** Switch to receive coins page */
- void gotoReceiveCoinsPage();
- /** Switch to send coins page */
- void gotoSendCoinsPage(QString addr = "");
-
- /** Show Sign/Verify Message dialog and switch to sign message tab */
- void gotoSignMessageTab(QString addr = "");
- /** Show Sign/Verify Message dialog and switch to verify message tab */
- void gotoVerifyMessageTab(QString addr = "");
-
- /** Encrypt the wallet */
- void encryptWallet(bool status);
- /** Backup the wallet */
- void backupWallet();
- /** Change encrypted wallet passphrase */
- void changePassphrase();
- /** Ask for passphrase to unlock wallet temporarily */
- void unlockWallet();
-
- /** Set the encryption status as shown in the UI.
- @param[in] status current encryption status
- @see WalletModel::EncryptionStatus
- */
- void setEncryptionStatus();
-};
-
-#endif // WALLETSTACK_H
diff --git a/src/qt/walletview.cpp b/src/qt/walletview.cpp
index efb74efaa0..d7cef971ed 100644
--- a/src/qt/walletview.cpp
+++ b/src/qt/walletview.cpp
@@ -29,9 +29,9 @@
#include <QFileDialog>
#include <QPushButton>
-WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui):
+WalletView::WalletView(QWidget *parent):
QStackedWidget(parent),
- gui(_gui),
+ gui(0),
clientModel(0),
walletModel(0)
{
@@ -54,12 +54,8 @@ WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui):
transactionsPage->setLayout(vbox);
addressBookPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::SendingTab);
-
receiveCoinsPage = new AddressBookPage(AddressBookPage::ForEditing, AddressBookPage::ReceivingTab);
-
- sendCoinsPage = new SendCoinsDialog(gui);
-
- signVerifyMessageDialog = new SignVerifyMessageDialog(gui);
+ sendCoinsPage = new SendCoinsDialog();
addWidget(overviewPage);
addWidget(transactionsPage);
@@ -68,7 +64,6 @@ WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui):
addWidget(sendCoinsPage);
// Clicking on a transaction on the overview page simply sends you to transaction history page
- connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), this, SLOT(gotoHistoryPage()));
connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), transactionView, SLOT(focusTransaction(QModelIndex)));
// Double-clicking on a transaction on the transaction history page shows details
@@ -82,8 +77,6 @@ WalletView::WalletView(QWidget *parent, BitcoinGUI *_gui):
connect(receiveCoinsPage, SIGNAL(signMessage(QString)), this, SLOT(gotoSignMessageTab(QString)));
// Clicking on "Export" allows to export the transaction list
connect(exportButton, SIGNAL(clicked()), transactionView, SLOT(exportClicked()));
-
- gotoOverviewPage();
}
WalletView::~WalletView()
@@ -93,6 +86,10 @@ WalletView::~WalletView()
void WalletView::setBitcoinGUI(BitcoinGUI *gui)
{
this->gui = gui;
+ if(gui)
+ {
+ connect(overviewPage, SIGNAL(transactionClicked(QModelIndex)), gui, SLOT(gotoHistoryPage()));
+ }
}
void WalletView::setClientModel(ClientModel *clientModel)
@@ -109,7 +106,7 @@ void WalletView::setClientModel(ClientModel *clientModel)
void WalletView::setWalletModel(WalletModel *walletModel)
{
this->walletModel = walletModel;
- if (walletModel)
+ if (walletModel && gui)
{
// Receive and report messages from wallet thread
connect(walletModel, SIGNAL(message(QString,QString,unsigned int)), gui, SLOT(message(QString,QString,unsigned int)));
@@ -120,7 +117,6 @@ void WalletView::setWalletModel(WalletModel *walletModel)
addressBookPage->setModel(walletModel->getAddressTableModel());
receiveCoinsPage->setModel(walletModel->getAddressTableModel());
sendCoinsPage->setModel(walletModel);
- signVerifyMessageDialog->setModel(walletModel);
setEncryptionStatus();
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), gui, SLOT(setEncryptionStatus(int)));
@@ -152,31 +148,26 @@ void WalletView::incomingTransaction(const QModelIndex& parent, int start, int /
void WalletView::gotoOverviewPage()
{
- gui->getOverviewAction()->setChecked(true);
setCurrentWidget(overviewPage);
}
void WalletView::gotoHistoryPage()
{
- gui->getHistoryAction()->setChecked(true);
setCurrentWidget(transactionsPage);
}
void WalletView::gotoAddressBookPage()
{
- gui->getAddressBookAction()->setChecked(true);
setCurrentWidget(addressBookPage);
}
void WalletView::gotoReceiveCoinsPage()
{
- gui->getReceiveCoinsAction()->setChecked(true);
setCurrentWidget(receiveCoinsPage);
}
void WalletView::gotoSendCoinsPage(QString addr)
{
- gui->getSendCoinsAction()->setChecked(true);
setCurrentWidget(sendCoinsPage);
if (!addr.isEmpty())
@@ -185,7 +176,10 @@ void WalletView::gotoSendCoinsPage(QString addr)
void WalletView::gotoSignMessageTab(QString addr)
{
- // call show() in showTab_SM()
+ // calls show() in showTab_SM()
+ SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
+ signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
+ signVerifyMessageDialog->setModel(walletModel);
signVerifyMessageDialog->showTab_SM(true);
if (!addr.isEmpty())
@@ -194,7 +188,10 @@ void WalletView::gotoSignMessageTab(QString addr)
void WalletView::gotoVerifyMessageTab(QString addr)
{
- // call show() in showTab_VM()
+ // calls show() in showTab_VM()
+ SignVerifyMessageDialog *signVerifyMessageDialog = new SignVerifyMessageDialog(this);
+ signVerifyMessageDialog->setAttribute(Qt::WA_DeleteOnClose);
+ signVerifyMessageDialog->setModel(walletModel);
signVerifyMessageDialog->showTab_VM(true);
if (!addr.isEmpty())
diff --git a/src/qt/walletview.h b/src/qt/walletview.h
index ce4e051098..e3ff253d3c 100644
--- a/src/qt/walletview.h
+++ b/src/qt/walletview.h
@@ -36,7 +36,7 @@ class WalletView : public QStackedWidget
Q_OBJECT
public:
- explicit WalletView(QWidget *parent, BitcoinGUI *_gui);
+ explicit WalletView(QWidget *parent);
~WalletView();
void setBitcoinGUI(BitcoinGUI *gui);
@@ -64,7 +64,6 @@ private:
AddressBookPage *addressBookPage;
AddressBookPage *receiveCoinsPage;
SendCoinsDialog *sendCoinsPage;
- SignVerifyMessageDialog *signVerifyMessageDialog;
TransactionView *transactionView;
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 957241d6a0..6ea805a7f1 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index 61cd07d507..3589b45900 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 Bitcoin Developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index f123c3a9e0..77dc13815d 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index f78f034e32..7685dec57b 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009-2012 Bitcoin Developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp
index 5384b65906..d5bd39cb4d 100644
--- a/src/rpcrawtransaction.cpp
+++ b/src/rpcrawtransaction.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 433cc8b735..a72c254e76 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1169,7 +1169,9 @@ Value listsinceblock(const Array& params, bool fHelp)
uint256 blockId = 0;
blockId.SetHex(params[0].get_str());
- pindex = CBlockLocator(blockId).GetBlockIndex();
+ std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(blockId);
+ if (it != mapBlockIndex.end())
+ pindex = it->second;
}
if (params.size() > 1)
diff --git a/src/script.cpp b/src/script.cpp
index 0fe2953548..4e4e95a678 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "script.h"
@@ -971,62 +971,118 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
+namespace {
+/** Wrapper that serializes like CTransaction, but with the modifications
+ * required for the signature hash done in-place
+ */
+class CTransactionSignatureSerializer {
+private:
+ const CTransaction &txTo; // reference to the spending transaction (the one being serialized)
+ const CScript &scriptCode; // output script being consumed
+ const unsigned int nIn; // input index of txTo being signed
+ const bool fAnyoneCanPay; // whether the hashtype has the SIGHASH_ANYONECANPAY flag set
+ const bool fHashSingle; // whether the hashtype is SIGHASH_SINGLE
+ const bool fHashNone; // whether the hashtype is SIGHASH_NONE
-
-uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
-{
- if (nIn >= txTo.vin.size())
- {
- LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
- return 1;
+public:
+ CTransactionSignatureSerializer(const CTransaction &txToIn, const CScript &scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
+ txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
+ fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
+ fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
+ fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {}
+
+ /** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
+ template<typename S>
+ void SerializeScriptCode(S &s, int nType, int nVersion) const {
+ CScript::const_iterator it = scriptCode.begin();
+ CScript::const_iterator itBegin = it;
+ opcodetype opcode;
+ unsigned int nCodeSeparators = 0;
+ while (scriptCode.GetOp(it, opcode)) {
+ if (opcode == OP_CODESEPARATOR)
+ nCodeSeparators++;
+ }
+ ::WriteCompactSize(s, scriptCode.size() - nCodeSeparators);
+ it = itBegin;
+ while (scriptCode.GetOp(it, opcode)) {
+ if (opcode == OP_CODESEPARATOR) {
+ s.write((char*)&itBegin[0], it-itBegin-1);
+ itBegin = it;
+ }
+ }
+ s.write((char*)&itBegin[0], it-itBegin);
}
- CTransaction txTmp(txTo);
- // In case concatenating two scripts ends up with two codeseparators,
- // or an extra one at the end, this prevents all those possible incompatibilities.
- scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
+ /** Serialize an input of txTo */
+ template<typename S>
+ void SerializeInput(S &s, unsigned int nInput, int nType, int nVersion) const {
+ // In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
+ if (fAnyoneCanPay)
+ nInput = nIn;
+ // Serialize the prevout
+ ::Serialize(s, txTo.vin[nInput].prevout, nType, nVersion);
+ // Serialize the script
+ if (nInput != nIn)
+ // Blank out other inputs' signatures
+ ::Serialize(s, CScript(), nType, nVersion);
+ else
+ SerializeScriptCode(s, nType, nVersion);
+ // Serialize the nSequence
+ if (nInput != nIn && (fHashSingle || fHashNone))
+ // let the others update at will
+ ::Serialize(s, (int)0, nType, nVersion);
+ else
+ ::Serialize(s, txTo.vin[nInput].nSequence, nType, nVersion);
+ }
- // Blank out other inputs' signatures
- for (unsigned int i = 0; i < txTmp.vin.size(); i++)
- txTmp.vin[i].scriptSig = CScript();
- txTmp.vin[nIn].scriptSig = scriptCode;
+ /** Serialize an output of txTo */
+ template<typename S>
+ void SerializeOutput(S &s, unsigned int nOutput, int nType, int nVersion) const {
+ if (fHashSingle && nOutput != nIn)
+ // Do not lock-in the txout payee at other indices as txin
+ ::Serialize(s, CTxOut(), nType, nVersion);
+ else
+ ::Serialize(s, txTo.vout[nOutput], nType, nVersion);
+ }
- // Blank out some of the outputs
- if ((nHashType & 0x1f) == SIGHASH_NONE)
- {
- // Wildcard payee
- txTmp.vout.clear();
+ /** Serialize txTo */
+ template<typename S>
+ void Serialize(S &s, int nType, int nVersion) const {
+ // Serialize nVersion
+ ::Serialize(s, txTo.nVersion, nType, nVersion);
+ // Serialize vin
+ unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
+ ::WriteCompactSize(s, nInputs);
+ for (unsigned int nInput = 0; nInput < nInputs; nInput++)
+ SerializeInput(s, nInput, nType, nVersion);
+ // Serialize vout
+ unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size());
+ ::WriteCompactSize(s, nOutputs);
+ for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
+ SerializeOutput(s, nOutput, nType, nVersion);
+ // Serialie nLockTime
+ ::Serialize(s, txTo.nLockTime, nType, nVersion);
+ }
+};
+}
- // Let the others update at will
- for (unsigned int i = 0; i < txTmp.vin.size(); i++)
- if (i != nIn)
- txTmp.vin[i].nSequence = 0;
+uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+{
+ if (nIn >= txTo.vin.size()) {
+ LogPrintf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ return 1;
}
- else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
- {
- // Only lock-in the txout payee at same index as txin
- unsigned int nOut = nIn;
- if (nOut >= txTmp.vout.size())
- {
- LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
+
+ // Check for invalid use of SIGHASH_SINGLE
+ if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
+ if (nIn >= txTo.vout.size()) {
+ LogPrintf("ERROR: SignatureHash() : nOut=%d out of range\n", nIn);
return 1;
}
- txTmp.vout.resize(nOut+1);
- for (unsigned int i = 0; i < nOut; i++)
- txTmp.vout[i].SetNull();
-
- // Let the others update at will
- for (unsigned int i = 0; i < txTmp.vin.size(); i++)
- if (i != nIn)
- txTmp.vin[i].nSequence = 0;
}
- // Blank out other inputs completely, not recommended for open transactions
- if (nHashType & SIGHASH_ANYONECANPAY)
- {
- txTmp.vin[0] = txTmp.vin[nIn];
- txTmp.vin.resize(1);
- }
+ // Wrapper to serialize only the necessary parts of the transaction being signed
+ CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType);
// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
diff --git a/src/script.h b/src/script.h
index 842b8512eb..d339f7880e 100644
--- a/src/script.h
+++ b/src/script.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef H_BITCOIN_SCRIPT
diff --git a/src/serialize.h b/src/serialize.h
index e3d9939bcc..4d9aec3426 100644
--- a/src/serialize.h
+++ b/src/serialize.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SERIALIZE_H
@@ -216,18 +216,24 @@ uint64 ReadCompactSize(Stream& is)
unsigned short xSize;
READDATA(is, xSize);
nSizeRet = xSize;
+ if (nSizeRet < 253)
+ throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
else if (chSize == 254)
{
unsigned int xSize;
READDATA(is, xSize);
nSizeRet = xSize;
+ if (nSizeRet < 0x10000u)
+ throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
else
{
uint64 xSize;
READDATA(is, xSize);
nSizeRet = xSize;
+ if (nSizeRet < 0x100000000LLu)
+ throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
if (nSizeRet > (uint64)MAX_SIZE)
throw std::ios_base::failure("ReadCompactSize() : size too large");
diff --git a/src/sync.cpp b/src/sync.cpp
index 29a455f9b2..d6444141dc 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -78,7 +78,7 @@ static void push_lock(void* c, const CLockLocation& locklocation, bool fTry)
if (lockstack.get() == NULL)
lockstack.reset(new LockStack);
- if (fDebug) LogPrintf("Locking: %s\n", locklocation.ToString().c_str());
+ LogPrint("lock", "Locking: %s\n", locklocation.ToString().c_str());
dd_mutex.lock();
(*lockstack).push_back(std::make_pair(c, locklocation));
@@ -108,7 +108,7 @@ static void pop_lock()
if (fDebug)
{
const CLockLocation& locklocation = (*lockstack).rbegin()->second;
- LogPrintf("Unlocked: %s\n", locklocation.ToString().c_str());
+ LogPrint("lock", "Unlocked: %s\n", locklocation.ToString().c_str());
}
dd_mutex.lock();
(*lockstack).pop_back();
diff --git a/src/sync.h b/src/sync.h
index 64de7cc57c..10e0470a20 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SYNC_H
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index a859eb1de8..c3495095d9 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -34,7 +34,7 @@ test_bitcoin_SOURCES = accounting_tests.cpp alert_tests.cpp \
netbase_tests.cpp pmt_tests.cpp rpc_tests.cpp script_P2SH_tests.cpp \
script_tests.cpp serialize_tests.cpp sigopcount_tests.cpp test_bitcoin.cpp \
transaction_tests.cpp uint160_tests.cpp uint256_tests.cpp util_tests.cpp \
- wallet_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES)
+ wallet_tests.cpp sighash_tests.cpp $(JSON_TEST_FILES) $(RAW_TEST_FILES)
nodist_test_bitcoin_SOURCES = $(BUILT_SOURCES)
diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp
index 9ef932b5b4..7f6f141c62 100644
--- a/src/test/multisig_tests.cpp
+++ b/src/test/multisig_tests.cpp
@@ -19,7 +19,7 @@ using namespace boost::assign;
typedef vector<unsigned char> valtype;
-extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
BOOST_AUTO_TEST_SUITE(multisig_tests)
diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp
index dfa5529b87..32be914414 100644
--- a/src/test/script_tests.cpp
+++ b/src/test/script_tests.cpp
@@ -21,7 +21,7 @@ using namespace std;
using namespace json_spirit;
using namespace boost::algorithm;
-extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
static const unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
diff --git a/src/test/serialize_tests.cpp b/src/test/serialize_tests.cpp
index 19ffdcab66..50139df09e 100644
--- a/src/test/serialize_tests.cpp
+++ b/src/test/serialize_tests.cpp
@@ -39,7 +39,67 @@ BOOST_AUTO_TEST_CASE(varints)
ss >> VARINT(j);
BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
}
+}
+
+BOOST_AUTO_TEST_CASE(compactsize)
+{
+ CDataStream ss(SER_DISK, 0);
+ vector<char>::size_type i, j;
+
+ for (i = 1; i <= MAX_SIZE; i *= 2)
+ {
+ WriteCompactSize(ss, i-1);
+ WriteCompactSize(ss, i);
+ }
+ for (i = 1; i <= MAX_SIZE; i *= 2)
+ {
+ j = ReadCompactSize(ss);
+ BOOST_CHECK_MESSAGE((i-1) == j, "decoded:" << j << " expected:" << (i-1));
+ j = ReadCompactSize(ss);
+ BOOST_CHECK_MESSAGE(i == j, "decoded:" << j << " expected:" << i);
+ }
+}
+
+static bool isCanonicalException(const std::ios_base::failure& ex)
+{
+ return std::string("non-canonical ReadCompactSize()") == ex.what();
+}
+
+BOOST_AUTO_TEST_CASE(noncanonical)
+{
+ // Write some non-canonical CompactSize encodings, and
+ // make sure an exception is thrown when read back.
+ CDataStream ss(SER_DISK, 0);
+ vector<char>::size_type n;
+
+ // zero encoded with three bytes:
+ ss.write("\xfd\x00\x00", 3);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xfc encoded with three bytes:
+ ss.write("\xfd\xfc\x00", 3);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xfd encoded with three bytes is OK:
+ ss.write("\xfd\xfd\x00", 3);
+ n = ReadCompactSize(ss);
+ BOOST_CHECK(n == 0xfd);
+
+ // zero encoded with five bytes:
+ ss.write("\xfe\x00\x00\x00\x00", 5);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // 0xffff encoded with five bytes:
+ ss.write("\xfe\xff\xff\x00\x00", 5);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+
+ // zero encoded with nine bytes:
+ ss.write("\xff\x00\x00\x00\x00\x00\x00\x00\x00", 9);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
+ // 0x01ffffff encoded with nine bytes:
+ ss.write("\xff\xff\xff\xff\x01\x00\x00\x00\x00", 9);
+ BOOST_CHECK_EXCEPTION(ReadCompactSize(ss), std::ios_base::failure, isCanonicalException);
}
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp
new file mode 100644
index 0000000000..f098d46186
--- /dev/null
+++ b/src/test/sighash_tests.cpp
@@ -0,0 +1,120 @@
+#include <boost/test/unit_test.hpp>
+
+#include "main.h"
+#include "util.h"
+
+extern uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
+
+// Old script.cpp SignatureHash function
+uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType)
+{
+ if (nIn >= txTo.vin.size())
+ {
+ printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
+ return 1;
+ }
+ CTransaction txTmp(txTo);
+
+ // In case concatenating two scripts ends up with two codeseparators,
+ // or an extra one at the end, this prevents all those possible incompatibilities.
+ scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR));
+
+ // Blank out other inputs' signatures
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ txTmp.vin[i].scriptSig = CScript();
+ txTmp.vin[nIn].scriptSig = scriptCode;
+
+ // Blank out some of the outputs
+ if ((nHashType & 0x1f) == SIGHASH_NONE)
+ {
+ // Wildcard payee
+ txTmp.vout.clear();
+
+ // Let the others update at will
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ if (i != nIn)
+ txTmp.vin[i].nSequence = 0;
+ }
+ else if ((nHashType & 0x1f) == SIGHASH_SINGLE)
+ {
+ // Only lock-in the txout payee at same index as txin
+ unsigned int nOut = nIn;
+ if (nOut >= txTmp.vout.size())
+ {
+ printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut);
+ return 1;
+ }
+ txTmp.vout.resize(nOut+1);
+ for (unsigned int i = 0; i < nOut; i++)
+ txTmp.vout[i].SetNull();
+
+ // Let the others update at will
+ for (unsigned int i = 0; i < txTmp.vin.size(); i++)
+ if (i != nIn)
+ txTmp.vin[i].nSequence = 0;
+ }
+
+ // Blank out other inputs completely, not recommended for open transactions
+ if (nHashType & SIGHASH_ANYONECANPAY)
+ {
+ txTmp.vin[0] = txTmp.vin[nIn];
+ txTmp.vin.resize(1);
+ }
+
+ // Serialize and hash
+ CHashWriter ss(SER_GETHASH, 0);
+ ss << txTmp << nHashType;
+ return ss.GetHash();
+}
+
+void static RandomScript(CScript &script) {
+ static const opcodetype oplist[] = {OP_FALSE, OP_1, OP_2, OP_3, OP_CHECKSIG, OP_IF, OP_VERIF, OP_RETURN, OP_CODESEPARATOR};
+ script = CScript();
+ int ops = (insecure_rand() % 10);
+ for (int i=0; i<ops; i++)
+ script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
+}
+
+void static RandomTransaction(CTransaction &tx, bool fSingle) {
+ tx.nVersion = insecure_rand();
+ tx.vin.clear();
+ tx.vout.clear();
+ tx.nLockTime = (insecure_rand() % 2) ? insecure_rand() : 0;
+ int ins = (insecure_rand() % 4) + 1;
+ int outs = fSingle ? ins : (insecure_rand() % 4) + 1;
+ for (int in = 0; in < ins; in++) {
+ tx.vin.push_back(CTxIn());
+ CTxIn &txin = tx.vin.back();
+ txin.prevout.hash = GetRandHash();
+ txin.prevout.n = insecure_rand() % 4;
+ RandomScript(txin.scriptSig);
+ txin.nSequence = (insecure_rand() % 2) ? insecure_rand() : (unsigned int)-1;
+ }
+ for (int out = 0; out < outs; out++) {
+ tx.vout.push_back(CTxOut());
+ CTxOut &txout = tx.vout.back();
+ txout.nValue = insecure_rand() % 100000000;
+ RandomScript(txout.scriptPubKey);
+ }
+}
+
+BOOST_AUTO_TEST_SUITE(sighash_tests)
+
+BOOST_AUTO_TEST_CASE(sighash_test)
+{
+ seed_insecure_rand(false);
+
+ for (int i=0; i<50000; i++) {
+ int nHashType = insecure_rand();
+ CTransaction txTo;
+ RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
+ CScript scriptCode;
+ RandomScript(scriptCode);
+ int nIn = insecure_rand() % txTo.vin.size();
+ BOOST_CHECK(SignatureHash(scriptCode, txTo, nIn, nHashType) ==
+ SignatureHashOld(scriptCode, txTo, nIn, nHashType));
+ }
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 24ee8ec3e8..5e7b78296c 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
diff --git a/src/txdb.h b/src/txdb.h
index f59fc5da86..e3560a9c5c 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_TXDB_LEVELDB_H
diff --git a/src/uint256.h b/src/uint256.h
index 45ab8abb5e..79404f1b16 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_UINT256_H
diff --git a/src/util.cpp b/src/util.cpp
index cfaf5bdf8c..71994587cf 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -95,8 +95,6 @@ void locking_callback(int mode, int i, const char* file, int line)
}
}
-LockedPageManager LockedPageManager::instance;
-
// Init
class CInit
{
diff --git a/src/util.h b/src/util.h
index c3fb01dbf0..258910e2fb 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_UTIL_H
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 0f0ce7e631..5eb2808920 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -1231,9 +1231,10 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
}
int64 nChange = nValueIn - nValue - nFeeRet;
- // if sub-cent change is required, the fee must be raised to at least nMinTxFee
- // or until nChange becomes zero
- // NOTE: this depends on the exact behaviour of GetMinFee
+ // The following if statement should be removed once enough miners
+ // have upgraded to the 0.9 GetMinFee() rules. Until then, this avoids
+ // creating free transactions that have change outputs less than
+ // CENT bitcoins.
if (nFeeRet < CTransaction::nMinTxFee && nChange > 0 && nChange < CENT)
{
int64 nMoveToFee = min(nChange, CTransaction::nMinTxFee - nFeeRet);
@@ -1299,7 +1300,15 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
strFailReason = _("Transaction too large");
return false;
}
- dPriority /= nBytes;
+ unsigned int nTxSizeMod = nBytes;
+ // See miner.c's dPriority logic for the matching network-node side code.
+ BOOST_FOREACH(const CTxIn& txin, (*(CTransaction*)&wtxNew).vin)
+ {
+ unsigned int offset = 41U + min(110U, (unsigned int)txin.scriptSig.size());
+ if (nTxSizeMod > offset)
+ nTxSizeMod -= offset;
+ }
+ dPriority /= nTxSizeMod;
// Check that enough fee is included
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
diff --git a/src/wallet.h b/src/wallet.h
index 51bc9f67c4..f87e9b08c4 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLET_H
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 635fda1b42..831ef8b00d 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@@ -306,6 +306,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
}
CKey key;
CPrivKey pkey;
+ uint256 hash = 0;
+
if (strType == "key")
{
wss.nKeys++;
@@ -315,14 +317,40 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssValue >> wkey;
pkey = wkey.vchPrivKey;
}
- if (!key.SetPrivKey(pkey, vchPubKey.IsCompressed()))
+
+ // Old wallets store keys as "key" [pubkey] => [privkey]
+ // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
+ // using EC operations as a checksum.
+ // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
+ // remaining backwards-compatible.
+ try
{
- strErr = "Error reading wallet database: CPrivKey corrupt";
- return false;
+ ssValue >> hash;
+ }
+ catch(...){}
+
+ bool fSkipCheck = false;
+
+ if (hash != 0)
+ {
+ // hash pubkey/privkey to accelerate wallet load
+ std::vector<unsigned char> vchKey;
+ vchKey.reserve(vchPubKey.size() + pkey.size());
+ vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
+ vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
+
+ if (Hash(vchKey.begin(), vchKey.end()) != hash)
+ {
+ strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
+ return false;
+ }
+
+ fSkipCheck = true;
}
- if (key.GetPubKey() != vchPubKey)
+
+ if (!key.Load(pkey, vchPubKey, fSkipCheck))
{
- strErr = "Error reading wallet database: CPrivKey pubkey inconsistency";
+ strErr = "Error reading wallet database: CPrivKey corrupt";
return false;
}
if (!pwallet->LoadKey(key, vchPubKey))
diff --git a/src/walletdb.h b/src/walletdb.h
index 09ebebe5ac..b6d0d45449 100644
--- a/src/walletdb.h
+++ b/src/walletdb.h
@@ -1,5 +1,5 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2012 The Bitcoin developers
+// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WALLETDB_H
@@ -93,8 +93,14 @@ public:
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
keyMeta))
return false;
-
- return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
+
+ // hash pubkey/privkey to accelerate wallet load
+ std::vector<unsigned char> vchKey;
+ vchKey.reserve(vchPubKey.size() + vchPrivKey.size());
+ vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
+ vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end());
+
+ return Write(std::make_pair(std::string("key"), vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey.begin(), vchKey.end())), false);
}
bool WriteCryptedKey(const CPubKey& vchPubKey,