mirror of
https://github.com/dashpay/dash.git
synced 2024-12-29 13:59:06 +01:00
removed checkpointer
This commit is contained in:
parent
c4fec291ed
commit
9930f5ff21
526
src/checkpointsync.cpp
Normal file
526
src/checkpointsync.cpp
Normal file
@ -0,0 +1,526 @@
|
||||
// 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;
|
||||
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() != 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;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define CLIENT_VERSION_MAJOR 0
|
||||
#define CLIENT_VERSION_MINOR 10
|
||||
#define CLIENT_VERSION_REVISION 9
|
||||
#define CLIENT_VERSION_BUILD 0
|
||||
#define CLIENT_VERSION_BUILD 11
|
||||
|
||||
// Set to true for release, false for prerelease or test build
|
||||
#define CLIENT_VERSION_IS_RELEASE true
|
||||
|
@ -1125,6 +1125,8 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||
return InitError(_("Invalid masternodeprivkey. Please see documenation."));
|
||||
}
|
||||
|
||||
darkSendPool.pubkeyMasterNode2 = pubkey;
|
||||
|
||||
} else {
|
||||
return InitError(_("You must specific a masternodeprivkey in the configuration. Please see documentation for help."));
|
||||
}
|
||||
|
170
src/main.cpp
170
src/main.cpp
@ -237,7 +237,6 @@ bool CCoinsViewCache::SetCoins(const uint256 &txid, const CCoins &coins) {
|
||||
}
|
||||
|
||||
bool CCoinsViewCache::HaveCoins(const uint256 &txid) {
|
||||
|
||||
return FetchCoins(txid) != cacheCoins.end();
|
||||
}
|
||||
|
||||
@ -1026,6 +1025,7 @@ bool CTransaction::AcceptableInputs(CValidationState &state, bool fLimitFree)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int GetInputAge(CTxIn& vin)
|
||||
{
|
||||
// Fetch previous transactions (inputs):
|
||||
@ -1048,6 +1048,7 @@ int GetInputAge(CTxIn& vin)
|
||||
return pindexBest->nHeight - coins.nHeight;
|
||||
}
|
||||
|
||||
|
||||
bool CTxMemPool::addUnchecked(const uint256& hash, const CTransaction &tx)
|
||||
{
|
||||
// Add to memory pool without checking anything. Don't call this directly,
|
||||
@ -1343,7 +1344,7 @@ int64 static GetBlockValue(int nBits, int nHeight, int64 nFees)
|
||||
if (nSubsidy < 1) nSubsidy = 1;
|
||||
}
|
||||
|
||||
//printf("height %u diff %4.2f reward %i \n", nHeight, dDiff, nSubsidy);
|
||||
// printf("height %u diff %4.2f reward %i \n", nHeight, dDiff, nSubsidy);
|
||||
nSubsidy *= COIN;
|
||||
|
||||
// yearly decline of production by 7% per year, projected 21.3M coins max by year 2050.
|
||||
@ -2624,7 +2625,7 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
if(fTestNet){
|
||||
if(nTime > START_MASTERNODE_PAYMENTS_TESTNET) MasternodePayments = true;
|
||||
} else {
|
||||
if(nTime > START_MASTERNODE_PAYMENTS && nTime < START_MASTERNODE_PAYMENTS_STOP) MasternodePayments = true;
|
||||
if(nTime > START_MASTERNODE_PAYMENTS) MasternodePayments = true;
|
||||
}
|
||||
|
||||
if(MasternodePayments)
|
||||
@ -2637,11 +2638,10 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
int votingRecordsBlockPrev = 0;
|
||||
int matchingVoteRecords = 0;
|
||||
int badVote = 0;
|
||||
int foundMasterNodePaymentPrev = 0;
|
||||
int foundMasterNodePayment = 0;
|
||||
int removedMasterNodePayments = 0;
|
||||
|
||||
int64 masternodePaymentAmount = vtx[0].GetValueOut()/10;
|
||||
int64 masternodePaymentAmount = vtx[0].GetValueOut()/5;
|
||||
bool fIsInitialDownload = IsInitialBlockDownload();
|
||||
|
||||
if (pindexPrev != NULL && fCheckVotes && !fIsInitialDownload){
|
||||
@ -2652,14 +2652,8 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
return state.DoS(100, error("CheckBlock() : hashBestChain != pindexPrev->GetBlockHash()"));
|
||||
}
|
||||
|
||||
if(hashPrevBlock != pindexPrev->GetBlockHash()){
|
||||
printf ("CheckBlock() : hashPrevBlock != pindexPrev->GetBlockHash() : %s != %s\n", hashPrevBlock.ToString().c_str(), pindexPrev->GetBlockHash().ToString().c_str());
|
||||
return state.DoS(100, error("CheckBlock() : pblock->hashPrevBlock != blockLast->GetBlockHash()"));
|
||||
}
|
||||
|
||||
|
||||
printf ("CheckBlock() : nHeight : %d\n", pindexPrev->nHeight);
|
||||
printf ("CheckBlock() : hashPrevBlock : %s\n", hashPrevBlock);
|
||||
printf ("CheckBlock() : hashBestChain : %s\n", hashBestChain.ToString().c_str());
|
||||
printf ("CheckBlock() : pindexPrev->GetBlockHash() : %s\n", pindexPrev->GetBlockHash().ToString().c_str());
|
||||
|
||||
votingRecordsBlockPrev = blockLast.vmn.size();
|
||||
@ -2668,17 +2662,19 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
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 && foundMasterNodePaymentPrev < MASTERNODE_PAYMENTS_MAX) {
|
||||
} else if(mv1.GetVotes() >= MASTERNODE_PAYMENTS_MIN_VOTES-1 && foundMasterNodePayment < MASTERNODE_PAYMENTS_MAX) {
|
||||
for (unsigned int i = 1; i < vtx[0].vout.size(); i++)
|
||||
if(vtx[0].vout[i].nValue == masternodePaymentAmount && mv1.GetPubKey() == vtx[0].vout[i].scriptPubKey)
|
||||
if(vtx[0].vout[i].nValue == masternodePaymentAmount && mv1.GetPubKey() == vtx[0].vout[i].scriptPubKey) {
|
||||
foundMasterNodePayment++;
|
||||
foundMasterNodePaymentPrev++;
|
||||
} else if(mv1.GetPubKey() == vtx[0].vout[i].scriptPubKey) {
|
||||
printf(" BAD MASTERNODE PAYMENT DETECTED: %"PRI64u" %s\n", vtx[0].vout[i].nValue);
|
||||
}
|
||||
} else {
|
||||
BOOST_FOREACH(CMasterNodeVote mv2, vmn){
|
||||
if((mv1.blockHeight == mv2.blockHeight && mv1.GetPubKey() == mv2.GetPubKey())){
|
||||
if((mv1.blockHeight == mv2.blockHeight && (mv1.GetVotes() == 1 || mv1.GetPubKey() == mv2.GetPubKey()))){
|
||||
matchingVoteRecords++;
|
||||
if(mv1.GetVotes() != mv2.GetVotes() && mv1.GetVotes()+1 != mv2.GetVotes()) {
|
||||
printf(" BAD VOTE DETECTED: %d %d\n", mv1.blockHeight, mv1.GetPubKey().ToString().c_str());
|
||||
printf(" BAD VOTE DETECTED: %"PRI64u" %s\n", mv1.blockHeight, mv1.GetPubKey().ToString().c_str());
|
||||
printf(" -- %d %d\n", mv1.GetVotes(), mv2.GetVotes());
|
||||
badVote++;
|
||||
}
|
||||
@ -2687,11 +2683,34 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
}
|
||||
}
|
||||
|
||||
printf ("CheckBlock(): votingRecordsBlockPrev %d\n", votingRecordsBlockPrev);
|
||||
printf ("CheckBlock(): matchingVoteRecords %d\n", matchingVoteRecords);
|
||||
printf ("CheckBlock(): badVote %d\n", badVote);\
|
||||
printf ("CheckBlock(): foundMasterNodePayment %d\n", foundMasterNodePayment);
|
||||
printf ("CheckBlock(): removedMasterNodePayments %d\n", removedMasterNodePayments);
|
||||
|
||||
|
||||
//find new votes, must be for this block height
|
||||
bool foundThisBlock = false;
|
||||
BOOST_FOREACH(CMasterNodeVote mv2, vmn){
|
||||
printf("CheckBlock(): height %d %s\n", mv2.blockHeight, mv2.GetPubKey().ToString().c_str());
|
||||
std::string blockHeight = boost::lexical_cast<std::string>(mv2.blockHeight);
|
||||
|
||||
CScript pubkey;
|
||||
pubkey.SetDestination(mv2.pubkey.GetID());
|
||||
CTxDestination address1;
|
||||
ExtractDestination(pubkey, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
std::string addr = address2.ToString();
|
||||
|
||||
std::string votes = boost::lexical_cast<std::string>(mv2.votes);
|
||||
|
||||
|
||||
stringstream ss;
|
||||
ss << setw(10) << blockHeight << setw(40) << addr << setw(10) << votes;
|
||||
|
||||
printf("CheckBlock(): %s\n", ss.str().c_str());
|
||||
}
|
||||
|
||||
if(mv2.GetPubKey().size() != 25)
|
||||
return state.DoS(100, error("CheckBlock() : pubkey wrong size"));
|
||||
@ -2705,7 +2724,7 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
BOOST_FOREACH(CMasterNodeVote mv1, blockLast.vmn){
|
||||
printf("CheckBlock(): height2 %d %s\n", mv1.blockHeight, mv1.GetPubKey().ToString().c_str());
|
||||
|
||||
if((mv1.blockHeight == mv2.blockHeight && mv1.GetPubKey() == mv2.GetPubKey()))
|
||||
if((mv1.blockHeight == mv2.blockHeight && (mv1.GetVotes() == 1 || mv1.GetPubKey() == mv2.GetPubKey())))
|
||||
found = true;
|
||||
}
|
||||
|
||||
@ -2718,10 +2737,6 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
|
||||
if(badVote!=0)
|
||||
return state.DoS(100, error("CheckBlock() : Bad vote detected"));
|
||||
|
||||
if(foundMasterNodePayment!=foundMasterNodePaymentPrev) {
|
||||
return state.DoS(100, error("CheckBlock() : Required masternode payment missing"));
|
||||
}
|
||||
|
||||
if(matchingVoteRecords+foundMasterNodePayment+removedMasterNodePayments!=votingRecordsBlockPrev)
|
||||
return state.DoS(100, error("CheckBlock() : Missing masternode votes"));
|
||||
|
||||
@ -2982,6 +2997,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
||||
darkSendPool.NewBlock();
|
||||
|
||||
printf("ProcessBlock: ACCEPTED\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3251,6 +3267,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);
|
||||
@ -3642,6 +3663,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);
|
||||
@ -3700,6 +3728,7 @@ bool static AlreadyHave(const CInv& inv)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void static ProcessGetData(CNode* pfrom)
|
||||
{
|
||||
std::deque<CInv>::iterator it = pfrom->vRecvGetData.begin();
|
||||
@ -3858,6 +3887,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
nTimeLastPrintMessageStart = GetAdjustedTime();
|
||||
}
|
||||
|
||||
|
||||
if (strCommand == "version")
|
||||
{
|
||||
// Each connection can only send one version message
|
||||
@ -3979,6 +4009,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == "verack")
|
||||
{
|
||||
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
|
||||
@ -4106,7 +4137,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
printf("Sending master node entry - %s \n", mn.addr.ToString().c_str());
|
||||
mn.Check();
|
||||
if(mn.IsEnabled()) {
|
||||
pfrom->PushMessage("dsee", mn.vin, mn.addr, mn.sig, mn.now, mn.pubkey, mn.pubkey2, count, i);
|
||||
pfrom->PushMessage("dsee", mn.vin, mn.addr, mn.sig, mn.now, mn.pubkey, mn.pubkey2, count, i, mn.lastTimeSeen);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@ -4127,7 +4158,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
int64 sigTime;
|
||||
int count;
|
||||
int current;
|
||||
vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current;
|
||||
int64 lastUpdated;
|
||||
vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated;
|
||||
|
||||
std::string vchPubKey(pubkey.begin(), pubkey.end());
|
||||
|
||||
@ -4166,11 +4198,15 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
//printf(" -- %s\n", mn.vin.ToString().c_str());
|
||||
|
||||
if(mn.vin == vin) {
|
||||
if(!mn.UpdatedWithin(5*60*1000)){
|
||||
if(!mn.UpdatedWithin(MASTERNODE_MIN_MICROSECONDS)){
|
||||
mn.UpdateLastSeen();
|
||||
|
||||
if(pubkey2 == darkSendPool.pubkeyMasterNode2){
|
||||
darkSendPool.EnableHotColdMasterNode(vin, sigTime, addr);
|
||||
}
|
||||
|
||||
if(count == -1)
|
||||
RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current);
|
||||
RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -4193,13 +4229,16 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
CMasterNode mn(addr, vin, pubkey, vchSig, sigTime, pubkey2);
|
||||
mn.UpdateLastSeen();
|
||||
mn.UpdateLastSeen(lastUpdated);
|
||||
darkSendMasterNodes.push_back(mn);
|
||||
|
||||
if(pubkey2 == darkSendPool.pubkeyMasterNode2){
|
||||
darkSendPool.EnableHotColdMasterNode(vin, sigTime, addr);
|
||||
}
|
||||
|
||||
if(count == -1)
|
||||
RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current);
|
||||
RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated);
|
||||
|
||||
} else {
|
||||
printf("dsee - Rejected masternode entry\n");
|
||||
@ -4743,12 +4782,11 @@ bool ProcessMessages(CNode* pfrom)
|
||||
// (4) checksum
|
||||
// (x) data
|
||||
//
|
||||
bool fOk = true;
|
||||
|
||||
unsigned char pchMessageStart[4];
|
||||
GetMessageStart(pchMessageStart);
|
||||
|
||||
bool fOk = true;
|
||||
|
||||
if (!pfrom->vRecvGetData.empty())
|
||||
ProcessGetData(pfrom);
|
||||
|
||||
@ -5132,6 +5170,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
{
|
||||
// Create new block
|
||||
@ -5162,7 +5201,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
bMasterNodePayment = true;
|
||||
}
|
||||
}else{
|
||||
if (GetTimeMicros() > START_MASTERNODE_PAYMENTS && GetTimeMicros() < START_MASTERNODE_PAYMENTS_STOP ){
|
||||
if (GetTimeMicros() > START_MASTERNODE_PAYMENTS){
|
||||
bMasterNodePayment = true;
|
||||
}
|
||||
}
|
||||
@ -5187,6 +5226,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
mv1.Vote();
|
||||
break;
|
||||
}
|
||||
if((mv1.blockHeight == mv2.blockHeight && mv1.GetVotes() == 1)) {
|
||||
mv1.Set(mv2.GetPubKey(), mv2.GetHeight());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5422,12 +5465,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
printf("CreateNewBlock(): total size %"PRI64u"\n", nBlockSize);
|
||||
|
||||
int64 blockValue = GetBlockValue(pindexPrev->nBits, pindexPrev->nHeight, nFees);
|
||||
int64 blockValueTenth = blockValue/10;
|
||||
int64 blockValueFifth = blockValue/5;
|
||||
|
||||
for(int i = 1; i < payments; i++){
|
||||
printf("%d\n", i);
|
||||
pblock->vtx[0].vout[i].nValue = blockValueTenth;
|
||||
blockValue -= blockValueTenth;
|
||||
pblock->vtx[0].vout[i].nValue = blockValueFifth;
|
||||
blockValue -= blockValueFifth;
|
||||
}
|
||||
pblock->vtx[0].vout[0].nValue = blockValue;
|
||||
|
||||
@ -5456,6 +5499,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||
return pblocktemplate.release();
|
||||
}
|
||||
|
||||
|
||||
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
|
||||
{
|
||||
CPubKey pubkey;
|
||||
@ -6370,27 +6414,27 @@ bool CDarkSendPool::SubscribeToMasterNode()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDarkSendPool::EnableHotColdMasterNode(CTxIn& vin, int64 sigTime, CService& addr)
|
||||
{
|
||||
if(!fMasterNode) return false;
|
||||
|
||||
isCapableMasterNode = MASTERNODE_IS_CAPABLE;
|
||||
|
||||
vinMasterNode = vin;
|
||||
masterNodeSignatureTime = sigTime;
|
||||
masterNodeSignAddr = addr;
|
||||
|
||||
printf("CDarkSendPool::EnableHotColdMasterNode() - Enabled! You may shut down the cold daemon.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDarkSendPool::RegisterAsMasterNode(bool stop)
|
||||
{
|
||||
if(!fMasterNode) return;
|
||||
|
||||
// Choose coins to use
|
||||
CService addr;
|
||||
std::string errorMessage;
|
||||
|
||||
if(strMasterNodeAddr.empty()) {
|
||||
if(!GetLocal(addr)) return;
|
||||
} else {
|
||||
addr = CService(strMasterNodeAddr);
|
||||
}
|
||||
|
||||
if((fTestNet && addr.GetPort() != 19999) || (!fTestNet && addr.GetPort() != 9999)) {
|
||||
printf("CDarkSendPool::RegisterAsMasterNode() - Invalid port");
|
||||
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
CKey key2;
|
||||
CPubKey pubkey2;
|
||||
|
||||
@ -6407,6 +6451,18 @@ void CDarkSendPool::RegisterAsMasterNode(bool stop)
|
||||
}
|
||||
|
||||
if(isCapableMasterNode == MASTERNODE_NOT_PROCESSED) {
|
||||
if(strMasterNodeAddr.empty()) {
|
||||
if(!GetLocal(masterNodeSignAddr)) return;
|
||||
} else {
|
||||
masterNodeSignAddr = CService(strMasterNodeAddr);
|
||||
}
|
||||
|
||||
if((fTestNet && masterNodeSignAddr.GetPort() != 19999) || (!fTestNet && masterNodeSignAddr.GetPort() != 9999)) {
|
||||
printf("CDarkSendPool::RegisterAsMasterNode() - Invalid port");
|
||||
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if(pwalletMain->IsLocked()){
|
||||
return;
|
||||
}
|
||||
@ -6414,6 +6470,7 @@ void CDarkSendPool::RegisterAsMasterNode(bool stop)
|
||||
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
|
||||
|
||||
CKey SecretKey;
|
||||
// Choose coins to use
|
||||
if(GetMasterNodeVin(vinMasterNode, pubkeyMasterNode, SecretKey)) {
|
||||
|
||||
if(GetInputAge(vinMasterNode) < MASTERNODE_MIN_CONFIRMATIONS){
|
||||
@ -6425,7 +6482,7 @@ void CDarkSendPool::RegisterAsMasterNode(bool stop)
|
||||
masterNodeSignatureTime = GetTimeMicros();
|
||||
|
||||
std::string vchPubKey(pubkeyMasterNode.begin(), pubkeyMasterNode.end());
|
||||
std::string strMessage = addr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey;
|
||||
std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey;
|
||||
|
||||
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, SecretKey)) {
|
||||
printf("CDarkSendPool::RegisterAsMasterNode() - Sign message failed");
|
||||
@ -6449,14 +6506,14 @@ void CDarkSendPool::RegisterAsMasterNode(bool stop)
|
||||
found = true;
|
||||
|
||||
if(!found) {
|
||||
printf("CDarkSendPool::RegisterAsMasterNode() - Adding myself to masternode list %s - %s\n", addr.ToString().c_str(), vinMasterNode.ToString().c_str());
|
||||
CMasterNode mn(addr, vinMasterNode, pubkeyMasterNode, vchMasterNodeSignature, masterNodeSignatureTime, pubkey2);
|
||||
mn.UpdateLastSeen();
|
||||
printf("CDarkSendPool::RegisterAsMasterNode() - Adding myself to masternode list %s - %s\n", masterNodeSignAddr.ToString().c_str(), vinMasterNode.ToString().c_str());
|
||||
CMasterNode mn(masterNodeSignAddr, vinMasterNode, pubkeyMasterNode, vchMasterNodeSignature, masterNodeSignatureTime, pubkey2);
|
||||
mn.UpdateLastSeen(masterNodeSignatureTime);
|
||||
darkSendMasterNodes.push_back(mn);
|
||||
printf("CDarkSendPool::RegisterAsMasterNode() - Masternode input = %s\n", vinMasterNode.ToString().c_str());
|
||||
}
|
||||
|
||||
RelayDarkSendElectionEntry(vinMasterNode, addr, vchMasterNodeSignature, masterNodeSignatureTime, pubkeyMasterNode, pubkey2, -1, -1);
|
||||
RelayDarkSendElectionEntry(vinMasterNode, masterNodeSignAddr, vchMasterNodeSignature, masterNodeSignatureTime, pubkeyMasterNode, pubkey2, -1, -1, masterNodeSignatureTime);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -6466,7 +6523,7 @@ void CDarkSendPool::RegisterAsMasterNode(bool stop)
|
||||
|
||||
masterNodeSignatureTime = GetTimeMicros();
|
||||
|
||||
std::string strMessage = addr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + boost::lexical_cast<std::string>(stop);
|
||||
std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + boost::lexical_cast<std::string>(stop);
|
||||
|
||||
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) {
|
||||
printf("CDarkSendPool::RegisterAsMasterNode() - Sign message failed");
|
||||
@ -6678,6 +6735,7 @@ void CMasterNode::Check()
|
||||
|
||||
if(!tx.AcceptableInputs(state, true)) {
|
||||
enabled = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
enabled = 1; // OK
|
||||
|
57
src/main.h
57
src/main.h
@ -33,13 +33,35 @@ class CMasterNode;
|
||||
class CMasterNodeVote;
|
||||
class CBitcoinAddress;
|
||||
|
||||
#define MASTERNODE_PAYMENTS_MIN_VOTES 6
|
||||
#define MASTERNODE_PAYMENTS_MIN_VOTES 5
|
||||
#define MASTERNODE_PAYMENTS_MAX 1
|
||||
#define MASTERNODE_PAYMENTS_EXPIRATION 10
|
||||
#define START_MASTERNODE_PAYMENTS_TESTNET 1401757793
|
||||
#define START_MASTERNODE_PAYMENTS 1401033600 //Sun, 25 May 2014 16:00:00 GMT
|
||||
#define START_MASTERNODE_PAYMENTS_STOP 1401134533 // Mon, 26 May 2014 20:02:13 GMT
|
||||
|
||||
#define START_MASTERNODE_PAYMENTS_TESTNET 1401937744
|
||||
#define START_MASTERNODE_PAYMENTS 1403107200 //Wed, 18 Jun 2014 16:00:00 GMT
|
||||
|
||||
#define POOL_MAX_TRANSACTIONS 3 // wait for X transactions to merge and publish
|
||||
#define POOL_STATUS_UNKNOWN 0 // waiting for update
|
||||
#define POOL_STATUS_IDLE 1 // waiting for update
|
||||
#define POOL_STATUS_ACCEPTING_ENTRIES 2 // accepting entries
|
||||
#define POOL_STATUS_FINALIZE_TRANSACTION 3 // master node will broadcast what it accepted
|
||||
#define POOL_STATUS_SIGNING 4 // check inputs/outputs, sign final tx
|
||||
#define POOL_STATUS_TRANSMISSION 5 // transmit transaction
|
||||
#define POOL_STATUS_ERROR 6 // error
|
||||
#define POOL_STATUS_SUCCESS 7 // success
|
||||
|
||||
#define MASTERNODE_NOT_PROCESSED 0 // initial state
|
||||
#define MASTERNODE_IS_CAPABLE 1
|
||||
#define MASTERNODE_NOT_CAPABLE 2
|
||||
#define MASTERNODE_STOPPED 3
|
||||
#define MASTERNODE_INPUT_TOO_NEW 4
|
||||
|
||||
#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
|
||||
|
||||
|
||||
>>>>>>> 10bdae8... Stabilized masternodes and payments.
|
||||
struct CBlockIndexWorkComparator;
|
||||
|
||||
/** The maximum allowed size for a serialized block, in bytes (network rule) */
|
||||
@ -1394,7 +1416,7 @@ public:
|
||||
if(fTestNet){
|
||||
if(nTime > START_MASTERNODE_PAYMENTS_TESTNET) READWRITE(vmn);
|
||||
} else {
|
||||
if(nTime > START_MASTERNODE_PAYMENTS && nTime < START_MASTERNODE_PAYMENTS_STOP) READWRITE(vmn);
|
||||
if(nTime > START_MASTERNODE_PAYMENTS) READWRITE(vmn);
|
||||
}
|
||||
)
|
||||
|
||||
@ -1586,7 +1608,7 @@ public:
|
||||
if(fTestNet){
|
||||
if(nTime > START_MASTERNODE_PAYMENTS_TESTNET) return true;
|
||||
} else {
|
||||
if(nTime > START_MASTERNODE_PAYMENTS && nTime < START_MASTERNODE_PAYMENTS_STOP) return true;
|
||||
if(nTime > START_MASTERNODE_PAYMENTS) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -2441,17 +2463,22 @@ public:
|
||||
|
||||
uint256 CalculateScore(int mod=10);
|
||||
|
||||
void UpdateLastSeen()
|
||||
void UpdateLastSeen(int64 override=0)
|
||||
{
|
||||
lastTimeSeen = GetTimeMillis();
|
||||
if(override == 0){
|
||||
lastTimeSeen = GetTimeMicros();
|
||||
} else {
|
||||
lastTimeSeen = override;
|
||||
}
|
||||
}
|
||||
|
||||
void Check();
|
||||
|
||||
bool UpdatedWithin(int milliSeconds)
|
||||
bool UpdatedWithin(int microSeconds)
|
||||
{
|
||||
//printf("UpdatedWithin %"PRI64u"\n", GetTimeMillis() - lastTimeSeen);
|
||||
return GetTimeMillis() - lastTimeSeen < milliSeconds;
|
||||
//printf("UpdatedWithin %"PRI64u", %"PRI64u" -- %d \n", GetTimeMicros() , lastTimeSeen, (GetTimeMicros() - lastTimeSeen) < microSeconds);
|
||||
|
||||
return (GetTimeMicros() - lastTimeSeen) < microSeconds;
|
||||
}
|
||||
|
||||
void Disable()
|
||||
@ -2556,7 +2583,7 @@ static const int64 POOL_FEE_AMOUNT = 0.025*COIN;
|
||||
class CDarkSendPool
|
||||
{
|
||||
public:
|
||||
static const int MIN_PEER_PROTO_VERSION = 70015;
|
||||
static const int MIN_PEER_PROTO_VERSION = 70018;
|
||||
|
||||
std::vector<CDarkSendEntry> myEntries;
|
||||
std::vector<CDarkSendEntry> entries;
|
||||
@ -2573,12 +2600,15 @@ public:
|
||||
|
||||
CTxIn vinMasterNode;
|
||||
CPubKey pubkeyMasterNode;
|
||||
CPubKey pubkeyMasterNode2;
|
||||
|
||||
std::string strMasterNodeSignMessage;
|
||||
std::vector<unsigned char> vchMasterNodeSignature;
|
||||
|
||||
int isCapableMasterNode;
|
||||
uint256 masterNodeBlockHash;
|
||||
std::string masterNodeAddr;
|
||||
CService masterNodeSignAddr;
|
||||
int64 masterNodeSignatureTime;
|
||||
|
||||
std::string lastMessage;
|
||||
@ -2688,6 +2718,7 @@ public:
|
||||
|
||||
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
|
||||
void RelayDarkDeclareWinner();
|
||||
bool EnableHotColdMasterNode(CTxIn& vin, int64 sigTime, CService& addr);
|
||||
void RegisterAsMasterNode(bool stop);
|
||||
bool GetLastValidBlockHash(uint256& hash, int mod=10);
|
||||
void NewBlock();
|
||||
|
@ -21,7 +21,7 @@ LIBS = $(addprefix -L,$(BOOST_LIB_PATH) $(BDB_LIB_PATH) $(OPENSSL_LIB_PATH))
|
||||
TESTDEFS = -DTEST_DATA_DIR=$(abspath test/data)
|
||||
|
||||
STATIC = 1
|
||||
LMODE = dynamiic
|
||||
LMODE = dynamic
|
||||
LMODE2 = dynamic
|
||||
ifdef STATIC
|
||||
LMODE = static
|
||||
|
@ -409,7 +409,7 @@ void ThreadGetMyExternalIP(void* parg)
|
||||
if (GetMyExternalIP(addrLocalHost))
|
||||
{
|
||||
printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str());
|
||||
AddLocal(addrLocalHost, LOCAL_HTTP);
|
||||
AddLocal(addrLocalHost, LOCAL_HTTP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1956,12 +1956,12 @@ void RelayDarkSendStatus(const int newState, const int newEntriesCount, const in
|
||||
}
|
||||
}
|
||||
|
||||
void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current)
|
||||
void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated)
|
||||
{
|
||||
LOCK(cs_vNodes);
|
||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||
{
|
||||
pnode->PushMessage("dsee", vin, addr, vchSig, nNow, pubkey, pubkey2, count, current);
|
||||
pnode->PushMessage("dsee", vin, addr, vchSig, nNow, pubkey, pubkey2, count, current, lastUpdated);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -648,7 +648,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
|
||||
void RelayDarkSendFinalTransaction(const CTransaction& txNew);
|
||||
void RelayDarkSendIn(const CTxIn& in, const int64& nAmount, const CTransaction& txCollateral, const CTransaction& txSupporting, const CTxOut& out, const CTxOut& out2);
|
||||
void RelayDarkSendStatus(const int newState, const int newEntriesCount, const int newAccepted, const std::string error="");
|
||||
void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current);
|
||||
void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated);
|
||||
void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64 nNow, const bool stop);
|
||||
void RelayDarkSendCompletedTransaction(const bool error, const std::string errorMessage);
|
||||
void RelayDarkDeclareWinner();
|
||||
|
@ -104,16 +104,43 @@ Value masternode(const Array& params, bool fHelp)
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
if (strCommand == "list")
|
||||
if (strCommand == "list")
|
||||
{
|
||||
std::string strCommand = "active";
|
||||
|
||||
if (params.size() == 2){
|
||||
strCommand = params[1].get_str().c_str();
|
||||
}
|
||||
|
||||
if (strCommand != "active" && strCommand != "vin" && strCommand != "pubkey" && strCommand != "lastseen" && strCommand != "activeseconds"){
|
||||
throw runtime_error(
|
||||
"list supports 'active', 'vin', 'pubkey', 'lastseen', 'activeseconds'\n");
|
||||
}
|
||||
|
||||
Object obj;
|
||||
BOOST_FOREACH(CMasterNode mn, darkSendMasterNodes) {
|
||||
mn.Check();
|
||||
obj.push_back(Pair(mn.addr.ToString().c_str(), (int)mn.IsEnabled()));
|
||||
mn.Check();
|
||||
|
||||
if(strCommand == "active"){
|
||||
obj.push_back(Pair(mn.addr.ToString().c_str(), (int)mn.IsEnabled()));
|
||||
} else if (strCommand == "vin") {
|
||||
obj.push_back(Pair(mn.addr.ToString().c_str(), mn.vin.prevout.hash.ToString().c_str()));
|
||||
} else if (strCommand == "pubkey") {
|
||||
CScript pubkey;
|
||||
pubkey.SetDestination(mn.pubkey.GetID());
|
||||
CTxDestination address1;
|
||||
ExtractDestination(pubkey, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
obj.push_back(Pair(mn.addr.ToString().c_str(), address2.ToString().c_str()));
|
||||
} else if (strCommand == "lastseen") {
|
||||
obj.push_back(Pair(mn.addr.ToString().c_str(), (int64_t)mn.lastTimeSeen));
|
||||
} else if (strCommand == "activeseconds") {
|
||||
obj.push_back(Pair(mn.addr.ToString().c_str(), (int64_t)(mn.lastTimeSeen - mn.now)/(1000*1000)));
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
if (strCommand == "count") return (int)darkSendMasterNodes.size();
|
||||
|
||||
if (strCommand == "start")
|
||||
|
@ -25,7 +25,7 @@ extern const std::string CLIENT_DATE;
|
||||
// network protocol versioning
|
||||
//
|
||||
|
||||
static const int PROTOCOL_VERSION = 70015;
|
||||
static const int PROTOCOL_VERSION = 70018;
|
||||
|
||||
// intial proto version, to be increased after version/verack negotiation
|
||||
static const int INIT_PROTO_VERSION = 209;
|
||||
|
Loading…
Reference in New Issue
Block a user