mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 13:32:47 +01:00
merged: Officially launching masternode payments!
This commit is contained in:
commit
23563ef25e
@ -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
|
||||
|
||||
|
@ -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<std::stri
|
||||
if (strMethod == "importprivkey" && n > 2) ConvertTo<bool>(params[2]);
|
||||
if (strMethod == "verifychain" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "verifychain" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
if (strMethod == "getpoolinfo" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
if (strMethod == "enforcecheckpoint" && n > 0) ConvertTo<bool>(params[0]);
|
||||
if (strMethod == "enforcecheckpoint" && n > 1) ConvertTo<boost::int64_t>(params[1]);
|
||||
|
||||
return params;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -146,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);
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,12 @@ namespace Checkpoints
|
||||
// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
|
||||
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& 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);
|
||||
}
|
||||
|
||||
|
535
src/checkpointsync.cpp
Normal file
535
src/checkpointsync.cpp
Normal file
@ -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 <boost/foreach.hpp>
|
||||
|
||||
#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<unsigned char>(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<unsigned char>(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 <blockhash>\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 <enforce> <enforcemasternodepayments>\n"
|
||||
"<enforce> is true or false to enable or disable enforcement of broadcasted checkpoints by developer."
|
||||
"<enforcemasternodepayments> 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;
|
||||
}
|
||||
|
136
src/checkpointsync.h
Normal file
136
src/checkpointsync.h
Normal file
@ -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<unsigned char> vchMsg;
|
||||
std::vector<unsigned char> 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
|
@ -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 10
|
||||
#define CLIENT_VERSION_BUILD 2
|
||||
#define CLIENT_VERSION_REVISION 11
|
||||
#define CLIENT_VERSION_BUILD 4
|
||||
|
||||
// Set to true for release, false for prerelease or test build
|
||||
#define CLIENT_VERSION_IS_RELEASE true
|
||||
|
28
src/init.cpp
28
src/init.cpp
@ -10,6 +10,7 @@
|
||||
#include "init.h"
|
||||
#include "util.h"
|
||||
#include "ui_interface.h"
|
||||
#include "checkpointsync.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
@ -303,7 +304,8 @@ std::string HelpMessage()
|
||||
" -datadir=<dir> " + _("Specify data directory") + "\n" +
|
||||
" -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n" +
|
||||
" -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n" +
|
||||
" -proxy=<ip:port> " + _("Connect through socks proxy") + "\n" +
|
||||
" -proxy=<ip:port> " + _("Exclusively connect through socks proxy") + "\n" +
|
||||
" -proxytoo=<ip:port> " + _("Also connect through socks proxy") + "\n" +
|
||||
" -socks=<n> " + _("Select the version of socks proxy to use (4-5, default: 5)") + "\n" +
|
||||
" -tor=<ip:port> " + _("Use proxy to reach tor hidden services (default: same as -proxy)") + "\n"
|
||||
" -dns " + _("Allow DNS lookups for -addnode, -seednode and -connect") + "\n" +
|
||||
@ -315,6 +317,7 @@ std::string HelpMessage()
|
||||
" -externalip=<ip> " + _("Specify your own public address") + "\n" +
|
||||
" -onlynet=<net> " + _("Only connect to nodes in network <net> (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=<addr> " + _("Bind to given address and always listen on it. Use [host]:port notation for IPv6") + "\n" +
|
||||
@ -634,6 +637,12 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
return InitError(strprintf(_("Invalid amount for -mininput=<amount>: '%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();
|
||||
@ -780,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);
|
||||
|
343
src/main.cpp
343
src/main.cpp
@ -11,6 +11,7 @@
|
||||
#include "init.h"
|
||||
#include "ui_interface.h"
|
||||
#include "checkqueue.h"
|
||||
#include "checkpointsync.h"
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
@ -46,6 +47,7 @@ uint256 hashBestChain = 0;
|
||||
CBlockIndex* pindexBest = NULL;
|
||||
set<CBlockIndex*, CBlockIndexWorkComparator> 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;
|
||||
@ -59,6 +61,7 @@ CDarkSendPool darkSendPool;
|
||||
CDarkSendSigner darkSendSigner;
|
||||
std::vector<CMasterNode> darkSendMasterNodes;
|
||||
std::vector<CMasterNodeVote> darkSendMasterNodeVotes;
|
||||
int64 enforceMasternodePaymentsTime = 4085657524;
|
||||
|
||||
|
||||
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
|
||||
@ -302,7 +305,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 +1048,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 +1176,7 @@ int CMerkleTx::GetBlocksToMaturity() const
|
||||
{
|
||||
if (!IsCoinBase())
|
||||
return 0;
|
||||
|
||||
return max(0, (COINBASE_MATURITY+20) - GetDepthInMainChain());
|
||||
}
|
||||
|
||||
@ -1801,15 +1805,37 @@ void CBlockHeader::UpdateTime(const CBlockIndex* pindexPrev)
|
||||
nBits = GetNextWorkRequired(pindexPrev, this);
|
||||
}
|
||||
|
||||
uint256 CBlockHeader::GetHash() const
|
||||
{
|
||||
return Hash9(BEGIN(nVersion), END(nNonce));
|
||||
}
|
||||
|
||||
uint256 CBlockHeader::GetSpecialHash() const
|
||||
{
|
||||
// calculate additional masternode vote info to include in hash
|
||||
uint256 hash = 0;
|
||||
uint256 vmnAdditional = 0;
|
||||
|
||||
//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,14 +2636,10 @@ 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)
|
||||
if(MasternodePayments && EnforceMasternodePayments)
|
||||
{
|
||||
LOCK2(cs_main, mempool.cs);
|
||||
|
||||
@ -2639,19 +2661,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,7 +2685,7 @@ 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) {
|
||||
@ -2704,12 +2729,13 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
std::string votes = boost::lexical_cast<std::string>(mv2.votes);
|
||||
|
||||
|
||||
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) {
|
||||
@ -2718,24 +2744,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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2837,10 +2872,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)
|
||||
@ -2893,6 +2927,9 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
|
||||
pnode->PushInventory(CInv(MSG_BLOCK, hash));
|
||||
}
|
||||
|
||||
// Check pending sync-checkpoint
|
||||
AcceptPendingSyncCheckpoint();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2926,22 +2963,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))
|
||||
@ -2955,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;
|
||||
}
|
||||
@ -2989,6 +3020,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;
|
||||
}
|
||||
|
||||
@ -3257,6 +3293,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);
|
||||
@ -3397,8 +3438,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);
|
||||
@ -3457,11 +3502,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;
|
||||
}
|
||||
|
||||
@ -3641,6 +3692,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 != "")
|
||||
{
|
||||
@ -3655,6 +3713,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);
|
||||
@ -3981,11 +4046,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());
|
||||
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);
|
||||
|
||||
if (!IsInitialBlockDownload())
|
||||
AskForPendingSyncCheckpoint(pfrom);
|
||||
}
|
||||
|
||||
|
||||
@ -4002,8 +4077,14 @@ 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", pfrom->id, howmuch);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -4021,7 +4102,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();
|
||||
@ -4102,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);
|
||||
@ -4118,7 +4200,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();
|
||||
@ -4132,15 +4214,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;
|
||||
}
|
||||
|
||||
@ -4236,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4274,12 +4358,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());
|
||||
}
|
||||
@ -4301,10 +4387,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);
|
||||
@ -4324,7 +4410,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)
|
||||
@ -4468,7 +4554,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());
|
||||
@ -4575,6 +4661,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;
|
||||
@ -4784,9 +4889,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
|
||||
@ -4917,7 +5027,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)
|
||||
{
|
||||
@ -5083,46 +5193,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5816,6 +5942,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;
|
||||
|
177
src/main.h
177
src/main.h
@ -36,13 +36,14 @@ 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 4085657524 //Fri, 20 Jun 2014 16:00:00 GMT
|
||||
#define START_MASTERNODE_PAYMENTS_TESTNET 1403568776 //Tue, 24 Jun 2014 00:12:56 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
|
||||
#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;
|
||||
@ -120,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;
|
||||
@ -127,7 +129,9 @@ extern CDarkSendSigner darkSendSigner;
|
||||
extern std::vector<CMasterNode> darkSendMasterNodes;
|
||||
extern std::vector<CMasterNodeVote> darkSendMasterNodeVotes;
|
||||
extern std::string strMasterNodePrivKey;
|
||||
extern int64 enforceMasternodePaymentsTime;
|
||||
extern CWallet pmainWallet;
|
||||
extern std::map<uint256, CBlock*> mapOrphanBlocks;
|
||||
|
||||
// Settings
|
||||
extern int64 nTransactionFee;
|
||||
@ -1304,6 +1308,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 +1398,8 @@ public:
|
||||
unsigned int nTime;
|
||||
unsigned int nBits;
|
||||
unsigned int nNonce;
|
||||
unsigned int vmnAdditional;
|
||||
std::vector<CMasterNodeVote> vmn;
|
||||
|
||||
CBlockHeader()
|
||||
{
|
||||
@ -1354,10 +1432,9 @@ public:
|
||||
return (nBits == 0);
|
||||
}
|
||||
|
||||
uint256 GetHash() const
|
||||
{
|
||||
return Hash9(BEGIN(nVersion), END(nNonce));
|
||||
}
|
||||
//special has includes voting info in the hash
|
||||
uint256 GetSpecialHash() const;
|
||||
uint256 GetHash() const;
|
||||
|
||||
int64 GetBlockTime() const
|
||||
{
|
||||
@ -1372,7 +1449,6 @@ class CBlock : public CBlockHeader
|
||||
public:
|
||||
// network and disk
|
||||
std::vector<CTransaction> vtx;
|
||||
std::vector<CMasterNodeVote> vmn;
|
||||
|
||||
// memory only
|
||||
mutable CScript payee;
|
||||
@ -1393,19 +1469,12 @@ 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()
|
||||
{
|
||||
CBlockHeader::SetNull();
|
||||
vtx.clear();
|
||||
vmn.clear();
|
||||
vMerkleTree.clear();
|
||||
payee = CScript();
|
||||
}
|
||||
@ -1583,9 +1652,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 +1661,13 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MasterNodePaymentsEnforcing() const
|
||||
{
|
||||
if(nTime > enforceMasternodePaymentsTime) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -2346,74 +2421,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:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = -
|
||||
|
@ -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
|
||||
|
||||
|
15
src/net.cpp
15
src/net.cpp
@ -69,6 +69,9 @@ CCriticalSection cs_setservAddNodeAddresses;
|
||||
vector<std::string> vAddedNodes;
|
||||
CCriticalSection cs_vAddedNodes;
|
||||
|
||||
NodeId nLastNodeId = 0;
|
||||
CCriticalSection cs_nLastNodeId;
|
||||
|
||||
static CSemaphore *semOutbound = NULL;
|
||||
|
||||
void AddOneShot(string strDest)
|
||||
@ -82,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
|
||||
@ -471,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;
|
||||
@ -544,7 +548,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<string>()), nBestHeight);
|
||||
}
|
||||
@ -586,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
|
||||
|
17
src/net.h
17
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<CInv, int64> mapAlreadyAskedFor;
|
||||
extern std::vector<std::string> vAddedNodes;
|
||||
extern CCriticalSection cs_vAddedNodes;
|
||||
|
||||
|
||||
extern NodeId nLastNodeId;
|
||||
extern CCriticalSection cs_nLastNodeId;
|
||||
|
||||
|
||||
class CNodeStats
|
||||
@ -191,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
|
||||
@ -200,6 +204,7 @@ public:
|
||||
CCriticalSection cs_filter;
|
||||
CBloomFilter* pfilter;
|
||||
int nRefCount;
|
||||
NodeId id;
|
||||
protected:
|
||||
|
||||
// Denial-of-service detection/prevention
|
||||
@ -220,6 +225,7 @@ public:
|
||||
std::set<CAddress> setAddrKnown;
|
||||
bool fGetAddr;
|
||||
std::set<uint256> setKnown;
|
||||
uint256 hashCheckpointKnown;
|
||||
|
||||
// inventory based relay
|
||||
mruset<CInv> setInventoryKnown;
|
||||
@ -249,6 +255,8 @@ public:
|
||||
fNetworkNode = false;
|
||||
fSuccessfullyConnected = false;
|
||||
fDisconnect = false;
|
||||
hashCheckpointKnown = 0;
|
||||
fAskedForBlocks = false;
|
||||
nRefCount = 0;
|
||||
nSendSize = 0;
|
||||
nSendOffset = 0;
|
||||
@ -263,6 +271,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();
|
||||
@ -608,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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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("<br>") + 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("<br>") + tr("Copyright") + QString(" © ") + tr("%1 The DarkCoin developers").arg(ABOUTDIALOG_COPYRIGHT_YEAR) + QString("<br>") + tr("Copyright") + QString(" © 2012-%1 ").arg(COPYRIGHT_YEAR) + tr("The Peercoin developers"));
|
||||
}
|
||||
|
||||
void AboutDialog::setModel(ClientModel *model)
|
||||
|
@ -92,7 +92,8 @@
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Copyright &copy; 2009-YYYY The Bitcoin developers
|
||||
Copyright &copy; 2011-YYYY The DarkCoin developers</string>
|
||||
Copyright &copy; YYYY The DarkCoin developers
|
||||
Copyright &copy; 2012-YYYY The Peercoin developers</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::RichText</enum>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
20
src/txdb.cpp
20
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -31,7 +31,7 @@ static const int PROTOCOL_VERSION = 70018;
|
||||
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 = 70015;
|
||||
|
||||
// nTime field added to CAddress, starting with this version;
|
||||
// if possible, avoid requesting addresses nodes older than this
|
||||
|
Loading…
Reference in New Issue
Block a user