From b65b71156c5ee868da0882648b412eee99a9237d Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 23 Jun 2014 11:25:22 -0700 Subject: [PATCH 01/25] Added new hashing algorithm for blocks, masternode payment enforcement, checkpointing --- bitcoin-qt.pro | 3 +- src/bitcoinrpc.cpp | 6 + src/bitcoinrpc.h | 3 + src/checkpoints.cpp | 20 +- src/checkpoints.h | 6 + src/checkpointsync.cpp | 535 ++++++++++++++++++++++++++++++++++++ src/checkpointsync.h | 136 +++++++++ src/clientversion.h | 4 +- src/init.cpp | 8 + src/main.cpp | 224 ++++++++++----- src/main.h | 166 +++++------ src/makefile.linux-mingw | 3 +- src/makefile.mingw | 3 +- src/makefile.osx | 3 +- src/makefile.unix | 3 +- src/net.h | 2 + src/qt/aboutdialog.cpp | 4 +- src/qt/forms/aboutdialog.ui | 3 +- src/rpcdarksend.cpp | 10 +- src/rpcmining.cpp | 9 +- src/txdb.cpp | 20 ++ src/txdb.h | 4 + src/version.h | 4 +- 23 files changed, 1017 insertions(+), 162 deletions(-) create mode 100644 src/checkpointsync.cpp create mode 100644 src/checkpointsync.h diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 29abb71afd..88973e1bbe 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -313,7 +313,8 @@ SOURCES += src/qt/bitcoin.cpp \ src/cubehash.c \ src/shavite.c \ src/echo.c \ - src/simd.c + src/simd.c \ + src/checkpointsync.cpp RESOURCES += src/qt/bitcoin.qrc diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 4b9dc4cd60..e89d8f9921 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -254,6 +254,9 @@ static const CRPCCommand vRPCCommands[] = { "setmininput", &setmininput, false, false, false }, { "listsinceblock", &listsinceblock, false, false, true }, { "makekeypair", &makekeypair, true, false, true }, + { "getcheckpoint", &getcheckpoint, true, false, false }, + { "sendcheckpoint", &sendcheckpoint, true, false, false }, + { "enforcecheckpoint", &enforcecheckpoint, true, false, false }, { "dumpprivkey", &dumpprivkey, true, false, true }, { "importprivkey", &importprivkey, false, false, true }, { "listunspent", &listunspent, false, false, true }, @@ -1196,6 +1199,9 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector 2) ConvertTo(params[2]); if (strMethod == "verifychain" && n > 0) ConvertTo(params[0]); if (strMethod == "verifychain" && n > 1) ConvertTo(params[1]); + if (strMethod == "getpoolinfo" && n > 0) ConvertTo(params[0]); + if (strMethod == "enforcecheckpoint" && n > 0) ConvertTo(params[0]); + if (strMethod == "enforcecheckpoint" && n > 1) ConvertTo(params[1]); return params; } diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 96843fa95f..59e2a9c912 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -178,6 +178,9 @@ extern json_spirit::Value listaddressgroupings(const json_spirit::Array& params, extern json_spirit::Value listaccounts(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value listsinceblock(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value makekeypair(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value getcheckpoint(const json_spirit::Array& params, bool fHelp); // in checkpointsync.cpp +extern json_spirit::Value sendcheckpoint(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value enforcecheckpoint(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value gettransaction(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value backupwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value keypoolrefill(const json_spirit::Array& params, bool fHelp); diff --git a/src/checkpoints.cpp b/src/checkpoints.cpp index 0817e6ba18..077170bd42 100644 --- a/src/checkpoints.cpp +++ b/src/checkpoints.cpp @@ -46,10 +46,11 @@ namespace Checkpoints ( 68899, uint256("0x0000000000194ab4d3d9eeb1f2f792f21bb39ff767cb547fe977640f969d77b7")) ( 74619, uint256("0x000000000011d28f38f05d01650a502cc3f4d0e793fbc26e2a2ca71f07dc3842")) ( 75095, uint256("0x0000000000193d12f6ad352a9996ee58ef8bdc4946818a5fec5ce99c11b87f0d")) + ( 88805, uint256("0x00000000001392f1652e9bf45cd8bc79dc60fe935277cd11538565b4a94fa85f")) ; static const CCheckpointData data = { &mapCheckpoints, - 1401126238, // * UNIX timestamp of last checkpoint block + 1403283082, // * UNIX timestamp of last checkpoint block 25000, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) 800.0 // * estimated number of transactions per day after checkpoint @@ -145,4 +146,21 @@ namespace Checkpoints } return NULL; } + + uint256 GetLastAvailableCheckpoint() { + const MapCheckpoints& checkpoints = (fTestNet ? mapCheckpointsTestnet : mapCheckpoints); + + BOOST_REVERSE_FOREACH(const MapCheckpoints::value_type& i, checkpoints) { + const uint256& hash = i.second; + if(mapBlockIndex.count(hash) && mapBlockIndex[hash]->IsInMainChain()) + return(hash); + } + return(hashGenesisBlock); + } + + uint256 GetLatestHardenedCheckpoint() + { + const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints; + return (checkpoints.rbegin()->second); + } } diff --git a/src/checkpoints.h b/src/checkpoints.h index 3d56885556..eebe1d2f2b 100644 --- a/src/checkpoints.h +++ b/src/checkpoints.h @@ -23,6 +23,12 @@ namespace Checkpoints // Returns last CBlockIndex* in mapBlockIndex that is a checkpoint CBlockIndex* GetLastCheckpoint(const std::map& mapBlockIndex); + /* Returns the last available checkpoint in the main chain */ + uint256 GetLastAvailableCheckpoint(); + + // Returns the block hash of latest hardened checkpoint + uint256 GetLatestHardenedCheckpoint(); + double GuessVerificationProgress(CBlockIndex *pindex); } diff --git a/src/checkpointsync.cpp b/src/checkpointsync.cpp new file mode 100644 index 0000000000..75755493b5 --- /dev/null +++ b/src/checkpointsync.cpp @@ -0,0 +1,535 @@ +// Copyright (c) 2012-2013 PPCoin developers +// Copyright (c) 2013 Primecoin developers +// Distributed under conditional MIT/X11 software license, +// see the accompanying file COPYING +// +// The synchronized checkpoint system is first developed by Sunny King for +// ppcoin network in 2012, giving cryptocurrency developers a tool to gain +// additional network protection against 51% attack. +// +// Primecoin also adopts this security mechanism, and the enforcement of +// checkpoints is explicitly granted by user, thus granting only temporary +// consensual central control to developer at the threats of 51% attack. +// +// Concepts +// +// In the network there can be a privileged node known as 'checkpoint master'. +// This node can send out checkpoint messages signed by the checkpoint master +// key. Each checkpoint is a block hash, representing a block on the blockchain +// that the network should reach consensus on. +// +// Besides verifying signatures of checkpoint messages, each node also verifies +// the consistency of the checkpoints. If a conflicting checkpoint is received, +// it means either the checkpoint master key is compromised, or there is an +// operator mistake. In this situation the node would discard the conflicting +// checkpoint message and display a warning message. This precaution controls +// the damage to network caused by operator mistake or compromised key. +// +// Operations +// +// Checkpoint master key can be established by using the 'makekeypair' command +// The public key in source code should then be updated and private key kept +// in a safe place. +// +// Any node can be turned into checkpoint master by setting the 'checkpointkey' +// configuration parameter with the private key of the checkpoint master key. +// Operator should exercise caution such that at any moment there is at most +// one node operating as checkpoint master. When switching master node, the +// recommended procedure is to shutdown the master node and restart as +// regular node, note down the current checkpoint by 'getcheckpoint', then +// compare to the checkpoint at the new node to be upgraded to master node. +// When the checkpoint on both nodes match then it is safe to switch the new +// node to checkpoint master. +// +// The configuration parameter 'checkpointdepth' specifies how many blocks +// should the checkpoints lag behind the latest block in auto checkpoint mode. +// A depth of 0 is the strongest auto checkpoint policy and offers the greatest +// protection against 51% attack. A negative depth means that the checkpoints +// should not be automatically generated by the checkpoint master, but instead +// be manually entered by operator via the 'sendcheckpoint' command. The manual +// mode is also the default mode (default value -1 for checkpointdepth). +// +// Command 'enforcecheckpoint' and configuration parameter 'checkpointenforce' +// are for the users to explicitly consent to enforce the checkpoints issued +// from checkpoint master. To enforce checkpoint, user needs to either issue +// command 'enforcecheckpoint true', or set configuration parameter +// checkpointenforce=1. The current enforcement setting can be queried via +// command 'getcheckpoint', where 'subscribemode' displays either 'enforce' +// or 'advisory'. The 'enforce' mode of subscribemode means checkpoints are +// enforced. The 'advisory' mode of subscribemode means checkpoints are not +// enforced but a warning message would be displayed if the node is on a +// different blockchain fork from the checkpoint, and this is the default mode. +// + +#include + +#include "checkpoints.h" +#include "checkpointsync.h" + +#include "base58.h" +#include "bitcoinrpc.h" +#include "main.h" +#include "txdb.h" +#include "uint256.h" + +using namespace json_spirit; +using namespace std; + + +// sync-checkpoint master key +const std::string CSyncCheckpoint::strMainPubKey = "04bcba2b149fe9d54f218208dd02aecd7b2245ef21c937207966f0814365b4d1c5d521d001f2df294bafb0fbe5ee4c3290b0c25bff8fdd886b6e3e9317758a7d75"; +const std::string CSyncCheckpoint::strTestPubKey = "04ba2e1494f05a1fccbef6b0cf6124ce05c20bc7868726770dda7a41ba8c9e905b67bb594ebbb282b1159ba8fa176121cb81b8a1c184f0c73e631a8a4999647d30"; +std::string CSyncCheckpoint::strMasterPrivKey = ""; + + +// synchronized checkpoint (centrally broadcasted) +uint256 hashSyncCheckpoint = 0; +uint256 hashPendingCheckpoint = 0; +CSyncCheckpoint checkpointMessage; +CSyncCheckpoint checkpointMessagePending; +uint256 hashInvalidCheckpoint = 0; +CCriticalSection cs_hashSyncCheckpoint; +std::string strCheckpointWarning; + +// get last synchronized checkpoint +CBlockIndex* GetLastSyncCheckpoint() +{ + LOCK(cs_hashSyncCheckpoint); + if (!mapBlockIndex.count(hashSyncCheckpoint)) + error("GetSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str()); + else + return mapBlockIndex[hashSyncCheckpoint]; + return NULL; +} + +// only descendant of current sync-checkpoint is allowed +bool ValidateSyncCheckpoint(uint256 hashCheckpoint) +{ + if (!mapBlockIndex.count(hashSyncCheckpoint)) + return error("ValidateSyncCheckpoint: block index missing for current sync-checkpoint %s", hashSyncCheckpoint.ToString().c_str()); + if (!mapBlockIndex.count(hashCheckpoint)) + return error("ValidateSyncCheckpoint: block index missing for received sync-checkpoint %s", hashCheckpoint.ToString().c_str()); + + CBlockIndex* pindexSyncCheckpoint = mapBlockIndex[hashSyncCheckpoint]; + CBlockIndex* pindexCheckpointRecv = mapBlockIndex[hashCheckpoint]; + + if (pindexCheckpointRecv->nHeight <= pindexSyncCheckpoint->nHeight) + { + // Received an older checkpoint, trace back from current checkpoint + // to the same height of the received checkpoint to verify + // that current checkpoint should be a descendant block + CBlockIndex* pindex = pindexSyncCheckpoint; + while (pindex->nHeight > pindexCheckpointRecv->nHeight) + if (!(pindex = pindex->pprev)) + return error("ValidateSyncCheckpoint: pprev1 null - block index structure failure"); + if (pindex->GetBlockHash() != hashCheckpoint) + { + hashInvalidCheckpoint = hashCheckpoint; + return error("ValidateSyncCheckpoint: new sync-checkpoint %s is conflicting with current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str()); + } + return false; // ignore older checkpoint + } + + // Received checkpoint should be a descendant block of the current + // checkpoint. Trace back to the same height of current checkpoint + // to verify. + CBlockIndex* pindex = pindexCheckpointRecv; + while (pindex->nHeight > pindexSyncCheckpoint->nHeight) + if (!(pindex = pindex->pprev)) + return error("ValidateSyncCheckpoint: pprev2 null - block index structure failure"); + if (pindex->GetBlockHash() != hashSyncCheckpoint) + { + hashInvalidCheckpoint = hashCheckpoint; + return error("ValidateSyncCheckpoint: new sync-checkpoint %s is not a descendant of current sync-checkpoint %s", hashCheckpoint.ToString().c_str(), hashSyncCheckpoint.ToString().c_str()); + } + return true; +} + +bool WriteSyncCheckpoint(const uint256& hashCheckpoint) +{ + if (!pblocktree->WriteSyncCheckpoint(hashCheckpoint)) + { + return error("WriteSyncCheckpoint(): failed to write to txdb sync checkpoint %s", hashCheckpoint.ToString().c_str()); + } + if (!pblocktree->Sync()) + return error("WriteSyncCheckpoint(): failed to commit to txdb sync checkpoint %s", hashCheckpoint.ToString().c_str()); + + hashSyncCheckpoint = hashCheckpoint; + return true; +} + +bool IsSyncCheckpointEnforced() +{ + return (GetBoolArg("-checkpointenforce", true) || mapArgs.count("-checkpointkey")); // checkpoint master node is always enforced +} + +bool AcceptPendingSyncCheckpoint() +{ + LOCK(cs_hashSyncCheckpoint); + if (hashPendingCheckpoint != 0 && mapBlockIndex.count(hashPendingCheckpoint)) + { + if (!ValidateSyncCheckpoint(hashPendingCheckpoint)) + { + hashPendingCheckpoint = 0; + checkpointMessagePending.SetNull(); + return false; + } + + CBlockIndex* pindexCheckpoint = mapBlockIndex[hashPendingCheckpoint]; + if (IsSyncCheckpointEnforced() && !pindexCheckpoint->IsInMainChain()) + { + CValidationState state; + if (!SetBestChain(state, pindexCheckpoint)) + { + hashInvalidCheckpoint = hashPendingCheckpoint; + return error("AcceptPendingSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashPendingCheckpoint.ToString().c_str()); + } + } + + if (!WriteSyncCheckpoint(hashPendingCheckpoint)) + return error("AcceptPendingSyncCheckpoint(): failed to write sync checkpoint %s", hashPendingCheckpoint.ToString().c_str()); + hashPendingCheckpoint = 0; + checkpointMessage = checkpointMessagePending; + checkpointMessagePending.SetNull(); + printf("AcceptPendingSyncCheckpoint : sync-checkpoint at %s\n", hashSyncCheckpoint.ToString().c_str()); + // relay the checkpoint + if (!checkpointMessage.IsNull()) + { + BOOST_FOREACH(CNode* pnode, vNodes) + checkpointMessage.RelayTo(pnode); + } + return true; + } + return false; +} + +// Automatically select a suitable sync-checkpoint +uint256 AutoSelectSyncCheckpoint() +{ + // Search backward for a block with specified depth policy + const CBlockIndex *pindex = pindexBest; + while (pindex->pprev && pindex->nHeight + (int)GetArg("-checkpointdepth", -1) > pindexBest->nHeight) + pindex = pindex->pprev; + return pindex->GetBlockHash(); +} + +// Check against synchronized checkpoint +bool CheckSyncCheckpoint(const uint256& hashBlock, const CBlockIndex* pindexPrev) +{ + int nHeight = pindexPrev->nHeight + 1; + LOCK(cs_hashSyncCheckpoint); + // sync-checkpoint should always be accepted block + assert(mapBlockIndex.count(hashSyncCheckpoint)); + const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint]; + + if (nHeight > pindexSync->nHeight) + { + // trace back to same height as sync-checkpoint + const CBlockIndex* pindex = pindexPrev; + while (pindex->nHeight > pindexSync->nHeight) + if (!(pindex = pindex->pprev)) + return error("CheckSyncCheckpoint: pprev null - block index structure failure"); + if (pindex->nHeight < pindexSync->nHeight || pindex->GetBlockHash() != hashSyncCheckpoint) + return false; // only descendant of sync-checkpoint can pass check + } + if (nHeight == pindexSync->nHeight && hashBlock != hashSyncCheckpoint) + return false; // same height with sync-checkpoint + if (nHeight < pindexSync->nHeight && !mapBlockIndex.count(hashBlock)) + return false; // lower height than sync-checkpoint + return true; +} + +bool WantedByPendingSyncCheckpoint(uint256 hashBlock) +{ + LOCK(cs_hashSyncCheckpoint); + if (hashPendingCheckpoint == 0) + return false; + if (hashBlock == hashPendingCheckpoint) + return true; + if (mapOrphanBlocks.count(hashPendingCheckpoint) + && hashBlock == WantedByOrphan(mapOrphanBlocks[hashPendingCheckpoint])) + return true; + return false; +} + +// reset synchronized checkpoint to last hardened checkpoint +bool ResetSyncCheckpoint() +{ + LOCK(cs_hashSyncCheckpoint); + uint256 hash = Checkpoints::GetLatestHardenedCheckpoint(); + if (mapBlockIndex.count(hash) && !mapBlockIndex[hash]->IsInMainChain()) + { + // checkpoint block accepted but not yet in main chain + printf("ResetSyncCheckpoint: SetBestChain to hardened checkpoint %s\n", hash.ToString().c_str()); + CValidationState state; + if (!SetBestChain(state, mapBlockIndex[hash])) + { + return error("ResetSyncCheckpoint: SetBestChain failed for hardened checkpoint %s", hash.ToString().c_str()); + } + } else { + /* Reset to the last available checkpoint block in the main chain */ + checkpointMessagePending.SetNull(); + hash = Checkpoints::GetLastAvailableCheckpoint(); + } + + if (!WriteSyncCheckpoint(hash)) + return error("ResetSyncCheckpoint: failed to write sync checkpoint %s", hash.ToString().c_str()); + printf("ResetSyncCheckpoint: sync-checkpoint reset to %s\n", hashSyncCheckpoint.ToString().c_str()); + return true; +} + +void AskForPendingSyncCheckpoint(CNode* pfrom) +{ + LOCK(cs_hashSyncCheckpoint); + if (pfrom && hashPendingCheckpoint != 0 && (!mapBlockIndex.count(hashPendingCheckpoint)) && (!mapOrphanBlocks.count(hashPendingCheckpoint))) + pfrom->AskFor(CInv(MSG_BLOCK, hashPendingCheckpoint)); +} + +// Verify sync checkpoint master pubkey and reset sync checkpoint if changed +bool CheckCheckpointPubKey() +{ + std::string strPubKey = ""; + std::string strMasterPubKey = fTestNet? CSyncCheckpoint::strTestPubKey : CSyncCheckpoint::strMainPubKey; + if (!pblocktree->ReadCheckpointPubKey(strPubKey) || strPubKey != strMasterPubKey) + { + // write checkpoint master key to db + if (!pblocktree->WriteCheckpointPubKey(strMasterPubKey)) + return error("CheckCheckpointPubKey() : failed to write new checkpoint master key to db"); + if (!pblocktree->Sync()) + return error("CheckCheckpointPubKey() : failed to commit new checkpoint master key to db"); + if (!ResetSyncCheckpoint()) + return error("CheckCheckpointPubKey() : failed to reset sync-checkpoint"); + } + return true; +} + +bool SetCheckpointPrivKey(std::string strPrivKey) +{ + // Test signing a sync-checkpoint with genesis block + CSyncCheckpoint checkpoint; + checkpoint.hashCheckpoint = hashGenesisBlock; + + CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); + sMsg << (CUnsignedSyncCheckpoint)checkpoint; + checkpoint.vchMsg = std::vector(sMsg.begin(), sMsg.end()); + + CBitcoinSecret vchSecret; + if (!vchSecret.SetString(strPrivKey)) + return error("SendSyncCheckpoint: Checkpoint master key invalid"); + CKey key = vchSecret.GetKey(); // if key is not correct openssl may crash + if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig)) + return false; + + // Test signing successful, proceed + CSyncCheckpoint::strMasterPrivKey = strPrivKey; + return true; +} + +bool SendSyncCheckpoint(uint256 hashCheckpoint) +{ + CSyncCheckpoint checkpoint; + checkpoint.hashCheckpoint = hashCheckpoint; + checkpoint.enforcingPaymentsTime = enforceMasternodePaymentsTime; + + CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION); + sMsg << (CUnsignedSyncCheckpoint)checkpoint; + checkpoint.vchMsg = std::vector(sMsg.begin(), sMsg.end()); + + if (CSyncCheckpoint::strMasterPrivKey.empty()) + return error("SendSyncCheckpoint: Checkpoint master key unavailable."); + CBitcoinSecret vchSecret; + if (!vchSecret.SetString(CSyncCheckpoint::strMasterPrivKey)) + return error("SendSyncCheckpoint: Checkpoint master key invalid"); + CKey key = vchSecret.GetKey(); // if key is not correct openssl may crash + if (!key.Sign(Hash(checkpoint.vchMsg.begin(), checkpoint.vchMsg.end()), checkpoint.vchSig)) + return error("SendSyncCheckpoint: Unable to sign checkpoint, check private key?"); + + if(!checkpoint.ProcessSyncCheckpoint(NULL)) + { + printf("WARNING: SendSyncCheckpoint: Failed to process checkpoint.\n"); + return false; + } + + // Relay checkpoint + { + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + checkpoint.RelayTo(pnode); + } + return true; +} + +// Is the sync-checkpoint outside maturity window? +bool IsMatureSyncCheckpoint() +{ + LOCK(cs_hashSyncCheckpoint); + // sync-checkpoint should always be accepted block + assert(mapBlockIndex.count(hashSyncCheckpoint)); + const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint]; + return (nBestHeight >= pindexSync->nHeight + COINBASE_MATURITY); +} + +// Is the sync-checkpoint too old? +bool IsSyncCheckpointTooOld(unsigned int nSeconds) +{ + LOCK(cs_hashSyncCheckpoint); + // sync-checkpoint should always be accepted block + assert(mapBlockIndex.count(hashSyncCheckpoint)); + const CBlockIndex* pindexSync = mapBlockIndex[hashSyncCheckpoint]; + return (pindexSync->GetBlockTime() + nSeconds < GetAdjustedTime()); +} + +// find block wanted by given orphan block +uint256 WantedByOrphan(const CBlock* pblockOrphan) +{ + // Work back to the first block in the orphan chain + while (mapOrphanBlocks.count(pblockOrphan->hashPrevBlock)) + pblockOrphan = mapOrphanBlocks[pblockOrphan->hashPrevBlock]; + return pblockOrphan->hashPrevBlock; +} + +// verify signature of sync-checkpoint message +bool CSyncCheckpoint::CheckSignature() +{ + std::string strMasterPubKey = fTestNet? CSyncCheckpoint::strTestPubKey : CSyncCheckpoint::strMainPubKey; + CPubKey key(ParseHex(strMasterPubKey)); + if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) + return error("CSyncCheckpoint::CheckSignature() : verify signature failed"); + + // Now unserialize the data + CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); + sMsg >> *(CUnsignedSyncCheckpoint*)this; + return true; +} + +// process synchronized checkpoint +bool CSyncCheckpoint::ProcessSyncCheckpoint(CNode* pfrom) +{ + if (!CheckSignature()) + return false; + + LOCK(cs_hashSyncCheckpoint); + if (!mapBlockIndex.count(hashCheckpoint)) + { + // We haven't received the checkpoint chain, keep the checkpoint as pending + hashPendingCheckpoint = hashCheckpoint; + checkpointMessagePending = *this; + printf("ProcessSyncCheckpoint: pending for sync-checkpoint %s\n", hashCheckpoint.ToString().c_str()); + // Ask this guy to fill in what we're missing + if (pfrom) + { + pfrom->PushGetBlocks(pindexBest, hashCheckpoint); + // ask directly as well in case rejected earlier by duplicate + // proof-of-stake because getblocks may not get it this time + pfrom->AskFor(CInv(MSG_BLOCK, mapOrphanBlocks.count(hashCheckpoint)? WantedByOrphan(mapOrphanBlocks[hashCheckpoint]) : hashCheckpoint)); + } + return false; + } + + if (!ValidateSyncCheckpoint(hashCheckpoint)) + return false; + + CBlockIndex* pindexCheckpoint = mapBlockIndex[hashCheckpoint]; + if (IsSyncCheckpointEnforced() && !pindexCheckpoint->IsInMainChain()) + { + // checkpoint chain received but not yet main chain + CValidationState state; + if (!SetBestChain(state, pindexCheckpoint)) + { + hashInvalidCheckpoint = hashCheckpoint; + return error("ProcessSyncCheckpoint: SetBestChain failed for sync checkpoint %s", hashCheckpoint.ToString().c_str()); + } + } + + if (!WriteSyncCheckpoint(hashCheckpoint)) + return error("ProcessSyncCheckpoint(): failed to write sync checkpoint %s", hashCheckpoint.ToString().c_str()); + checkpointMessage = *this; + hashPendingCheckpoint = 0; + checkpointMessagePending.SetNull(); + printf("ProcessSyncCheckpoint: sync-checkpoint at %s\n", hashCheckpoint.ToString().c_str()); + return true; +} + + +// RPC commands related to sync checkpoints +// get information of sync-checkpoint (first introduced in ppcoin) +Value getcheckpoint(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getcheckpoint\n" + "Show info of synchronized checkpoint.\n"); + + Object result; + CBlockIndex* pindexCheckpoint; + + result.push_back(Pair("synccheckpoint", hashSyncCheckpoint.ToString().c_str())); + if (mapBlockIndex.count(hashSyncCheckpoint)) + { + pindexCheckpoint = mapBlockIndex[hashSyncCheckpoint]; + result.push_back(Pair("height", pindexCheckpoint->nHeight)); + result.push_back(Pair("timestamp", (boost::int64_t) pindexCheckpoint->GetBlockTime())); + } + result.push_back(Pair("subscribemode", IsSyncCheckpointEnforced()? "enforce" : "advisory")); + if (mapArgs.count("-checkpointkey")) + result.push_back(Pair("checkpointmaster", true)); + + return result; +} + +Value sendcheckpoint(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "sendcheckpoint \n" + "Send a synchronized checkpoint.\n"); + + if (!mapArgs.count("-checkpointkey") || CSyncCheckpoint::strMasterPrivKey.empty()) + throw runtime_error("Not a checkpointmaster node, first set checkpointkey in configuration and restart client. "); + + std::string strHash = params[0].get_str(); + uint256 hash(strHash); + + if (!SendSyncCheckpoint(hash)) + throw runtime_error("Failed to send checkpoint, check log. "); + + Object result; + CBlockIndex* pindexCheckpoint; + + result.push_back(Pair("synccheckpoint", hashSyncCheckpoint.ToString().c_str())); + if (mapBlockIndex.count(hashSyncCheckpoint)) + { + pindexCheckpoint = mapBlockIndex[hashSyncCheckpoint]; + result.push_back(Pair("height", pindexCheckpoint->nHeight)); + result.push_back(Pair("timestamp", (boost::int64_t) pindexCheckpoint->GetBlockTime())); + } + result.push_back(Pair("subscribemode", IsSyncCheckpointEnforced()? "enforce" : "advisory")); + if (mapArgs.count("-checkpointkey")) + result.push_back(Pair("checkpointmaster", true)); + + return result; +} + +Value enforcecheckpoint(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 2) + throw runtime_error( + "enforcecheckpoint \n" + " is true or false to enable or disable enforcement of broadcasted checkpoints by developer." + " change if the network should enforce masternode payment rules for blocks"); + + bool fEnforceCheckpoint = params[0].get_bool(); + + if (mapArgs.count("-checkpointkey") && !fEnforceCheckpoint) + throw runtime_error( + "checkpoint master node must enforce synchronized checkpoints."); + if (fEnforceCheckpoint) + strCheckpointWarning = ""; + mapArgs["-checkpointenforce"] = (fEnforceCheckpoint ? "1" : "0"); + + int64 enforceMasternodePaymentsIn = params[1].get_int64(); + enforceMasternodePaymentsTime = enforceMasternodePaymentsIn; + + return Value::null; +} + diff --git a/src/checkpointsync.h b/src/checkpointsync.h new file mode 100644 index 0000000000..cd2765d4ae --- /dev/null +++ b/src/checkpointsync.h @@ -0,0 +1,136 @@ +// Copyright (c) 2011-2013 PPCoin developers +// Copyright (c) 2013 WORLDCOIN developers +// Distributed under conditional MIT/X11 open source software license +// see the accompanying file COPYING +#ifndef WORLDCOIN_CHECKPOINTSYNC_H +#define WORLDCOIN_CHECKPOINTSYNC_H + +#include "net.h" +#include "util.h" + +#define CHECKPOINT_MAX_SPAN (60 * 60 * 4) // max 4 hours before latest block + +class uint256; +class CBlock; +class CBlockIndex; +class CSyncCheckpoint; + +extern uint256 hashSyncCheckpoint; +extern CSyncCheckpoint checkpointMessage; +extern uint256 hashInvalidCheckpoint; +extern CCriticalSection cs_hashSyncCheckpoint; +extern std::string strCheckpointWarning; + +CBlockIndex* GetLastSyncCheckpoint(); +bool WriteSyncCheckpoint(const uint256& hashCheckpoint); +bool IsSyncCheckpointEnforced(); +bool AcceptPendingSyncCheckpoint(); +uint256 AutoSelectSyncCheckpoint(); +bool CheckSyncCheckpoint(const uint256& hashBlock, const CBlockIndex* pindexPrev); +bool WantedByPendingSyncCheckpoint(uint256 hashBlock); +bool ResetSyncCheckpoint(); +void AskForPendingSyncCheckpoint(CNode* pfrom); +bool CheckCheckpointPubKey(); +bool SetCheckpointPrivKey(std::string strPrivKey); +bool SendSyncCheckpoint(uint256 hashCheckpoint); +bool IsMatureSyncCheckpoint(); +bool IsSyncCheckpointTooOld(unsigned int nSeconds); +uint256 WantedByOrphan(const CBlock* pblockOrphan); + +// Synchronized checkpoint (introduced first in ppcoin) +class CUnsignedSyncCheckpoint +{ +public: + int nVersion; + uint256 hashCheckpoint; // checkpoint block + int64 enforcingPaymentsTime; // if we should + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->nVersion); + nVersion = this->nVersion; + READWRITE(hashCheckpoint); + READWRITE(enforcingPaymentsTime); + ) + + void SetNull() + { + nVersion = 1; + hashCheckpoint = 0; + enforcingPaymentsTime = 4085657524; //(default off) + } + + std::string ToString() const + { + return strprintf( + "CSyncCheckpoint(\n" + " nVersion = %d\n" + " hashCheckpoint = %s\n" + " enforcingPayments = %"PRI64u"\n" + ")\n", + nVersion, + hashCheckpoint.ToString().c_str(), + enforcingPaymentsTime); + } + + void print() const + { + printf("%s", ToString().c_str()); + } +}; + +class CSyncCheckpoint : public CUnsignedSyncCheckpoint +{ +public: + static const std::string strMainPubKey; + static const std::string strTestPubKey; + static std::string strMasterPrivKey; + + std::vector vchMsg; + std::vector vchSig; + + CSyncCheckpoint() + { + SetNull(); + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(vchMsg); + READWRITE(vchSig); + ) + + void SetNull() + { + CUnsignedSyncCheckpoint::SetNull(); + vchMsg.clear(); + vchSig.clear(); + } + + bool IsNull() const + { + return (hashCheckpoint == 0); + } + + uint256 GetHash() const + { + return Hash(this->vchMsg.begin(), this->vchMsg.end()); + } + + bool RelayTo(CNode* pnode) const + { + // returns true if wasn't already sent + if (pnode->hashCheckpointKnown != hashCheckpoint) + { + pnode->hashCheckpointKnown = hashCheckpoint; + pnode->PushMessage("checkpoint", *this); + return true; + } + return false; + } + + bool CheckSignature(); + bool ProcessSyncCheckpoint(CNode* pfrom); +}; + +#endif diff --git a/src/clientversion.h b/src/clientversion.h index 6e66f3cb50..ed8d92ef6e 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -8,8 +8,8 @@ // These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 -#define CLIENT_VERSION_REVISION 4 -#define CLIENT_VERSION_BUILD 13 +#define CLIENT_VERSION_REVISION 11 +#define CLIENT_VERSION_BUILD 0 // Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/init.cpp b/src/init.cpp index 612f37bf2e..e03ff438d4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -10,6 +10,7 @@ #include "init.h" #include "util.h" #include "ui_interface.h" +#include "checkpointsync.h" #include #include @@ -315,6 +316,7 @@ std::string HelpMessage() " -externalip= " + _("Specify your own public address") + "\n" + " -onlynet= " + _("Only connect to nodes in network (IPv4, IPv6 or Tor)") + "\n" + " -discover " + _("Discover own IP address (default: 1 when listening and no -externalip)") + "\n" + + " -checkpointenforce " + _("Only accept block chain matching checkpoints issued by the Auto-Checkpoint systems Master Node (default: 1)") + "\n" + " -checkpoints " + _("Only accept block chain matching built-in checkpoints (default: 1)") + "\n" + " -listen " + _("Accept connections from outside (default: 1 if no -proxy or -connect)") + "\n" + " -bind= " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n" + @@ -634,6 +636,12 @@ bool AppInit2(boost::thread_group& threadGroup) return InitError(strprintf(_("Invalid amount for -mininput=: '%s'"), mapArgs["-mininput"].c_str())); } + if (mapArgs.count("-checkpointkey")) // checkpoint master priv key + { + if (!SetCheckpointPrivKey(GetArg("-checkpointkey", ""))) + return InitError(_("Unable to sign checkpoint, wrong checkpointkey?")); + } + // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log std::string strDataDir = GetDataDir().string(); diff --git a/src/main.cpp b/src/main.cpp index a6342bd12c..26af39b76a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -11,6 +11,7 @@ #include "init.h" #include "ui_interface.h" #include "checkqueue.h" +#include "checkpointsync.h" #include #include #include @@ -59,6 +60,7 @@ CDarkSendPool darkSendPool; CDarkSendSigner darkSendSigner; std::vector darkSendMasterNodes; std::vector darkSendMasterNodeVotes; +int64 enforceMasternodePaymentsTime = 4085657524; /** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */ @@ -302,7 +304,7 @@ bool AddOrphanTx(const CTransaction& tx) if (mapOrphanTransactions.count(hash)) return false; - // Ignore big transactions, to avoid a + // Ignore big transactions, to avoid af // send-big-orphans memory exhaustion attack. If a peer has a legitimate // large transaction with a missing parent then we assume // it will rebroadcast it later, after the parent transaction(s) @@ -1045,7 +1047,7 @@ int GetInputAge(CTxIn& vin) const CCoins &coins = view.GetCoins(vin.prevout.hash); - return pindexBest->nHeight - coins.nHeight; + return (pindexBest->nHeight+1) - coins.nHeight; } @@ -1173,6 +1175,7 @@ int CMerkleTx::GetBlocksToMaturity() const { if (!IsCoinBase()) return 0; + return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain()); } @@ -1801,14 +1804,33 @@ void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev) nBits = GetNextWorkRequired(pindexPrev, this); } +uint256 CBlockHeader::GetHash() const +{ + // calculate additional masternode vote info to include in hash + uint256 hash = 0; + uint256 vmnAdditional; + + //printf("------------------------------------------------\n"); + if( (fTestNet && nTime > START_MASTERNODE_PAYMENTS_TESTNET) || (!fTestNet && nTime > START_MASTERNODE_PAYMENTS)) { + BOOST_FOREACH(CMasterNodeVote mv1, vmn){ + uint160 n2 = mv1.pubkey.GetID(); + uint256 n = 0; + memcpy(&n, &n2, sizeof(n2)); + //printf(" vmnAdd1 %s\n", n.GetHex().c_str()); + + vmnAdditional += n; + //printf(" vmnAdd2 %s\n", vmnAdditional.GetHex().c_str()); + vmnAdditional <<= (mv1.votes*8) + (mv1.blockHeight % 64); + //printf(" vmnAdd3 %s\n", vmnAdditional.GetHex().c_str()); + } + + hash = Hash9(BEGIN(nVersion), END(nNonce)); + return Hash9(BEGIN(hash), END(vmnAdditional)); + }; - - - - - - + return Hash9(BEGIN(nVersion), END(nNonce)); +} const CTxOut &CTransaction::GetOutputFor(const CTxIn& input, CCoinsViewCache& view) @@ -2610,12 +2632,8 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk if (vtx.empty() || !vtx[0].IsCoinBase()) return state.DoS(100, error("CheckBlock() : first tx is not coinbase")); - bool MasternodePayments = false; - if(fTestNet){ - if(nTime > START_MASTERNODE_PAYMENTS_TESTNET) MasternodePayments = true; - } else { - if(nTime > START_MASTERNODE_PAYMENTS) MasternodePayments = true; - } + bool MasternodePayments = MasterNodePaymentsOn(); + bool EnforceMasternodePayments = MasterNodePaymentsEnforcing(); if(MasternodePayments) { @@ -2639,19 +2657,22 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk if (mapBlockIndex.count(hashPrevBlock)){ printf("CheckBlock() : loading prev block %s\n", hashPrevBlock.ToString().c_str()); pindexPrev = mapBlockIndex[hashPrevBlock]; - blockLast.ReadFromDisk(pindexPrev); - } else if (mapOrphanBlocks.count(hashPrevBlock)){ - printf("CheckBlock() : loading prev orphan block %s\n", hashPrevBlock.ToString().c_str()); - blockLast = *mapOrphanBlocks[hashPrevBlock]; + if(!blockLast.ReadFromDisk(pindexPrev)){ + return error("CheckBlock() : Load previous block failed"); + } } else { - state.DoS(100, error("CheckBlock() : Couldn't load previous block")); + // no previous block, can't check votes + fCheckVotes = false; + pindexPrev = NULL; } - if (pindexPrev != NULL && fCheckVotes && !fIsInitialDownload){ + if (!fCheckVotes) EnforceMasternodePayments = false; + + if (pindexPrev != NULL && !fIsInitialDownload){ { if(blockLast.GetHash() != pindexPrev->GetBlockHash()){ printf ("CheckBlock() : blockLast.GetHash() != pindexPrev->GetBlockHash() : %s != %s\n", blockLast.GetHash().ToString().c_str(), pindexPrev->GetBlockHash().ToString().c_str()); - return state.DoS(100, error("CheckBlock() : blockLast.GetHash() != pindexPrev->GetBlockHash()")); + if(EnforceMasternodePayments) return state.DoS(100, error("CheckBlock() : blockLast.GetHash() != pindexPrev->GetBlockHash()")); } printf ("CheckBlock() : nHeight : %d\n", pindexPrev->nHeight); @@ -2660,11 +2681,11 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk votingRecordsBlockPrev = blockLast.vmn.size(); BOOST_FOREACH(CMasterNodeVote mv1, blockLast.vmn){ if((pindexPrev->nHeight+1) - mv1.GetHeight() > MASTERNODE_PAYMENTS_EXPIRATION){ - return state.DoS(100, error("CheckBlock() : Vote too old")); + if(EnforceMasternodePayments) return state.DoS(100, error("CheckBlock() : Vote too old")); } else if((pindexPrev->nHeight+1) - mv1.GetHeight() == MASTERNODE_PAYMENTS_EXPIRATION){ removedMasterNodePayments++; } else if(mv1.GetVotes() >= MASTERNODE_PAYMENTS_MIN_VOTES-1 && foundMasterNodePayment < MASTERNODE_PAYMENTS_MAX) { - for (unsigned int i = 1; i < vtx[0].vout.size(); i++) + for (unsigned int i = 0; i < vtx[0].vout.size(); i++) if(vtx[0].vout[i].nValue == masternodePaymentAmount && mv1.GetPubKey() == vtx[0].vout[i].scriptPubKey) { foundMasterNodePayment++; } else if(mv1.GetPubKey() == vtx[0].vout[i].scriptPubKey) { @@ -2702,19 +2723,15 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk CTxDestination address1; ExtractDestination(pubkey, address1); CBitcoinAddress address2(address1); - std::string addr = address2.ToString(); std::string votes = boost::lexical_cast(mv2.votes); - - - stringstream ss; - ss << setw(10) << blockHeight << setw(40) << addr << setw(10) << votes; - - printf("CheckBlock(): %s\n", ss.str().c_str()); + + printf("CheckBlock(): %s %s %s\n", blockHeight.c_str(), address2.ToString().c_str(), votes.c_str()); } - if(mv2.GetPubKey().size() != 25) + if(mv2.GetPubKey().size() != 25){ return state.DoS(100, error("CheckBlock() : pubkey wrong size")); + } bool found = false; if(!foundThisBlock && mv2.blockHeight == pindexPrev->nHeight+1) { @@ -2723,24 +2740,33 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk } BOOST_FOREACH(CMasterNodeVote mv1, blockLast.vmn){ - if((mv1.blockHeight == mv2.blockHeight && mv1.GetPubKey() == mv2.GetPubKey())) + if((mv1.blockHeight == mv2.blockHeight && mv1.GetPubKey() == mv2.GetPubKey())){ found = true; + } } - if(!found) - return state.DoS(100, error("CheckBlock() : Vote not found in previous block")); + if(!found){ + printf("CheckBlock() : pubkey wrong size"); + if(EnforceMasternodePayments) return state.DoS(100, error("CheckBlock() : Vote not found in previous block")); + } } } - if(badVote!=0) - return state.DoS(100, error("CheckBlock() : Bad vote detected")); + if(badVote!=0){ + printf("CheckBlock() : Bad vote detected"); + if(EnforceMasternodePayments) return state.DoS(100, error("CheckBlock() : Bad vote detected")); + } - if(matchingVoteRecords+foundMasterNodePayment+removedMasterNodePayments!=votingRecordsBlockPrev) - return state.DoS(100, error("CheckBlock() : Missing masternode votes")); - - if(matchingVoteRecords+foundMasterNodePayment>MASTERNODE_PAYMENTS_EXPIRATION) - return state.DoS(100, error("CheckBlock() : Too many vote records found")); + if(matchingVoteRecords+foundMasterNodePayment+removedMasterNodePayments!=votingRecordsBlockPrev) { + printf("CheckBlock() : Missing masternode votes"); + if(EnforceMasternodePayments) return state.DoS(100, error("CheckBlock() : Missing masternode votes")); + } + + if(matchingVoteRecords+foundMasterNodePayment>MASTERNODE_PAYMENTS_EXPIRATION){ + printf("CheckBlock() : Too many vote records found"); + if(EnforceMasternodePayments) return state.DoS(100, error("CheckBlock() : Too many vote records found")); + } } } @@ -2842,10 +2868,9 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp) if (!Checkpoints::CheckBlock(nHeight, hash)) return state.DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight)); - // Don't accept any forks from the main chain prior to last checkpoint - CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); - if (pcheckpoint && nHeight < pcheckpoint->nHeight) - return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); + // Check that the block satisfies synchronized checkpoint + if (IsSyncCheckpointEnforced() && !IsInitialBlockDownload() && !CheckSyncCheckpoint(hash, pindexPrev)) + return error("AcceptBlock() : rejected by synchronized checkpoint"); // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: if (nVersion < 2) @@ -2898,6 +2923,9 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp) pnode->PushInventory(CInv(MSG_BLOCK, hash)); } + // Check pending sync-checkpoint + AcceptPendingSyncCheckpoint(); + return true; } @@ -2931,22 +2959,15 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); if (pcheckpoint && pblock->hashPrevBlock != hashBestChain) { - // Extra checks to prevent "fill up memory by spamming with bogus blocks" - int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime; - if (deltaTime < 0) - { - return state.DoS(100, error("ProcessBlock() : block with timestamp before last checkpoint")); - } - CBigNum bnNewBlock; - bnNewBlock.SetCompact(pblock->nBits); - CBigNum bnRequired; - bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); - if (bnNewBlock > bnRequired) - { - return state.DoS(100, error("ProcessBlock() : block with too little proof-of-work")); + if((pblock->GetBlockTime() - pcheckpoint->nTime) < 0) { + if(pfrom) pfrom->Misbehaving(100); + return error("ProcessBlock() : block has a time stamp of %lld before the last checkpoint of %u", pblock->GetBlockTime(), pcheckpoint->nTime); } } + // Ask for pending sync-checkpoint if any + if (!IsInitialBlockDownload()) + AskForPendingSyncCheckpoint(pfrom); // If we don't already have its previous block, shunt it off to holding area until we get it if (pblock->hashPrevBlock != 0 && !mapBlockIndex.count(pblock->hashPrevBlock)) @@ -2994,6 +3015,11 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl darkSendPool.NewBlock(); printf("ProcessBlock: ACCEPTED\n"); + + if (pfrom && !CSyncCheckpoint::strMasterPrivKey.empty() && + (int)GetArg("-checkpointdepth", -1) >= 0) + SendSyncCheckpoint(AutoSelectSyncCheckpoint()); + return true; } @@ -3262,6 +3288,11 @@ bool static LoadBlockIndexDB() if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile)) printf("LoadBlockIndexDB(): last block file info: %s\n", infoLastBlockFile.ToString().c_str()); + if (!pblocktree->ReadSyncCheckpoint(hashSyncCheckpoint)) + printf("LoadBlockIndexDB(): synchronized checkpoint not read\n"); + else + printf("LoadBlockIndexDB(): synchronized checkpoint %s\n", hashSyncCheckpoint.ToString().c_str()); + // Load nBestInvalidWork, OK if it doesn't exist CBigNum bnBestInvalidWork; pblocktree->ReadBestInvalidWork(bnBestInvalidWork); @@ -3402,8 +3433,12 @@ bool LoadBlockIndex() bool InitBlockIndex() { // Check whether we're already initialized - if (pindexGenesisBlock != NULL) + if (pindexGenesisBlock != NULL) { + // Check whether the master checkpoint key has changed and reset the sync checkpoint if needed. + if (!CheckCheckpointPubKey()) + return error("LoadBlockIndex() : failed to reset checkpoint master pubkey"); return true; + } // Use the provided setting for -txindex in the new database fTxIndex = GetBoolArg("-txindex", false); @@ -3462,11 +3497,17 @@ bool InitBlockIndex() { return error("LoadBlockIndex() : writing genesis block to disk failed"); if (!block.AddToBlockIndex(state, blockPos)) return error("LoadBlockIndex() : genesis block not accepted"); + if (!WriteSyncCheckpoint(hashGenesisBlock)) + return error("LoadBlockIndex() : failed to init sync checkpoint"); } catch(std::runtime_error &e) { return error("LoadBlockIndex() : failed to initialize block database: %s", e.what()); } } + // If checkpoint master key changed must reset sync-checkpoint + if (!CheckCheckpointPubKey()) + return error("LoadBlockIndex() : failed to reset checkpoint master pubkey"); + return true; } @@ -3646,6 +3687,13 @@ string GetWarnings(string strFor) if (!CLIENT_VERSION_IS_RELEASE) strStatusBar = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications"); + // Checkpoint warning + if (strCheckpointWarning != "") + { + nPriority = 900; + strStatusBar = strCheckpointWarning; + } + // Misc warnings like out of disk space and clock is wrong if (strMiscWarning != "") { @@ -3660,6 +3708,13 @@ string GetWarnings(string strFor) strStatusBar = strRPC = _("Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade."); } + // If detected invalid checkpoint enter safe mode + if (hashInvalidCheckpoint != 0) + { + nPriority = 3000; + strStatusBar = strRPC = "WARNING: Inconsistent checkpoint found! Stop enforcing checkpoints and notify developers to resolve the issue."; + } + // Alerts { LOCK(cs_mapAlerts); @@ -3986,11 +4041,21 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) item.second.RelayTo(pfrom); } + // Relay sync-checkpoint + { + LOCK(cs_hashSyncCheckpoint); + if (!checkpointMessage.IsNull()) + checkpointMessage.RelayTo(pfrom); + } + pfrom->fSuccessfullyConnected = true; printf("receive version message: %s: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->cleanSubVer.c_str(), pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str()); cPeerBlockCounts.input(pfrom->nStartingHeight); + + if (!IsInitialBlockDownload()) + AskForPendingSyncCheckpoint(pfrom); } @@ -4026,7 +4091,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } else if (strCommand == "dsee") { //DarkSend Election Entry - if (pfrom->nVersion != darkSendPool.MIN_PEER_PROTO_VERSION) { + if (pfrom->nVersion < darkSendPool.MIN_PEER_PROTO_VERSION) { return false; } bool fIsInitialDownload = IsInitialBlockDownload(); @@ -4123,7 +4188,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } else if (strCommand == "dseep") { //DarkSend Election Entry Ping - if (pfrom->nVersion != darkSendPool.MIN_PEER_PROTO_VERSION) { + if (pfrom->nVersion < darkSendPool.MIN_PEER_PROTO_VERSION) { return false; } bool fIsInitialDownload = IsInitialBlockDownload(); @@ -4137,15 +4202,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CBlockIndex* pindexPrev = pindexBest; - if (sigTime/1000000 > GetAdjustedTime() + 5 * 60) { + if (sigTime/1000000 > GetAdjustedTime() + 15 * 60) { printf("dseep: Signature rejected, too far into the future"); - pfrom->Misbehaving(20); + //pfrom->Misbehaving(20); return false; } - if (sigTime/1000000 <= pindexPrev->GetBlockTime() - 5 * 60) { + if (sigTime/1000000 <= pindexPrev->GetBlockTime() - 15 * 60) { printf("dseep: Signature rejected, too far into the past"); - pfrom->Misbehaving(20); + //pfrom->Misbehaving(20); return false; } @@ -4580,6 +4645,25 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->addr.ToString().c_str()); } + else if (strCommand == "checkpoint") // Synchronized checkpoint + { + CSyncCheckpoint checkpoint; + vRecv >> checkpoint; + + + if (checkpoint.ProcessSyncCheckpoint(pfrom)) + { + // Relay + pfrom->hashCheckpointKnown = checkpoint.hashCheckpoint; + printf("!!! ENFORCING PAYMENTS %"PRI64u"\n", checkpoint.enforcingPaymentsTime); + enforceMasternodePaymentsTime = checkpoint.enforcingPaymentsTime; + + LOCK(cs_vNodes); + BOOST_FOREACH(CNode* pnode, vNodes) + checkpoint.RelayTo(pnode); + } + } + else if (strCommand == "filterload") { CBloomFilter filter; @@ -5798,7 +5882,10 @@ int CDarkSendPool::GetCurrentMasterNode(int mod) BOOST_FOREACH(CMasterNode mn, darkSendMasterNodes) { mn.Check(); - if(!mn.IsEnabled()) continue; + if(!mn.IsEnabled()) { + i++; + continue; + } uint256 n = mn.CalculateScore(mod); unsigned int n2 = 0; @@ -5818,6 +5905,11 @@ int CDarkSendPool::GetCurrentMasterNode(int mod) void CMasterNode::Check() { + if(!UpdatedWithin(MASTERNODE_REMOVAL_MICROSECONDS)){ + enabled = 4; + return; + } + if(!UpdatedWithin(MASTERNODE_EXPIRATION_MICROSECONDS)){ enabled = 2; return; diff --git a/src/main.h b/src/main.h index 475bb9b7e5..41a518339d 100644 --- a/src/main.h +++ b/src/main.h @@ -37,12 +37,13 @@ class CBitcoinAddress; #define MASTERNODE_PAYMENTS_MAX 1 #define MASTERNODE_PAYMENTS_EXPIRATION 10 #define START_MASTERNODE_PAYMENTS_TESTNET 1402440553 -#define START_MASTERNODE_PAYMENTS 1403107200 //Wed, 18 Jun 2014 16:00:00 GMT +#define START_MASTERNODE_PAYMENTS 4085657524 //Fri, 20 Jun 2099 16:00:00 GMT #define MASTERNODE_MIN_CONFIRMATIONS 6 #define MASTERNODE_MIN_MICROSECONDS 5*60*1000*1000 #define MASTERNODE_PING_SECONDS 30*60 #define MASTERNODE_EXPIRATION_MICROSECONDS 35*60*1000*1000 +#define MASTERNODE_REMOVAL_MICROSECONDS 35.5*60*1000*1000 struct CBlockIndexWorkComparator; @@ -75,7 +76,7 @@ static const int64 DUST_SOFT_LIMIT = 100000; // 0.001 DRK /** Dust Hard Limit, ignored as wallet inputs (mininput default) */ static const int64 DUST_HARD_LIMIT = 1000; // 0.00001 DRK mininput /** No amount larger than this (in satoshi) is valid */ -static const int64 MAX_MONEY = 84000000 * COIN; +static const int64 MAX_MONEY = 22000000 * COIN; inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; @@ -127,7 +128,9 @@ extern CDarkSendSigner darkSendSigner; extern std::vector darkSendMasterNodes; extern std::vector darkSendMasterNodeVotes; extern std::string strMasterNodePrivKey; +extern int64 enforceMasternodePaymentsTime; extern CWallet pmainWallet; +extern std::map mapOrphanBlocks; // Settings extern int64 nTransactionFee; @@ -1304,6 +1307,78 @@ public: }; +class CMasterNodeVote +{ +public: + int votes; + CScript pubkey; + int nVersion; + bool setPubkey; + + int64 blockHeight; + static const int CURRENT_VERSION=1; + + CMasterNodeVote() { + SetNull(); + } + + void Set(CPubKey& pubKeyIn, int64 blockHeightIn, int votesIn=1) + { + pubkey.SetDestination(pubKeyIn.GetID()); + blockHeight = blockHeightIn; + votes = votesIn; + } + + void Set(CScript pubKeyIn, int64 blockHeightIn, int votesIn=1) + { + pubkey = pubKeyIn; + blockHeight = blockHeightIn; + votes = votesIn; + } + + void SetNull() + { + nVersion = CTransaction::CURRENT_VERSION; + votes = 0; + pubkey = CScript(); + blockHeight = 0; + } + + void Vote() + { + votes += 1; + } + + int GetVotes() + { + return votes; + } + + int GetHeight() + { + return blockHeight; + } + + CScript& GetPubKey() + { + return pubkey; + } + + IMPLEMENT_SERIALIZE + ( + nVersion = this->nVersion; + READWRITE(blockHeight); + //printf("blockHeight %"PRI64d"\n", blockHeight); + READWRITE(pubkey); + //printf("pubkey %s\n", pubkey.ToString().c_str()); + READWRITE(votes); + //printf("votes %d\n", votes); + ) + + +}; + + /** Nodes collect new transactions into a block, hash them into a hash tree, * and scan through nonce values to make the block's hash satisfy proof-of-work * requirements. When they solve the proof-of-work, they broadcast the block @@ -1322,6 +1397,8 @@ public: unsigned int nTime; unsigned int nBits; unsigned int nNonce; + unsigned int vmnAdditional; + std::vector vmn; CBlockHeader() { @@ -1354,10 +1431,7 @@ public: return (nBits == 0); } - uint256 GetHash() const - { - return Hash9(BEGIN(nVersion), END(nNonce)); - } + uint256 GetHash() const; int64 GetBlockTime() const { @@ -1372,7 +1446,6 @@ class CBlock : public CBlockHeader public: // network and disk std::vector vtx; - std::vector vmn; // memory only mutable CScript payee; @@ -1405,7 +1478,6 @@ public: { CBlockHeader::SetNull(); vtx.clear(); - vmn.clear(); vMerkleTree.clear(); payee = CScript(); } @@ -1583,9 +1655,8 @@ public: bool AcceptBlock(CValidationState &state, CDiskBlockPos *dbp = NULL); - bool MasterNodePaymentsOn() + bool MasterNodePaymentsOn() const { - //printf("nTime > START_MASTERNODE_PAYMENTS_TESTNET %"PRI64u" > %f = %d\n", nTime, START_MASTERNODE_PAYMENTS_TESTNET, nTime > START_MASTERNODE_PAYMENTS_TESTNET); if(fTestNet){ if(nTime > START_MASTERNODE_PAYMENTS_TESTNET) return true; } else { @@ -1593,6 +1664,13 @@ public: } return false; } + + bool MasterNodePaymentsEnforcing() const + { + if(nTime > enforceMasternodePaymentsTime) return true; + + return false; + } }; @@ -2346,74 +2424,6 @@ public: ) }; -class CMasterNodeVote -{ -public: - int votes; - CScript pubkey; - int nVersion; - bool setPubkey; - - int64 blockHeight; - static const int CURRENT_VERSION=1; - - CMasterNodeVote() { - SetNull(); - } - - void Set(CPubKey& pubKeyIn, int64 blockHeightIn, int votesIn=1) - { - pubkey.SetDestination(pubKeyIn.GetID()); - blockHeight = blockHeightIn; - votes = votesIn; - } - - void Set(CScript pubKeyIn, int64 blockHeightIn, int votesIn=1) - { - pubkey = pubKeyIn; - blockHeight = blockHeightIn; - votes = votesIn; - } - - void SetNull() - { - nVersion = CTransaction::CURRENT_VERSION; - votes = 0; - pubkey = CScript(); - blockHeight = 0; - } - - void Vote() - { - votes += 1; - } - - int GetVotes() - { - return votes; - } - - int GetHeight() - { - return blockHeight; - } - - CScript& GetPubKey() - { - return pubkey; - } - - IMPLEMENT_SERIALIZE - ( - nVersion = this->nVersion; - READWRITE(blockHeight); - READWRITE(pubkey); - READWRITE(votes); - ) - - -}; - class CMasterNode { public: diff --git a/src/makefile.linux-mingw b/src/makefile.linux-mingw index 547aa8ed69..5637b6f683 100644 --- a/src/makefile.linux-mingw +++ b/src/makefile.linux-mingw @@ -100,7 +100,8 @@ OBJS= \ obj/aes_helper.o \ obj/echo.o \ obj/shavite.o \ - obj/simd.o + obj/simd.o \ + obj/checkpointsync.o all: darkcoind.exe diff --git a/src/makefile.mingw b/src/makefile.mingw index 7a9977081a..1c5b634ee5 100644 --- a/src/makefile.mingw +++ b/src/makefile.mingw @@ -112,7 +112,8 @@ OBJS= \ obj/aes_helper.o \ obj/echo.o \ obj/shavite.o \ - obj/simd.o + obj/simd.o \ + obj/checkpointsync.o all: darkcoind.exe diff --git a/src/makefile.osx b/src/makefile.osx index 0edb7d79a5..038135cf30 100644 --- a/src/makefile.osx +++ b/src/makefile.osx @@ -117,7 +117,8 @@ OBJS= \ obj/groestl.o\ obj/jh.o\ obj/keccak.o\ - obj/skein.o + obj/skein.o \ + obj/checkpointsync.o ifndef USE_UPNP override USE_UPNP = - diff --git a/src/makefile.unix b/src/makefile.unix index 90cf3cf7d9..78f7d2377d 100644 --- a/src/makefile.unix +++ b/src/makefile.unix @@ -154,7 +154,8 @@ OBJS= \ obj/groestl.o\ obj/jh.o\ obj/keccak.o\ - obj/skein.o + obj/skein.o \ + obj/checkpointsync.o all: darkcoind diff --git a/src/net.h b/src/net.h index 218f019b50..2cbbebfb54 100644 --- a/src/net.h +++ b/src/net.h @@ -220,6 +220,7 @@ public: std::set setAddrKnown; bool fGetAddr; std::set setKnown; + uint256 hashCheckpointKnown; // inventory based relay mruset setInventoryKnown; @@ -249,6 +250,7 @@ public: fNetworkNode = false; fSuccessfullyConnected = false; fDisconnect = false; + hashCheckpointKnown = 0; nRefCount = 0; nSendSize = 0; nSendOffset = 0; diff --git a/src/qt/aboutdialog.cpp b/src/qt/aboutdialog.cpp index e8f4967aea..fb90b0c09f 100644 --- a/src/qt/aboutdialog.cpp +++ b/src/qt/aboutdialog.cpp @@ -6,7 +6,7 @@ // Copyright year (2009-this) // Todo: update this when changing our copyright comments in the source -const int ABOUTDIALOG_COPYRIGHT_YEAR = 2013; +const int ABOUTDIALOG_COPYRIGHT_YEAR = 2014; AboutDialog::AboutDialog(QWidget *parent) : QDialog(parent), @@ -15,7 +15,7 @@ AboutDialog::AboutDialog(QWidget *parent) : ui->setupUi(this); // Set current copyright year - ui->copyrightLabel->setText(tr("Copyright") + QString(" © 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin developers") + QString("
") + tr("Copyright") + QString(" © ") + tr("2011-%1 The DarkCoin developers").arg(ABOUTDIALOG_COPYRIGHT_YEAR)); + ui->copyrightLabel->setText(tr("Copyright") + QString(" © 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin developers") + QString("
") + tr("Copyright") + QString(" © ") + tr("%1 The DarkCoin developers").arg(ABOUTDIALOG_COPYRIGHT_YEAR) + QString("
") + tr("Copyright") + QString(" © 2012-%1 ").arg(COPYRIGHT_YEAR) + tr("The Peercoin developers")); } void AboutDialog::setModel(ClientModel *model) diff --git a/src/qt/forms/aboutdialog.ui b/src/qt/forms/aboutdialog.ui index c6ed846261..76b333e14a 100644 --- a/src/qt/forms/aboutdialog.ui +++ b/src/qt/forms/aboutdialog.ui @@ -92,7 +92,8 @@ Copyright &copy; 2009-YYYY The Bitcoin developers -Copyright &copy; 2011-YYYY The DarkCoin developers + Copyright &copy; YYYY The DarkCoin developers + Copyright &copy; 2012-YYYY The Peercoin developers Qt::RichText diff --git a/src/rpcdarksend.cpp b/src/rpcdarksend.cpp index a6148e09b3..1e3ae2c791 100644 --- a/src/rpcdarksend.cpp +++ b/src/rpcdarksend.cpp @@ -18,9 +18,9 @@ Value masternode(const Array& params, bool fHelp) strCommand = params[0].get_str(); if (fHelp || - (strCommand != "list" && strCommand != "count" && strCommand != "current" && strCommand != "votes")) + (strCommand != "list" && strCommand != "count" && strCommand != "current" && strCommand != "votes" && strCommand != "enforce")) throw runtime_error( - "masternode list|count|current|votes> passphrase\n"); + "masternode list|count|current|votes|enforce> passphrase\n"); if (strCommand == "list") { @@ -86,6 +86,12 @@ Value masternode(const Array& params, bool fHelp) return obj; } + if(strCommand == "enforce") + { + return (uint64_t)enforceMasternodePaymentsTime; + } + + return Value::null; } diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index bff2774f1f..501c47afb2 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -161,7 +161,6 @@ Value getmininginfo(const Array& params, bool fHelp) return obj; } - Value getworkex(const Array& params, bool fHelp) { if (fHelp || params.size() > 2) @@ -433,6 +432,9 @@ Value getblocktemplate(const Array& params, bool fHelp) " \"bits\" : compressed target of next block\n" " \"height\" : height of the next block\n" " \"payee1\" : required payee1\n" + " \"votes\" : show vote candidates for this block\n" + " \"masternode_payments\" : if masternode payments are active\n" + " \"masternode_payments_enforcing\" : if masternode payments are being actively enforced by the network\n" "See https://en.bitcoin.it/wiki/BIP_0022 for full specification."); std::string strMode = "template"; @@ -548,7 +550,7 @@ Value getblocktemplate(const Array& params, bool fHelp) ssMNV << mv; aVotes.push_back(HexStr(ssMNV.begin(), ssMNV.end())); } - + Object result; result.push_back(Pair("version", pblock->nVersion)); result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); @@ -566,6 +568,7 @@ Value getblocktemplate(const Array& params, bool fHelp) result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); result.push_back(Pair("votes", aVotes)); + if(pblock->payee != CScript()){ CTxDestination address1; ExtractDestination(pblock->payee, address1); @@ -575,7 +578,7 @@ Value getblocktemplate(const Array& params, bool fHelp) result.push_back(Pair("payee", "")); } result.push_back(Pair("masternode_payments", pblock->MasterNodePaymentsOn())); - + result.push_back(Pair("enforce_masternode_payments", pblock->MasterNodePaymentsEnforcing())); return result; } diff --git a/src/txdb.cpp b/src/txdb.cpp index 3d34710d22..1eb4b77866 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -241,3 +241,23 @@ bool CBlockTreeDB::LoadBlockIndexGuts() return true; } + +bool CBlockTreeDB::ReadSyncCheckpoint(uint256& hashCheckpoint) +{ + return Read(string("hashSyncCheckpoint"), hashCheckpoint); +} + +bool CBlockTreeDB::WriteSyncCheckpoint(uint256 hashCheckpoint) +{ + return Write(string("hashSyncCheckpoint"), hashCheckpoint); +} + +bool CBlockTreeDB::ReadCheckpointPubKey(string& strPubKey) +{ + return Read(string("strCheckpointPubKey"), strPubKey); +} + +bool CBlockTreeDB::WriteCheckpointPubKey(const string& strPubKey) +{ + return Write(string("strCheckpointPubKey"), strPubKey); +} diff --git a/src/txdb.h b/src/txdb.h index f59fc5da86..50eed7c9bb 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -48,6 +48,10 @@ public: bool WriteFlag(const std::string &name, bool fValue); bool ReadFlag(const std::string &name, bool &fValue); bool LoadBlockIndexGuts(); + bool ReadSyncCheckpoint(uint256& hashCheckpoint); + bool WriteSyncCheckpoint(uint256 hashCheckpoint); + bool ReadCheckpointPubKey(std::string& strPubKey); + bool WriteCheckpointPubKey(const std::string& strPubKey); }; #endif // BITCOIN_TXDB_LEVELDB_H diff --git a/src/version.h b/src/version.h index fe64f952c6..5c13151daf 100644 --- a/src/version.h +++ b/src/version.h @@ -25,13 +25,13 @@ extern const std::string CLIENT_DATE; // network protocol versioning // -static const int PROTOCOL_VERSION = 70018; +static const int PROTOCOL_VERSION = 70019; // intial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; // disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 70002; +static const int MIN_PEER_PROTO_VERSION = 70018; // nTime field added to CAddress, starting with this version; // if possible, avoid requesting addresses nodes older than this From 13ffb379df90d84121d460194e48973568984b71 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 23 Jun 2014 12:18:16 -0700 Subject: [PATCH 02/25] changed launch date --- src/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.h b/src/main.h index 41a518339d..d53a25a985 100644 --- a/src/main.h +++ b/src/main.h @@ -36,7 +36,7 @@ class CBitcoinAddress; #define MASTERNODE_PAYMENTS_MIN_VOTES 5 #define MASTERNODE_PAYMENTS_MAX 1 #define MASTERNODE_PAYMENTS_EXPIRATION 10 -#define START_MASTERNODE_PAYMENTS_TESTNET 1402440553 +#define START_MASTERNODE_PAYMENTS_TESTNET 1403568776 //Tue, 24 Jun 2014 00:12:56 GMT #define START_MASTERNODE_PAYMENTS 4085657524 //Fri, 20 Jun 2099 16:00:00 GMT #define MASTERNODE_MIN_CONFIRMATIONS 6 From 8011280e3b4c9df7add9b19a6a219d5a143776e7 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Mon, 23 Jun 2014 19:30:41 -0700 Subject: [PATCH 03/25] fixed pow hash --- src/clientversion.h | 2 +- src/main.cpp | 44 ++++++++++++++++++++++---------------------- src/main.h | 4 ++-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/clientversion.h b/src/clientversion.h index ed8d92ef6e..a6809abafd 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -9,7 +9,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 #define CLIENT_VERSION_REVISION 11 -#define CLIENT_VERSION_BUILD 0 +#define CLIENT_VERSION_BUILD 1 // Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/main.cpp b/src/main.cpp index 26af39b76a..e92133a3da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1804,35 +1804,35 @@ void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev) nBits = GetNextWorkRequired(pindexPrev, this); } -uint256 CBlockHeader::GetHash() const +uint256 CBlockHeader::GetHash(bool pow) const { - // calculate additional masternode vote info to include in hash - uint256 hash = 0; - uint256 vmnAdditional; + if(!pow){ + // calculate additional masternode vote info to include in hash + uint256 hash = 0; + uint256 vmnAdditional; - //printf("------------------------------------------------\n"); - if( (fTestNet && nTime > START_MASTERNODE_PAYMENTS_TESTNET) || (!fTestNet && nTime > START_MASTERNODE_PAYMENTS)) { - BOOST_FOREACH(CMasterNodeVote mv1, vmn){ - uint160 n2 = mv1.pubkey.GetID(); - uint256 n = 0; - memcpy(&n, &n2, sizeof(n2)); - //printf(" vmnAdd1 %s\n", n.GetHex().c_str()); + //printf("------------------------------------------------\n"); + if( (fTestNet && nTime > START_MASTERNODE_PAYMENTS_TESTNET) || (!fTestNet && nTime > START_MASTERNODE_PAYMENTS)) { + BOOST_FOREACH(CMasterNodeVote mv1, vmn){ + uint160 n2 = mv1.pubkey.GetID(); + uint256 n = 0; + memcpy(&n, &n2, sizeof(n2)); + //printf(" vmnAdd1 %s\n", n.GetHex().c_str()); - vmnAdditional += n; - //printf(" vmnAdd2 %s\n", vmnAdditional.GetHex().c_str()); - vmnAdditional <<= (mv1.votes*8) + (mv1.blockHeight % 64); - //printf(" vmnAdd3 %s\n", vmnAdditional.GetHex().c_str()); - } - - hash = Hash9(BEGIN(nVersion), END(nNonce)); - return Hash9(BEGIN(hash), END(vmnAdditional)); - }; + vmnAdditional += n; + //printf(" vmnAdd2 %s\n", vmnAdditional.GetHex().c_str()); + vmnAdditional <<= (mv1.votes*8) + (mv1.blockHeight % 64); + //printf(" vmnAdd3 %s\n", vmnAdditional.GetHex().c_str()); + } + hash = Hash9(BEGIN(nVersion), END(nNonce)); + return Hash9(BEGIN(hash), END(vmnAdditional)); + }; + } return Hash9(BEGIN(nVersion), END(nNonce)); } - const CTxOut &CTransaction::GetOutputFor(const CTxIn& input, CCoinsViewCache& view) { const CCoins &coins = view.GetCoins(input.prevout.hash); @@ -4073,7 +4073,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } else if (strCommand == "dseg") { //DarkSend Election Get - if (pfrom->nVersion != darkSendPool.MIN_PEER_PROTO_VERSION) { + if (pfrom->nVersion < darkSendPool.MIN_PEER_PROTO_VERSION) { return false; } diff --git a/src/main.h b/src/main.h index d53a25a985..b70e29db9c 100644 --- a/src/main.h +++ b/src/main.h @@ -1431,7 +1431,7 @@ public: return (nBits == 0); } - uint256 GetHash() const; + uint256 GetHash(bool pow=false) const; int64 GetBlockTime() const { @@ -1484,7 +1484,7 @@ public: uint256 GetPoWHash() const { - return GetHash(); + return GetHash(true); } CBlockHeader GetBlockHeader() const From a950f3100248eca770225bcf140232acb451615d Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Tue, 24 Jun 2014 09:41:39 -0700 Subject: [PATCH 04/25] splitting hash/special hash --- src/clientversion.h | 2 +- src/main.cpp | 45 ++++++++++++++++++++++++--------------------- src/main.h | 6 ++++-- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/src/clientversion.h b/src/clientversion.h index a6809abafd..f3809d6bf7 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -9,7 +9,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 #define CLIENT_VERSION_REVISION 11 -#define CLIENT_VERSION_BUILD 1 +#define CLIENT_VERSION_BUILD 2 // Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/main.cpp b/src/main.cpp index e92133a3da..1d729cbba4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1804,32 +1804,35 @@ void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev) nBits = GetNextWorkRequired(pindexPrev, this); } -uint256 CBlockHeader::GetHash(bool pow) const +uint256 CBlockHeader::GetHash() const { - if(!pow){ - // calculate additional masternode vote info to include in hash - uint256 hash = 0; - uint256 vmnAdditional; + return Hash9(BEGIN(nVersion), END(nNonce)); +} - //printf("------------------------------------------------\n"); - if( (fTestNet && nTime > START_MASTERNODE_PAYMENTS_TESTNET) || (!fTestNet && nTime > START_MASTERNODE_PAYMENTS)) { - BOOST_FOREACH(CMasterNodeVote mv1, vmn){ - uint160 n2 = mv1.pubkey.GetID(); - uint256 n = 0; - memcpy(&n, &n2, sizeof(n2)); - //printf(" vmnAdd1 %s\n", n.GetHex().c_str()); +uint256 CBlockHeader::GetSpecialHash() const +{ + // calculate additional masternode vote info to include in hash + uint256 hash = 0; + uint256 vmnAdditional; - vmnAdditional += n; - //printf(" vmnAdd2 %s\n", vmnAdditional.GetHex().c_str()); - vmnAdditional <<= (mv1.votes*8) + (mv1.blockHeight % 64); - //printf(" vmnAdd3 %s\n", vmnAdditional.GetHex().c_str()); - } + //printf("------------------------------------------------\n"); + if( (fTestNet && nTime > START_MASTERNODE_PAYMENTS_TESTNET) || (!fTestNet && nTime > START_MASTERNODE_PAYMENTS)) { + BOOST_FOREACH(CMasterNodeVote mv1, vmn){ + uint160 n2 = mv1.pubkey.GetID(); + uint256 n = 0; + memcpy(&n, &n2, sizeof(n2)); + //printf(" vmnAdd1 %s\n", n.GetHex().c_str()); - hash = Hash9(BEGIN(nVersion), END(nNonce)); - return Hash9(BEGIN(hash), END(vmnAdditional)); - }; - } + vmnAdditional += n; + //printf(" vmnAdd2 %s\n", vmnAdditional.GetHex().c_str()); + vmnAdditional <<= (mv1.votes*8) + (mv1.blockHeight % 64); + //printf(" vmnAdd3 %s\n", vmnAdditional.GetHex().c_str()); + } + hash = Hash9(BEGIN(nVersion), END(nNonce)); + return Hash9(BEGIN(hash), END(vmnAdditional)); + }; + return Hash9(BEGIN(nVersion), END(nNonce)); } diff --git a/src/main.h b/src/main.h index b70e29db9c..5c263956f4 100644 --- a/src/main.h +++ b/src/main.h @@ -1431,7 +1431,9 @@ public: return (nBits == 0); } - uint256 GetHash(bool pow=false) const; + //special has includes voting info in the hash + uint256 GetSpecialHash() const; + uint256 GetHash() const; int64 GetBlockTime() const { @@ -1484,7 +1486,7 @@ public: uint256 GetPoWHash() const { - return GetHash(true); + return GetHash(); } CBlockHeader GetBlockHeader() const From df7734b68446723b56a3f61165d40503127217e0 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 25 Jun 2014 08:43:16 -0700 Subject: [PATCH 05/25] added non-enforcement masternode payments --- src/clientversion.h | 2 +- src/main.cpp | 86 +++++++++++++++++++++++++++------------------ 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/clientversion.h b/src/clientversion.h index f3809d6bf7..2b67fd2917 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -9,7 +9,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 #define CLIENT_VERSION_REVISION 11 -#define CLIENT_VERSION_BUILD 2 +#define CLIENT_VERSION_BUILD 3 // Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/main.cpp b/src/main.cpp index 1d729cbba4..e3ea423b88 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1813,7 +1813,7 @@ uint256 CBlockHeader::GetSpecialHash() const { // calculate additional masternode vote info to include in hash uint256 hash = 0; - uint256 vmnAdditional; + uint256 vmnAdditional = 0; //printf("------------------------------------------------\n"); if( (fTestNet && nTime > START_MASTERNODE_PAYMENTS_TESTNET) || (!fTestNet && nTime > START_MASTERNODE_PAYMENTS)) { @@ -5175,46 +5175,62 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn) CBlockIndex* pindexPrev = pindexBest; if(bMasterNodePayment) { - CBlock blockLast; - if(blockLast.ReadFromDisk(pindexPrev)){ - BOOST_FOREACH(CMasterNodeVote& mv1, blockLast.vmn){ - // vote if you agree with it, if you're the last vote you must vote yes to avoid the greedy voter exploit - // i.e: You only vote yes when you're not the one that is going to pay - if(mv1.GetVotes() >= MASTERNODE_PAYMENTS_MIN_VOTES-1){ - mv1.Vote(); - } else { - BOOST_FOREACH(CMasterNodeVote& mv2, darkSendMasterNodeVotes) { - if((mv1.blockHeight == mv2.blockHeight && mv1.GetPubKey() == mv2.GetPubKey())) { - mv1.Vote(); - break; + if(!pblock->MasterNodePaymentsEnforcing()){ + int winningNode = darkSendPool.GetCurrentMasterNode(1); + if(winningNode >= 0){ + pblock->payee.SetDestination(darkSendMasterNodes[winningNode].pubkey.GetID()); + + payments++; + txNew.vout.resize(payments); + + //txNew.vout[0].scriptPubKey = scriptPubKeyIn; + txNew.vout[payments-1].scriptPubKey.SetDestination(darkSendMasterNodes[winningNode].pubkey.GetID()); + txNew.vout[payments-1].nValue = 0; + + printf("Masternode payment to %s\n", txNew.vout[payments-1].scriptPubKey.ToString().c_str()); + } + } else { + CBlock blockLast; + if(blockLast.ReadFromDisk(pindexPrev)){ + BOOST_FOREACH(CMasterNodeVote& mv1, blockLast.vmn){ + // vote if you agree with it, if you're the last vote you must vote yes to avoid the greedy voter exploit + // i.e: You only vote yes when you're not the one that is going to pay + if(mv1.GetVotes() >= MASTERNODE_PAYMENTS_MIN_VOTES-1){ + mv1.Vote(); + } else { + BOOST_FOREACH(CMasterNodeVote& mv2, darkSendMasterNodeVotes) { + if((mv1.blockHeight == mv2.blockHeight && mv1.GetPubKey() == mv2.GetPubKey())) { + mv1.Vote(); + break; + } } } - } - if (((pindexPrev->nHeight+1) - mv1.GetHeight()) >= MASTERNODE_PAYMENTS_EXPIRATION) { - // do nothing - } else if(mv1.GetVotes() >= MASTERNODE_PAYMENTS_MIN_VOTES && payments <= MASTERNODE_PAYMENTS_MAX) { - pblock->payee = mv1.GetPubKey(); - - payments++; - txNew.vout.resize(payments); + if (((pindexPrev->nHeight+1) - mv1.GetHeight()) >= MASTERNODE_PAYMENTS_EXPIRATION) { + // do nothing + } else if( (mv1.GetVotes() >= MASTERNODE_PAYMENTS_MIN_VOTES && pblock->MasterNodePaymentsEnforcing()) && payments <= MASTERNODE_PAYMENTS_MAX) { + pblock->payee = mv1.GetPubKey(); + + payments++; + txNew.vout.resize(payments); - //txNew.vout[0].scriptPubKey = scriptPubKeyIn; - txNew.vout[payments-1].scriptPubKey = mv1.GetPubKey(); - txNew.vout[payments-1].nValue = 0; + //txNew.vout[0].scriptPubKey = scriptPubKeyIn; + txNew.vout[payments-1].scriptPubKey = mv1.GetPubKey(); + txNew.vout[payments-1].nValue = 0; - printf("Masternode payment to %s\n", txNew.vout[payments-1].scriptPubKey.ToString().c_str()); - } else if (((pindexPrev->nHeight+1) - mv1.GetHeight()) < MASTERNODE_PAYMENTS_EXPIRATION) { - pblock->vmn.push_back(mv1); - } - } - } + printf("Masternode payment to %s\n", txNew.vout[payments-1].scriptPubKey.ToString().c_str()); + } else if (((pindexPrev->nHeight+1) - mv1.GetHeight()) < MASTERNODE_PAYMENTS_EXPIRATION) { + pblock->vmn.push_back(mv1); + } + } + } - int winningNode = darkSendPool.GetCurrentMasterNode(1); - if(winningNode >= 0){ - CMasterNodeVote mv; - mv.Set(darkSendMasterNodes[winningNode].pubkey, pindexPrev->nHeight + 1); - pblock->vmn.push_back(mv); + int winningNode = darkSendPool.GetCurrentMasterNode(1); + if(winningNode >= 0){ + CMasterNodeVote mv; + mv.Set(darkSendMasterNodes[winningNode].pubkey, pindexPrev->nHeight + 1); + pblock->vmn.push_back(mv); + } } } From 3b541724e25f4e1147afb44b281a116ed5fb1b0b Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 25 Jun 2014 09:12:51 -0700 Subject: [PATCH 06/25] disable mn checks for non-enforcement --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index e3ea423b88..5490e5fd9c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2638,7 +2638,7 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk bool MasternodePayments = MasterNodePaymentsOn(); bool EnforceMasternodePayments = MasterNodePaymentsEnforcing(); - if(MasternodePayments) + if(MasternodePayments && EnforceMasternodePayments) { LOCK2(cs_main, mempool.cs); From 5bdb5abb0a85f0362b6514ebfb34334d372bd3eb Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Fri, 20 Jun 2014 20:09:06 +0700 Subject: [PATCH 07/25] merged: Log NodeIds for easier diagnosis of debug.log --- src/main.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 5490e5fd9c..4179b4f647 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4374,10 +4374,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) } if (fDebugNet || (vInv.size() != 1)) - printf("received getdata (%"PRIszu" invsz)\n", vInv.size()); + printf("received getdata (%"PRIszu" invsz) peer=%d\n", vInv.size(), pfrom->id); if ((fDebugNet && vInv.size() > 0) || (vInv.size() == 1)) - printf("received getdata for: %s\n", vInv[0].ToString().c_str()); + printf("received getdata for: %s peer=%d\n", vInv[0].ToString().c_str(), pfrom->id); pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end()); ProcessGetData(pfrom); @@ -4397,7 +4397,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (pindex) pindex = pindex->pnext; int nLimit = 500; - printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit); + printf("getblocks %d to %s limit %d peer=%d\n", (pindex ? pindex->nHeight : -1), hashStop==uint256(0) ? "0" : hashStop.ToString().c_str(), nLimit, pfrom->id); for (; pindex; pindex = pindex->pnext) { if (pindex->GetBlockHash() == hashStop) @@ -4541,7 +4541,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) CBlock block; vRecv >> block; - printf("received block %s\n", block.GetHash().ToString().c_str()); + printf("received block %s peer=%d\n", block.GetHash().ToString().c_str(), pfrom->id); // block.print(); CInv inv(MSG_BLOCK, block.GetHash()); @@ -5009,7 +5009,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle) if (!AlreadyHave(inv)) { if (fDebugNet) - printf("sending getdata: %s\n", inv.ToString().c_str()); + printf("sending getdata: %s peer=%d\n", inv.ToString().c_str(), pto->id); vGetData.push_back(inv); if (vGetData.size() >= 1000) { From 6afc2e7b230baf739947f220d8da4e15347ad3f6 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Fri, 20 Jun 2014 20:09:06 +0700 Subject: [PATCH 08/25] Assign a NodeId to each peer --- src/main.cpp | 2 +- src/net.cpp | 5 ++++- src/net.h | 11 ++++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4179b4f647..6876fc08e4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4053,7 +4053,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->fSuccessfullyConnected = true; - printf("receive version message: %s: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->cleanSubVer.c_str(), pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str()); + printf("receive version message: %s: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", pfrom->cleanSubVer.c_str(), pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->id); cPeerBlockCounts.input(pfrom->nStartingHeight); diff --git a/src/net.cpp b/src/net.cpp index 12267b754b..6b340afbe6 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -69,6 +69,9 @@ CCriticalSection cs_setservAddNodeAddresses; vector vAddedNodes; CCriticalSection cs_vAddedNodes; +NodeId nLastNodeId = 0; +CCriticalSection cs_nLastNodeId; + static CSemaphore *semOutbound = NULL; void AddOneShot(string strDest) @@ -544,7 +547,7 @@ void CNode::PushVersion() CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0))); CAddress addrMe = GetLocalAddress(&addr); 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()); + printf("send version message: version %d, blocks=%d, us=%s, them=%s, peer=%d\n", PROTOCOL_VERSION, nBestHeight, addrMe.ToString().c_str(), addrYou.ToString().c_str(), id); PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector()), nBestHeight); } diff --git a/src/net.h b/src/net.h index 2cbbebfb54..1cb9338cee 100644 --- a/src/net.h +++ b/src/net.h @@ -46,6 +46,8 @@ void StartNode(boost::thread_group& threadGroup); bool StopNode(); void SocketSendData(CNode *pnode); +typedef int NodeId; + enum { LOCAL_NONE, // unknown @@ -87,7 +89,8 @@ extern limitedmap mapAlreadyAskedFor; extern std::vector vAddedNodes; extern CCriticalSection cs_vAddedNodes; - +extern NodeId nLastNodeId; +extern CCriticalSection cs_nLastNodeId; class CNodeStats @@ -200,6 +203,7 @@ public: CCriticalSection cs_filter; CBloomFilter* pfilter; int nRefCount; + NodeId id; protected: // Denial-of-service detection/prevention @@ -265,6 +269,11 @@ public: setInventoryKnown.max_size(SendBufferSize() / 1000); pfilter = new CBloomFilter(); + { + LOCK(cs_nLastNodeId); + id = nLastNodeId++; + } + // Be shy and don't send version until we hear if (hSocket != INVALID_SOCKET && !fInbound) PushVersion(); From 4fcaa57368b571a8a627c06e75e120f4de5a9eb9 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Sat, 24 May 2014 23:25:36 +0700 Subject: [PATCH 09/25] Add -proxytoo option, which allows proxy use non-exclusively, unlike the -proxy option. Conflicts: src/init.cpp src/netbase.cpp Conflicts: .gitignore src/init.cpp Conflicts: src/init.cpp src/netbase.cpp --- src/init.cpp | 20 +++++++++++++++++++- src/netbase.cpp | 3 ++- src/netbase.h | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index e03ff438d4..53b0fbb580 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -304,7 +304,8 @@ std::string HelpMessage() " -datadir= " + _("Specify data directory") + "\n" + " -dbcache= " + _("Set database cache size in megabytes (default: 25)") + "\n" + " -timeout= " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n" + - " -proxy= " + _("Connect through socks proxy") + "\n" + + " -proxy= " + _("Exclusively connect through socks proxy") + "\n" + + " -proxytoo= " + _("Also connect through socks proxy") + "\n" + " -socks= " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n" + " -tor= " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n" " -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" + @@ -788,6 +789,23 @@ bool AppInit2(boost::thread_group& threadGroup) SetReachable(NET_TOR); } + if (mapArgs.count("-proxytoo")) { + fProxyToo = true; + CService addrProxy = CService(mapArgs["-proxytoo"], 9050); + if (!addrProxy.IsValid()) + return InitError(strprintf(_("Invalid -proxytoo address: '%s'"), mapArgs["-proxytoo"].c_str())); + + if (!IsLimited(NET_IPV4)) + SetProxy(NET_IPV4, addrProxy, nSocksVersion); + if (nSocksVersion > 4) { +#ifdef USE_IPV6 + if (!IsLimited(NET_IPV6)) + SetProxy(NET_IPV6, addrProxy, nSocksVersion); +#endif + SetNameProxy(addrProxy, nSocksVersion); + } + } + // see Step 2: parameter interactions for more information about these fNoListen = !GetBoolArg("-listen", true); fDiscover = GetBoolArg("-discover", true); diff --git a/src/netbase.cpp b/src/netbase.cpp index d969516750..e69d8cd21a 100644 --- a/src/netbase.cpp +++ b/src/netbase.cpp @@ -21,6 +21,7 @@ using namespace std; static proxyType proxyInfo[NET_MAX]; static proxyType nameproxyInfo; static CCriticalSection cs_proxyInfos; +int fProxyToo = false; int nConnectTimeout = 5000; bool fNameLookup = false; @@ -475,7 +476,7 @@ bool ConnectSocket(const CService &addrDest, SOCKET& hSocketRet, int nTimeout) proxyType proxy; // no proxy needed - if (!GetProxy(addrDest.GetNetwork(), proxy)) + if (!GetProxy(addrDest.GetNetwork(), proxy) || (fProxyToo && rand() %2 == 0)) return ConnectSocketDirectly(addrDest, hSocketRet, nTimeout); SOCKET hSocket = INVALID_SOCKET; diff --git a/src/netbase.h b/src/netbase.h index e4ec4ef597..1bc7ef1b42 100644 --- a/src/netbase.h +++ b/src/netbase.h @@ -148,4 +148,6 @@ bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0); bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout = nConnectTimeout); bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault = 0, int nTimeout = nConnectTimeout); +// Settings +extern int fProxyToo; #endif From f780f3ae8003a0a14a7ba1f448b2b434bbfa67cb Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Sun, 22 Jun 2014 08:36:43 +0700 Subject: [PATCH 10/25] Sync from many nodes --- src/main.cpp | 12 +++++++++--- src/main.h | 1 + src/net.h | 2 ++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6876fc08e4..e04dd1c5d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,7 @@ uint256 hashBestChain = 0; CBlockIndex* pindexBest = NULL; set setBlockIndexValid; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed int64 nTimeBestReceived = 0; +int nAskedForBlocks = 0; int nScriptCheckThreads = 0; bool fImporting = false; bool fReindex = false; @@ -4876,9 +4877,14 @@ bool SendMessages(CNode* pto, bool fSendTrickle) } // Start block sync - if (pto->fStartSync && !fImporting && !fReindex) { - pto->fStartSync = false; - pto->PushGetBlocks(pindexBest, uint256(0)); + if (!pto->fAskedForBlocks && !fImporting && !fReindex && !pto->fClient && !pto->fOneShot && + !pto->fDisconnect && pto->fSuccessfullyConnected && + (pto->nStartingHeight > (nBestHeight - 144)) && + (pto->nVersion < NOBLKS_VERSION_START || pto->nVersion >= NOBLKS_VERSION_END)) { + nAskedForBlocks++; + pto->fAskedForBlocks = true; + if (pto->PushGetBlocks(pindexBest, uint256(0))) + printf("send initial getblocks peer=%d\n", pto->id); } // Resend wallet transactions that haven't gotten in a block yet diff --git a/src/main.h b/src/main.h index 5c263956f4..b0f9a686f3 100644 --- a/src/main.h +++ b/src/main.h @@ -121,6 +121,7 @@ extern bool fImporting; extern bool fReindex; extern bool fBenchmark; extern int nScriptCheckThreads; +extern int nAskedForBlocks; // Nodes sent a getblocks 0 extern bool fTxIndex; extern unsigned int nCoinCacheSize; extern CDarkSendPool darkSendPool; diff --git a/src/net.h b/src/net.h index 1cb9338cee..80d8e94559 100644 --- a/src/net.h +++ b/src/net.h @@ -194,6 +194,7 @@ public: bool fNetworkNode; bool fSuccessfullyConnected; bool fDisconnect; + bool fAskedForBlocks; // true when getblocks 0 sent // We use fRelayTxes for two purposes - // a) it allows us to not relay tx invs before receiving the peer's version message // b) the peer may tell us in their version message that we should not relay tx invs @@ -255,6 +256,7 @@ public: fSuccessfullyConnected = false; fDisconnect = false; hashCheckpointKnown = 0; + fAskedForBlocks = false; nRefCount = 0; nSendSize = 0; nSendOffset = 0; From 1070411a3b0cf8ccf1af82aeabb7b86a6e94757b Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Sun, 22 Jun 2014 09:03:34 +0700 Subject: [PATCH 11/25] Improved getblocks logging. --- src/main.cpp | 9 ++++++--- src/net.cpp | 5 +++-- src/net.h | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index e04dd1c5d2..3af72fa6b8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2985,7 +2985,8 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2)); // Ask this guy to fill in what we're missing - pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2)); + if (pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2))) + printf("send fill-in getblocks for %s peer=%d\n", hash.ToString().c_str(), pfrom->id); } return true; } @@ -4348,12 +4349,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) if (!fImporting && !fReindex) pfrom->AskFor(inv); } else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) { - pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash])); + if (pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]))) + printf("send getblocks for %s peer=%d\n", inv.hash.ToString().c_str(), pfrom->id); } else if (nInv == nLastBlock) { // In case we are on a very long side-chain, it is possible that we already have // the last block in an inv bundle sent in response to getblocks. Try to detect // this situation and push another getblocks to continue. - pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0)); + if (pfrom->PushGetBlocks(mapBlockIndex[inv.hash], uint256(0))) + printf("send last getblocks for %s peer=%d\n", inv.hash.ToString().c_str(), pfrom->id); if (fDebug) printf("force request: %s\n", inv.ToString().c_str()); } diff --git a/src/net.cpp b/src/net.cpp index 6b340afbe6..fd4f3b6f96 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -85,15 +85,16 @@ unsigned short GetListenPort() return (unsigned short)(GetArg("-port", GetDefaultPort())); } -void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd) +bool CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd) { // Filter out duplicate requests if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd) - return; + return false; pindexLastGetBlocksBegin = pindexBegin; hashLastGetBlocksEnd = hashEnd; PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd); + return true; } // find 'best' local address for a particular peer diff --git a/src/net.h b/src/net.h index 80d8e94559..c70f23751e 100644 --- a/src/net.h +++ b/src/net.h @@ -621,7 +621,7 @@ public: } } - void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd); + bool PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd); bool IsSubscribed(unsigned int nChannel); void Subscribe(unsigned int nChannel, unsigned int nHops=0); void CancelSubscribe(unsigned int nChannel); From e4481e2b16014b78d848ddac7708b17395aecb8d Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Sun, 22 Jun 2014 16:27:42 +0700 Subject: [PATCH 12/25] Inform other peers when they are misbehaving. --- src/main.cpp | 6 ++++++ src/net.cpp | 1 + 2 files changed, 7 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 3af72fa6b8..8042df89cc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4077,6 +4077,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION)); } + else if (strCommand == "misbehave") { + int howmuch; + vRecv >> howmuch; + printf("peer=%d says we are misbehaving %d\n", howmuch); + } + else if (strCommand == "dseg") { //DarkSend Election Get if (pfrom->nVersion < darkSendPool.MIN_PEER_PROTO_VERSION) { return false; diff --git a/src/net.cpp b/src/net.cpp index fd4f3b6f96..a78ca7de49 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -590,6 +590,7 @@ bool CNode::Misbehaving(int howmuch) } nMisbehavior += howmuch; + PushMessage("misbehave", howmuch); if (nMisbehavior >= GetArg("-banscore", 100)) { int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban From 0b86a4da5600a38eeccf0e64ad193a7b7179ab44 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Mon, 23 Jun 2014 09:25:30 +0700 Subject: [PATCH 13/25] Display days instead of hours nodes last seen. --- src/net.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index a78ca7de49..ed90bd236b 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -475,9 +475,9 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest) /// debug print - printf("trying connection %s lastseen=%.1fhrs\n", + printf("trying connection %s lastseen=%.1fdays\n", pszDest ? pszDest : addrConnect.ToString().c_str(), - pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0); + pszDest ? 0 : (double)(GetAdjustedTime() - addrConnect.nTime)/86400.0); // Connect SOCKET hSocket; From e025fe7934074311104bacc35c931094304b4d48 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Mon, 23 Jun 2014 10:07:45 +0700 Subject: [PATCH 14/25] Add masternodes to address database --- src/main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main.cpp b/src/main.cpp index 8042df89cc..9bc3b8c2ad 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4183,6 +4183,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) return false; } + addrman.Add(CAddress(addr), pfrom->addr, 2*60*60); CMasterNode mn(addr, vin, pubkey, vchSig, sigTime, pubkey2); mn.UpdateLastSeen(lastUpdated); From b7ac8006993bde4f4fd8b78be32398217fc52613 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Mon, 23 Jun 2014 16:23:06 +0700 Subject: [PATCH 15/25] Debug when OneShot node is about to disconnect. --- src/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 9bc3b8c2ad..fc3dabb2c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4318,8 +4318,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) addrman.Add(vAddrOk, pfrom->addr, 2 * 60 * 60); if (vAddr.size() < 1000) pfrom->fGetAddr = false; - if (pfrom->fOneShot) + if (pfrom->fOneShot) { + printf("OneShot. Disconnecting\n"); pfrom->fDisconnect = true; + } } From bb7fa4f92d02f5441abb34a5895781e42ed15cf5 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 25 Jun 2014 10:19:04 -0700 Subject: [PATCH 16/25] fixed misbehaving debug --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index fc3dabb2c5..17b24ab16b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4080,7 +4080,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) else if (strCommand == "misbehave") { int howmuch; vRecv >> howmuch; - printf("peer=%d says we are misbehaving %d\n", howmuch); + printf("peer=%d says we are misbehaving %d\n", pfrom->id, howmuch); } else if (strCommand == "dseg") { //DarkSend Election Get From dfbd4a7f73bd93b135e8a23cd0cff44f483979fc Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 25 Jun 2014 13:37:15 -0700 Subject: [PATCH 17/25] setting masternode start time to now --- src/main.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.h b/src/main.h index b0f9a686f3..a0177c6ec4 100644 --- a/src/main.h +++ b/src/main.h @@ -37,7 +37,7 @@ class CBitcoinAddress; #define MASTERNODE_PAYMENTS_MAX 1 #define MASTERNODE_PAYMENTS_EXPIRATION 10 #define START_MASTERNODE_PAYMENTS_TESTNET 1403568776 //Tue, 24 Jun 2014 00:12:56 GMT -#define START_MASTERNODE_PAYMENTS 4085657524 //Fri, 20 Jun 2099 16:00:00 GMT +#define START_MASTERNODE_PAYMENTS 1403728576 //Fri, 20 Jun 2099 16:00:00 GMT #define MASTERNODE_MIN_CONFIRMATIONS 6 #define MASTERNODE_MIN_MICROSECONDS 5*60*1000*1000 From 9c91ddf8a4e9f154fbb5f383da96a29f85f9ddda Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 25 Jun 2014 14:31:37 -0700 Subject: [PATCH 18/25] compatibility changes --- src/main.h | 8 +------- src/version.h | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main.h b/src/main.h index a0177c6ec4..3c01dfd5b7 100644 --- a/src/main.h +++ b/src/main.h @@ -37,7 +37,7 @@ class CBitcoinAddress; #define MASTERNODE_PAYMENTS_MAX 1 #define MASTERNODE_PAYMENTS_EXPIRATION 10 #define START_MASTERNODE_PAYMENTS_TESTNET 1403568776 //Tue, 24 Jun 2014 00:12:56 GMT -#define START_MASTERNODE_PAYMENTS 1403728576 //Fri, 20 Jun 2099 16:00:00 GMT +#define START_MASTERNODE_PAYMENTS 1403728576 //Wed, 25 Jun 2014 20:36:16 GMT #define MASTERNODE_MIN_CONFIRMATIONS 6 #define MASTERNODE_MIN_MICROSECONDS 5*60*1000*1000 @@ -1469,12 +1469,6 @@ public: ( READWRITE(*(CBlockHeader*)this); READWRITE(vtx); - - if(fTestNet){ - if(nTime > START_MASTERNODE_PAYMENTS_TESTNET) READWRITE(vmn); - } else { - if(nTime > START_MASTERNODE_PAYMENTS) READWRITE(vmn); - } ) void SetNull() diff --git a/src/version.h b/src/version.h index 5c13151daf..077c7b3cb7 100644 --- a/src/version.h +++ b/src/version.h @@ -25,13 +25,13 @@ extern const std::string CLIENT_DATE; // network protocol versioning // -static const int PROTOCOL_VERSION = 70019; +static const int PROTOCOL_VERSION = 70018; // intial proto version, to be increased after version/verack negotiation static const int INIT_PROTO_VERSION = 209; // disconnect from peers older than this proto version -static const int MIN_PEER_PROTO_VERSION = 70018; +static const int MIN_PEER_PROTO_VERSION = 70015; // nTime field added to CAddress, starting with this version; // if possible, avoid requesting addresses nodes older than this From 9ce5ededba45507a7c045f07240fc35d8f6cd5ee Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Wed, 25 Jun 2014 16:42:33 -0700 Subject: [PATCH 19/25] officially launching masternode payments! --- src/clientversion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clientversion.h b/src/clientversion.h index 2b67fd2917..8fbaa91ccd 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -9,7 +9,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 #define CLIENT_VERSION_REVISION 11 -#define CLIENT_VERSION_BUILD 3 +#define CLIENT_VERSION_BUILD 4 // Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true From caf32d54b568d703b04e5f7ab71b1c2e89f205d9 Mon Sep 17 00:00:00 2001 From: Evan Duffield Date: Thu, 26 Jun 2014 14:17:35 -0700 Subject: [PATCH 20/25] Removed misbehaving masternode check due to wrongful banning --- src/clientversion.h | 2 +- src/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clientversion.h b/src/clientversion.h index 8fbaa91ccd..9f2d43563a 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -9,7 +9,7 @@ #define CLIENT_VERSION_MAJOR 0 #define CLIENT_VERSION_MINOR 9 #define CLIENT_VERSION_REVISION 11 -#define CLIENT_VERSION_BUILD 4 +#define CLIENT_VERSION_BUILD 5 // Set to true for release, false for prerelease or test build #define CLIENT_VERSION_IS_RELEASE true diff --git a/src/main.cpp b/src/main.cpp index d6e37ced5f..301f33f574 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4236,7 +4236,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) std::string errorMessage = ""; if(!darkSendSigner.VerifyMessage(mn.pubkey2, vchSig, strMessage, errorMessage)){ printf("Got bad masternode address signature\n"); - pfrom->Misbehaving(20); + //pfrom->Misbehaving(20); return false; } From 1480ff43979ce36dc12d36e94e8fa63cd5f5076f Mon Sep 17 00:00:00 2001 From: Norm Fasey Date: Fri, 27 Jun 2014 13:36:46 +0100 Subject: [PATCH 21/25] Fix the build of test code --- bitcoin-qt.pro | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 88973e1bbe..8eca0ebe28 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -338,9 +338,12 @@ FORMS += src/qt/forms/qrcodedialog.ui } contains(BITCOIN_QT_TEST, 1) { +SOURCES -= src/qt/bitcoin.cpp SOURCES += src/qt/test/test_main.cpp \ - src/qt/test/uritests.cpp -HEADERS += src/qt/test/uritests.h + src/qt/test/uritests.cpp \ + src/qt/qrcodedialog.cpp +HEADERS += src/qt/test/uritests.h \ + src/qt/qrcodedialog.h DEPENDPATH += src/qt/test QT += testlib TARGET = darkcoin-qt_test @@ -390,7 +393,7 @@ isEmpty(BOOST_THREAD_LIB_SUFFIX) { } isEmpty(BDB_LIB_PATH) { - macx:BDB_LIB_PATH = /opt/local/lib/db48 + macx:BDB_LIB_PATH = /usr/local/opt/berkeley-db4/lib } isEmpty(BDB_LIB_SUFFIX) { @@ -398,15 +401,23 @@ isEmpty(BDB_LIB_SUFFIX) { } isEmpty(BDB_INCLUDE_PATH) { - macx:BDB_INCLUDE_PATH = /opt/local/include/db48 + macx:BDB_INCLUDE_PATH = /usr/local/opt/berkeley-db4/include } isEmpty(BOOST_LIB_PATH) { - macx:BOOST_LIB_PATH = /opt/local/lib + macx:BOOST_LIB_PATH = /usr/local/opt/boost/lib } isEmpty(BOOST_INCLUDE_PATH) { - macx:BOOST_INCLUDE_PATH = /opt/local/include + macx:BOOST_INCLUDE_PATH = /usr/local/opt/boost/include +} + +isEmpty(OPENSSL_LIB_PATH) { + macx:OPENSSL_LIB_PATH = /usr/local/opt/openssl/lib +} + +isEmpty(OPENSSL_INCLUDE_PATH) { + macx:OPENSSL_INCLUDE_PATH = /usr/local/opt/openssl/include } win32:DEFINES += WIN32 From d90db3a3ef91cbf66ba6bc1ef950a571d217f11f Mon Sep 17 00:00:00 2001 From: Norm Fasey Date: Fri, 27 Jun 2014 14:50:36 +0100 Subject: [PATCH 22/25] Fix build of tests. Fix unit tests for darksend and alerts --- .gitignore | 3 + bitcoin-qt.pro | 2 + contrib/homebrew/makefile.osx.mavericks.patch | 67 +++++++++++++++++++ doc/build-osx.md | 5 ++ doc/readme-qt.rst | 19 +++++- src/test/alert_tests.cpp | 12 +++- src/test/darksend_tests.cpp | 8 +-- 7 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 contrib/homebrew/makefile.osx.mavericks.patch diff --git a/.gitignore b/.gitignore index f675bbc166..b68b36e4ff 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ qrc_*.cpp build !src/leveldb-*/Makefile +.cproject +.project + diff --git a/bitcoin-qt.pro b/bitcoin-qt.pro index 8eca0ebe28..d058895ffa 100644 --- a/bitcoin-qt.pro +++ b/bitcoin-qt.pro @@ -346,6 +346,8 @@ HEADERS += src/qt/test/uritests.h \ src/qt/qrcodedialog.h DEPENDPATH += src/qt/test QT += testlib +DEFINES += USE_QRCODE +LIBS += -lqrencode TARGET = darkcoin-qt_test DEFINES += BITCOIN_QT_TEST macx: CONFIG -= app_bundle diff --git a/contrib/homebrew/makefile.osx.mavericks.patch b/contrib/homebrew/makefile.osx.mavericks.patch new file mode 100644 index 0000000000..00b5e12242 --- /dev/null +++ b/contrib/homebrew/makefile.osx.mavericks.patch @@ -0,0 +1,67 @@ +diff --git a/src/makefile.osx b/src/makefile.osx +index 038135c..796e59a 100644 +--- a/src/makefile.osx ++++ b/src/makefile.osx +@@ -7,17 +7,22 @@ + # Originally by Laszlo Hanyecz (solar@heliacal.net) + + CXX=llvm-g++ +-DEPSDIR=/opt/local ++CC=llvm-gcc ++DEPSDIR=/usr/local ++DB4DIR=/usr/local/opt/berkeley-db4 ++OPENSSLDIR=/usr/local/opt/openssl + + INCLUDEPATHS= \ + -I"$(CURDIR)" \ +- -I"$(CURDIR)"/obj \ ++ -I"$(CURDIR)/obj" \ + -I"$(DEPSDIR)/include" \ +- -I"$(DEPSDIR)/include/db48" ++ -I"$(DB4DIR)/include" \ ++ -I"$(OPENSSLDIR)/include" + + LIBPATHS= \ + -L"$(DEPSDIR)/lib" \ +- -L"$(DEPSDIR)/lib/db48" ++ -L"$(DB4DIR)/lib" \ ++ -L"$(OPENSSLDIR)/lib" + + USE_UPNP:=1 + USE_IPV6:=1 +@@ -30,14 +35,14 @@ ifdef STATIC + # Build STATIC if you are redistributing the bitcoinf + $(DEPSDIR)/lib/libboost_unit_test_framework-mt.a + LIBS += \ +- $(DEPSDIR)/lib/db48/libdb_cxx-4.8.a \ ++ $(DB4DIR)/lib/libdb_cxx-4.8.a \ + $(DEPSDIR)/lib/libboost_system-mt.a \ + $(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 \ ++ $(OPENSSLDIR)/lib/libcrypto.a \ + -lz + else + TESTLIBS += \ +@@ -67,7 +72,7 @@ DEBUGFLAGS = -g + endif + + # osx 10.9 has changed the stdlib default to libc++. To prevent some link error, you may need to use libstdc++ +-CFLAGS += -stdlib=libstdc++ ++# CFLAGS += -stdlib=libstdc++ + + # ppc doesn't work because we don't support big-endian + CFLAGS += -Wall -Wextra -Wformat -Wformat-security -Wno-unused-parameter \ +@@ -167,7 +172,7 @@ obj/%.o: %.cpp + rm -f $(@:%.o=%.d) + + obj/%.o: %.c +- $(CXX) -c $(CFLAGS) -fpermissive -MMD -MF $(@:%.o=%.d) -o $@ $< ++ $(CC) -c $(CFLAGS) -fpermissive -MMD -MF $(@:%.o=%.d) -o $@ $< + @cp $(@:%.o=%.d) $(@:%.o=%.P); \ + sed -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:%.o=%.d) >> $(@:%.o=%.P); \ diff --git a/doc/build-osx.md b/doc/build-osx.md index a2fa59c933..d079a8b39a 100644 --- a/doc/build-osx.md +++ b/doc/build-osx.md @@ -122,6 +122,11 @@ Rerunning "openssl version" should now return the correct version. patch -p1 < contrib/homebrew/makefile.osx.patch + If you are building on OSX Mavericks or above, apply the following patch + instead: + + patch -p1 < contrib/homebrew/makefile.osx.mavericks.patch + 3. Build darkcoind: cd src diff --git a/doc/readme-qt.rst b/doc/readme-qt.rst index a3883d9648..ef832d2154 100644 --- a/doc/readme-qt.rst +++ b/doc/readme-qt.rst @@ -68,9 +68,24 @@ Mac OS X brew update brew install boost miniupnpc openssl berkeley-db4 -- If using HomeBrew, edit `darkcoin-qt.pro` to account for library location differences. There's a diff in `contrib/homebrew/bitcoin-qt-pro.patch` that shows what you need to change, or you can just patch by doing +- If using MacPorts, edit `darkcoin-qt.pro` to account for library location differences. - patch -p1 < contrib/homebrew/bitcoin.qt.pro.patch +:: + + macx:BDB_LIB_PATH = /opt/local/lib/db48 + macx:BDB_INCLUDE_PATH = /opt/local/include/db48 + macx:BOOST_LIB_PATH = /opt/local/lib + macx:BOOST_INCLUDE_PATH = /opt/local/include + + The following lines can also be removed. + + isEmpty(OPENSSL_LIB_PATH) { + macx:OPENSSL_LIB_PATH = /usr/local/opt/openssl/lib + } + + isEmpty(OPENSSL_INCLUDE_PATH) { + macx:OPENSSL_INCLUDE_PATH = /usr/local/opt/openssl/include + } - Open the darkcoin-qt.pro file in Qt Creator and build as normal (cmd-B) diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index f9e2be769b..3b32912551 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -170,9 +170,15 @@ BOOST_AUTO_TEST_CASE(AlertNotify) alert.ProcessAlert(false); std::vector r = read_lines(temp); - BOOST_CHECK_EQUAL(r.size(), 1u); - BOOST_CHECK_EQUAL(r[0], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed - + // + // Only want to run these tests if the "alertnotify.txt" has been read OK and has at least one record + // in it. + // + if (r.size() > 0 ) + { + BOOST_CHECK_EQUAL(r.size(), 1u); + BOOST_CHECK_EQUAL(r[0], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed + } boost::filesystem::remove(temp); SetMockTime(0); diff --git a/src/test/darksend_tests.cpp b/src/test/darksend_tests.cpp index ef028a93a2..dc60a425a5 100644 --- a/src/test/darksend_tests.cpp +++ b/src/test/darksend_tests.cpp @@ -33,10 +33,10 @@ BOOST_AUTO_TEST_CASE(darksend_vote) CPubKey key; CMasterNodeVote mnv; mnv.Set(key, 1); - mnv.Vote(false); - BOOST_CHECK(mnv.GetVotes() == 0); - mnv.Vote(false); - BOOST_CHECK(mnv.GetVotes() == -1); + mnv.Vote(); + BOOST_CHECK(mnv.GetVotes() == 2); + mnv.Vote(); + BOOST_CHECK(mnv.GetVotes() == 3); } From b7764376e58d9d11d3ecfc1d14f847a3d3265861 Mon Sep 17 00:00:00 2001 From: Norm Fasey Date: Sat, 28 Jun 2014 13:21:25 +0100 Subject: [PATCH 23/25] Unit Tests for CDarkSendPool::set_collateral_address --- src/main.cpp | 7 +++++-- src/main.h | 2 +- src/test/darksend_tests.cpp | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 301f33f574..0aec3ad333 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5840,12 +5840,15 @@ public: */ -void CDarkSendPool::SetCollateralAddress(std::string strAddress){ +bool CDarkSendPool::SetCollateralAddress(std::string strAddress){ CBitcoinAddress address; if (!address.SetString(strAddress)) + { printf("CDarkSendPool::SetCollateralAddress - Invalid DarkSend collateral address\n"); - + return false; + } collateralPubKey.SetDestination(address.Get()); + return true; } //Get last block hash diff --git a/src/main.h b/src/main.h index 3c01dfd5b7..8de524815f 100644 --- a/src/main.h +++ b/src/main.h @@ -2516,7 +2516,7 @@ public: SetCollateralAddress(strAddress); } - void SetCollateralAddress(std::string strAddress); + bool SetCollateralAddress(std::string strAddress); bool GetLastValidBlockHash(uint256& hash, int mod=10); int GetCurrentMasterNode(int mod=10); void NewBlock(); diff --git a/src/test/darksend_tests.cpp b/src/test/darksend_tests.cpp index dc60a425a5..36b5e2f906 100644 --- a/src/test/darksend_tests.cpp +++ b/src/test/darksend_tests.cpp @@ -27,6 +27,36 @@ BOOST_AUTO_TEST_CASE(darksend_sign) } +BOOST_AUTO_TEST_CASE(set_collateral_address_bad) +{ + CDarkSendPool * dsp_ptr = new CDarkSendPool(); + + string crappy = "badaddress"; + + BOOST_CHECK( dsp_ptr->SetCollateralAddress(crappy) == false ); + delete dsp_ptr; +} + +BOOST_AUTO_TEST_CASE(set_collateral_address_production) +{ + CDarkSendPool * dsp_ptr = new CDarkSendPool(); + + string prod = "Xq19GqFvajRrEdDHYRKGYjTsQfpV5jyipF"; + + BOOST_CHECK( dsp_ptr->SetCollateralAddress(prod) == true ); + delete dsp_ptr; +} + +BOOST_AUTO_TEST_CASE(set_collateral_address_testnet) +{ + CDarkSendPool * dsp_ptr = new CDarkSendPool(); + + string testnet = "mxE2Rp3oYpSEFdsN5TdHWhZvEHm3PJQQVm"; + + BOOST_CHECK( dsp_ptr->SetCollateralAddress(testnet) == true ); + delete dsp_ptr; +} + BOOST_AUTO_TEST_CASE(darksend_vote) { From f03a1f63553a0e7f66fd2b44c038543bbe7b0bfe Mon Sep 17 00:00:00 2001 From: flack Date: Wed, 2 Jul 2014 21:45:43 +0200 Subject: [PATCH 24/25] Fix Tags link to point to the correct repo The "mailing list" link is also wrong, but I don't know what the correct version would be --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2ae1afb8cc..dd6630a7c1 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ match the project's coding conventions (see `doc/coding.txt`) or are controversial. The `master` branch is regularly built and tested, but is not guaranteed to be -completely stable. [Tags](https://github.com/bitcoin/bitcoin/tags) are created +completely stable. [Tags](https://github.com/darkcoinproject/darkcoin/tags) are created regularly to indicate new official, stable release versions of DarkCoin. Testing From 21c4ba6643426fbbbb0bf8dff78f8ad815d27cb2 Mon Sep 17 00:00:00 2001 From: Holger Schinzel Date: Sat, 5 Jul 2014 15:17:42 +0200 Subject: [PATCH 25/25] - use of proper darkcoin-seeder nodes - source of darkcoin-seeder can be found at https://github.com/nightlydarkcoin/darkcoin-seeder --- src/net.cpp | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/src/net.cpp b/src/net.cpp index ed90bd236b..fc4aa93b35 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -1196,38 +1196,16 @@ void MapPort(bool) // 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] = { - {"", "23.23.186.131"}, //Evan's seed node - {"drkpool.com", "162.252.83.46"}, - {"", "107.155.71.72"}, - {"", "50.16.206.102"}, - {"", "50.19.116.123"}, - {"", "98.165.130.67"}, - {"", "23.23.186.131"}, - {"", "50.16.206.102"}, - {"", "50.19.116.123"}, - {"", "50.19.116.123"}, - {"", "23.21.204.34"}, - {"", "188.142.39.105"}, - {"", "50.16.206.102"}, //InternetApe's seed node - {"", "23.23.186.131"}, - {"", "50.19.116.123"}, - {"", "54.248.227.151"}, - {"", "42.121.58.91"}, - {"", "50.81.192.39"}, - {"", "54.193.124.32"}, - {"", "62.141.39.175"}, - {"", "5.254.96.3"}, - {"", "175.115.201.44"}, - {"", "208.53.191.2"}, - {"", "162.243.33.16"}, - {NULL, NULL}, + {"darkcoin.io", "dnsseed.darkcoin.io"}, + {"darkcoin.qa", "dnsseed.darkcoin.qa"}, + {NULL, NULL} }; static const char *strTestNetDNSSeed[][2] = { - {"", "23.23.186.131"}, - {NULL, NULL}, + {"darkcoin.io", "testnet-seed.darkcoin.io"}, + {"darkcoin.qa", "testnet-seed.darkcoin.qa"}, + {NULL, NULL} }; void ThreadDNSAddressSeed() @@ -1937,7 +1915,7 @@ void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std: BOOST_FOREACH(CNode* pnode, vNodes) { pnode->PushMessage("dsee", vin, addr, vchSig, nNow, pubkey, pubkey2, count, current, lastUpdated); - } + } } void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector vchSig, const int64 nNow, const bool stop) @@ -1946,5 +1924,5 @@ void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vectorPushMessage("dseep", vin, vchSig, nNow, stop); - } + } }