aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bitcoin-qt.pro2
-rw-r--r--contrib/homebrew/makefile.osx.patch5
-rw-r--r--contrib/test-patches/bitcoind-comparison.patch196
-rw-r--r--src/alert.cpp5
-rw-r--r--src/base58.h107
-rw-r--r--src/bitcoind.cpp4
-rw-r--r--src/bitcoinrpc.cpp19
-rw-r--r--src/bitcoinrpc.h4
-rw-r--r--src/chainparams.cpp286
-rw-r--r--src/chainparams.h102
-rw-r--r--src/checkpoints.cpp4
-rw-r--r--src/core.h127
-rw-r--r--src/db.cpp11
-rw-r--r--src/db.h4
-rw-r--r--src/init.cpp27
-rwxr-xr-xsrc/leveldb/build_detect_platform6
-rw-r--r--src/main.cpp481
-rw-r--r--src/main.h319
-rw-r--r--src/makefile.linux-mingw3
-rw-r--r--src/makefile.mingw3
-rw-r--r--src/makefile.osx3
-rw-r--r--src/makefile.unix3
-rw-r--r--src/net.cpp152
-rw-r--r--src/protocol.cpp6
-rw-r--r--src/protocol.h11
-rw-r--r--src/qt/clientmodel.cpp3
-rw-r--r--src/rpcblockchain.cpp18
-rw-r--r--src/rpcdump.cpp206
-rw-r--r--src/rpcmining.cpp3
-rw-r--r--src/rpcnet.cpp2
-rw-r--r--src/rpcwallet.cpp2
-rw-r--r--src/script.cpp36
-rw-r--r--src/script.h1
-rw-r--r--src/test/DoS_tests.cpp3
-rw-r--r--src/test/base58_tests.cpp21
-rw-r--r--src/test/checkblock_tests.cpp2
-rw-r--r--src/txdb.cpp3
-rw-r--r--src/util.cpp6
-rw-r--r--src/util.h1
-rw-r--r--src/wallet.cpp92
-rw-r--r--src/wallet.h12
-rw-r--r--src/walletdb.cpp15
-rw-r--r--src/walletdb.h14
43 files changed, 1306 insertions, 1024 deletions
diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro
index 8f49dccee3..1d62941e68 100644
--- a/bitcoin-qt.pro
+++ b/bitcoin-qt.pro
@@ -147,6 +147,7 @@ HEADERS += src/qt/bitcoingui.h \
src/addrman.h \
src/base58.h \
src/bignum.h \
+ src/chainparams.h \
src/checkpoints.h \
src/compat.h \
src/sync.h \
@@ -227,6 +228,7 @@ SOURCES += src/qt/bitcoin.cpp \
src/qt/editaddressdialog.cpp \
src/qt/bitcoinaddressvalidator.cpp \
src/alert.cpp \
+ src/chainparams.cpp \
src/version.cpp \
src/sync.cpp \
src/util.cpp \
diff --git a/contrib/homebrew/makefile.osx.patch b/contrib/homebrew/makefile.osx.patch
index 340de0efdf..287db2fdf2 100644
--- a/contrib/homebrew/makefile.osx.patch
+++ b/contrib/homebrew/makefile.osx.patch
@@ -1,5 +1,5 @@
diff --git a/src/makefile.osx b/src/makefile.osx
-index 8b7c559..8a0560c 100644
+index bef0ef3..07ef8d3 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -7,17 +7,21 @@
@@ -28,7 +28,7 @@ index 8b7c559..8a0560c 100644
USE_UPNP:=1
USE_IPV6:=1
-@@ -31,13 +35,13 @@ ifdef STATIC
+@@ -31,14 +35,14 @@ ifdef STATIC
TESTLIBS += \
$(DEPSDIR)/lib/libboost_unit_test_framework-mt.a
LIBS += \
@@ -38,6 +38,7 @@ index 8b7c559..8a0560c 100644
$(DEPSDIR)/lib/libboost_filesystem-mt.a \
$(DEPSDIR)/lib/libboost_program_options-mt.a \
$(DEPSDIR)/lib/libboost_thread-mt.a \
+ $(DEPSDIR)/lib/libboost_chrono-mt.a \
- $(DEPSDIR)/lib/libssl.a \
- $(DEPSDIR)/lib/libcrypto.a \
+ $(OPENSSLDIR)/lib/libssl.a \
diff --git a/contrib/test-patches/bitcoind-comparison.patch b/contrib/test-patches/bitcoind-comparison.patch
deleted file mode 100644
index f82b102e2a..0000000000
--- a/contrib/test-patches/bitcoind-comparison.patch
+++ /dev/null
@@ -1,196 +0,0 @@
-diff --git a/contrib/test-patches/bitcoind-comparison.patch b/contrib/test-patches/bitcoind-comparison.patch
-index 04a8618..519429a 100644
---- a/src/main.cpp
-+++ b/src/main.cpp
-@@ -31,8 +31,8 @@ CTxMemPool mempool;
-
- map<uint256, CBlockIndex*> mapBlockIndex;
- std::vector<CBlockIndex*> vBlockIndexByHeight;
--uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
--static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
-+uint256 hashGenesisBlock("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206");
-+static CBigNum bnProofOfWorkLimit(~uint256(0) >> 1);
- CBlockIndex* pindexGenesisBlock = NULL;
- int nBestHeight = -1;
- uint256 nBestChainWork = 0;
-@@ -1055,7 +1055,7 @@ int64 static GetBlockValue(int nHeight, int64 nFees)
- int64 nSubsidy = 50 * COIN;
-
- // Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years
-- nSubsidy >>= (nHeight / 210000);
-+ nSubsidy >>= (nHeight / 150);
-
- return nSubsidy + nFees;
- }
-@@ -2736,9 +2736,9 @@ bool InitBlockIndex() {
- block.hashPrevBlock = 0;
- block.hashMerkleRoot = block.BuildMerkleTree();
- block.nVersion = 1;
-- block.nTime = 1231006505;
-- block.nBits = 0x1d00ffff;
-- block.nNonce = 2083236893;
-+ block.nTime = 1296688602;
-+ block.nBits = 0x207fffff;
-+ block.nNonce = 2;
-
- if (fTestNet)
- {
-@@ -3024,7 +3024,7 @@ bool static AlreadyHave(const CInv& inv)
- // The message start string is designed to be unlikely to occur in normal data.
- // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
- // a large 4-byte int at any alignment.
--unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
-+unsigned char pchMessageStart[4] = { 0xfa, 0xbf, 0xb5, 0xda };
-
-
- void static ProcessGetData(CNode* pfrom)
-diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp
-index af28465..ee9a4db 100644
---- a/src/test/miner_tests.cpp
-+++ b/src/test/miner_tests.cpp
-@@ -15,34 +15,117 @@ struct {
- unsigned char extranonce;
- unsigned int nonce;
- } blockinfo[] = {
-- {4, 0xa4a3e223}, {2, 0x15c32f9e}, {1, 0x0375b547}, {1, 0x7004a8a5},
-- {2, 0xce440296}, {2, 0x52cfe198}, {1, 0x77a72cd0}, {2, 0xbb5d6f84},
-- {2, 0x83f30c2c}, {1, 0x48a73d5b}, {1, 0xef7dcd01}, {2, 0x6809c6c4},
-- {2, 0x0883ab3c}, {1, 0x087bbbe2}, {2, 0x2104a814}, {2, 0xdffb6daa},
-- {1, 0xee8a0a08}, {2, 0xba4237c1}, {1, 0xa70349dc}, {1, 0x344722bb},
-- {3, 0xd6294733}, {2, 0xec9f5c94}, {2, 0xca2fbc28}, {1, 0x6ba4f406},
-- {2, 0x015d4532}, {1, 0x6e119b7c}, {2, 0x43e8f314}, {2, 0x27962f38},
-- {2, 0xb571b51b}, {2, 0xb36bee23}, {2, 0xd17924a8}, {2, 0x6bc212d9},
-- {1, 0x630d4948}, {2, 0x9a4c4ebb}, {2, 0x554be537}, {1, 0xd63ddfc7},
-- {2, 0xa10acc11}, {1, 0x759a8363}, {2, 0xfb73090d}, {1, 0xe82c6a34},
-- {1, 0xe33e92d7}, {3, 0x658ef5cb}, {2, 0xba32ff22}, {5, 0x0227a10c},
-- {1, 0xa9a70155}, {5, 0xd096d809}, {1, 0x37176174}, {1, 0x830b8d0f},
-- {1, 0xc6e3910e}, {2, 0x823f3ca8}, {1, 0x99850849}, {1, 0x7521fb81},
-- {1, 0xaacaabab}, {1, 0xd645a2eb}, {5, 0x7aea1781}, {5, 0x9d6e4b78},
-- {1, 0x4ce90fd8}, {1, 0xabdc832d}, {6, 0x4a34f32a}, {2, 0xf2524c1c},
-- {2, 0x1bbeb08a}, {1, 0xad47f480}, {1, 0x9f026aeb}, {1, 0x15a95049},
-- {2, 0xd1cb95b2}, {2, 0xf84bbda5}, {1, 0x0fa62cd1}, {1, 0xe05f9169},
-- {1, 0x78d194a9}, {5, 0x3e38147b}, {5, 0x737ba0d4}, {1, 0x63378e10},
-- {1, 0x6d5f91cf}, {2, 0x88612eb8}, {2, 0xe9639484}, {1, 0xb7fabc9d},
-- {2, 0x19b01592}, {1, 0x5a90dd31}, {2, 0x5bd7e028}, {2, 0x94d00323},
-- {1, 0xa9b9c01a}, {1, 0x3a40de61}, {1, 0x56e7eec7}, {5, 0x859f7ef6},
-- {1, 0xfd8e5630}, {1, 0x2b0c9f7f}, {1, 0xba700e26}, {1, 0x7170a408},
-- {1, 0x70de86a8}, {1, 0x74d64cd5}, {1, 0x49e738a1}, {2, 0x6910b602},
-- {0, 0x643c565f}, {1, 0x54264b3f}, {2, 0x97ea6396}, {2, 0x55174459},
-- {2, 0x03e8779a}, {1, 0x98f34d8f}, {1, 0xc07b2b07}, {1, 0xdfe29668},
-- {1, 0x3141c7c1}, {1, 0xb3b595f4}, {1, 0x735abf08}, {5, 0x623bfbce},
-- {2, 0xd351e722}, {1, 0xf4ca48c9}, {1, 0x5b19c670}, {1, 0xa164bf0e},
-- {2, 0xbbbeb305}, {2, 0xfe1c810a},
-+{4, 2762203683},
-+{2, 365113248},
-+{1, 58045772},
-+{1, 1879353512},
-+{2, 3460563607},
-+{2, 1389355416},
-+{1, 2007444690},
-+{2, 3143462790},
-+{2, 2213743660},
-+{1, 1218919771},
-+{1, 4017999107},
-+{2, 1745471173},
-+{2, 142846780},
-+{1, 142326754},
-+{2, 553953301},
-+{2, 3757796778},
-+{1, 4002023946},
-+{2, 3124901826},
-+{1, 2802010589},
-+{1, 877077181},
-+{3, 3593029427},
-+{2, 3969866902},
-+{2, 3392125996},
-+{1, 1805972490},
-+{2, 22889779},
-+{1, 1846647676},
-+{2, 1139340052},
-+{2, 664153912},
-+{2, 3044128027},
-+{2, 3010194979},
-+{2, 3514377385},
-+{2, 1807880922},
-+{1, 1661815113},
-+{2, 2588692156},
-+{2, 1431037239},
-+{1, 3594379210},
-+{2, 2701839377},
-+{1, 1973060452},
-+{2, 4218620174},
-+{1, 3895224884},
-+{1, 3812528857},
-+{3, 1703867851},
-+{2, 3123904294},
-+{5, 36151564},
-+{1, 2846294357},
-+{5, 3499546633},
-+{1, 924279160},
-+{1, 2198572304},
-+{1, 3336802574},
-+{2, 2185182379},
-+{1, 2575632458},
-+{1, 1965161345},
-+{1, 2865408940},
-+{1, 3594887915},
-+{5, 2062161796},
-+{5, 2641251194},
-+{1, 1290342362},
-+{1, 2883355438},
-+{6, 1244984107},
-+{2, 4065479712},
-+{2, 465481866},
-+{1, 2907174016},
-+{1, 2667735788},
-+{1, 363417673},
-+{2, 3519780275},
-+{2, 4165713317},
-+{1, 262548689},
-+{1, 3764359529},
-+{1, 2027001003},
-+{5, 1043862655},
-+{5, 1937481940},
-+{1, 1664585233},
-+{1, 1834979792},
-+{2, 2288070330},
-+{2, 3915617412},
-+{1, 3086662813},
-+{2, 430970259},
-+{1, 1519443249},
-+{2, 1540874280},
-+{2, 2496660261},
-+{1, 2847522842},
-+{1, 977329763},
-+{1, 1458040519},
-+{5, 2241822454},
-+{1, 4253963824},
-+{1, 722247551},
-+{1, 3127905834},
-+{1, 1903207432},
-+{1, 1893631657},
-+{1, 1960201429},
-+{1, 1239890082},
-+{2, 1762702850},
-+{0, 1681675873},
-+{1, 1411795775},
-+{2, 2548720534},
-+{2, 1427588186},
-+{2, 65566621},
-+{1, 2566081936},
-+{1, 3229297415},
-+{1, 3756168812},
-+{1, 826394561},
-+{1, 3015022068},
-+{1, 1935326986},
-+{5, 1648098256},
-+{2, 3545360164},
-+{1, 4106897609},
-+{1, 1528415857},
-+{1, 2707734286},
-+{2, 3149837061},
-+{2, 4263280906},
-+
- };
-
- // NOTE: These tests rely on CreateNewBlock doing its own self-validation!
diff --git a/src/alert.cpp b/src/alert.cpp
index 44f4d5eec6..e00847aadb 100644
--- a/src/alert.cpp
+++ b/src/alert.cpp
@@ -19,9 +19,6 @@ using namespace std;
map<uint256, CAlert> mapAlerts;
CCriticalSection cs_mapAlerts;
-static const char* pszMainKey = "04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284";
-static const char* pszTestKey = "04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a";
-
void CUnsignedAlert::SetNull()
{
nVersion = 1;
@@ -144,7 +141,7 @@ bool CAlert::RelayTo(CNode* pnode) const
bool CAlert::CheckSignature() const
{
- CPubKey key(ParseHex(fTestNet ? pszTestKey : pszMainKey));
+ CPubKey key(Params().AlertKey());
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
return error("CAlert::CheckSignature() : verify signature failed");
diff --git a/src/base58.h b/src/base58.h
index efe3a95ebd..630d6fe9aa 100644
--- a/src/base58.h
+++ b/src/base58.h
@@ -18,6 +18,7 @@
#include <string>
#include <vector>
+#include "chainparams.h"
#include "bignum.h"
#include "key.h"
#include "script.h"
@@ -270,21 +271,13 @@ public:
class CBitcoinAddress : public CBase58Data
{
public:
- enum
- {
- PUBKEY_ADDRESS = 0,
- SCRIPT_ADDRESS = 5,
- PUBKEY_ADDRESS_TEST = 111,
- SCRIPT_ADDRESS_TEST = 196,
- };
-
bool Set(const CKeyID &id) {
- SetData(fTestNet ? PUBKEY_ADDRESS_TEST : PUBKEY_ADDRESS, &id, 20);
+ SetData(Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS), &id, 20);
return true;
}
bool Set(const CScriptID &id) {
- SetData(fTestNet ? SCRIPT_ADDRESS_TEST : SCRIPT_ADDRESS, &id, 20);
+ SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
return true;
}
@@ -295,32 +288,10 @@ public:
bool IsValid() const
{
- unsigned int nExpectedSize = 20;
- bool fExpectTestNet = false;
- switch(nVersion)
- {
- case PUBKEY_ADDRESS:
- nExpectedSize = 20; // Hash of public key
- fExpectTestNet = false;
- break;
- case SCRIPT_ADDRESS:
- nExpectedSize = 20; // Hash of CScript
- fExpectTestNet = false;
- break;
-
- case PUBKEY_ADDRESS_TEST:
- nExpectedSize = 20;
- fExpectTestNet = true;
- break;
- case SCRIPT_ADDRESS_TEST:
- nExpectedSize = 20;
- fExpectTestNet = true;
- break;
-
- default:
- return false;
- }
- return fExpectTestNet == fTestNet && vchData.size() == nExpectedSize;
+ bool fCorrectSize = vchData.size() == 20;
+ bool fKnownVersion = nVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
+ nVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
+ return fCorrectSize && fKnownVersion;
}
CBitcoinAddress()
@@ -345,48 +316,27 @@ public:
CTxDestination Get() const {
if (!IsValid())
return CNoDestination();
- switch (nVersion) {
- case PUBKEY_ADDRESS:
- case PUBKEY_ADDRESS_TEST: {
- uint160 id;
- memcpy(&id, &vchData[0], 20);
+ uint160 id;
+ memcpy(&id, &vchData[0], 20);
+ if (nVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
return CKeyID(id);
- }
- case SCRIPT_ADDRESS:
- case SCRIPT_ADDRESS_TEST: {
- uint160 id;
- memcpy(&id, &vchData[0], 20);
+ else if (nVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
return CScriptID(id);
- }
- }
- return CNoDestination();
+ else
+ return CNoDestination();
}
bool GetKeyID(CKeyID &keyID) const {
- if (!IsValid())
+ if (!IsValid() || nVersion != Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
return false;
- switch (nVersion) {
- case PUBKEY_ADDRESS:
- case PUBKEY_ADDRESS_TEST: {
- uint160 id;
- memcpy(&id, &vchData[0], 20);
- keyID = CKeyID(id);
- return true;
- }
- default: return false;
- }
+ uint160 id;
+ memcpy(&id, &vchData[0], 20);
+ keyID = CKeyID(id);
+ return true;
}
bool IsScript() const {
- if (!IsValid())
- return false;
- switch (nVersion) {
- case SCRIPT_ADDRESS:
- case SCRIPT_ADDRESS_TEST: {
- return true;
- }
- default: return false;
- }
+ return IsValid() && nVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
}
};
@@ -401,7 +351,7 @@ public:
void SetKey(const CKey& vchSecret)
{
assert(vchSecret.IsValid());
- SetData(fTestNet ? 239 : 128, vchSecret.begin(), vchSecret.size());
+ SetData(Params().Base58Prefix(CChainParams::SECRET_KEY), vchSecret.begin(), vchSecret.size());
if (vchSecret.IsCompressed())
vchData.push_back(1);
}
@@ -415,20 +365,9 @@ public:
bool IsValid() const
{
- bool fExpectTestNet = false;
- switch(nVersion)
- {
- case 128:
- break;
-
- case 239:
- fExpectTestNet = true;
- break;
-
- default:
- return false;
- }
- return fExpectTestNet == fTestNet && (vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1));
+ bool fExpectedFormat = vchData.size() == 32 || (vchData.size() == 33 && vchData[32] == 1);
+ bool fCorrectVersion = nVersion == Params().Base58Prefix(CChainParams::SECRET_KEY);
+ return fExpectedFormat && fCorrectVersion;
}
bool SetString(const char* pszSecret)
diff --git a/src/bitcoind.cpp b/src/bitcoind.cpp
index 682a214fb2..bc23cf5507 100644
--- a/src/bitcoind.cpp
+++ b/src/bitcoind.cpp
@@ -67,6 +67,10 @@ bool AppInit(int argc, char* argv[])
if (fCommandLine)
{
+ if (!SelectParamsFromCommandLine()) {
+ fprintf(stderr, "Error: invalid combination of -regtest and -testnet.\n");
+ return false;
+ }
int ret = CommandLineRPC(argc, argv);
exit(ret);
}
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index 285a88c8d8..5908126200 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -3,6 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "init.h"
#include "util.h"
#include "sync.h"
@@ -38,11 +39,6 @@ static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
static ssl::context* rpc_ssl_context = NULL;
static boost::thread_group* rpc_worker_group = NULL;
-static inline unsigned short GetDefaultRPCPort()
-{
- return GetBoolArg("-testnet", false) ? 18332 : 8332;
-}
-
Object JSONRPCError(int code, const string& message)
{
Object error;
@@ -247,7 +243,9 @@ static const CRPCCommand vRPCCommands[] =
{ "submitblock", &submitblock, false, false },
{ "listsinceblock", &listsinceblock, false, false },
{ "dumpprivkey", &dumpprivkey, true, false },
+ { "dumpwallet", &dumpwallet, true, false },
{ "importprivkey", &importprivkey, false, false },
+ { "importwallet", &importwallet, false, false },
{ "listunspent", &listunspent, false, false },
{ "getrawtransaction", &getrawtransaction, false, false },
{ "createrawtransaction", &createrawtransaction, false, false },
@@ -258,6 +256,7 @@ static const CRPCCommand vRPCCommands[] =
{ "gettxout", &gettxout, true, false },
{ "lockunspent", &lockunspent, false, false },
{ "listlockunspent", &listlockunspent, false, false },
+ { "verifychain", &verifychain, true, false },
};
CRPCTable::CRPCTable()
@@ -724,8 +723,8 @@ static void RPCAcceptHandler(boost::shared_ptr< basic_socket_acceptor<Protocol,
void StartRPCThreads()
{
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
- if ((mapArgs["-rpcpassword"] == "") ||
- (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"]))
+ if (((mapArgs["-rpcpassword"] == "") ||
+ (mapArgs["-rpcuser"] == mapArgs["-rpcpassword"])) && Params().RequireRPCPassword())
{
unsigned char rand_pwd[32];
RAND_bytes(rand_pwd, 32);
@@ -780,7 +779,7 @@ void StartRPCThreads()
// Try a dual IPv6/IPv4 socket, falling back to separate IPv4 and IPv6 sockets
const bool loopback = !mapArgs.count("-rpcallowip");
asio::ip::address bindAddress = loopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any();
- ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", GetDefaultRPCPort()));
+ ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", Params().RPCPort()));
boost::system::error_code v6_only_error;
boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(*rpc_io_service));
@@ -1078,7 +1077,7 @@ Object CallRPC(const string& strMethod, const Array& params)
asio::ssl::stream<asio::ip::tcp::socket> sslStream(io_service, context);
SSLIOStreamDevice<asio::ip::tcp> d(sslStream, fUseSSL);
iostreams::stream< SSLIOStreamDevice<asio::ip::tcp> > stream(d);
- if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(GetDefaultRPCPort()))))
+ if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", itostr(Params().RPCPort()))))
throw runtime_error("couldn't connect to server");
// HTTP basic authentication
@@ -1198,6 +1197,8 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "lockunspent" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "lockunspent" && n > 1) ConvertTo<Array>(params[1]);
if (strMethod == "importprivkey" && n > 2) ConvertTo<bool>(params[2]);
+ if (strMethod == "verifychain" && n > 0) ConvertTo<boost::int64_t>(params[0]);
+ if (strMethod == "verifychain" && n > 1) ConvertTo<boost::int64_t>(params[1]);
return params;
}
diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h
index 44c657f8dc..247c47adf9 100644
--- a/src/bitcoinrpc.h
+++ b/src/bitcoinrpc.h
@@ -145,8 +145,11 @@ extern json_spirit::Value getconnectioncount(const json_spirit::Array& params, b
extern json_spirit::Value getpeerinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp);
+
extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp
extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getgenerate(const json_spirit::Array& params, bool fHelp); // in rpcmining.cpp
extern json_spirit::Value setgenerate(const json_spirit::Array& params, bool fHelp);
@@ -205,5 +208,6 @@ extern json_spirit::Value getblockhash(const json_spirit::Array& params, bool fH
extern json_spirit::Value getblock(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
#endif
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
new file mode 100644
index 0000000000..8859424d20
--- /dev/null
+++ b/src/chainparams.cpp
@@ -0,0 +1,286 @@
+// Copyright (c) 2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 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 "assert.h"
+
+#include "chainparams.h"
+#include "main.h"
+#include "util.h"
+
+//
+// Main network
+//
+
+unsigned int pnSeed[] =
+{
+ 0xe473042e, 0xb177f2ad, 0xd63f3fb2, 0xf864f736, 0x44a23ac7, 0xcf6d9650, 0xd648042e, 0x0536f447,
+ 0x3c654ed0, 0x3e16a5bc, 0xa38e09b0, 0xdfae795b, 0xabfeca5b, 0x94ad7840, 0xf3b9f1c7, 0xbe70e0ad,
+ 0x3bbd09b0, 0x8d0c7dd5, 0x3b2a7332, 0x1a06175e, 0x581f175e, 0xca0d2dcc, 0x0fdbc658, 0xcf591ec7,
+ 0x295a12b2, 0xb4707bce, 0x68bb09b0, 0x4e735747, 0x89709553, 0x05a7814e, 0x5b8ec658, 0x402c5512,
+ 0xe80d0905, 0x17681a5e, 0xc02aa748, 0x9f811741, 0x5f321cb0, 0x23e1ee47, 0xaf7f170c, 0xaa240ab0,
+ 0xedea6257, 0x76106bc1, 0x2cf310cc, 0x08612acb, 0x9c682e4e, 0x8e963c6c, 0x443c795b, 0x22e246b8,
+ 0xfa1f2dcc, 0x90118140, 0x3821042e, 0x33c3fd2e, 0x10046d5b, 0x40d14b3e, 0x7fb8f8ce, 0x67696550,
+ 0xeeecbe58, 0x4f341745, 0x46b8fbd5, 0xc8463932, 0x6b73e862, 0x4c715932, 0x4a6785d5, 0xce3a64c2,
+ 0xde9604c7, 0x9b06884f, 0x18002a45, 0xea9bc345, 0xc4f1c658, 0xe475c1c7, 0xdd3e795b, 0x9722175e,
+ 0x34562f4e, 0x66c46e4e, 0x40bb1243, 0x7d9171d0, 0x17b8dbd5, 0x63cbfd2e, 0x1a08b8d8, 0x6175a73b,
+ 0x228d2660, 0x8627c658, 0x9c566644, 0x38cca5bc, 0x3089de5b, 0x92e25f5d, 0xa393f73f, 0xcc92dc3e,
+ 0x27487446, 0x62cbfd2e, 0x9d983b45, 0xf72a09b0, 0xf75f042e, 0x6434bb6a, 0xb29e77d8, 0x19be4fd9,
+ 0x76443243, 0x9dd72645, 0x694cef43, 0x89c2efd5, 0x5f1c5058, 0x46c6e45b, 0xe1391b40, 0x77ccefd5,
+ 0x472e5a6d, 0x85709553, 0xdd4f5d4c, 0x64ef5a46, 0x7f0ae502, 0xcf08d850, 0x3460042e, 0xeafa2d42,
+ 0x793c9044, 0x9d094746, 0x1ab9b153, 0xbfe9a5bc, 0x34771fb0, 0xb7722e32, 0x1168964b, 0x19b06ab8,
+ 0x19243b25, 0x13188045, 0xb4070905, 0x728ebb5d, 0x44f24ac8, 0xa317fead, 0x642f6a57, 0x3d951f32,
+ 0x3d312e4e, 0xfac4d048, 0xefc4dd50, 0x52b9f1c7, 0xc14d3cc3, 0x0219ea44, 0x3b79d058, 0xfa217242,
+ 0x39c80647, 0xfb697252, 0x1d495a42, 0x0aa81f4e, 0x58249ab8, 0xe6a8e6c3, 0x2bc4dad8, 0x85963c6c,
+ 0xa4ce09b0, 0x2005f536, 0x5cc2703e, 0x1992de43, 0x74e86b4c, 0xe7085653, 0xf5e15a51, 0xb4872b60,
+ 0x29e2b162, 0xa07ea053, 0x8229fd18, 0x4562ec4d, 0x8dec814e, 0x36cfa4cf, 0x96461032, 0x3c8770de,
+ 0xd10a1f5f, 0x95934641, 0x97cd65d0, 0x2e35324a, 0x2566ba1f, 0x1ca1a9d1, 0xb808b8d5, 0xf9a24a5d,
+ 0xafc8d431, 0xe4b8d9b2, 0x0f5321b2, 0x330bc658, 0x74b347ce, 0x972babd5, 0x044f7d4f, 0x06562f4e,
+ 0x8b8d3c6c, 0x3507c658, 0xe4174e4d, 0xf1c009b0, 0x52249ab8, 0x27211772, 0xf6a9ba59, 0x7a391b40,
+ 0x855dc6c0, 0x291f20b2, 0xe29bc345, 0x90963c6c, 0x0af70732, 0x4242a91f, 0x4c531d48, 0xa32df948,
+ 0x627e3044, 0x65be1f54, 0x1a0cbf83, 0x6a443532, 0x8d5f1955, 0xbafa8132, 0x3534bdd5, 0xca019dd9,
+ 0x8a0d9332, 0x5584e7d8, 0x7cd1f25e, 0xeabe3fb2, 0x2945d0d1, 0x46415718, 0x70d6042e, 0x99eb76d0,
+ 0x9ece09b0, 0xb3777418, 0x5e5e91d9, 0x237a3ab0, 0xf512b62e, 0x45dec347, 0x59b7f862, 0x4c443b25,
+ 0x3cc6484b, 0x9a8ec6d1, 0x021eea44, 0xc9483944, 0xfd567e32, 0xfd204bb2, 0xc5330bcc, 0x5202894e,
+ 0xf9e309b0, 0x4cc17557, 0xdb9064ae, 0xe19e77d8, 0x25857f60, 0xeb4a15ad, 0x1f47f554, 0xea4472d9,
+ 0xd20de593, 0xf5733b25, 0x11892b54, 0x5729d35f, 0xe6188cd1, 0x488b132e, 0x541c534a, 0xa8e854ae,
+ 0xa255a66c, 0x33688763, 0xc6629ac6, 0xc20a6265, 0xcd92a059, 0x72029d3b, 0x4c298f5e, 0x51452e4e,
+ 0xbb065058, 0x15fd2dcc, 0xf40c135e, 0x615a0bad, 0x0c6a6805, 0x4971a7ad, 0x17f2a5d5, 0xf8babf47,
+ 0xb61f50ad, 0x4e1451b1, 0xf72d9252, 0x5c2abe58, 0xbd987c61, 0x084ae5cf, 0x20781fb0, 0x38b0f160,
+ 0x18aac705, 0x14f86dc1, 0x5556f481, 0x0a36c144, 0xeb446e4c, 0x2c1c0d6c, 0xbd0ff860, 0x869f92db,
+ 0x36c94f4c, 0x05502444, 0x148fe55b, 0xd5301e59, 0xd57a8f45, 0x110dc04a, 0x8670fc36, 0xee733b25,
+ 0xca56f481, 0x2a5c3bae, 0x844b0905, 0x1e51fe53, 0x0241c244, 0x59c0614e, 0x94e70a55, 0x7312fead,
+ 0xb735be44, 0xa55d0905, 0x2f63962e, 0x14a4e15b, 0x63f8f05c, 0x62d0d262, 0x3cab41ad, 0x87f1b1cb,
+ 0x018da6b8, 0xb3967dd5, 0xcb56f481, 0x685ad718, 0x3b4aeeca, 0x8d106bc1, 0x51180905, 0x72660f48,
+ 0x1521a243, 0x5b56f481, 0x6390e560, 0xdd61464e, 0x58353b25, 0x553fc062, 0x27c45d59, 0xacc62e4e,
+ 0x0d5a1cd9, 0x7f65f442, 0xbdeef660, 0xf1bd1855, 0xf8473cae, 0x13b120b2, 0x442440d0, 0x53fd4352,
+ 0xa305fc57, 0x458be84d, 0x639ce1c3, 0xebaaee47, 0x95e2c247, 0xf056f481, 0x6256f481, 0x1d87c65e,
+ 0x0a453418, 0x5beb175e, 0xd64f1618, 0xc360795b, 0x2fbf5753, 0xa8c58e53, 0x651cec52, 0x9d37b043,
+ 0x124a9758, 0x5242e4a9, 0x89913c6c, 0x880efe2e, 0x2f2f2f0c, 0x72b26751, 0x2896e46d, 0x80f4166c,
+ 0x320d59ad, 0xc50151d0, 0x11a8aa43, 0xccf56057, 0x5fbad118, 0x4719b151, 0x2b5f4bc0, 0x4d7a4a50,
+ 0xad06e047, 0x62ef5a46, 0x5aebde58, 0xdf7aa66c, 0x851acb50, 0x66b9a559, 0x3e9bb153, 0xcc512f2e,
+ 0xc073b08e, 0xd519be58, 0xe981ea4d, 0x12fd50cb, 0x378739ad, 0x06683cae, 0xa22310b2, 0xc185c705,
+ 0x8741b545, 0xa26c8318, 0x22d5bc43, 0x39201ec0, 0x68581e3e, 0xdc9bcf62, 0xd508cc82, 0xb149675b,
+ 0x4c9609b0, 0x84feb84c, 0x08291e2e, 0xfd2253b2, 0x1fd269c1, 0xc9483932, 0x4d641fb0, 0x7d37c918,
+ 0xa9de20ad, 0x77e2d655, 0x6d421b59, 0xd7668f80, 0xced09b62, 0xa9e5a5bc, 0xa4074e18, 0x60fc5ecc,
+ 0x01300148, 0x68062444, 0xb4224847, 0xed3aa443, 0xb772fb43, 0x9f56f481, 0x220dfd18, 0x8e1c3d6c,
+ 0xc44f09b0, 0x7df2bb73, 0xe22fb844, 0xea534242, 0xb6a755d4, 0xa036654b, 0x138ece5b, 0xda65d3c3,
+ 0x955871bc, 0x792124b0, 0xfc82594c, 0x851d494b, 0x2c7aee47, 0x26af46b8, 0x1416252e, 0xa8abb944,
+ 0x36c49d25, 0x674f645d, 0x363646b8, 0x9e1a2942, 0x66d0c154, 0xc6c2a545, 0x3570f2ad, 0xe7d547c7,
+ 0x7d104932, 0x18cb9c18, 0x1dcfa4cf, 0xd156f481, 0x2a02b91f, 0x3eeb3fa8, 0xcac4175e, 0x34146d42,
+ 0x994c4d46, 0x5666f440, 0x85d6713e, 0x5ecb296c, 0x0ea0ae46, 0x87e69f42, 0xc58409b0, 0x1f3436ae,
+ 0x21dc6a57, 0x4ad1cd42, 0xfb8c1a4c, 0x52d3dab2, 0x3769894b, 0xb52f1c62, 0x3677916d, 0x82b3fe57,
+ 0x493d4ac6, 0x9f963c6c, 0x5d91ff60, 0x458e0dad, 0xa49d0947, 0x491a3e18, 0x4aadcd5b, 0x0e46494b,
+ 0x1d1610ad, 0x1a10af5d, 0x4956f481, 0x207a3eae, 0x77e73244, 0xfa3b8742, 0x3261fc36, 0xfcebf536,
+ 0x1662e836, 0xf655f636, 0xa2dbd0ad, 0x23036693, 0x30448432, 0xa2b03463, 0x30730344, 0x8e4a6882,
+ 0x0c50a1cb, 0xc8d8c06b, 0xc9cd6191, 0xf443db50, 0xa9553c50, 0x23145847, 0xc35da66c, 0x29c12a60,
+ 0x55c2b447, 0x7434f75c, 0x61660640, 0xde2a7018, 0xc639494c, 0x1c306fce, 0x19b89244, 0xd29a6462,
+ 0x462cd1b2, 0x29902f44, 0x2817fa53, 0x21a30905, 0x7777ae46, 0x288443a1, 0x7bee5148, 0xc2a8b043,
+ 0xf5c3d35f, 0x2311ef84, 0x57de08a4, 0x6b221bb2, 0xf2625846, 0x4b9e09b0, 0xa24f880e, 0x22b11447,
+ 0xb3a0c744, 0x919e77d8, 0xec8b64ae, 0xff5c8d45, 0x7b15b484, 0x32679a5f, 0xba80b62e, 0x05c25c61,
+ 0x60014746, 0x5e8fb04c, 0xe67c0905, 0x4329c658, 0xac8fe555, 0xf875e647, 0x67406386, 0x35ceea18,
+ 0xbb79484b, 0xd7b9fa62, 0x238209b0, 0x208a1d32, 0x9630995e, 0x039c1318, 0x6e48006c, 0x60582344,
+ 0xadbb0150, 0x853fd462, 0x03772e4e, 0x652ce960, 0x49b630ad, 0x9993af43, 0x3735b34b, 0x548a07d9,
+ 0x55a44aad, 0xa23d1bcc, 0xfdbb2f4e, 0x530b24a0, 0x0a44b451, 0x6827c657, 0x1f66494b, 0x4e680a47,
+ 0x77e7b747, 0xa5eb3fa8, 0x6649764a, 0xd4e76c4b, 0x2c691fb0, 0xf1292e44, 0xc6d6c774, 0x85d23775,
+ 0x28275f4d, 0x259ae46d, 0x02424e81, 0x5f16be58, 0xe707c658, 0x49eae5c7, 0xd5d147ad, 0x9a7abdc3,
+ 0xe8ac7fc7, 0x84ec3aae, 0xc24942d0, 0x294aa318, 0x08ac3d18, 0x8894042e, 0xb24609b0, 0x9bcaab58,
+ 0xc400f712, 0xd5c512b8, 0x2c02cc62, 0x25080fd8, 0xed74a847, 0x18a5ec5e, 0x9850ec6d, 0xf8909758,
+ 0x7f56f481, 0x4496f23c, 0xae27784f, 0xcb7cd93e, 0x06e32860, 0x50b9a84f, 0x3660434a, 0x09161f5f,
+ 0x900486bc, 0x08055459, 0xe7ec1017, 0x7e39494c, 0x4f443b25, 0x14751a8a, 0x717d03d4, 0xbd0e24d8,
+ 0x054b6f56, 0x854c496c, 0xd92a454a, 0xc39bd054, 0x6093614b, 0x9dbad754, 0x5bf0604a, 0x99f22305
+};
+
+class CMainParams : public CChainParams {
+public:
+ CMainParams() {
+ // The message start string is designed to be unlikely to occur in normal data.
+ // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
+ // a large 4-byte int at any alignment.
+ pchMessageStart[0] = 0xf9;
+ pchMessageStart[1] = 0xbe;
+ pchMessageStart[2] = 0xb4;
+ pchMessageStart[3] = 0xd9;
+ vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
+ nDefaultPort = 8333;
+ nRPCPort = 8332;
+ bnProofOfWorkLimit = CBigNum(~uint256(0) >> 32);
+ nSubsidyHalvingInterval = 210000;
+
+ // Build the genesis block. Note that the output of the genesis coinbase cannot
+ // be spent as it did not originally exist in the database.
+ //
+ // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
+ // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
+ // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
+ // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
+ // vMerkleTree: 4a5e1e
+ const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
+ CTransaction txNew;
+ txNew.vin.resize(1);
+ txNew.vout.resize(1);
+ txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
+ txNew.vout[0].nValue = 50 * COIN;
+ txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
+ genesis.vtx.push_back(txNew);
+ genesis.hashPrevBlock = 0;
+ genesis.hashMerkleRoot = genesis.BuildMerkleTree();
+ genesis.nVersion = 1;
+ genesis.nTime = 1231006505;
+ genesis.nBits = 0x1d00ffff;
+ genesis.nNonce = 2083236893;
+
+ hashGenesisBlock = genesis.GetHash();
+ assert(hashGenesisBlock == uint256("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
+ assert(genesis.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
+
+ vSeeds.push_back(CDNSSeedData("bitcoin.sipa.be", "seed.bitcoin.sipa.be"));
+ vSeeds.push_back(CDNSSeedData("bluematt.me", "dnsseed.bluematt.me"));
+ vSeeds.push_back(CDNSSeedData("dashjr.org", "dnsseed.bitcoin.dashjr.org"));
+ vSeeds.push_back(CDNSSeedData("xf2.org", "bitseed.xf2.org"));
+
+ base58Prefixes[PUBKEY_ADDRESS] = 0;
+ base58Prefixes[SCRIPT_ADDRESS] = 5;
+ base58Prefixes[SECRET_KEY] = 128;
+
+ // Convert the pnSeeds array into usable address objects.
+ for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
+ {
+ // It'll only connect to one or two seed nodes because once it connects,
+ // it'll get a pile of addresses with newer timestamps.
+ // Seed nodes are given a random 'last seen time' of between one and two
+ // weeks ago.
+ const int64 nOneWeek = 7*24*60*60;
+ struct in_addr ip;
+ memcpy(&ip, &pnSeed[i], sizeof(ip));
+ CAddress addr(CService(ip, GetDefaultPort()));
+ addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
+ vFixedSeeds.push_back(addr);
+ }
+ }
+
+ virtual const CBlock& GenesisBlock() const { return genesis; }
+ virtual Network NetworkID() const { return CChainParams::MAIN; }
+
+ virtual const vector<CAddress>& FixedSeeds() const {
+ return vFixedSeeds;
+ }
+protected:
+ CBlock genesis;
+ vector<CAddress> vFixedSeeds;
+};
+static CMainParams mainParams;
+
+
+//
+// Testnet (v3)
+//
+class CTestNetParams : public CMainParams {
+public:
+ CTestNetParams() {
+ // The message start string is designed to be unlikely to occur in normal data.
+ // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
+ // a large 4-byte int at any alignment.
+ pchMessageStart[0] = 0x0b;
+ pchMessageStart[1] = 0x11;
+ pchMessageStart[2] = 0x09;
+ pchMessageStart[3] = 0x07;
+ vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
+ nDefaultPort = 18333;
+ nRPCPort = 18332;
+ strDataDir = "testnet3";
+
+ // Modify the testnet genesis block so the timestamp is valid for a later start.
+ genesis.nTime = 1296688602;
+ genesis.nNonce = 414098458;
+ hashGenesisBlock = genesis.GetHash();
+ assert(hashGenesisBlock == uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"));
+
+ vFixedSeeds.clear();
+ vSeeds.clear();
+ vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org"));
+ vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
+
+ base58Prefixes[PUBKEY_ADDRESS] = 111;
+ base58Prefixes[SCRIPT_ADDRESS] = 196;
+ base58Prefixes[SECRET_KEY] = 239;
+
+ }
+ virtual Network NetworkID() const { return CChainParams::TESTNET; }
+};
+static CTestNetParams testNetParams;
+
+
+//
+// Regression test
+//
+class CRegTestParams : public CTestNetParams {
+public:
+ CRegTestParams() {
+ pchMessageStart[0] = 0xfa;
+ pchMessageStart[1] = 0xbf;
+ pchMessageStart[2] = 0xb5;
+ pchMessageStart[3] = 0xda;
+ nSubsidyHalvingInterval = 150;
+ bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
+ genesis.nTime = 1296688602;
+ genesis.nBits = 0x207fffff;
+ genesis.nNonce = 2;
+ hashGenesisBlock = genesis.GetHash();
+ nDefaultPort = 18444;
+ strDataDir = "regtest";
+ assert(hashGenesisBlock == uint256("0x0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206"));
+
+ vSeeds.clear(); // Regtest mode doesn't have any DNS seeds.
+
+ base58Prefixes[PUBKEY_ADDRESS] = 0;
+ base58Prefixes[SCRIPT_ADDRESS] = 5;
+ base58Prefixes[SECRET_KEY] = 128;
+ }
+
+ virtual bool RequireRPCPassword() const { return false; }
+ virtual Network NetworkID() const { return CChainParams::REGTEST; }
+};
+static CRegTestParams regTestParams;
+
+static CChainParams *pCurrentParams = &mainParams;
+
+const CChainParams &Params() {
+ return *pCurrentParams;
+}
+
+void SelectParams(CChainParams::Network network) {
+ switch (network) {
+ case CChainParams::MAIN:
+ pCurrentParams = &mainParams;
+ break;
+ case CChainParams::TESTNET:
+ pCurrentParams = &testNetParams;
+ break;
+ case CChainParams::REGTEST:
+ pCurrentParams = &regTestParams;
+ break;
+ default:
+ assert(false && "Unimplemented network");
+ return;
+ }
+}
+
+bool SelectParamsFromCommandLine() {
+ bool fRegTest = GetBoolArg("-regtest", false);
+ bool fTestNet = GetBoolArg("-testnet", false);
+
+ if (fTestNet && fRegTest) {
+ return false;
+ }
+
+ if (fRegTest) {
+ SelectParams(CChainParams::REGTEST);
+ } else if (fTestNet) {
+ SelectParams(CChainParams::TESTNET);
+ } else {
+ SelectParams(CChainParams::MAIN);
+ }
+ return true;
+}
diff --git a/src/chainparams.h b/src/chainparams.h
new file mode 100644
index 0000000000..572712b589
--- /dev/null
+++ b/src/chainparams.h
@@ -0,0 +1,102 @@
+// Copyright (c) 2009-2010 Satoshi Nakamoto
+// 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_CHAIN_PARAMS_H
+#define BITCOIN_CHAIN_PARAMS_H
+
+#include "bignum.h"
+#include "uint256.h"
+#include "util.h"
+
+#include <vector>
+
+using namespace std;
+
+#define MESSAGE_START_SIZE 4
+typedef unsigned char MessageStartChars[MESSAGE_START_SIZE];
+
+class CAddress;
+class CBlock;
+
+struct CDNSSeedData {
+ string name, host;
+ CDNSSeedData(const string &strName, const string &strHost) : name(strName), host(strHost) {}
+};
+
+/**
+ * CChainParams defines various tweakable parameters of a given instance of the
+ * Bitcoin system. There are three: the main network on which people trade goods
+ * and services, the public test network which gets reset from time to time and
+ * a regression test mode which is intended for private networks only. It has
+ * minimal difficulty to ensure that blocks can be found instantly.
+ */
+class CChainParams
+{
+public:
+ enum Network {
+ MAIN,
+ TESTNET,
+ REGTEST,
+ };
+
+ enum Base58Type {
+ PUBKEY_ADDRESS,
+ SCRIPT_ADDRESS,
+ SECRET_KEY,
+
+ MAX_BASE58_TYPES
+ };
+
+ const uint256& HashGenesisBlock() const { return hashGenesisBlock; }
+ const MessageStartChars& MessageStart() const { return pchMessageStart; }
+ const vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
+ int GetDefaultPort() const { return nDefaultPort; }
+ const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
+ int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; }
+ virtual const CBlock& GenesisBlock() const = 0;
+ virtual bool RequireRPCPassword() const { return true; }
+ const string& DataDir() const { return strDataDir; }
+ virtual Network NetworkID() const = 0;
+ const vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
+ int Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
+ virtual const vector<CAddress>& FixedSeeds() const = 0;
+ int RPCPort() const { return nRPCPort; }
+protected:
+ CChainParams() {};
+
+ uint256 hashGenesisBlock;
+ MessageStartChars pchMessageStart;
+ // Raw pub key bytes for the broadcast alert signing key.
+ vector<unsigned char> vAlertPubKey;
+ int nDefaultPort;
+ int nRPCPort;
+ CBigNum bnProofOfWorkLimit;
+ int nSubsidyHalvingInterval;
+ string strDataDir;
+ vector<CDNSSeedData> vSeeds;
+ int base58Prefixes[MAX_BASE58_TYPES];
+};
+
+/**
+ * Return the currently selected parameters. This won't change after app startup
+ * outside of the unit tests.
+ */
+const CChainParams &Params();
+
+/** Sets the params returned by Params() to those for the given network. */
+void SelectParams(CChainParams::Network network);
+
+/**
+ * Looks for -regtest or -testnet and then calls SelectParams as appropriate.
+ * Returns false if an invalid combination is given.
+ */
+bool SelectParamsFromCommandLine();
+
+inline bool TestNet() {
+ // Note: it's deliberate that this returns "false" for regression test mode.
+ return Params().NetworkID() == CChainParams::TESTNET;
+}
+
+#endif
diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp
index 7643ec5df8..ba29e2463e 100644
--- a/src/checkpoints.cpp
+++ b/src/checkpoints.cpp
@@ -56,7 +56,7 @@ namespace Checkpoints
60000.0 // * estimated number of transactions per day after checkpoint
};
- static MapCheckpoints mapCheckpointsTestnet =
+ static MapCheckpoints mapCheckpointsTestnet =
boost::assign::map_list_of
( 546, uint256("000000002a936ca763904c3c35fce2f3556c559c0214345d31b1bcebf76acb70"))
;
@@ -68,7 +68,7 @@ namespace Checkpoints
};
const CCheckpointData &Checkpoints() {
- if (fTestNet)
+ if (TestNet())
return dataTestnet;
else
return data;
diff --git a/src/core.h b/src/core.h
index cba3ab233f..fce9ccc162 100644
--- a/src/core.h
+++ b/src/core.h
@@ -192,10 +192,10 @@ public:
// which has units satoshis-per-kilobyte.
// If you'd pay more than 1/3 in fees
// to spend something, then we consider it dust.
- // A typical txout is 33 bytes big, and will
+ // A typical txout is 34 bytes big, and will
// need a CTxIn of at least 148 bytes to spend,
// so dust is a txout less than 54 uBTC
- // (5430 satoshis) with default nMinRelayTxFee
+ // (5460 satoshis) with default nMinRelayTxFee
return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0)+148)) < nMinRelayTxFee);
}
@@ -733,4 +733,127 @@ public:
}
};
+
+class CBlock : public CBlockHeader
+{
+public:
+ // network and disk
+ std::vector<CTransaction> vtx;
+
+ // memory only
+ mutable std::vector<uint256> vMerkleTree;
+
+ CBlock()
+ {
+ SetNull();
+ }
+
+ CBlock(const CBlockHeader &header)
+ {
+ SetNull();
+ *((CBlockHeader*)this) = header;
+ }
+
+ IMPLEMENT_SERIALIZE
+ (
+ READWRITE(*(CBlockHeader*)this);
+ READWRITE(vtx);
+ )
+
+ void SetNull()
+ {
+ CBlockHeader::SetNull();
+ vtx.clear();
+ vMerkleTree.clear();
+ }
+
+ CBlockHeader GetBlockHeader() const
+ {
+ CBlockHeader block;
+ block.nVersion = nVersion;
+ block.hashPrevBlock = hashPrevBlock;
+ block.hashMerkleRoot = hashMerkleRoot;
+ block.nTime = nTime;
+ block.nBits = nBits;
+ block.nNonce = nNonce;
+ return block;
+ }
+
+ uint256 BuildMerkleTree() const
+ {
+ vMerkleTree.clear();
+ BOOST_FOREACH(const CTransaction& tx, vtx)
+ vMerkleTree.push_back(tx.GetHash());
+ int j = 0;
+ for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ for (int i = 0; i < nSize; i += 2)
+ {
+ int i2 = std::min(i+1, nSize-1);
+ vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
+ BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
+ }
+ j += nSize;
+ }
+ return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
+ }
+
+ const uint256 &GetTxHash(unsigned int nIndex) const {
+ assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
+ assert(nIndex < vtx.size());
+ return vMerkleTree[nIndex];
+ }
+
+ std::vector<uint256> GetMerkleBranch(int nIndex) const
+ {
+ if (vMerkleTree.empty())
+ BuildMerkleTree();
+ std::vector<uint256> vMerkleBranch;
+ int j = 0;
+ for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
+ {
+ int i = std::min(nIndex^1, nSize-1);
+ vMerkleBranch.push_back(vMerkleTree[j+i]);
+ nIndex >>= 1;
+ j += nSize;
+ }
+ return vMerkleBranch;
+ }
+
+ static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
+ {
+ if (nIndex == -1)
+ return 0;
+ BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
+ {
+ if (nIndex & 1)
+ hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
+ else
+ hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
+ nIndex >>= 1;
+ }
+ return hash;
+ }
+
+ void print() const
+ {
+ printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
+ GetHash().ToString().c_str(),
+ nVersion,
+ hashPrevBlock.ToString().c_str(),
+ hashMerkleRoot.ToString().c_str(),
+ nTime, nBits, nNonce,
+ vtx.size());
+ for (unsigned int i = 0; i < vtx.size(); i++)
+ {
+ printf(" ");
+ vtx[i].print();
+ }
+ printf(" vMerkleTree: ");
+ for (unsigned int i = 0; i < vMerkleTree.size(); i++)
+ printf("%s ", vMerkleTree[i].ToString().c_str());
+ printf("\n");
+ }
+};
+
#endif
diff --git a/src/db.cpp b/src/db.cpp
index 1f53917602..93f3f5d8c4 100644
--- a/src/db.cpp
+++ b/src/db.cpp
@@ -3,6 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "db.h"
#include "util.h"
#include "hash.h"
@@ -488,8 +489,6 @@ void CDBEnv::Flush(bool fShutdown)
// CAddrDB
//
-unsigned char CAddrDB::pchMessageStart[4] = { 0x00, 0x00, 0x00, 0x00 };
-
CAddrDB::CAddrDB()
{
pathAddr = GetDataDir() / "peers.dat";
@@ -504,7 +503,7 @@ bool CAddrDB::Write(const CAddrMan& addr)
// serialize addresses, checksum data up to that point, then append csum
CDataStream ssPeers(SER_DISK, CLIENT_VERSION);
- ssPeers << FLATDATA(CAddrDB::pchMessageStart);
+ ssPeers << FLATDATA(Params().MessageStart());
ssPeers << addr;
uint256 hash = Hash(ssPeers.begin(), ssPeers.end());
ssPeers << hash;
@@ -569,11 +568,11 @@ bool CAddrDB::Read(CAddrMan& addr)
unsigned char pchMsgTmp[4];
try {
- // de-serialize file header (CAddrDB::pchMessageStart magic number) and
+ // de-serialize file header (network specific magic number) and ..
ssPeers >> FLATDATA(pchMsgTmp);
- // verify the network matches ours
- if (memcmp(pchMsgTmp, CAddrDB::pchMessageStart, sizeof(pchMsgTmp)))
+ // ... verify the network matches ours
+ if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
return error("CAddrman::Read() : invalid network magic number");
// de-serialize address data into one CAddrMan object
diff --git a/src/db.h b/src/db.h
index 92241f6cf2..b3f269f3da 100644
--- a/src/db.h
+++ b/src/db.h
@@ -318,14 +318,10 @@ class CAddrDB
{
private:
boost::filesystem::path pathAddr;
- static unsigned char pchMessageStart[4];
-
public:
CAddrDB();
bool Write(const CAddrMan& addr);
bool Read(CAddrMan& addr);
-
- static void SetMessageStart(unsigned char _pchMessageStart[]) { memcpy(CAddrDB::pchMessageStart, _pchMessageStart, sizeof(CAddrDB::pchMessageStart)); }
};
#endif // BITCOIN_DB_H
diff --git a/src/init.cpp b/src/init.cpp
index fe74cd6963..e88055bdea 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -6,6 +6,7 @@
#include "init.h"
#include "main.h"
#include "core.h"
+#include "chainparams.h"
#include "txdb.h"
#include "walletdb.h"
#include "bitcoinrpc.h"
@@ -210,6 +211,8 @@ std::string HelpMessage()
strUsage += " -logtimestamps " + _("Prepend debug output with timestamp") + "\n";
strUsage += " -shrinkdebugfile " + _("Shrink debug.log file on client startup (default: 1 when no -debug)") + "\n";
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
+ strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be "
+ "solved instantly. This is intended for regression testing tools and app development.") + "\n";
#ifdef WIN32
strUsage += " -printtodebugger " + _("Send trace/debug info to debugger") + "\n";
#endif
@@ -366,8 +369,10 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 2: parameter interactions
- fTestNet = GetBoolArg("-testnet", false);
Checkpoints::fEnabled = GetBoolArg("-checkpoints", true);
+ if (!SelectParamsFromCommandLine()) {
+ return InitError("Invalid combination of -testnet and -regtest.");
+ }
if (mapArgs.count("-bind")) {
// when specifying an explicit binding address, you want to listen on it
@@ -572,7 +577,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// ********************************************************* Step 6: network initialization
RegisterNodeSignals(GetNodeSignals());
-
+
int nSocksVersion = GetArg("-socks", 5);
if (nSocksVersion != 4 && nSocksVersion != 5)
return InitError(strprintf(_("Unknown -socks proxy version requested: %i"), nSocksVersion));
@@ -744,20 +749,21 @@ bool AppInit2(boost::thread_group& threadGroup)
if (!mapBlockIndex.empty() && pindexGenesisBlock == NULL)
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
- // Check for changed -txindex state (only necessary if we are not reindexing anyway)
- if (!fReindex && fTxIndex != GetBoolArg("-txindex", false)) {
- strLoadError = _("You need to rebuild the database using -reindex to change -txindex");
- break;
- }
-
// Initialize the block index (no-op if non-empty database was already loaded)
if (!InitBlockIndex()) {
strLoadError = _("Error initializing block database");
break;
}
+ // Check for changed -txindex state
+ if (fTxIndex != GetBoolArg("-txindex", false)) {
+ strLoadError = _("You need to rebuild the database using -reindex to change -txindex");
+ break;
+ }
+
uiInterface.InitMessage(_("Verifying blocks..."));
- if (!VerifyDB()) {
+ if (!VerifyDB(GetArg("-checklevel", 3),
+ GetArg( "-checkblocks", 288))) {
strLoadError = _("Corrupted block database detected");
break;
}
@@ -814,7 +820,7 @@ bool AppInit2(boost::thread_group& threadGroup)
{
CBlockIndex* pindex = (*mi).second;
CBlock block;
- block.ReadFromDisk(pindex);
+ ReadBlockFromDisk(block, pindex);
block.BuildMerkleTree();
block.print();
printf("\n");
@@ -937,7 +943,6 @@ bool AppInit2(boost::thread_group& threadGroup)
nStart = GetTimeMillis();
{
- CAddrDB::SetMessageStart(pchMessageStart);
CAddrDB adb;
if (!adb.Read(addrman))
printf("Invalid or missing peers.dat; recreating\n");
diff --git a/src/leveldb/build_detect_platform b/src/leveldb/build_detect_platform
index 609cb51224..a3ad057eee 100755
--- a/src/leveldb/build_detect_platform
+++ b/src/leveldb/build_detect_platform
@@ -94,6 +94,12 @@ case "$TARGET_OS" in
PLATFORM_LIBS="-lpthread"
PORT_FILE=port/port_posix.cc
;;
+ GNU/kFreeBSD)
+ PLATFORM=OS_KFREEBSD
+ COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_KFREEBSD"
+ PLATFORM_LIBS="-lpthread"
+ PORT_FILE=port/port_posix.cc
+ ;;
NetBSD)
PLATFORM=OS_NETBSD
COMMON_FLAGS="$MEMCMP_FLAG -D_REENTRANT -DOS_NETBSD"
diff --git a/src/main.cpp b/src/main.cpp
index f0c08d273f..da928a4b90 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -11,6 +11,7 @@
#include "init.h"
#include "ui_interface.h"
#include "checkqueue.h"
+#include "chainparams.h"
#include <boost/algorithm/string/replace.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
@@ -32,8 +33,6 @@ unsigned int nTransactionsUpdated = 0;
map<uint256, CBlockIndex*> mapBlockIndex;
std::vector<CBlockIndex*> vBlockIndexByHeight;
-uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
-static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
CBlockIndex* pindexGenesisBlock = NULL;
int nBestHeight = -1;
uint256 nBestChainWork = 0;
@@ -158,8 +157,6 @@ void static ResendWalletTransactions()
pwallet->ResendWalletTransactions();
}
-
-
//////////////////////////////////////////////////////////////////////////////
//
// Registration of network node signals.
@@ -177,7 +174,95 @@ void UnregisterNodeSignals(CNodeSignals& nodeSignals)
nodeSignals.SendMessages.disconnect(&SendMessages);
}
+//////////////////////////////////////////////////////////////////////////////
+//
+// CBlockLocator implementation
+//
+
+CBlockLocator::CBlockLocator(uint256 hashBlock)
+{
+ std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
+ if (mi != mapBlockIndex.end())
+ Set((*mi).second);
+}
+
+void CBlockLocator::Set(const CBlockIndex* pindex)
+{
+ vHave.clear();
+ int nStep = 1;
+ while (pindex)
+ {
+ vHave.push_back(pindex->GetBlockHash());
+
+ // Exponentially larger steps back
+ for (int i = 0; pindex && i < nStep; i++)
+ pindex = pindex->pprev;
+ 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 (pindex->IsInMainChain())
+ return nDistance;
+ }
+ nDistance += nStep;
+ if (nDistance > 10)
+ nStep *= 2;
+ }
+ return nDistance;
+}
+
+CBlockIndex *CBlockLocator::GetBlockIndex()
+{
+ // 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 (pindex->IsInMainChain())
+ return pindex;
+ }
+ }
+ return pindexGenesisBlock;
+}
+
+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 (pindex->IsInMainChain())
+ return hash;
+ }
+ }
+ return Params().HashGenesisBlock();
+}
+int CBlockLocator::GetHeight()
+{
+ CBlockIndex* pindex = GetBlockIndex();
+ if (!pindex)
+ return 0;
+ return pindex->nHeight;
+}
//////////////////////////////////////////////////////////////////////////////
//
@@ -542,7 +627,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
if (pcoinsTip->GetCoins(GetHash(), coins)) {
CBlockIndex *pindex = FindBlockByHeight(coins.nHeight);
if (pindex) {
- if (!blockTmp.ReadFromDisk(pindex))
+ if (!ReadBlockFromDisk(blockTmp, pindex))
return 0;
pblock = &blockTmp;
}
@@ -634,30 +719,23 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
return true;
}
-int64 GetMinFee(const CTransaction& tx, unsigned int nBlockSize, bool fAllowFree, enum GetMinFee_mode mode)
+int64 GetMinFee(const CTransaction& tx, bool fAllowFree, enum GetMinFee_mode mode)
{
// Base fee is either nMinTxFee or nMinRelayTxFee
int64 nBaseFee = (mode == GMF_RELAY) ? tx.nMinRelayTxFee : tx.nMinTxFee;
unsigned int nBytes = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
- unsigned int nNewBlockSize = nBlockSize + nBytes;
int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
if (fAllowFree)
{
- if (nBlockSize == 1)
- {
- // Transactions under 10K are free
- // (about 4500 BTC if made of 50 BTC inputs)
- if (nBytes < 10000)
- nMinFee = 0;
- }
- else
- {
- // Free transaction area
- if (nNewBlockSize < 27000)
- nMinFee = 0;
- }
+ // 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)))
+ nMinFee = 0;
}
// To limit dust spam, require base fee if any output is less than 0.01
@@ -668,14 +746,6 @@ int64 GetMinFee(const CTransaction& tx, unsigned int nBlockSize, bool fAllowFree
nMinFee = nBaseFee;
}
- // Raise the price as the block approaches full
- if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
- {
- if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
- return MAX_MONEY;
- nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
- }
-
if (!MoneyRange(nMinFee))
nMinFee = MAX_MONEY;
return nMinFee;
@@ -712,7 +782,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
// Rather not work on nonstandard transactions (unless -testnet)
- if (!fTestNet && !IsStandardTx(tx))
+ if (!TestNet() && !IsStandardTx(tx))
return error("CTxMemPool::accept() : nonstandard transaction type");
// is it already in the memory pool?
@@ -787,7 +857,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
}
// Check for non-standard pay-to-script-hash in inputs
- if (!AreInputsStandard(tx, view) && !fTestNet)
+ if (!TestNet() && !AreInputsStandard(tx, view))
return error("CTxMemPool::accept() : nonstandard transaction input");
// Note: if you modify this code to accept non-standard transactions, then
@@ -798,7 +868,7 @@ bool CTxMemPool::accept(CValidationState &state, CTransaction &tx, bool fLimitFr
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
// Don't accept it if it can't get into a block
- int64 txMinFee = GetMinFee(tx, 1000, true, GMF_RELAY);
+ int64 txMinFee = GetMinFee(tx, true, GMF_RELAY);
if (fLimitFree && nFees < txMinFee)
return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d,
hash.ToString().c_str(),
@@ -1044,7 +1114,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
if (pindexSlow) {
CBlock block;
- if (block.ReadFromDisk(pindexSlow)) {
+ if (ReadBlockFromDisk(block, pindexSlow)) {
BOOST_FOREACH(const CTransaction &tx, block.vtx) {
if (tx.GetHash() == hash) {
txOut = tx;
@@ -1076,12 +1146,62 @@ CBlockIndex* FindBlockByHeight(int nHeight)
return vBlockIndexByHeight[nHeight];
}
-bool CBlock::ReadFromDisk(const CBlockIndex* pindex)
+bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
+{
+ // Open history file to append
+ CAutoFile fileout = CAutoFile(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
+ if (!fileout)
+ return error("WriteBlockToDisk() : OpenBlockFile failed");
+
+ // Write index header
+ unsigned int nSize = fileout.GetSerializeSize(block);
+ fileout << FLATDATA(Params().MessageStart()) << nSize;
+
+ // Write block
+ long fileOutPos = ftell(fileout);
+ if (fileOutPos < 0)
+ return error("WriteBlockToDisk() : ftell failed");
+ pos.nPos = (unsigned int)fileOutPos;
+ fileout << block;
+
+ // Flush stdio buffers and commit to disk before returning
+ fflush(fileout);
+ if (!IsInitialBlockDownload())
+ FileCommit(fileout);
+
+ return true;
+}
+
+bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos)
+{
+ block.SetNull();
+
+ // Open history file to read
+ CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
+ if (!filein)
+ return error("ReadBlockFromDisk(CBlock&, CDiskBlockPos&) : OpenBlockFile failed");
+
+ // Read block
+ try {
+ filein >> block;
+ }
+ catch (std::exception &e) {
+ return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
+ }
+
+ // Check the header
+ if (!CheckProofOfWork(block.GetHash(), block.nBits))
+ return error("ReadBlockFromDisk(CBlock&, CDiskBlockPos&) : errors in block header");
+
+ return true;
+}
+
+bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex)
{
- if (!ReadFromDisk(pindex->GetBlockPos()))
+ if (!ReadBlockFromDisk(block, pindex->GetBlockPos()))
return false;
- if (GetHash() != pindex->GetBlockHash())
- return error("CBlock::ReadFromDisk() : GetHash() doesn't match index");
+ if (block.GetHash() != pindex->GetBlockHash())
+ return error("ReadBlockFromDisk(CBlock&, CBlockIndex*) : GetHash() doesn't match index");
return true;
}
@@ -1097,8 +1217,8 @@ int64 static GetBlockValue(int nHeight, int64 nFees)
{
int64 nSubsidy = 50 * COIN;
- // Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years
- nSubsidy >>= (nHeight / 210000);
+ // Subsidy is cut in half every 210,000 blocks which will occur approximately every 4 years.
+ nSubsidy >>= (nHeight / Params().SubsidyHalvingInterval());
return nSubsidy + nFees;
}
@@ -1113,28 +1233,29 @@ static const int64 nInterval = nTargetTimespan / nTargetSpacing;
//
unsigned int ComputeMinWork(unsigned int nBase, int64 nTime)
{
+ const CBigNum &bnLimit = Params().ProofOfWorkLimit();
// Testnet has min-difficulty blocks
// after nTargetSpacing*2 time between blocks:
- if (fTestNet && nTime > nTargetSpacing*2)
- return bnProofOfWorkLimit.GetCompact();
+ if (TestNet() && nTime > nTargetSpacing*2)
+ return bnLimit.GetCompact();
CBigNum bnResult;
bnResult.SetCompact(nBase);
- while (nTime > 0 && bnResult < bnProofOfWorkLimit)
+ while (nTime > 0 && bnResult < bnLimit)
{
// Maximum 400% adjustment...
bnResult *= 4;
// ... in best-case exactly 4-times-normal target time
nTime -= nTargetTimespan*4;
}
- if (bnResult > bnProofOfWorkLimit)
- bnResult = bnProofOfWorkLimit;
+ if (bnResult > bnLimit)
+ bnResult = bnLimit;
return bnResult.GetCompact();
}
unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHeader *pblock)
{
- unsigned int nProofOfWorkLimit = bnProofOfWorkLimit.GetCompact();
+ unsigned int nProofOfWorkLimit = Params().ProofOfWorkLimit().GetCompact();
// Genesis block
if (pindexLast == NULL)
@@ -1143,9 +1264,9 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl
// Only change once per interval
if ((pindexLast->nHeight+1) % nInterval != 0)
{
- // Special difficulty rule for testnet:
- if (fTestNet)
+ if (TestNet())
{
+ // Special difficulty rule for testnet:
// If the new block's timestamp is more than 2* 10 minutes
// then allow mining of a min-difficulty block.
if (pblock->nTime > pindexLast->nTime + nTargetSpacing*2)
@@ -1159,7 +1280,6 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl
return pindex->nBits;
}
}
-
return pindexLast->nBits;
}
@@ -1183,8 +1303,8 @@ unsigned int static GetNextWorkRequired(const CBlockIndex* pindexLast, const CBl
bnNew *= nActualTimespan;
bnNew /= nTargetTimespan;
- if (bnNew > bnProofOfWorkLimit)
- bnNew = bnProofOfWorkLimit;
+ if (bnNew > Params().ProofOfWorkLimit())
+ bnNew = Params().ProofOfWorkLimit();
/// debug print
printf("GetNextWorkRequired RETARGET\n");
@@ -1201,7 +1321,7 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits)
bnTarget.SetCompact(nBits);
// Check range
- if (bnTarget <= 0 || bnTarget > bnProofOfWorkLimit)
+ if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())
return error("CheckProofOfWork() : nBits below minimum work");
// Check proof of work matches claimed amount
@@ -1319,7 +1439,7 @@ void UpdateTime(CBlockHeader& block, const CBlockIndex* pindexPrev)
block.nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
// Updating time can change work required on testnet:
- if (fTestNet)
+ if (TestNet())
block.nBits = GetNextWorkRequired(pindexPrev, &block);
}
@@ -1483,7 +1603,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, CCoinsViewCach
-bool CBlock::DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &view, bool *pfClean)
+bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool* pfClean)
{
assert(pindex == view.GetBestBlock());
@@ -1499,12 +1619,12 @@ bool CBlock::DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoin
if (!blockUndo.ReadFromDisk(pos, pindex->pprev->GetBlockHash()))
return error("DisconnectBlock() : failure reading undo data");
- if (blockUndo.vtxundo.size() + 1 != vtx.size())
+ if (blockUndo.vtxundo.size() + 1 != block.vtx.size())
return error("DisconnectBlock() : block and undo data inconsistent");
// undo transactions in reverse order
- for (int i = vtx.size() - 1; i >= 0; i--) {
- const CTransaction &tx = vtx[i];
+ for (int i = block.vtx.size() - 1; i >= 0; i--) {
+ const CTransaction &tx = block.vtx[i];
uint256 hash = tx.GetHash();
// check that all outputs are available
@@ -1597,10 +1717,10 @@ void ThreadScriptCheck() {
scriptcheckqueue.Thread();
}
-bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsViewCache &view, bool fJustCheck)
+bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, bool fJustCheck)
{
// Check it again in case a previous version let a bad block in
- if (!CheckBlock(state, !fJustCheck, !fJustCheck))
+ if (!CheckBlock(block, state, !fJustCheck, !fJustCheck))
return false;
// verify that the view's current state corresponds to the previous block
@@ -1608,7 +1728,7 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
// Special case for the genesis block, skipping connection of its transactions
// (its coinbase is unspendable)
- if (GetHash() == hashGenesisBlock) {
+ if (block.GetHash() == Params().HashGenesisBlock()) {
view.SetBestBlock(pindex);
pindexGenesisBlock = pindex;
return true;
@@ -1632,8 +1752,8 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
!((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) ||
(pindex->nHeight==91880 && pindex->GetBlockHash() == uint256("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")));
if (fEnforceBIP30) {
- for (unsigned int i=0; i<vtx.size(); i++) {
- uint256 hash = GetTxHash(i);
+ for (unsigned int i = 0; i < block.vtx.size(); i++) {
+ uint256 hash = block.GetTxHash(i);
if (view.HaveCoins(hash) && !view.GetCoins(hash).IsPruned())
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"));
}
@@ -1654,12 +1774,12 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
int64 nFees = 0;
int nInputs = 0;
unsigned int nSigOps = 0;
- CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(vtx.size()));
+ CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
std::vector<std::pair<uint256, CDiskTxPos> > vPos;
- vPos.reserve(vtx.size());
- for (unsigned int i=0; i<vtx.size(); i++)
+ vPos.reserve(block.vtx.size());
+ for (unsigned int i = 0; i < block.vtx.size(); i++)
{
- const CTransaction &tx = vtx[i];
+ const CTransaction &tx = block.vtx[i];
nInputs += tx.vin.size();
nSigOps += GetLegacySigOpCount(tx);
@@ -1690,19 +1810,19 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
}
CTxUndo txundo;
- UpdateCoins(tx, state, view, txundo, pindex->nHeight, GetTxHash(i));
+ UpdateCoins(tx, state, view, txundo, pindex->nHeight, block.GetTxHash(i));
if (!tx.IsCoinBase())
blockundo.vtxundo.push_back(txundo);
- vPos.push_back(std::make_pair(GetTxHash(i), pos));
+ vPos.push_back(std::make_pair(block.GetTxHash(i), pos));
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
}
int64 nTime = GetTimeMicros() - nStart;
if (fBenchmark)
- printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)vtx.size(), 0.001 * nTime, 0.001 * nTime / vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1));
+ printf("- Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin)\n", (unsigned)block.vtx.size(), 0.001 * nTime, 0.001 * nTime / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * nTime / (nInputs-1));
- if (GetValueOut(vtx[0]) > GetBlockValue(pindex->nHeight, nFees))
- return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", GetValueOut(vtx[0]), GetBlockValue(pindex->nHeight, nFees)));
+ if (GetValueOut(block.vtx[0]) > GetBlockValue(pindex->nHeight, nFees))
+ return state.DoS(100, error("ConnectBlock() : coinbase pays too much (actual=%"PRI64d" vs limit=%"PRI64d")", GetValueOut(block.vtx[0]), GetBlockValue(pindex->nHeight, nFees)));
if (!control.Wait())
return state.DoS(100, false);
@@ -1743,8 +1863,8 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
assert(view.SetBestBlock(pindex));
// Watch for transactions paying to me
- for (unsigned int i=0; i<vtx.size(); i++)
- SyncWithWallets(GetTxHash(i), vtx[i], this, true);
+ for (unsigned int i = 0; i < block.vtx.size(); i++)
+ SyncWithWallets(block.GetTxHash(i), block.vtx[i], &block, true);
return true;
}
@@ -1790,10 +1910,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
vector<CTransaction> vResurrect;
BOOST_FOREACH(CBlockIndex* pindex, vDisconnect) {
CBlock block;
- if (!block.ReadFromDisk(pindex))
+ if (!ReadBlockFromDisk(block, pindex))
return state.Abort(_("Failed to read block"));
int64 nStart = GetTimeMicros();
- if (!block.DisconnectBlock(state, pindex, view))
+ if (!DisconnectBlock(block, state, pindex, view))
return error("SetBestBlock() : DisconnectBlock %s failed", pindex->GetBlockHash().ToString().c_str());
if (fBenchmark)
printf("- Disconnect: %.2fms\n", (GetTimeMicros() - nStart) * 0.001);
@@ -1810,10 +1930,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
vector<CTransaction> vDelete;
BOOST_FOREACH(CBlockIndex *pindex, vConnect) {
CBlock block;
- if (!block.ReadFromDisk(pindex))
+ if (!ReadBlockFromDisk(block, pindex))
return state.Abort(_("Failed to read block"));
int64 nStart = GetTimeMicros();
- if (!block.ConnectBlock(state, pindex, view)) {
+ if (!ConnectBlock(block, state, pindex, view)) {
if (state.IsInvalid()) {
InvalidChainFound(pindexNew);
InvalidBlockFound(pindex);
@@ -1923,25 +2043,25 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
}
-bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
+bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos)
{
// Check for duplicate
- uint256 hash = GetHash();
+ uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash))
return state.Invalid(error("AddToBlockIndex() : %s already exists", hash.ToString().c_str()));
// Construct new block index object
- CBlockIndex* pindexNew = new CBlockIndex(*this);
+ CBlockIndex* pindexNew = new CBlockIndex(block);
assert(pindexNew);
map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.insert(make_pair(hash, pindexNew)).first;
pindexNew->phashBlock = &((*mi).first);
- map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(hashPrevBlock);
+ map<uint256, CBlockIndex*>::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
if (miPrev != mapBlockIndex.end())
{
pindexNew->pprev = (*miPrev).second;
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
}
- pindexNew->nTx = vtx.size();
+ pindexNew->nTx = block.vtx.size();
pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork().getuint256();
pindexNew->nChainTx = (pindexNew->pprev ? pindexNew->pprev->nChainTx : 0) + pindexNew->nTx;
pindexNew->nFile = pos.nFile;
@@ -1962,7 +2082,7 @@ bool CBlock::AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos)
// Notify UI to display prev block's coinbase if it was ours
static uint256 hashPrevBestCoinBase;
UpdatedTransaction(hashPrevBestCoinBase);
- hashPrevBestCoinBase = GetTxHash(0);
+ hashPrevBestCoinBase = block.GetTxHash(0);
}
if (!pblocktree->Flush())
@@ -2068,51 +2188,51 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne
}
-bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerkleRoot) const
+bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot)
{
// These are checks that are independent of context
// that can be verified before saving an orphan block.
// Size limits
- if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
+ if (block.vtx.empty() || block.vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(block, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock() : size limits failed"));
// Check proof of work matches claimed amount
- if (fCheckPOW && !CheckProofOfWork(GetHash(), nBits))
+ if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits))
return state.DoS(50, error("CheckBlock() : proof of work failed"));
// Check timestamp
- if (GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
+ if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60)
return state.Invalid(error("CheckBlock() : block timestamp too far in the future"));
// First transaction must be coinbase, the rest must not be
- if (vtx.empty() || !vtx[0].IsCoinBase())
+ if (block.vtx.empty() || !block.vtx[0].IsCoinBase())
return state.DoS(100, error("CheckBlock() : first tx is not coinbase"));
- for (unsigned int i = 1; i < vtx.size(); i++)
- if (vtx[i].IsCoinBase())
+ for (unsigned int i = 1; i < block.vtx.size(); i++)
+ if (block.vtx[i].IsCoinBase())
return state.DoS(100, error("CheckBlock() : more than one coinbase"));
// Check transactions
- BOOST_FOREACH(const CTransaction& tx, vtx)
+ BOOST_FOREACH(const CTransaction& tx, block.vtx)
if (!CheckTransaction(tx, state))
return error("CheckBlock() : CheckTransaction failed");
// Build the merkle tree already. We need it anyway later, and it makes the
// block cache the transaction hashes, which means they don't need to be
// recalculated many times during this block's validation.
- BuildMerkleTree();
+ block.BuildMerkleTree();
// Check for duplicate txids. This is caught by ConnectInputs(),
// but catching it earlier avoids a potential DoS attack:
set<uint256> uniqueTx;
- for (unsigned int i=0; i<vtx.size(); i++) {
- uniqueTx.insert(GetTxHash(i));
+ for (unsigned int i = 0; i < block.vtx.size(); i++) {
+ uniqueTx.insert(block.GetTxHash(i));
}
- if (uniqueTx.size() != vtx.size())
+ if (uniqueTx.size() != block.vtx.size())
return state.DoS(100, error("CheckBlock() : duplicate transaction"));
unsigned int nSigOps = 0;
- BOOST_FOREACH(const CTransaction& tx, vtx)
+ BOOST_FOREACH(const CTransaction& tx, block.vtx)
{
nSigOps += GetLegacySigOpCount(tx);
}
@@ -2120,40 +2240,40 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
return state.DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));
// Check merkle root
- if (fCheckMerkleRoot && hashMerkleRoot != BuildMerkleTree())
+ if (fCheckMerkleRoot && block.hashMerkleRoot != block.BuildMerkleTree())
return state.DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"));
return true;
}
-bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
+bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
{
// Check for duplicate
- uint256 hash = GetHash();
+ uint256 hash = block.GetHash();
if (mapBlockIndex.count(hash))
return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex"));
// Get prev block index
CBlockIndex* pindexPrev = NULL;
int nHeight = 0;
- if (hash != hashGenesisBlock) {
- map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashPrevBlock);
+ if (hash != Params().HashGenesisBlock()) {
+ map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi == mapBlockIndex.end())
return state.DoS(10, error("AcceptBlock() : prev block not found"));
pindexPrev = (*mi).second;
nHeight = pindexPrev->nHeight+1;
// Check proof of work
- if (nBits != GetNextWorkRequired(pindexPrev, this))
+ if (block.nBits != GetNextWorkRequired(pindexPrev, &block))
return state.DoS(100, error("AcceptBlock() : incorrect proof of work"));
// Check timestamp against prev
- if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
+ if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast())
return state.Invalid(error("AcceptBlock() : block's timestamp is too early"));
// Check that all transactions are finalized
- BOOST_FOREACH(const CTransaction& tx, vtx)
- if (!IsFinalTx(tx, nHeight, GetBlockTime()))
+ BOOST_FOREACH(const CTransaction& tx, block.vtx)
+ if (!IsFinalTx(tx, nHeight, block.GetBlockTime()))
return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"));
// Check that the block chain matches the known block chain up to a checkpoint
@@ -2161,23 +2281,23 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
// Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded:
- if (nVersion < 2)
+ if (block.nVersion < 2)
{
- if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) ||
- (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
+ if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) ||
+ (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100)))
{
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"));
}
}
// Enforce block.nVersion=2 rule that the coinbase starts with serialized block height
- if (nVersion >= 2)
+ if (block.nVersion >= 2)
{
// if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet):
- if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) ||
- (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
+ if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) ||
+ (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100)))
{
CScript expect = CScript() << nHeight;
- if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin()))
+ if (!std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin()))
return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"));
}
}
@@ -2185,16 +2305,16 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
// Write block to history file
try {
- unsigned int nBlockSize = ::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION);
+ unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos;
if (dbp != NULL)
blockPos = *dbp;
- if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, nTime, dbp != NULL))
+ if (!FindBlockPos(state, blockPos, nBlockSize+8, nHeight, block.nTime, dbp != NULL))
return error("AcceptBlock() : FindBlockPos failed");
if (dbp == NULL)
- if (!WriteToDisk(blockPos))
+ if (!WriteBlockToDisk(block, blockPos))
return state.Abort(_("Failed to write block"));
- if (!AddToBlockIndex(state, blockPos))
+ if (!AddToBlockIndex(block, state, blockPos))
return error("AcceptBlock() : AddToBlockIndex failed");
} catch(std::runtime_error &e) {
return state.Abort(_("System error: ") + e.what());
@@ -2246,7 +2366,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
return state.Invalid(error("ProcessBlock() : already have block (orphan) %s", hash.ToString().c_str()));
// Preliminary checks
- if (!pblock->CheckBlock(state))
+ if (!CheckBlock(*pblock, state))
return error("ProcessBlock() : CheckBlock FAILED");
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
@@ -2287,7 +2407,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
}
// Store to disk
- if (!pblock->AcceptBlock(state, dbp))
+ if (!AcceptBlock(*pblock, state, dbp))
return error("ProcessBlock() : AcceptBlock FAILED");
// Recursively process any orphan blocks that depended on this one
@@ -2303,7 +2423,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
CBlock* pblockOrphan = (*mi).second;
// Use a dummy CValidationState so someone can't setup nodes to counter-DoS based on orphan resolution (that is, feeding people an invalid block based on LegitBlockX in order to get anyone relaying LegitBlockX banned)
CValidationState stateDummy;
- if (pblockOrphan->AcceptBlock(stateDummy))
+ if (AcceptBlock(*pblockOrphan, stateDummy))
vWorkQueue.push_back(pblockOrphan->GetHash());
mapOrphanBlocks.erase(pblockOrphan->GetHash());
delete pblockOrphan;
@@ -2616,14 +2736,13 @@ bool static LoadBlockIndexDB()
return true;
}
-bool VerifyDB() {
+bool VerifyDB(int nCheckLevel, int nCheckDepth)
+{
if (pindexBest == NULL || pindexBest->pprev == NULL)
return true;
// Verify blocks in the best chain
- int nCheckLevel = GetArg("-checklevel", 3);
- int nCheckDepth = GetArg( "-checkblocks", 288);
- if (nCheckDepth == 0)
+ if (nCheckDepth <= 0)
nCheckDepth = 1000000000; // suffices until the year 19000
if (nCheckDepth > nBestHeight)
nCheckDepth = nBestHeight;
@@ -2641,10 +2760,10 @@ bool VerifyDB() {
break;
CBlock block;
// check level 0: read from disk
- if (!block.ReadFromDisk(pindex))
- return error("VerifyDB() : *** block.ReadFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
+ if (!ReadBlockFromDisk(block, pindex))
+ return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
// check level 1: verify block validity
- if (nCheckLevel >= 1 && !block.CheckBlock(state))
+ if (nCheckLevel >= 1 && !CheckBlock(block, state))
return error("VerifyDB() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
// check level 2: verify undo validity
if (nCheckLevel >= 2 && pindex) {
@@ -2658,7 +2777,7 @@ bool VerifyDB() {
// check level 3: check for inconsistencies during memory-only disconnect of tip blocks
if (nCheckLevel >= 3 && pindex == pindexState && (coins.GetCacheSize() + pcoinsTip->GetCacheSize()) <= 2*nCoinCacheSize + 32000) {
bool fClean = true;
- if (!block.DisconnectBlock(state, pindex, coins, &fClean))
+ if (!DisconnectBlock(block, state, pindex, coins, &fClean))
return error("VerifyDB() : *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
pindexState = pindex->pprev;
if (!fClean) {
@@ -2678,9 +2797,9 @@ bool VerifyDB() {
boost::this_thread::interruption_point();
pindex = pindex->GetNextInMainChain();
CBlock block;
- if (!block.ReadFromDisk(pindex))
- return error("VerifyDB() : *** block.ReadFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
- if (!block.ConnectBlock(state, pindex, coins))
+ if (!ReadBlockFromDisk(block, pindex))
+ return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
+ if (!ConnectBlock(block, state, pindex, coins))
return error("VerifyDB() : *** found unconnectable block at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
}
}
@@ -2704,21 +2823,9 @@ void UnloadBlockIndex()
bool LoadBlockIndex()
{
- if (fTestNet)
- {
- pchMessageStart[0] = 0x0b;
- pchMessageStart[1] = 0x11;
- pchMessageStart[2] = 0x09;
- pchMessageStart[3] = 0x07;
- hashGenesisBlock = uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943");
- }
-
- //
// Load block index from databases
- //
if (!fReindex && !LoadBlockIndexDB())
return false;
-
return true;
}
@@ -2735,55 +2842,17 @@ bool InitBlockIndex() {
// Only add the genesis block if not reindexing (in which case we reuse the one already on disk)
if (!fReindex) {
- // Genesis Block:
- // CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
- // CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
- // CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
- // CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
- // vMerkleTree: 4a5e1e
-
- // Genesis block
- const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
- CTransaction txNew;
- txNew.vin.resize(1);
- txNew.vout.resize(1);
- txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
- txNew.vout[0].nValue = 50 * COIN;
- txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
- CBlock block;
- block.vtx.push_back(txNew);
- block.hashPrevBlock = 0;
- block.hashMerkleRoot = block.BuildMerkleTree();
- block.nVersion = 1;
- block.nTime = 1231006505;
- block.nBits = 0x1d00ffff;
- block.nNonce = 2083236893;
-
- if (fTestNet)
- {
- block.nTime = 1296688602;
- block.nNonce = 414098458;
- }
-
- //// debug print
- uint256 hash = block.GetHash();
- printf("%s\n", hash.ToString().c_str());
- printf("%s\n", hashGenesisBlock.ToString().c_str());
- printf("%s\n", block.hashMerkleRoot.ToString().c_str());
- assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));
- block.print();
- assert(hash == hashGenesisBlock);
-
- // Start new block file
try {
+ CBlock &block = const_cast<CBlock&>(Params().GenesisBlock());
+ // Start new block file
unsigned int nBlockSize = ::GetSerializeSize(block, SER_DISK, CLIENT_VERSION);
CDiskBlockPos blockPos;
CValidationState state;
if (!FindBlockPos(state, blockPos, nBlockSize+8, 0, block.nTime))
return error("LoadBlockIndex() : FindBlockPos failed");
- if (!block.WriteToDisk(blockPos))
+ if (!WriteBlockToDisk(block, blockPos))
return error("LoadBlockIndex() : writing genesis block to disk failed");
- if (!block.AddToBlockIndex(state, blockPos))
+ if (!AddToBlockIndex(block, state, blockPos))
return error("LoadBlockIndex() : genesis block not accepted");
} catch(std::runtime_error &e) {
return error("LoadBlockIndex() : failed to initialize block database: %s", e.what());
@@ -2839,7 +2908,7 @@ void PrintBlockTree()
// print item
CBlock block;
- block.ReadFromDisk(pindex);
+ ReadBlockFromDisk(block, pindex);
printf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"",
pindex->nHeight,
pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos,
@@ -2892,10 +2961,10 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
try {
// locate a header
unsigned char buf[4];
- blkdat.FindByte(pchMessageStart[0]);
+ blkdat.FindByte(Params().MessageStart()[0]);
nRewind = blkdat.GetPos()+1;
blkdat >> FLATDATA(buf);
- if (memcmp(buf, pchMessageStart, 4))
+ if (memcmp(buf, Params().MessageStart(), 4))
continue;
// read size
blkdat >> nSize;
@@ -3040,12 +3109,6 @@ bool static AlreadyHave(const CInv& inv)
-// The message start string is designed to be unlikely to occur in normal data.
-// The characters are rarely used upper ASCII, not valid as UTF-8, and produce
-// a large 4-byte int at any alignment.
-unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
-
-
void static ProcessGetData(CNode* pfrom)
{
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
@@ -3069,7 +3132,7 @@ void static ProcessGetData(CNode* pfrom)
if (mi != mapBlockIndex.end())
{
CBlock block;
- block.ReadFromDisk((*mi).second);
+ ReadBlockFromDisk(block, (*mi).second);
if (inv.type == MSG_BLOCK)
pfrom->PushMessage("block", block);
else // MSG_FILTERED_BLOCK)
@@ -3768,7 +3831,7 @@ bool ProcessMessages(CNode* pfrom)
it++;
// Scan for message start
- if (memcmp(msg.hdr.pchMessageStart, pchMessageStart, sizeof(pchMessageStart)) != 0) {
+ if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
printf("\n\nPROCESSMESSAGE: INVALID MESSAGESTART\n\n");
fOk = false;
break;
@@ -4186,7 +4249,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// How much of the block should be dedicated to high-priority transactions,
// included regardless of the fees they pay
- unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
+ unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE);
nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
// Minimum block size you want to create; block will be filled with free transactions
@@ -4314,7 +4377,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Prioritize by fee once past the priority size or we run out of high-priority
// transactions:
if (!fSortedByFee &&
- ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 144 / 250)))
+ ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree(dPriority)))
{
fSortedByFee = true;
comparer = TxPriorityCompare(fSortedByFee);
@@ -4391,7 +4454,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
indexDummy.nHeight = pindexPrev->nHeight + 1;
CCoinsViewCache viewNew(*pcoinsTip, true);
CValidationState state;
- if (!pblock->ConnectBlock(state, &indexDummy, viewNew, true))
+ if (!ConnectBlock(*pblock, state, &indexDummy, viewNew, true))
throw std::runtime_error("CreateNewBlock() : ConnectBlock failed");
}
@@ -4512,8 +4575,12 @@ void static BitcoinMiner(CWallet *pwallet)
unsigned int nExtraNonce = 0;
try { loop {
- while (vNodes.empty())
- MilliSleep(1000);
+ if (Params().NetworkID() != CChainParams::REGTEST) {
+ // Busy-wait for the network to come online so we don't waste time mining
+ // on an obsolete chain. In regtest mode we expect to fly solo.
+ while (vNodes.empty())
+ MilliSleep(1000);
+ }
//
// Create new block
@@ -4575,6 +4642,12 @@ void static BitcoinMiner(CWallet *pwallet)
SetThreadPriority(THREAD_PRIORITY_NORMAL);
CheckWork(pblock, *pwalletMain, reservekey);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
+
+ // In regression test mode, stop mining after a block is found. This
+ // allows developers to controllably generate a block on demand.
+ if (Params().NetworkID() == CChainParams::REGTEST)
+ throw boost::thread_interrupted();
+
break;
}
}
@@ -4610,7 +4683,7 @@ void static BitcoinMiner(CWallet *pwallet)
// Check for stop or if block needs to be rebuilt
boost::this_thread::interruption_point();
- if (vNodes.empty())
+ if (vNodes.empty() && Params().NetworkID() != CChainParams::REGTEST)
break;
if (nBlockNonce >= 0xffff0000)
break;
@@ -4622,7 +4695,7 @@ void static BitcoinMiner(CWallet *pwallet)
// Update nTime every few seconds
UpdateTime(*pblock, pindexPrev);
nBlockTime = ByteReverse(pblock->nTime);
- if (fTestNet)
+ if (TestNet())
{
// Changing pblock->nTime can change work required on testnet:
nBlockBits = ByteReverse(pblock->nBits);
@@ -4642,8 +4715,12 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet)
static boost::thread_group* minerThreads = NULL;
int nThreads = GetArg("-genproclimit", -1);
- if (nThreads < 0)
- nThreads = boost::thread::hardware_concurrency();
+ if (nThreads < 0) {
+ if (Params().NetworkID() == CChainParams::REGTEST)
+ nThreads = 1;
+ else
+ nThreads = boost::thread::hardware_concurrency();
+ }
if (minerThreads != NULL)
{
diff --git a/src/main.h b/src/main.h
index 87f1dbfa8f..9e0235fa57 100644
--- a/src/main.h
+++ b/src/main.h
@@ -52,6 +52,8 @@ static const int COINBASE_MATURITY = 100;
static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
/** Maximum number of script-checking threads allowed */
static const int MAX_SCRIPTCHECK_THREADS = 16;
+/** Default amount of block size reserved for high-priority transactions (in bytes) */
+static const int DEFAULT_BLOCK_PRIORITY_SIZE = 27000;
#ifdef USE_UPNP
static const int fHaveUPnP = true;
#else
@@ -70,7 +72,6 @@ extern CCriticalSection cs_main;
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
extern std::vector<CBlockIndex*> vBlockIndexByHeight;
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
-extern uint256 hashGenesisBlock;
extern CBlockIndex* pindexGenesisBlock;
extern int nBestHeight;
extern uint256 nBestChainWork;
@@ -86,7 +87,6 @@ extern int64 nHPSTimerStart;
extern int64 nTimeBestReceived;
extern CCriticalSection cs_setpwalletRegistered;
extern std::set<CWallet*> setpwalletRegistered;
-extern unsigned char pchMessageStart[4];
extern bool fImporting;
extern bool fReindex;
extern bool fBenchmark;
@@ -146,7 +146,7 @@ bool LoadBlockIndex();
/** Unload database information */
void UnloadBlockIndex();
/** Verify consistency of the block and coin databases */
-bool VerifyDB();
+bool VerifyDB(int nCheckLevel, int nCheckDepth);
/** Print the loaded block tree */
void PrintBlockTree();
/** Find a block by height in the currently-connected chain */
@@ -262,12 +262,11 @@ struct CDiskTxPos : public CDiskBlockPos
enum GetMinFee_mode
{
- GMF_BLOCK,
GMF_RELAY,
GMF_SEND,
};
-int64 GetMinFee(const CTransaction& tx, unsigned int nBlockSize = 1, bool fAllowFree = true, enum GetMinFee_mode mode = GMF_BLOCK);
+int64 GetMinFee(const CTransaction& tx, bool fAllowFree, enum GetMinFee_mode mode);
//
// Check transaction inputs, and make sure any
@@ -353,7 +352,7 @@ public:
// Write index header
unsigned int nSize = fileout.GetSerializeSize(*this);
- fileout << FLATDATA(pchMessageStart) << nSize;
+ fileout << FLATDATA(Params().MessageStart()) << nSize;
// Write undo data
long fileOutPos = ftell(fileout);
@@ -582,204 +581,33 @@ public:
};
-class CBlock : public CBlockHeader
-{
-public:
- // network and disk
- std::vector<CTransaction> vtx;
- // memory only
- mutable std::vector<uint256> vMerkleTree;
+/** Functions for disk access for blocks */
+bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos);
+bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos);
+bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
- CBlock()
- {
- SetNull();
- }
- CBlock(const CBlockHeader &header)
- {
- SetNull();
- *((CBlockHeader*)this) = header;
- }
+/** Functions for validating blocks and updating the block tree */
- IMPLEMENT_SERIALIZE
- (
- READWRITE(*(CBlockHeader*)this);
- READWRITE(vtx);
- )
+/** Undo the effects of this block (with given index) on the UTXO set represented by coins.
+ * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
+ * will be true if no problems were found. Otherwise, the return value will be false in case
+ * of problems. Note that in any case, coins may be modified. */
+bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL);
- void SetNull()
- {
- CBlockHeader::SetNull();
- vtx.clear();
- vMerkleTree.clear();
- }
+// Apply the effects of this block (with given index) on the UTXO set represented by coins
+bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false);
- CBlockHeader GetBlockHeader() const
- {
- CBlockHeader block;
- block.nVersion = nVersion;
- block.hashPrevBlock = hashPrevBlock;
- block.hashMerkleRoot = hashMerkleRoot;
- block.nTime = nTime;
- block.nBits = nBits;
- block.nNonce = nNonce;
- return block;
- }
-
- uint256 BuildMerkleTree() const
- {
- vMerkleTree.clear();
- BOOST_FOREACH(const CTransaction& tx, vtx)
- vMerkleTree.push_back(tx.GetHash());
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- for (int i = 0; i < nSize; i += 2)
- {
- int i2 = std::min(i+1, nSize-1);
- vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
- BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
- }
- j += nSize;
- }
- return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
- }
-
- const uint256 &GetTxHash(unsigned int nIndex) const {
- assert(vMerkleTree.size() > 0); // BuildMerkleTree must have been called first
- assert(nIndex < vtx.size());
- return vMerkleTree[nIndex];
- }
-
- std::vector<uint256> GetMerkleBranch(int nIndex) const
- {
- if (vMerkleTree.empty())
- BuildMerkleTree();
- std::vector<uint256> vMerkleBranch;
- int j = 0;
- for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
- {
- int i = std::min(nIndex^1, nSize-1);
- vMerkleBranch.push_back(vMerkleTree[j+i]);
- nIndex >>= 1;
- j += nSize;
- }
- return vMerkleBranch;
- }
-
- static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
- {
- if (nIndex == -1)
- return 0;
- BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
- {
- if (nIndex & 1)
- hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
- else
- hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
- nIndex >>= 1;
- }
- return hash;
- }
-
- bool WriteToDisk(CDiskBlockPos &pos)
- {
- // Open history file to append
- CAutoFile fileout = CAutoFile(OpenBlockFile(pos), SER_DISK, CLIENT_VERSION);
- if (!fileout)
- return error("CBlock::WriteToDisk() : OpenBlockFile failed");
-
- // Write index header
- unsigned int nSize = fileout.GetSerializeSize(*this);
- fileout << FLATDATA(pchMessageStart) << nSize;
-
- // Write block
- long fileOutPos = ftell(fileout);
- if (fileOutPos < 0)
- return error("CBlock::WriteToDisk() : ftell failed");
- pos.nPos = (unsigned int)fileOutPos;
- fileout << *this;
-
- // Flush stdio buffers and commit to disk before returning
- fflush(fileout);
- if (!IsInitialBlockDownload())
- FileCommit(fileout);
-
- return true;
- }
-
- bool ReadFromDisk(const CDiskBlockPos &pos)
- {
- SetNull();
-
- // Open history file to read
- CAutoFile filein = CAutoFile(OpenBlockFile(pos, true), SER_DISK, CLIENT_VERSION);
- if (!filein)
- return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
-
- // Read block
- try {
- filein >> *this;
- }
- catch (std::exception &e) {
- return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__);
- }
-
- // Check the header
- if (!CheckProofOfWork(GetHash(), nBits))
- return error("CBlock::ReadFromDisk() : errors in block header");
-
- return true;
- }
-
-
-
- void print() const
- {
- printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu")\n",
- GetHash().ToString().c_str(),
- nVersion,
- hashPrevBlock.ToString().c_str(),
- hashMerkleRoot.ToString().c_str(),
- nTime, nBits, nNonce,
- vtx.size());
- for (unsigned int i = 0; i < vtx.size(); i++)
- {
- printf(" ");
- vtx[i].print();
- }
- printf(" vMerkleTree: ");
- for (unsigned int i = 0; i < vMerkleTree.size(); i++)
- printf("%s ", vMerkleTree[i].ToString().c_str());
- printf("\n");
- }
-
-
- /** Undo the effects of this block (with given index) on the UTXO set represented by coins.
- * In case pfClean is provided, operation will try to be tolerant about errors, and *pfClean
- * will be true if no problems were found. Otherwise, the return value will be false in case
- * of problems. Note that in any case, coins may be modified. */
- bool DisconnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &coins, bool *pfClean = NULL);
-
- // Apply the effects of this block (with given index) on the UTXO set represented by coins
- bool ConnectBlock(CValidationState &state, CBlockIndex *pindex, CCoinsViewCache &coins, bool fJustCheck=false);
-
- // Read a block from disk
- bool ReadFromDisk(const CBlockIndex* pindex);
-
- // Add this block to the block index, and if necessary, switch the active block chain to this
- bool AddToBlockIndex(CValidationState &state, const CDiskBlockPos &pos);
-
- // Context-independent validity checks
- bool CheckBlock(CValidationState &state, bool fCheckPOW=true, bool fCheckMerkleRoot=true) const;
-
- // Store block on disk
- // if dbp is provided, the file is known to already reside on disk
- bool AcceptBlock(CValidationState &state, CDiskBlockPos *dbp = NULL);
-};
+// Add this block to the block index, and if necessary, switch the active block chain to this
+bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos& pos);
+// Context-independent validity checks
+bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
+// Store block on disk
+// if dbp is provided, the file is known to already reside on disk
+bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp = NULL);
@@ -1202,22 +1030,14 @@ class CBlockLocator
protected:
std::vector<uint256> vHave;
public:
-
- CBlockLocator()
- {
- }
+ CBlockLocator() {}
explicit CBlockLocator(const CBlockIndex* pindex)
{
Set(pindex);
}
- explicit CBlockLocator(uint256 hashBlock)
- {
- std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
- if (mi != mapBlockIndex.end())
- Set((*mi).second);
- }
+ explicit CBlockLocator(uint256 hashBlock);
CBlockLocator(const std::vector<uint256>& vHaveIn)
{
@@ -1241,83 +1061,16 @@ public:
return vHave.empty();
}
- void Set(const CBlockIndex* pindex)
- {
- vHave.clear();
- int nStep = 1;
- while (pindex)
- {
- vHave.push_back(pindex->GetBlockHash());
-
- // Exponentially larger steps back
- for (int i = 0; pindex && i < nStep; i++)
- pindex = pindex->pprev;
- if (vHave.size() > 10)
- nStep *= 2;
- }
- vHave.push_back(hashGenesisBlock);
- }
-
- int 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 (pindex->IsInMainChain())
- return nDistance;
- }
- nDistance += nStep;
- if (nDistance > 10)
- nStep *= 2;
- }
- return nDistance;
- }
-
- CBlockIndex* GetBlockIndex()
- {
- // 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 (pindex->IsInMainChain())
- return pindex;
- }
- }
- return pindexGenesisBlock;
- }
-
- uint256 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 (pindex->IsInMainChain())
- return hash;
- }
- }
- return hashGenesisBlock;
- }
-
- int GetHeight()
- {
- CBlockIndex* pindex = GetBlockIndex();
- if (!pindex)
- return 0;
- return pindex->nHeight;
- }
+ /** 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/makefile.linux-mingw b/src/makefile.linux-mingw
index 9cfab5942a..26d541664e 100644
--- a/src/makefile.linux-mingw
+++ b/src/makefile.linux-mingw
@@ -93,7 +93,8 @@ OBJS= \
obj/hash.o \
obj/bloom.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
all: bitcoind.exe
diff --git a/src/makefile.mingw b/src/makefile.mingw
index 33cc7e6b4a..3659f52040 100644
--- a/src/makefile.mingw
+++ b/src/makefile.mingw
@@ -101,7 +101,8 @@ OBJS= \
obj/bloom.o \
obj/noui.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
all: bitcoind.exe
diff --git a/src/makefile.osx b/src/makefile.osx
index bef0ef3518..269460c1ba 100644
--- a/src/makefile.osx
+++ b/src/makefile.osx
@@ -104,7 +104,8 @@ OBJS= \
obj/bloom.o \
obj/noui.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
ifndef USE_UPNP
override USE_UPNP = -
diff --git a/src/makefile.unix b/src/makefile.unix
index a83bab1047..f17de05cb9 100644
--- a/src/makefile.unix
+++ b/src/makefile.unix
@@ -143,7 +143,8 @@ OBJS= \
obj/bloom.o \
obj/noui.o \
obj/leveldb.o \
- obj/txdb.o
+ obj/txdb.o \
+ obj/chainparams.o
all: bitcoind
diff --git a/src/net.cpp b/src/net.cpp
index 1f8b39ac98..0adf26ef0d 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -3,6 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "db.h"
#include "net.h"
#include "core.h"
@@ -80,7 +81,7 @@ void AddOneShot(string strDest)
unsigned short GetListenPort()
{
- return (unsigned short)(GetArg("-port", GetDefaultPort()));
+ return (unsigned short)(GetArg("-port", Params().GetDefaultPort()));
}
// find 'best' local address for a particular peer
@@ -464,7 +465,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest)
// Connect
SOCKET hSocket;
- if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
+ if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, Params().GetDefaultPort()) : ConnectSocket(addrConnect, hSocket))
{
addrman.Attempt(addrConnect);
@@ -533,7 +534,7 @@ void CNode::PushVersion()
RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), addr.ToString().c_str());
PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe,
- nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight);
+ nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight, true);
}
@@ -1170,53 +1171,31 @@ void MapPort(bool)
-
-
-
-// DNS seeds
-// Each pair gives a source name and a seed name.
-// The first name is used as information source for addrman.
-// The second name should resolve to a list of seed addresses.
-static const char *strMainNetDNSSeed[][2] = {
- {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"},
- {"bluematt.me", "dnsseed.bluematt.me"},
- {"dashjr.org", "dnsseed.bitcoin.dashjr.org"},
- {"xf2.org", "bitseed.xf2.org"},
- {NULL, NULL}
-};
-
-static const char *strTestNetDNSSeed[][2] = {
- {"bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org"},
- {"bluematt.me", "testnet-seed.bluematt.me"},
- {NULL, NULL}
-};
-
void ThreadDNSAddressSeed()
{
- static const char *(*strDNSSeed)[2] = fTestNet ? strTestNetDNSSeed : strMainNetDNSSeed;
-
+ const vector<CDNSSeedData> &vSeeds = Params().DNSSeeds();
int found = 0;
printf("Loading addresses from DNS seeds (could take a while)\n");
- for (unsigned int seed_idx = 0; strDNSSeed[seed_idx][0] != NULL; seed_idx++) {
+ BOOST_FOREACH(const CDNSSeedData &seed, vSeeds) {
if (HaveNameProxy()) {
- AddOneShot(strDNSSeed[seed_idx][1]);
+ AddOneShot(seed.host);
} else {
- vector<CNetAddr> vaddr;
+ vector<CNetAddr> vIPs;
vector<CAddress> vAdd;
- if (LookupHost(strDNSSeed[seed_idx][1], vaddr))
+ if (LookupHost(seed.host.c_str(), vIPs))
{
- BOOST_FOREACH(CNetAddr& ip, vaddr)
+ BOOST_FOREACH(CNetAddr& ip, vIPs)
{
int nOneDay = 24*3600;
- CAddress addr = CAddress(CService(ip, GetDefaultPort()));
+ CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()));
addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
found++;
}
}
- addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true));
+ addrman.Add(vAdd, CNetAddr(seed.name, true));
}
}
@@ -1234,85 +1213,6 @@ void ThreadDNSAddressSeed()
-unsigned int pnSeed[] =
-{
- 0xe473042e, 0xb177f2ad, 0xd63f3fb2, 0xf864f736, 0x44a23ac7, 0xcf6d9650, 0xd648042e, 0x0536f447,
- 0x3c654ed0, 0x3e16a5bc, 0xa38e09b0, 0xdfae795b, 0xabfeca5b, 0x94ad7840, 0xf3b9f1c7, 0xbe70e0ad,
- 0x3bbd09b0, 0x8d0c7dd5, 0x3b2a7332, 0x1a06175e, 0x581f175e, 0xca0d2dcc, 0x0fdbc658, 0xcf591ec7,
- 0x295a12b2, 0xb4707bce, 0x68bb09b0, 0x4e735747, 0x89709553, 0x05a7814e, 0x5b8ec658, 0x402c5512,
- 0xe80d0905, 0x17681a5e, 0xc02aa748, 0x9f811741, 0x5f321cb0, 0x23e1ee47, 0xaf7f170c, 0xaa240ab0,
- 0xedea6257, 0x76106bc1, 0x2cf310cc, 0x08612acb, 0x9c682e4e, 0x8e963c6c, 0x443c795b, 0x22e246b8,
- 0xfa1f2dcc, 0x90118140, 0x3821042e, 0x33c3fd2e, 0x10046d5b, 0x40d14b3e, 0x7fb8f8ce, 0x67696550,
- 0xeeecbe58, 0x4f341745, 0x46b8fbd5, 0xc8463932, 0x6b73e862, 0x4c715932, 0x4a6785d5, 0xce3a64c2,
- 0xde9604c7, 0x9b06884f, 0x18002a45, 0xea9bc345, 0xc4f1c658, 0xe475c1c7, 0xdd3e795b, 0x9722175e,
- 0x34562f4e, 0x66c46e4e, 0x40bb1243, 0x7d9171d0, 0x17b8dbd5, 0x63cbfd2e, 0x1a08b8d8, 0x6175a73b,
- 0x228d2660, 0x8627c658, 0x9c566644, 0x38cca5bc, 0x3089de5b, 0x92e25f5d, 0xa393f73f, 0xcc92dc3e,
- 0x27487446, 0x62cbfd2e, 0x9d983b45, 0xf72a09b0, 0xf75f042e, 0x6434bb6a, 0xb29e77d8, 0x19be4fd9,
- 0x76443243, 0x9dd72645, 0x694cef43, 0x89c2efd5, 0x5f1c5058, 0x46c6e45b, 0xe1391b40, 0x77ccefd5,
- 0x472e5a6d, 0x85709553, 0xdd4f5d4c, 0x64ef5a46, 0x7f0ae502, 0xcf08d850, 0x3460042e, 0xeafa2d42,
- 0x793c9044, 0x9d094746, 0x1ab9b153, 0xbfe9a5bc, 0x34771fb0, 0xb7722e32, 0x1168964b, 0x19b06ab8,
- 0x19243b25, 0x13188045, 0xb4070905, 0x728ebb5d, 0x44f24ac8, 0xa317fead, 0x642f6a57, 0x3d951f32,
- 0x3d312e4e, 0xfac4d048, 0xefc4dd50, 0x52b9f1c7, 0xc14d3cc3, 0x0219ea44, 0x3b79d058, 0xfa217242,
- 0x39c80647, 0xfb697252, 0x1d495a42, 0x0aa81f4e, 0x58249ab8, 0xe6a8e6c3, 0x2bc4dad8, 0x85963c6c,
- 0xa4ce09b0, 0x2005f536, 0x5cc2703e, 0x1992de43, 0x74e86b4c, 0xe7085653, 0xf5e15a51, 0xb4872b60,
- 0x29e2b162, 0xa07ea053, 0x8229fd18, 0x4562ec4d, 0x8dec814e, 0x36cfa4cf, 0x96461032, 0x3c8770de,
- 0xd10a1f5f, 0x95934641, 0x97cd65d0, 0x2e35324a, 0x2566ba1f, 0x1ca1a9d1, 0xb808b8d5, 0xf9a24a5d,
- 0xafc8d431, 0xe4b8d9b2, 0x0f5321b2, 0x330bc658, 0x74b347ce, 0x972babd5, 0x044f7d4f, 0x06562f4e,
- 0x8b8d3c6c, 0x3507c658, 0xe4174e4d, 0xf1c009b0, 0x52249ab8, 0x27211772, 0xf6a9ba59, 0x7a391b40,
- 0x855dc6c0, 0x291f20b2, 0xe29bc345, 0x90963c6c, 0x0af70732, 0x4242a91f, 0x4c531d48, 0xa32df948,
- 0x627e3044, 0x65be1f54, 0x1a0cbf83, 0x6a443532, 0x8d5f1955, 0xbafa8132, 0x3534bdd5, 0xca019dd9,
- 0x8a0d9332, 0x5584e7d8, 0x7cd1f25e, 0xeabe3fb2, 0x2945d0d1, 0x46415718, 0x70d6042e, 0x99eb76d0,
- 0x9ece09b0, 0xb3777418, 0x5e5e91d9, 0x237a3ab0, 0xf512b62e, 0x45dec347, 0x59b7f862, 0x4c443b25,
- 0x3cc6484b, 0x9a8ec6d1, 0x021eea44, 0xc9483944, 0xfd567e32, 0xfd204bb2, 0xc5330bcc, 0x5202894e,
- 0xf9e309b0, 0x4cc17557, 0xdb9064ae, 0xe19e77d8, 0x25857f60, 0xeb4a15ad, 0x1f47f554, 0xea4472d9,
- 0xd20de593, 0xf5733b25, 0x11892b54, 0x5729d35f, 0xe6188cd1, 0x488b132e, 0x541c534a, 0xa8e854ae,
- 0xa255a66c, 0x33688763, 0xc6629ac6, 0xc20a6265, 0xcd92a059, 0x72029d3b, 0x4c298f5e, 0x51452e4e,
- 0xbb065058, 0x15fd2dcc, 0xf40c135e, 0x615a0bad, 0x0c6a6805, 0x4971a7ad, 0x17f2a5d5, 0xf8babf47,
- 0xb61f50ad, 0x4e1451b1, 0xf72d9252, 0x5c2abe58, 0xbd987c61, 0x084ae5cf, 0x20781fb0, 0x38b0f160,
- 0x18aac705, 0x14f86dc1, 0x5556f481, 0x0a36c144, 0xeb446e4c, 0x2c1c0d6c, 0xbd0ff860, 0x869f92db,
- 0x36c94f4c, 0x05502444, 0x148fe55b, 0xd5301e59, 0xd57a8f45, 0x110dc04a, 0x8670fc36, 0xee733b25,
- 0xca56f481, 0x2a5c3bae, 0x844b0905, 0x1e51fe53, 0x0241c244, 0x59c0614e, 0x94e70a55, 0x7312fead,
- 0xb735be44, 0xa55d0905, 0x2f63962e, 0x14a4e15b, 0x63f8f05c, 0x62d0d262, 0x3cab41ad, 0x87f1b1cb,
- 0x018da6b8, 0xb3967dd5, 0xcb56f481, 0x685ad718, 0x3b4aeeca, 0x8d106bc1, 0x51180905, 0x72660f48,
- 0x1521a243, 0x5b56f481, 0x6390e560, 0xdd61464e, 0x58353b25, 0x553fc062, 0x27c45d59, 0xacc62e4e,
- 0x0d5a1cd9, 0x7f65f442, 0xbdeef660, 0xf1bd1855, 0xf8473cae, 0x13b120b2, 0x442440d0, 0x53fd4352,
- 0xa305fc57, 0x458be84d, 0x639ce1c3, 0xebaaee47, 0x95e2c247, 0xf056f481, 0x6256f481, 0x1d87c65e,
- 0x0a453418, 0x5beb175e, 0xd64f1618, 0xc360795b, 0x2fbf5753, 0xa8c58e53, 0x651cec52, 0x9d37b043,
- 0x124a9758, 0x5242e4a9, 0x89913c6c, 0x880efe2e, 0x2f2f2f0c, 0x72b26751, 0x2896e46d, 0x80f4166c,
- 0x320d59ad, 0xc50151d0, 0x11a8aa43, 0xccf56057, 0x5fbad118, 0x4719b151, 0x2b5f4bc0, 0x4d7a4a50,
- 0xad06e047, 0x62ef5a46, 0x5aebde58, 0xdf7aa66c, 0x851acb50, 0x66b9a559, 0x3e9bb153, 0xcc512f2e,
- 0xc073b08e, 0xd519be58, 0xe981ea4d, 0x12fd50cb, 0x378739ad, 0x06683cae, 0xa22310b2, 0xc185c705,
- 0x8741b545, 0xa26c8318, 0x22d5bc43, 0x39201ec0, 0x68581e3e, 0xdc9bcf62, 0xd508cc82, 0xb149675b,
- 0x4c9609b0, 0x84feb84c, 0x08291e2e, 0xfd2253b2, 0x1fd269c1, 0xc9483932, 0x4d641fb0, 0x7d37c918,
- 0xa9de20ad, 0x77e2d655, 0x6d421b59, 0xd7668f80, 0xced09b62, 0xa9e5a5bc, 0xa4074e18, 0x60fc5ecc,
- 0x01300148, 0x68062444, 0xb4224847, 0xed3aa443, 0xb772fb43, 0x9f56f481, 0x220dfd18, 0x8e1c3d6c,
- 0xc44f09b0, 0x7df2bb73, 0xe22fb844, 0xea534242, 0xb6a755d4, 0xa036654b, 0x138ece5b, 0xda65d3c3,
- 0x955871bc, 0x792124b0, 0xfc82594c, 0x851d494b, 0x2c7aee47, 0x26af46b8, 0x1416252e, 0xa8abb944,
- 0x36c49d25, 0x674f645d, 0x363646b8, 0x9e1a2942, 0x66d0c154, 0xc6c2a545, 0x3570f2ad, 0xe7d547c7,
- 0x7d104932, 0x18cb9c18, 0x1dcfa4cf, 0xd156f481, 0x2a02b91f, 0x3eeb3fa8, 0xcac4175e, 0x34146d42,
- 0x994c4d46, 0x5666f440, 0x85d6713e, 0x5ecb296c, 0x0ea0ae46, 0x87e69f42, 0xc58409b0, 0x1f3436ae,
- 0x21dc6a57, 0x4ad1cd42, 0xfb8c1a4c, 0x52d3dab2, 0x3769894b, 0xb52f1c62, 0x3677916d, 0x82b3fe57,
- 0x493d4ac6, 0x9f963c6c, 0x5d91ff60, 0x458e0dad, 0xa49d0947, 0x491a3e18, 0x4aadcd5b, 0x0e46494b,
- 0x1d1610ad, 0x1a10af5d, 0x4956f481, 0x207a3eae, 0x77e73244, 0xfa3b8742, 0x3261fc36, 0xfcebf536,
- 0x1662e836, 0xf655f636, 0xa2dbd0ad, 0x23036693, 0x30448432, 0xa2b03463, 0x30730344, 0x8e4a6882,
- 0x0c50a1cb, 0xc8d8c06b, 0xc9cd6191, 0xf443db50, 0xa9553c50, 0x23145847, 0xc35da66c, 0x29c12a60,
- 0x55c2b447, 0x7434f75c, 0x61660640, 0xde2a7018, 0xc639494c, 0x1c306fce, 0x19b89244, 0xd29a6462,
- 0x462cd1b2, 0x29902f44, 0x2817fa53, 0x21a30905, 0x7777ae46, 0x288443a1, 0x7bee5148, 0xc2a8b043,
- 0xf5c3d35f, 0x2311ef84, 0x57de08a4, 0x6b221bb2, 0xf2625846, 0x4b9e09b0, 0xa24f880e, 0x22b11447,
- 0xb3a0c744, 0x919e77d8, 0xec8b64ae, 0xff5c8d45, 0x7b15b484, 0x32679a5f, 0xba80b62e, 0x05c25c61,
- 0x60014746, 0x5e8fb04c, 0xe67c0905, 0x4329c658, 0xac8fe555, 0xf875e647, 0x67406386, 0x35ceea18,
- 0xbb79484b, 0xd7b9fa62, 0x238209b0, 0x208a1d32, 0x9630995e, 0x039c1318, 0x6e48006c, 0x60582344,
- 0xadbb0150, 0x853fd462, 0x03772e4e, 0x652ce960, 0x49b630ad, 0x9993af43, 0x3735b34b, 0x548a07d9,
- 0x55a44aad, 0xa23d1bcc, 0xfdbb2f4e, 0x530b24a0, 0x0a44b451, 0x6827c657, 0x1f66494b, 0x4e680a47,
- 0x77e7b747, 0xa5eb3fa8, 0x6649764a, 0xd4e76c4b, 0x2c691fb0, 0xf1292e44, 0xc6d6c774, 0x85d23775,
- 0x28275f4d, 0x259ae46d, 0x02424e81, 0x5f16be58, 0xe707c658, 0x49eae5c7, 0xd5d147ad, 0x9a7abdc3,
- 0xe8ac7fc7, 0x84ec3aae, 0xc24942d0, 0x294aa318, 0x08ac3d18, 0x8894042e, 0xb24609b0, 0x9bcaab58,
- 0xc400f712, 0xd5c512b8, 0x2c02cc62, 0x25080fd8, 0xed74a847, 0x18a5ec5e, 0x9850ec6d, 0xf8909758,
- 0x7f56f481, 0x4496f23c, 0xae27784f, 0xcb7cd93e, 0x06e32860, 0x50b9a84f, 0x3660434a, 0x09161f5f,
- 0x900486bc, 0x08055459, 0xe7ec1017, 0x7e39494c, 0x4f443b25, 0x14751a8a, 0x717d03d4, 0xbd0e24d8,
- 0x054b6f56, 0x854c496c, 0xd92a454a, 0xc39bd054, 0x6093614b, 0x9dbad754, 0x5bf0604a, 0x99f22305
-};
-
void DumpAddresses()
{
int64 nStart = GetTimeMillis();
@@ -1374,24 +1274,14 @@ void ThreadOpenConnections()
CSemaphoreGrant grant(*semOutbound);
boost::this_thread::interruption_point();
- // Add seed nodes if IRC isn't working
- if (addrman.size()==0 && (GetTime() - nStart > 60) && !fTestNet)
- {
- std::vector<CAddress> vAdd;
- for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++)
- {
- // It'll only connect to one or two seed nodes because once it connects,
- // it'll get a pile of addresses with newer timestamps.
- // Seed nodes are given a random 'last seen time' of between one and two
- // weeks ago.
- const int64 nOneWeek = 7*24*60*60;
- struct in_addr ip;
- memcpy(&ip, &pnSeed[i], sizeof(ip));
- CAddress addr(CService(ip, GetDefaultPort()));
- addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek;
- vAdd.push_back(addr);
+ // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
+ if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
+ static bool done = false;
+ if (!done) {
+ printf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
+ addrman.Add(Params().FixedSeeds(), CNetAddr("127.0.0.1"));
+ done = true;
}
- addrman.Add(vAdd, CNetAddr("127.0.0.1"));
}
//
@@ -1440,7 +1330,7 @@ void ThreadOpenConnections()
continue;
// do not allow non-default ports, unless after 50 invalid addresses selected already
- if (addr.GetPort() != GetDefaultPort() && nTries < 50)
+ if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
continue;
addrConnect = addr;
@@ -1490,7 +1380,7 @@ void ThreadOpenAddedConnections()
BOOST_FOREACH(string& strAddNode, lAddresses)
{
vector<CService> vservNode(0);
- if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
+ if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
{
lservAddressesToAdd.push_back(vservNode);
{
diff --git a/src/protocol.cpp b/src/protocol.cpp
index 1e22467a33..745b4338e4 100644
--- a/src/protocol.cpp
+++ b/src/protocol.cpp
@@ -21,7 +21,7 @@ static const char* ppszTypeName[] =
CMessageHeader::CMessageHeader()
{
- memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
+ memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
memset(pchCommand, 0, sizeof(pchCommand));
pchCommand[1] = 1;
nMessageSize = -1;
@@ -30,7 +30,7 @@ CMessageHeader::CMessageHeader()
CMessageHeader::CMessageHeader(const char* pszCommand, unsigned int nMessageSizeIn)
{
- memcpy(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart));
+ memcpy(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE);
strncpy(pchCommand, pszCommand, COMMAND_SIZE);
nMessageSize = nMessageSizeIn;
nChecksum = 0;
@@ -47,7 +47,7 @@ std::string CMessageHeader::GetCommand() const
bool CMessageHeader::IsValid() const
{
// Check start string
- if (memcmp(pchMessageStart, ::pchMessageStart, sizeof(pchMessageStart)) != 0)
+ if (memcmp(pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0)
return false;
// Check the command string for errors
diff --git a/src/protocol.h b/src/protocol.h
index 4998425070..ae541dfdba 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -10,20 +10,12 @@
#ifndef __INCLUDED_PROTOCOL_H__
#define __INCLUDED_PROTOCOL_H__
+#include "chainparams.h"
#include "serialize.h"
#include "netbase.h"
#include <string>
#include "uint256.h"
-extern bool fTestNet;
-static inline unsigned short GetDefaultPort(const bool testnet = fTestNet)
-{
- return testnet ? 18333 : 8333;
-}
-
-
-extern unsigned char pchMessageStart[4];
-
/** Message header.
* (4) message start.
* (12) command.
@@ -50,7 +42,6 @@ class CMessageHeader
// TODO: make private (improves encapsulation)
public:
enum {
- MESSAGE_START_SIZE=sizeof(::pchMessageStart),
COMMAND_SIZE=12,
MESSAGE_SIZE_SIZE=sizeof(int),
CHECKSUM_SIZE=sizeof(int),
diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp
index e8d99a8d45..5cf4dd8111 100644
--- a/src/qt/clientmodel.cpp
+++ b/src/qt/clientmodel.cpp
@@ -5,6 +5,7 @@
#include "addresstablemodel.h"
#include "transactiontablemodel.h"
+#include "chainparams.h"
#include "alert.h"
#include "main.h"
#include "checkpoints.h"
@@ -110,7 +111,7 @@ void ClientModel::updateAlert(const QString &hash, int status)
bool ClientModel::isTestNet() const
{
- return fTestNet;
+ return TestNet();
}
bool ClientModel::inInitialBlockDownload() const
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index a0ddc4d9ee..3c24016fe3 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -163,7 +163,7 @@ Value getblock(const Array& params, bool fHelp)
CBlock block;
CBlockIndex* pblockindex = mapBlockIndex[hash];
- block.ReadFromDisk(pblockindex);
+ ReadBlockFromDisk(block, pblockindex);
if (!fVerbose)
{
@@ -243,4 +243,20 @@ Value gettxout(const Array& params, bool fHelp)
return ret;
}
+Value verifychain(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 2)
+ throw runtime_error(
+ "verifychain [check level] [num blocks]\n"
+ "Verifies blockchain database.");
+
+ int nCheckLevel = GetArg("-checklevel", 3);
+ int nCheckDepth = GetArg("-checkblocks", 288);
+ if (params.size() > 0)
+ nCheckLevel = params[0].get_int();
+ if (params.size() > 1)
+ nCheckDepth = params[1].get_int();
+
+ return VerifyDB(nCheckLevel, nCheckDepth);
+}
diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp
index d46309eaa4..dcfb023f35 100644
--- a/src/rpcdump.cpp
+++ b/src/rpcdump.cpp
@@ -2,35 +2,68 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include <iostream>
+#include <fstream>
+
#include "init.h" // for pwalletMain
#include "bitcoinrpc.h"
#include "ui_interface.h"
#include "base58.h"
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/variant/get.hpp>
+#include <boost/algorithm/string.hpp>
#define printf OutputDebugStringF
using namespace json_spirit;
using namespace std;
-class CTxDump
-{
-public:
- CBlockIndex *pindex;
- int64 nValue;
- bool fSpent;
- CWalletTx* ptx;
- int nOut;
- CTxDump(CWalletTx* ptx = NULL, int nOut = -1)
- {
- pindex = NULL;
- nValue = 0;
- fSpent = false;
- this->ptx = ptx;
- this->nOut = nOut;
+void EnsureWalletIsUnlocked();
+
+std::string static EncodeDumpTime(int64 nTime) {
+ return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
+}
+
+int64 static DecodeDumpTime(const std::string &str) {
+ static const boost::posix_time::time_input_facet facet("%Y-%m-%dT%H:%M:%SZ");
+ static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
+ const std::locale loc(std::locale::classic(), &facet);
+ std::istringstream iss(str);
+ iss.imbue(loc);
+ boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
+ iss >> ptime;
+ if (ptime.is_not_a_date_time())
+ return 0;
+ return (ptime - epoch).total_seconds();
+}
+
+std::string static EncodeDumpString(const std::string &str) {
+ std::stringstream ret;
+ BOOST_FOREACH(unsigned char c, str) {
+ if (c <= 32 || c >= 128 || c == '%') {
+ ret << '%' << HexStr(&c, &c + 1);
+ } else {
+ ret << c;
+ }
+ }
+ return ret.str();
+}
+
+std::string DecodeDumpString(const std::string &str) {
+ std::stringstream ret;
+ for (unsigned int pos = 0; pos < str.length(); pos++) {
+ unsigned char c = str[pos];
+ if (c == '%' && pos+2 < str.length()) {
+ c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
+ ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
+ pos += 2;
+ }
+ ret << c;
}
-};
+ return ret.str();
+}
Value importprivkey(const Array& params, bool fHelp)
{
@@ -63,6 +96,10 @@ Value importprivkey(const Array& params, bool fHelp)
pwalletMain->MarkDirty();
pwalletMain->SetAddressBookName(vchAddress, strLabel);
+ // Don't throw error in case a key is already there
+ if (pwalletMain->HaveKey(vchAddress))
+ return Value::null;
+
if (!pwalletMain->AddKeyPubKey(key, pubkey))
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
@@ -75,6 +112,86 @@ Value importprivkey(const Array& params, bool fHelp)
return Value::null;
}
+Value importwallet(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "importwallet <filename>\n"
+ "Imports keys from a wallet dump file (see dumpwallet).");
+
+ EnsureWalletIsUnlocked();
+
+ ifstream file;
+ file.open(params[0].get_str().c_str());
+ if (!file.is_open())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
+
+ int64 nTimeBegin = pindexBest->nTime;
+
+ bool fGood = true;
+
+ while (file.good()) {
+ std::string line;
+ std::getline(file, line);
+ if (line.empty() || line[0] == '#')
+ continue;
+
+ std::vector<std::string> vstr;
+ boost::split(vstr, line, boost::is_any_of(" "));
+ if (vstr.size() < 2)
+ continue;
+ CBitcoinSecret vchSecret;
+ if (!vchSecret.SetString(vstr[0]))
+ continue;
+ CKey key = vchSecret.GetKey();
+ CPubKey pubkey = key.GetPubKey();
+ CKeyID keyid = pubkey.GetID();
+ if (pwalletMain->HaveKey(keyid)) {
+ printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
+ continue;
+ }
+ int64 nTime = DecodeDumpTime(vstr[1]);
+ std::string strLabel;
+ bool fLabel = true;
+ for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
+ if (boost::algorithm::starts_with(vstr[nStr], "#"))
+ break;
+ if (vstr[nStr] == "change=1")
+ fLabel = false;
+ if (vstr[nStr] == "reserve=1")
+ fLabel = false;
+ if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
+ strLabel = DecodeDumpString(vstr[nStr].substr(6));
+ fLabel = true;
+ }
+ }
+ printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
+ if (!pwalletMain->AddKeyPubKey(key, pubkey)) {
+ fGood = false;
+ continue;
+ }
+ pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
+ if (fLabel)
+ pwalletMain->SetAddressBookName(keyid, strLabel);
+ nTimeBegin = std::min(nTimeBegin, nTime);
+ }
+ file.close();
+
+ CBlockIndex *pindex = pindexBest;
+ while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
+ pindex = pindex->pprev;
+
+ printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
+ pwalletMain->ScanForWalletTransactions(pindex);
+ pwalletMain->ReacceptWalletTransactions();
+ pwalletMain->MarkDirty();
+
+ if (!fGood)
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
+
+ return Value::null;
+}
+
Value dumpprivkey(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
@@ -82,6 +199,8 @@ Value dumpprivkey(const Array& params, bool fHelp)
"dumpprivkey <bitcoinaddress>\n"
"Reveals the private key corresponding to <bitcoinaddress>.");
+ EnsureWalletIsUnlocked();
+
string strAddress = params[0].get_str();
CBitcoinAddress address;
if (!address.SetString(strAddress))
@@ -94,3 +213,58 @@ Value dumpprivkey(const Array& params, bool fHelp)
throw JSONRPCError(RPC_WALLET_ERROR, "Private key for address " + strAddress + " is not known");
return CBitcoinSecret(vchSecret).ToString();
}
+
+
+Value dumpwallet(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "dumpwallet <filename>\n"
+ "Dumps all wallet keys in a human-readable format.");
+
+ EnsureWalletIsUnlocked();
+
+ ofstream file;
+ file.open(params[0].get_str().c_str());
+ if (!file.is_open())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
+
+ std::map<CKeyID, int64> mapKeyBirth;
+ std::set<CKeyID> setKeyPool;
+ pwalletMain->GetKeyBirthTimes(mapKeyBirth);
+ pwalletMain->GetAllReserveKeys(setKeyPool);
+
+ // sort time/key pairs
+ std::vector<std::pair<int64, CKeyID> > vKeyBirth;
+ for (std::map<CKeyID, int64>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
+ vKeyBirth.push_back(std::make_pair(it->second, it->first));
+ }
+ mapKeyBirth.clear();
+ std::sort(vKeyBirth.begin(), vKeyBirth.end());
+
+ // produce output
+ file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
+ file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
+ file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
+ file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
+ file << "\n";
+ for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
+ const CKeyID &keyid = it->second;
+ std::string strTime = EncodeDumpTime(it->first);
+ std::string strAddr = CBitcoinAddress(keyid).ToString();
+ CKey key;
+ if (pwalletMain->GetKey(keyid, key)) {
+ if (pwalletMain->mapAddressBook.count(keyid)) {
+ file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(key).ToString().c_str(), strTime.c_str(), EncodeDumpString(pwalletMain->mapAddressBook[keyid]).c_str(), strAddr.c_str());
+ } else if (setKeyPool.count(keyid)) {
+ file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(key).ToString().c_str(), strTime.c_str(), strAddr.c_str());
+ } else {
+ file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(key).ToString().c_str(), strTime.c_str(), strAddr.c_str());
+ }
+ }
+ }
+ file << "\n";
+ file << "# End of dump\n";
+ file.close();
+ return Value::null;
+}
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 6f8ac7a112..d0b0a70be4 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -3,6 +3,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#include "chainparams.h"
#include "main.h"
#include "db.h"
#include "init.h"
@@ -93,7 +94,7 @@ Value getmininginfo(const Array& params, bool fHelp)
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
- obj.push_back(Pair("testnet", fTestNet));
+ obj.push_back(Pair("testnet", TestNet()));
return obj;
}
diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp
index 644c2675ae..bd7bc0ba10 100644
--- a/src/rpcnet.cpp
+++ b/src/rpcnet.cpp
@@ -157,7 +157,7 @@ Value getaddednodeinfo(const Array& params, bool fHelp)
BOOST_FOREACH(string& strAddNode, laddedNodes)
{
vector<CService> vservNode(0);
- if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0))
+ if(Lookup(strAddNode.c_str(), vservNode, Params().GetDefaultPort(), fNameLookup, 0))
laddedAddreses.push_back(make_pair(strAddNode, vservNode));
else
{
diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp
index 585bdb2bfb..5388bd4d84 100644
--- a/src/rpcwallet.cpp
+++ b/src/rpcwallet.cpp
@@ -79,7 +79,7 @@ Value getinfo(const Array& params, bool fHelp)
obj.push_back(Pair("connections", (int)vNodes.size()));
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
- obj.push_back(Pair("testnet", fTestNet));
+ obj.push_back(Pair("testnet", TestNet()));
obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime()));
obj.push_back(Pair("keypoolsize", pwalletMain->GetKeyPoolSize()));
obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee)));
diff --git a/src/script.cpp b/src/script.cpp
index cf6eeaf392..14fe80e207 100644
--- a/src/script.cpp
+++ b/src/script.cpp
@@ -1474,6 +1474,42 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, vecto
return true;
}
+class CAffectedKeysVisitor : public boost::static_visitor<void> {
+private:
+ const CKeyStore &keystore;
+ std::vector<CKeyID> &vKeys;
+
+public:
+ CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
+
+ void Process(const CScript &script) {
+ txnouttype type;
+ std::vector<CTxDestination> vDest;
+ int nRequired;
+ if (ExtractDestinations(script, type, vDest, nRequired)) {
+ BOOST_FOREACH(const CTxDestination &dest, vDest)
+ boost::apply_visitor(*this, dest);
+ }
+ }
+
+ void operator()(const CKeyID &keyId) {
+ if (keystore.HaveKey(keyId))
+ vKeys.push_back(keyId);
+ }
+
+ void operator()(const CScriptID &scriptId) {
+ CScript script;
+ if (keystore.GetCScript(scriptId, script))
+ Process(script);
+ }
+
+ void operator()(const CNoDestination &none) {}
+};
+
+void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys) {
+ CAffectedKeysVisitor(keystore, vKeys).Process(scriptPubKey);
+}
+
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
unsigned int flags, int nHashType)
{
diff --git a/src/script.h b/src/script.h
index f963467c94..03afe8b652 100644
--- a/src/script.h
+++ b/src/script.h
@@ -674,6 +674,7 @@ int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned c
bool IsStandard(const CScript& scriptPubKey);
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
bool IsMine(const CKeyStore& keystore, const CTxDestination &dest);
+void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index b1e98f65ed..ea0cc1bcef 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -8,6 +8,7 @@
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
+#include "chainparams.h"
#include "main.h"
#include "wallet.h"
#include "net.h"
@@ -25,7 +26,7 @@ CService ip(uint32_t i)
{
struct in_addr s;
s.s_addr = i;
- return CService(CNetAddr(s), GetDefaultPort());
+ return CService(CNetAddr(s), Params().GetDefaultPort());
}
BOOST_AUTO_TEST_SUITE(DoS_tests)
diff --git a/src/test/base58_tests.cpp b/src/test/base58_tests.cpp
index 2741672a88..af65416485 100644
--- a/src/test/base58_tests.cpp
+++ b/src/test/base58_tests.cpp
@@ -108,8 +108,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
std::vector<unsigned char> result;
CBitcoinSecret secret;
CBitcoinAddress addr;
- // Save global state
- bool fTestNet_stored = fTestNet;
BOOST_FOREACH(Value& tv, tests)
{
@@ -125,7 +123,10 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
const Object &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
- fTestNet = isTestnet; // Override testnet flag
+ if (isTestnet)
+ SelectParams(CChainParams::TESTNET);
+ else
+ SelectParams(CChainParams::MAIN);
if(isPrivkey)
{
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
@@ -156,8 +157,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_parse)
BOOST_CHECK_MESSAGE(!secret.IsValid(), "IsValid pubkey as privkey:" + strTest);
}
}
- // Restore global state
- fTestNet = fTestNet_stored;
+ SelectParams(CChainParams::MAIN);
}
// Goal: check that generated keys match test vectors
@@ -165,9 +165,6 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
{
Array tests = read_json("base58_keys_valid.json");
std::vector<unsigned char> result;
- // Save global state
- bool fTestNet_stored = fTestNet;
-
BOOST_FOREACH(Value& tv, tests)
{
Array test = tv.get_array();
@@ -182,7 +179,10 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
const Object &metadata = test[2].get_obj();
bool isPrivkey = find_value(metadata, "isPrivkey").get_bool();
bool isTestnet = find_value(metadata, "isTestnet").get_bool();
- fTestNet = isTestnet; // Override testnet flag
+ if (isTestnet)
+ SelectParams(CChainParams::TESTNET);
+ else
+ SelectParams(CChainParams::MAIN);
if(isPrivkey)
{
bool isCompressed = find_value(metadata, "isCompressed").get_bool();
@@ -225,8 +225,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
CTxDestination nodest = CNoDestination();
BOOST_CHECK(!boost::apply_visitor(CBitcoinAddressVisitor(&dummyAddr), nodest));
- // Restore global state
- fTestNet = fTestNet_stored;
+ SelectParams(CChainParams::MAIN);
}
// Goal: check that base58 parsing code is robust against a variety of corrupted data
diff --git a/src/test/checkblock_tests.cpp b/src/test/checkblock_tests.cpp
index d626f9a6f4..5675c40e76 100644
--- a/src/test/checkblock_tests.cpp
+++ b/src/test/checkblock_tests.cpp
@@ -55,7 +55,7 @@ BOOST_AUTO_TEST_CASE(May15)
// After May 15'th, big blocks are OK:
forkingBlock.nTime = tMay15; // Invalidates PoW
- BOOST_CHECK(forkingBlock.CheckBlock(state, false, false));
+ BOOST_CHECK(CheckBlock(forkingBlock, state, false, false));
}
SetMockTime(0);
diff --git a/src/txdb.cpp b/src/txdb.cpp
index 3d34710d22..34836eaa97 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -6,6 +6,7 @@
#include "txdb.h"
#include "main.h"
#include "hash.h"
+#include "chainparams.h"
using namespace std;
@@ -223,7 +224,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
pindexNew->nTx = diskindex.nTx;
// Watch for genesis block
- if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == hashGenesisBlock)
+ if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == Params().HashGenesisBlock())
pindexGenesisBlock = pindexNew;
if (!pindexNew->CheckIndex())
diff --git a/src/util.cpp b/src/util.cpp
index f4892a2387..bfb6d75838 100644
--- a/src/util.cpp
+++ b/src/util.cpp
@@ -13,6 +13,7 @@
#include <sys/resource.h>
#endif
+#include "chainparams.h"
#include "util.h"
#include "sync.h"
#include "version.h"
@@ -78,7 +79,6 @@ bool fDaemon = false;
bool fServer = false;
bool fCommandLine = false;
string strMiscWarning;
-bool fTestNet = false;
bool fNoListen = false;
bool fLogTimestamps = false;
CMedianFilter<int64> vTimeOffsets(200,0);
@@ -1068,8 +1068,8 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
} else {
path = GetDefaultDataDir();
}
- if (fNetSpecific && GetBoolArg("-testnet", false))
- path /= "testnet3";
+ if (fNetSpecific)
+ path /= Params().DataDir();
fs::create_directories(path);
diff --git a/src/util.h b/src/util.h
index 9173b5bb58..86a38ad331 100644
--- a/src/util.h
+++ b/src/util.h
@@ -143,7 +143,6 @@ extern bool fDaemon;
extern bool fServer;
extern bool fCommandLine;
extern std::string strMiscWarning;
-extern bool fTestNet;
extern bool fNoListen;
extern bool fLogTimestamps;
extern volatile bool fReopenDebugLog;
diff --git a/src/wallet.cpp b/src/wallet.cpp
index 4cd04bb6e2..488787f967 100644
--- a/src/wallet.cpp
+++ b/src/wallet.cpp
@@ -40,18 +40,20 @@ CPubKey CWallet::GenerateNewKey()
SetMinVersion(FEATURE_COMPRPUBKEY);
CPubKey pubkey = secret.GetPubKey();
+
+ // Create new metadata
+ int64 nCreationTime = GetTime();
+ mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
+ if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
+ nTimeFirstKey = nCreationTime;
+
if (!AddKeyPubKey(secret, pubkey))
throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
return pubkey;
}
-bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey,
- int64 nCreateTime)
+bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
{
- if (!nCreateTime)
- nCreateTime = GetTime();
- if (!nTimeFirstKey || (nCreateTime < nTimeFirstKey))
- nTimeFirstKey = nCreateTime;
if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
return false;
if (!fFileBacked)
@@ -59,19 +61,14 @@ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey,
if (!IsCrypted()) {
return CWalletDB(strWalletFile).WriteKey(pubkey,
secret.GetPrivKey(),
- nCreateTime);
+ mapKeyMetadata[pubkey.GetID()]);
}
return true;
}
bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
- const vector<unsigned char> &vchCryptedSecret,
- int64 nCreateTime)
+ const vector<unsigned char> &vchCryptedSecret)
{
- if (!nCreateTime)
- nCreateTime = GetTime();
- if (!nTimeFirstKey || (nCreateTime < nTimeFirstKey))
- nTimeFirstKey = nCreateTime;
if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
return false;
if (!fFileBacked)
@@ -81,15 +78,24 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
if (pwalletdbEncryption)
return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
vchCryptedSecret,
- nCreateTime);
+ mapKeyMetadata[vchPubKey.GetID()]);
else
return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
vchCryptedSecret,
- nCreateTime);
+ mapKeyMetadata[vchPubKey.GetID()]);
}
return false;
}
+bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
+{
+ if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
+ nTimeFirstKey = meta.nCreateTime;
+
+ mapKeyMetadata[pubkey.GetID()] = meta;
+ return true;
+}
+
bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
{
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
@@ -798,7 +804,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
}
CBlock block;
- block.ReadFromDisk(pindex);
+ ReadBlockFromDisk(block, pindex);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
@@ -1301,7 +1307,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
// Check that enough fee is included
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
bool fAllowFree = AllowFree(dPriority);
- int64 nMinFee = GetMinFee(wtxNew, 1, fAllowFree, GMF_SEND);
+ int64 nMinFee = GetMinFee(wtxNew, fAllowFree, GMF_SEND);
if (nFeeRet < max(nPayFee, nMinFee))
{
nFeeRet = max(nPayFee, nMinFee);
@@ -1840,7 +1846,7 @@ void CReserveKey::ReturnKey()
vchPubKey = CPubKey();
}
-void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress)
+void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
{
setAddress.clear();
@@ -1902,3 +1908,53 @@ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
}
}
+void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
+ mapKeyBirth.clear();
+
+ // get birth times for keys with metadata
+ for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
+ if (it->second.nCreateTime)
+ mapKeyBirth[it->first] = it->second.nCreateTime;
+
+ // map in which we'll infer heights of other keys
+ CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
+ std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
+ std::set<CKeyID> setKeys;
+ GetKeys(setKeys);
+ BOOST_FOREACH(const CKeyID &keyid, setKeys) {
+ if (mapKeyBirth.count(keyid) == 0)
+ mapKeyFirstBlock[keyid] = pindexMax;
+ }
+ setKeys.clear();
+
+ // if there are no such keys, we're done
+ if (mapKeyFirstBlock.empty())
+ return;
+
+ // find first block that affects those keys, if there are any left
+ std::vector<CKeyID> vAffected;
+ for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
+ // iterate over all wallet transactions...
+ const CWalletTx &wtx = (*it).second;
+ std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
+ if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
+ // ... which are already in a block
+ int nHeight = blit->second->nHeight;
+ BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
+ // iterate over all their outputs
+ ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
+ BOOST_FOREACH(const CKeyID &keyid, vAffected) {
+ // ... and all their affected keys
+ std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
+ if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
+ rit->second = blit->second;
+ }
+ vAffected.clear();
+ }
+ }
+ }
+
+ // Extract block timestamps for those keys
+ for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
+ mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
+}
diff --git a/src/wallet.h b/src/wallet.h
index 2b3131261c..36b3608fb0 100644
--- a/src/wallet.h
+++ b/src/wallet.h
@@ -87,7 +87,7 @@ public:
std::string strWalletFile;
std::set<int64> setKeyPool;
-
+ std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
@@ -140,14 +140,16 @@ public:
// Generate a new key
CPubKey GenerateNewKey();
// Adds a key to the store, and saves it to disk.
- bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey, int64 nCreateTime = 0);
+ bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
// Adds a key to the store, without saving it to disk (used by LoadWallet)
bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
+ // Load metadata (used by LoadWallet)
+ bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
// Adds an encrypted key to the store, and saves it to disk.
- bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret, int64 nCreateTime = 0);
+ bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
// Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
bool AddCScript(const CScript& redeemScript);
@@ -157,6 +159,8 @@ public:
bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
bool EncryptWallet(const SecureString& strWalletPassphrase);
+ void GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const;
+
/** Increment the next transaction order id
@return next transaction order id
*/
@@ -198,7 +202,7 @@ public:
void ReturnKey(int64 nIndex);
bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true);
int64 GetOldestKeyPoolTime();
- void GetAllReserveKeys(std::set<CKeyID>& setAddress);
+ void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
std::set< std::set<CTxDestination> > GetAddressGroupings();
std::map<CTxDestination, int64> GetAddressBalances();
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 96fd4a5fc1..702e219a5b 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -344,12 +344,14 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
}
else if (strType == "keymeta")
{
- vector<unsigned char> vchPubKey;
+ CPubKey vchPubKey;
ssKey >> vchPubKey;
CKeyMetadata keyMeta;
ssValue >> keyMeta;
wss.nKeyMeta++;
+ pwallet->LoadKeyMetadata(vchPubKey, keyMeta);
+
// find earliest key creation time, as wallet birthday
if (!pwallet->nTimeFirstKey ||
(keyMeta.nCreateTime < pwallet->nTimeFirstKey))
@@ -363,7 +365,16 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
{
int64 nIndex;
ssKey >> nIndex;
+ CKeyPool keypool;
+ ssValue >> keypool;
pwallet->setKeyPool.insert(nIndex);
+
+ // If no metadata exists yet, create a default with the pool key's
+ // creation time. Note that this may be overwritten by actually
+ // stored metadata for that key later, which is fine.
+ CKeyID keyid = keypool.vchPubKey.GetID();
+ if (pwallet->mapKeyMetadata.count(keyid) == 0)
+ pwallet->mapKeyMetadata[keyid] = CKeyMetadata(keypool.nTime);
}
else if (strType == "version")
{
@@ -483,7 +494,7 @@ DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
// nTimeFirstKey is only reliable if all keys have metadata
if ((wss.nKeys + wss.nCKeys) != wss.nKeyMeta)
- pwallet->nTimeFirstKey = 0;
+ pwallet->nTimeFirstKey = 1; // 0 would be considered 'no value'
BOOST_FOREACH(uint256 hash, wss.vWalletUpgrade)
WriteTx(hash, pwallet->mapWallet[hash]);
diff --git a/src/walletdb.h b/src/walletdb.h
index 287361b33d..4dfa35d82a 100644
--- a/src/walletdb.h
+++ b/src/walletdb.h
@@ -30,7 +30,7 @@ class CKeyMetadata
public:
static const int CURRENT_VERSION=1;
int nVersion;
- int64 nCreateTime;
+ int64 nCreateTime; // 0 means unknown
CKeyMetadata()
{
@@ -52,7 +52,7 @@ public:
void SetNull()
{
nVersion = CKeyMetadata::CURRENT_VERSION;
- nCreateTime = GetTime();
+ nCreateTime = 0;
}
};
@@ -84,13 +84,12 @@ public:
}
bool WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey,
- int64 nCreateTime)
+ const CKeyMetadata &keyMeta)
{
nWalletDBUpdated++;
- CKeyMetadata keyMeta(nCreateTime);
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
- keyMeta, false))
+ keyMeta))
return false;
return Write(std::make_pair(std::string("key"), vchPubKey), vchPrivKey, false);
@@ -98,14 +97,13 @@ public:
bool WriteCryptedKey(const CPubKey& vchPubKey,
const std::vector<unsigned char>& vchCryptedSecret,
- int64 nCreateTime)
+ const CKeyMetadata &keyMeta)
{
const bool fEraseUnencryptedKey = true;
nWalletDBUpdated++;
- CKeyMetadata keyMeta(nCreateTime);
if (!Write(std::make_pair(std::string("keymeta"), vchPubKey),
- keyMeta, false))
+ keyMeta))
return false;
if (!Write(std::make_pair(std::string("ckey"), vchPubKey), vchCryptedSecret, false))