Primecoin: Synchronized checkpoint system with user consent
parent
c6955f4ca4
commit
ea4c132406
|
@ -279,8 +279,9 @@ SOURCES += src/qt/bitcoin.cpp \
|
|||
src/noui.cpp \
|
||||
src/leveldb.cpp \
|
||||
src/txdb.cpp \
|
||||
src/qt/splashscreen.cpp \
|
||||
src/prime.cpp \
|
||||
src/qt/splashscreen.cpp
|
||||
src/checkpointsync.cpp
|
||||
|
||||
RESOURCES += src/qt/bitcoin.qrc
|
||||
|
||||
|
|
|
@ -252,6 +252,9 @@ static const CRPCCommand vRPCCommands[] =
|
|||
{ "listsinceblock", &listsinceblock, false, false },
|
||||
{ "dumpprivkey", &dumpprivkey, true, false },
|
||||
{ "importprivkey", &importprivkey, false, false },
|
||||
{ "getcheckpoint", &getcheckpoint, true, false },
|
||||
{ "sendcheckpoint", &sendcheckpoint, true, false },
|
||||
{ "enforcecheckpoint", &enforcecheckpoint, true, false },
|
||||
{ "makekeypair", &makekeypair, true, false },
|
||||
{ "sendalert", &sendalert, true, false },
|
||||
{ "listunspent", &listunspent, false, false },
|
||||
|
@ -1173,6 +1176,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
|
|||
if (strMethod == "sendalert" && n > 4) ConvertTo<boost::int64_t>(params[4]);
|
||||
if (strMethod == "sendalert" && n > 5) ConvertTo<boost::int64_t>(params[5]);
|
||||
if (strMethod == "sendalert" && n > 6) ConvertTo<boost::int64_t>(params[6]);
|
||||
if (strMethod == "enforcecheckpoint" && n > 0) ConvertTo<bool>(params[0]);
|
||||
if (strMethod == "sendmany" && n > 1) ConvertTo<Object>(params[1]);
|
||||
if (strMethod == "sendmany" && n > 2) ConvertTo<boost::int64_t>(params[2]);
|
||||
if (strMethod == "addmultisigaddress" && n > 0) ConvertTo<boost::int64_t>(params[0]);
|
||||
|
|
|
@ -141,6 +141,9 @@ extern json_spirit::Value addnode(const json_spirit::Array& params, bool fHelp);
|
|||
extern json_spirit::Value getaddednodeinfo(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value makekeypair(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value sendalert(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 dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp
|
||||
extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Copyright (c) 2013 Primecoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
// Distributed under conditional MIT/X11 software license,
|
||||
// see the accompanying file COPYING
|
||||
|
||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||
#include <boost/foreach.hpp>
|
||||
|
@ -133,4 +133,10 @@ namespace Checkpoints
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint256 GetLatestHardenedCheckpoint()
|
||||
{
|
||||
const MapCheckpoints& checkpoints = *Checkpoints().mapCheckpoints;
|
||||
return (checkpoints.rbegin()->second);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@ namespace Checkpoints
|
|||
// Returns last CBlockIndex* in mapBlockIndex that is a checkpoint
|
||||
CBlockIndex* GetLastCheckpoint(const std::map<uint256, CBlockIndex*>& mapBlockIndex);
|
||||
|
||||
// Returns the block hash of latest hardened checkpoint
|
||||
uint256 GetLatestHardenedCheckpoint();
|
||||
|
||||
double GuessVerificationProgress(CBlockIndex *pindex);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,531 @@
|
|||
// 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;
|
||||
|
||||
|
||||
// ppcoin: sync-checkpoint master key
|
||||
const std::string CSyncCheckpoint::strMasterPubKey = "04c0c1815811b4fd1bbb74f6e7519f8a9fc01f8e714d8c6191faaeb9dde48c09163a7236cdd42d96db391736ae04e04cb229dd9958b0e2e63399cadc7526256b3b";
|
||||
|
||||
std::string CSyncCheckpoint::strMasterPrivKey = "";
|
||||
|
||||
|
||||
// ppcoin: synchronized checkpoint (centrally broadcasted)
|
||||
uint256 hashSyncCheckpoint = 0;
|
||||
uint256 hashPendingCheckpoint = 0;
|
||||
CSyncCheckpoint checkpointMessage;
|
||||
CSyncCheckpoint checkpointMessagePending;
|
||||
uint256 hashInvalidCheckpoint = 0;
|
||||
CCriticalSection cs_hashSyncCheckpoint;
|
||||
std::string strCheckpointWarning;
|
||||
|
||||
// ppcoin: 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;
|
||||
}
|
||||
|
||||
// ppcoin: 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 AcceptPendingSyncCheckpoint()
|
||||
{
|
||||
LOCK(cs_hashSyncCheckpoint);
|
||||
if (hashPendingCheckpoint != 0 && mapBlockIndex.count(hashPendingCheckpoint))
|
||||
{
|
||||
if (!ValidateSyncCheckpoint(hashPendingCheckpoint))
|
||||
{
|
||||
hashPendingCheckpoint = 0;
|
||||
checkpointMessagePending.SetNull();
|
||||
return false;
|
||||
}
|
||||
|
||||
CBlockIndex* pindexCheckpoint = mapBlockIndex[hashPendingCheckpoint];
|
||||
if (!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;
|
||||
}
|
||||
|
||||
// ppcoin: reset synchronized checkpoint to last hardened checkpoint
|
||||
bool ResetSyncCheckpoint()
|
||||
{
|
||||
LOCK(cs_hashSyncCheckpoint);
|
||||
const 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 if(!mapBlockIndex.count(hash))
|
||||
{
|
||||
// checkpoint block not yet accepted
|
||||
hashPendingCheckpoint = hash;
|
||||
checkpointMessagePending.SetNull();
|
||||
printf("ResetSyncCheckpoint: pending for sync-checkpoint %s\n", hashPendingCheckpoint.ToString().c_str());
|
||||
}
|
||||
|
||||
if (!WriteSyncCheckpoint((mapBlockIndex.count(hash) && mapBlockIndex[hash]->IsInMainChain())? hash : hashGenesisBlock))
|
||||
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 = "";
|
||||
if (!pblocktree->ReadCheckpointPubKey(strPubKey) || strPubKey != CSyncCheckpoint::strMasterPubKey)
|
||||
{
|
||||
// write checkpoint master key to db
|
||||
if (!pblocktree->WriteCheckpointPubKey(CSyncCheckpoint::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;
|
||||
bool fCompressed;
|
||||
CSecret secret = vchSecret.GetSecret(fCompressed);
|
||||
key.SetSecret(secret, fCompressed); // 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;
|
||||
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;
|
||||
bool fCompressed;
|
||||
CSecret secret = vchSecret.GetSecret(fCompressed);
|
||||
key.SetSecret(secret, fCompressed); // 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());
|
||||
}
|
||||
|
||||
// ppcoin: 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;
|
||||
}
|
||||
|
||||
// ppcoin: verify signature of sync-checkpoint message
|
||||
bool CSyncCheckpoint::CheckSignature()
|
||||
{
|
||||
CKey key;
|
||||
if (!key.SetPubKey(ParseHex(CSyncCheckpoint::strMasterPubKey)))
|
||||
return error("CSyncCheckpoint::CheckSignature() : SetPubKey failed");
|
||||
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;
|
||||
}
|
||||
|
||||
// ppcoin: 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 (!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", (GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey")? "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", (GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey")? "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() != 1)
|
||||
throw runtime_error(
|
||||
"enforcecheckpoint <enforce>\n"
|
||||
"<enforce> is true or false to enable or disable enforcement of broadcasted checkpoints by developer.");
|
||||
|
||||
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");
|
||||
return Value::null;
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
// Copyright (c) 2011-2013 PPCoin developers
|
||||
// Copyright (c) 2013 Primecoin developers
|
||||
// Distributed under conditional MIT/X11 open source software license
|
||||
// see the accompanying file COPYING
|
||||
#ifndef PRIMECOIN_CHECKPOINTSYNC_H
|
||||
#define PRIMECOIN_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 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
|
||||
|
||||
IMPLEMENT_SERIALIZE
|
||||
(
|
||||
READWRITE(this->nVersion);
|
||||
nVersion = this->nVersion;
|
||||
READWRITE(hashCheckpoint);
|
||||
)
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
hashCheckpoint = 0;
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return strprintf(
|
||||
"CSyncCheckpoint(\n"
|
||||
" nVersion = %d\n"
|
||||
" hashCheckpoint = %s\n"
|
||||
")\n",
|
||||
nVersion,
|
||||
hashCheckpoint.ToString().c_str());
|
||||
}
|
||||
|
||||
void print() const
|
||||
{
|
||||
printf("%s", ToString().c_str());
|
||||
}
|
||||
};
|
||||
|
||||
class CSyncCheckpoint : public CUnsignedSyncCheckpoint
|
||||
{
|
||||
public:
|
||||
static const std::string strMasterPubKey;
|
||||
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
|
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Copyright (c) 2011-2013 PPCoin developers
|
||||
// Copyright (c) 2013 Primecoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
@ -11,6 +12,7 @@
|
|||
#include "init.h"
|
||||
#include "util.h"
|
||||
#include "ui_interface.h"
|
||||
#include "checkpointsync.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
@ -618,6 +620,12 @@ bool AppInit2(boost::thread_group& threadGroup)
|
|||
InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
|
||||
}
|
||||
|
||||
if (mapArgs.count("-checkpointkey")) // ppcoin: 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();
|
||||
|
|
88
src/main.cpp
88
src/main.cpp
|
@ -1,8 +1,9 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Copyright (c) 2013 The Primecoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
// Copyright (c) 2011-2013 PPCoin developers
|
||||
// Copyright (c) 2013 Primecoin developers
|
||||
// Distributed under conditional MIT/X11 software license,
|
||||
// see the accompanying file COPYING
|
||||
|
||||
#include "alert.h"
|
||||
#include "checkpoints.h"
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include "ui_interface.h"
|
||||
#include "checkqueue.h"
|
||||
#include "prime.h"
|
||||
#include "checkpointsync.h"
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
@ -1860,6 +1862,14 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
|||
strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
|
||||
}
|
||||
|
||||
if (!(GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey"))) // checkpoint advisory mode
|
||||
{
|
||||
if (pindexBest->pprev && !CheckSyncCheckpoint(pindexBest->GetBlockHash(), pindexBest->pprev))
|
||||
strCheckpointWarning = _("Warning: checkpoint on different blockchain fork, contact developers to resolve the issue");
|
||||
else
|
||||
strCheckpointWarning = "";
|
||||
}
|
||||
|
||||
std::string strCmd = GetArg("-blocknotify", "");
|
||||
|
||||
if (!fIsInitialDownload && !strCmd.empty())
|
||||
|
@ -2129,6 +2139,11 @@ 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));
|
||||
|
||||
// ppcoin: check that the block satisfies synchronized checkpoint
|
||||
if ((GetBoolArg("-checkpointenforce", false) || mapArgs.count("-checkpointkey")) // checkpoint enforce mode
|
||||
&& !CheckSyncCheckpoint(hash, pindexPrev))
|
||||
return error("AcceptBlock() : rejected by synchronized checkpoint");
|
||||
|
||||
// Primecoin: block version starts from 2
|
||||
if (nVersion < 2)
|
||||
return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"));
|
||||
|
@ -2173,6 +2188,9 @@ bool CBlock::AcceptBlock(CValidationState &state, CDiskBlockPos *dbp)
|
|||
pnode->PushInventory(CInv(MSG_BLOCK, hash));
|
||||
}
|
||||
|
||||
// ppcoin: check pending sync-checkpoint
|
||||
AcceptPendingSyncCheckpoint();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2232,6 +2250,9 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
|||
}
|
||||
}
|
||||
|
||||
// ppcoin: 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))
|
||||
|
@ -2276,6 +2297,12 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
|||
}
|
||||
|
||||
printf("ProcessBlock: ACCEPTED\n");
|
||||
|
||||
// ppcoin: if responsible for sync-checkpoint send it
|
||||
if (pfrom && !CSyncCheckpoint::strMasterPrivKey.empty() &&
|
||||
(int)GetArg("-checkpointdepth", -1) >= 0)
|
||||
SendSyncCheckpoint(AutoSelectSyncCheckpoint());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2547,6 +2574,12 @@ bool static LoadBlockIndexDB()
|
|||
if (pblocktree->ReadBlockFileInfo(nLastBlockFile, infoLastBlockFile))
|
||||
printf("LoadBlockIndexDB(): last block file info: %s\n", infoLastBlockFile.ToString().c_str());
|
||||
|
||||
// ppcoin: load hashSyncCheckpoint
|
||||
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);
|
||||
|
@ -2758,11 +2791,19 @@ bool InitBlockIndex() {
|
|||
return error("LoadBlockIndex() : writing genesis block to disk failed");
|
||||
if (!block.AddToBlockIndex(state, blockPos))
|
||||
return error("LoadBlockIndex() : genesis block not accepted");
|
||||
|
||||
// ppcoin: initialize synchronized checkpoint
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
// ppcoin: if checkpoint master key changed must reset sync-checkpoint
|
||||
if (!CheckCheckpointPubKey())
|
||||
return error("LoadBlockIndex() : failed to reset checkpoint master pubkey");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2939,6 +2980,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 != "")
|
||||
{
|
||||
|
@ -2953,6 +3001,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.");
|
||||
}
|
||||
|
||||
// ppcoin: 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);
|
||||
|
@ -3236,11 +3291,22 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
item.second.RelayTo(pfrom);
|
||||
}
|
||||
|
||||
// ppcoin: relay sync-checkpoint
|
||||
{
|
||||
LOCK(cs_hashSyncCheckpoint);
|
||||
if (!checkpointMessage.IsNull())
|
||||
checkpointMessage.RelayTo(pfrom);
|
||||
}
|
||||
|
||||
pfrom->fSuccessfullyConnected = true;
|
||||
|
||||
printf("receive version message: version %d, blocks=%d, us=%s, them=%s, peer=%s\n", pfrom->nVersion, pfrom->nStartingHeight, addrMe.ToString().c_str(), addrFrom.ToString().c_str(), pfrom->addr.ToString().c_str());
|
||||
|
||||
cPeerBlockCounts.input(pfrom->nStartingHeight);
|
||||
|
||||
// ppcoin: ask for pending sync-checkpoint if any
|
||||
if (!IsInitialBlockDownload())
|
||||
AskForPendingSyncCheckpoint(pfrom);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3638,6 +3704,22 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
|||
}
|
||||
|
||||
|
||||
else if (strCommand == "checkpoint") // ppcoin synchronized checkpoint
|
||||
{
|
||||
CSyncCheckpoint checkpoint;
|
||||
vRecv >> checkpoint;
|
||||
|
||||
if (checkpoint.ProcessSyncCheckpoint(pfrom))
|
||||
{
|
||||
// Relay
|
||||
pfrom->hashCheckpointKnown = checkpoint.hashCheckpoint;
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
checkpoint.RelayTo(pnode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == "filterload")
|
||||
{
|
||||
CBloomFilter filter;
|
||||
|
|
|
@ -89,6 +89,7 @@ extern int64 nHPSTimerStart;
|
|||
extern int64 nTimeBestReceived;
|
||||
extern CCriticalSection cs_setpwalletRegistered;
|
||||
extern std::set<CWallet*> setpwalletRegistered;
|
||||
extern std::map<uint256, CBlock*> mapOrphanBlocks;
|
||||
extern unsigned char pchMessageStart[4];
|
||||
extern bool fImporting;
|
||||
extern bool fReindex;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
# Copyright (c) 2013 Primecoin Developers
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
# Distributed under the conditional MIT/X11 software license,
|
||||
# see the accompanying file COPYING
|
||||
|
||||
DEPSDIR:=/usr/i586-mingw32msvc
|
||||
|
||||
|
@ -93,7 +93,8 @@ OBJS= \
|
|||
obj/bloom.o \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/prime.o
|
||||
obj/prime.o \
|
||||
obj/checkpointsync.o
|
||||
|
||||
all: primecoind.exe
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
# Copyright (c) 2013 Primecoin Developers
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
# Distributed under the conditional MIT/X11 software license,
|
||||
# see the accompanying file COPYING.
|
||||
|
||||
# Makefile for the MinGW g++ compiler/toolchain
|
||||
#
|
||||
|
@ -101,7 +101,8 @@ OBJS= \
|
|||
obj/noui.o \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/prime.o
|
||||
obj/prime.o \
|
||||
obj/checkpointsync.o
|
||||
|
||||
|
||||
all: primecoind.exe
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# -*- mode: Makefile; -*-
|
||||
# Copyright (c) 2011 Bitcoin Developers
|
||||
# Copyright (c) 2013 Primecoin Developers
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
# Distributed under conditional MIT/X11 software license,
|
||||
# see the accompanying file COPYING.
|
||||
|
||||
# Mac OS X makefile for bitcoin
|
||||
# Originally by Laszlo Hanyecz (solar@heliacal.net)
|
||||
|
@ -104,7 +104,8 @@ OBJS= \
|
|||
obj/noui.o \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/prime.o
|
||||
obj/prime.o \
|
||||
obj/checkpointsync.o
|
||||
|
||||
ifndef USE_UPNP
|
||||
override USE_UPNP = -
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
# Distributed under the MIT/X11 software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
# Copyright (c) 2013 Primecoind developers
|
||||
# Distributed under conditional MIT/X11 software license,
|
||||
# see the accompanying file COPYING
|
||||
|
||||
# :=0 --> UPnP support turned off by default at runtime
|
||||
# :=1 --> UPnP support turned on by default at runtime
|
||||
|
@ -142,8 +143,8 @@ OBJS= \
|
|||
obj/noui.o \
|
||||
obj/leveldb.o \
|
||||
obj/txdb.o \
|
||||
obj/prime.o
|
||||
|
||||
obj/prime.o \
|
||||
obj/checkpointsync.o
|
||||
|
||||
all: primecoind
|
||||
|
||||
|
|
|
@ -213,6 +213,7 @@ public:
|
|||
std::set<CAddress> setAddrKnown;
|
||||
bool fGetAddr;
|
||||
std::set<uint256> setKnown;
|
||||
uint256 hashCheckpointKnown; // ppcoin: known sent sync-checkpoint
|
||||
|
||||
// inventory based relay
|
||||
mruset<CInv> setInventoryKnown;
|
||||
|
@ -251,6 +252,7 @@ public:
|
|||
fStartSync = false;
|
||||
fGetAddr = false;
|
||||
nMisbehavior = 0;
|
||||
hashCheckpointKnown = 0;
|
||||
fRelayTxes = false;
|
||||
setInventoryKnown.max_size(SendBufferSize() / 1000);
|
||||
pfilter = NULL;
|
||||
|
|
22
src/txdb.cpp
22
src/txdb.cpp
|
@ -1,5 +1,6 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Copyright (c) 2011-2013 PPCoin developers
|
||||
// Copyright (c) 2013 The Primecoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
@ -245,3 +246,24 @@ 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);
|
||||
}
|
||||
|
||||
|
|
12
src/txdb.h
12
src/txdb.h
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
// Copyright (c) 2011-2013 PPCoin developers
|
||||
// Copyright (c) 2013 Primecoin developers
|
||||
// Distributed under conditional MIT/X11 software license,
|
||||
// see the accompanying file COPYING.
|
||||
#ifndef BITCOIN_TXDB_LEVELDB_H
|
||||
#define BITCOIN_TXDB_LEVELDB_H
|
||||
|
||||
|
@ -48,6 +50,12 @@ public:
|
|||
bool WriteFlag(const std::string &name, bool fValue);
|
||||
bool ReadFlag(const std::string &name, bool &fValue);
|
||||
bool LoadBlockIndexGuts();
|
||||
|
||||
// ppcoin sync checkpoint related data
|
||||
bool ReadSyncCheckpoint(uint256& hashCheckpoint);
|
||||
bool WriteSyncCheckpoint(uint256 hashCheckpoint);
|
||||
bool ReadCheckpointPubKey(std::string& strPubKey);
|
||||
bool WriteCheckpointPubKey(const std::string& strPubKey);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_TXDB_LEVELDB_H
|
||||
|
|
Loading…
Reference in New Issue