Full Spork Implementation

Many sporks are supported at once, with efficient broadcasting
via inventory messages.
This commit is contained in:
Evan Duffield 2015-02-09 12:28:29 -07:00
parent 5dc643f9b0
commit 257078d2a4
11 changed files with 91 additions and 16 deletions

View File

@ -76,6 +76,7 @@ BITCOIN_CORE_H = \
sph_simd.h \
sph_skein.h \
sph_types.h \
spork.h \
sync.h \
threadsafety.h \
tinyformat.h \
@ -169,6 +170,7 @@ libdarkcoin_common_a_SOURCES = \
shavite.c \
keccak.c \
skein.c \
spork.cpp \
bmw.c \
simd.c \
cubehash.c \

View File

@ -2113,6 +2113,7 @@ bool CDarksendQueue::CheckSignature()
}
//TODO: Rename/move to core
void ThreadCheckDarkSendPool()
{
if(fLiteMode) return; //disable all darksend/masternode related functionality
@ -2178,6 +2179,7 @@ void ThreadCheckDarkSendPool()
pnode->PushMessage("dseg", CTxIn()); //request full mn list
pnode->PushMessage("mnget"); //sync payees
pnode->PushMessage("getsporks"); //get current network sporks
RequestedMasterNodeList++;
}
}

View File

@ -21,6 +21,7 @@
#include "ui_interface.h"
#include "util.h"
#include "activemasternode.h"
#include "spork.h"
#ifdef ENABLE_WALLET
#include "db.h"
#include "wallet.h"
@ -699,6 +700,8 @@ bool AppInit2(boost::thread_group& threadGroup)
{
if (!masternodePayments.SetPrivKey(GetArg("-masternodepaymentskey", "")))
return InitError(_("Unable to sign masternode payment winner, wrong key?"));
if (!sporkManager.SetPrivKey(GetArg("-masternodepaymentskey", "")))
return InitError(_("Unable to sign spork message, wrong key?"));
}
//ignore masternodes below protocol version

View File

@ -13,6 +13,7 @@
#include "masternode.h"
#include "activemasternode.h"
#include "darksend.h"
#include "spork.h"
#include <boost/lexical_cast.hpp>
using namespace std;
@ -35,6 +36,7 @@ int nCompleteTXLocks;
void ProcessMessageInstantX(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
{
if(fLiteMode) return; //disable all darksend/masternode related functionality
if(!IsSporkActive(SPORK_2_INSTANTX)) return;
if (strCommand == "txlreq")
{

View File

@ -20,6 +20,7 @@
#include "txmempool.h"
#include "ui_interface.h"
#include "util.h"
#include "spork.h"
#include <sstream>
@ -69,7 +70,6 @@ struct COrphanBlock {
};
map<uint256, COrphanBlock*> mapOrphanBlocks;
multimap<uint256, COrphanBlock*> mapOrphanBlocksByPrev;
bool fManyOrphansFound;
struct COrphanTx {
CTransaction tx;
@ -1177,6 +1177,7 @@ int CMerkleTx::GetDepthInMainChainINTERNAL(CBlockIndex* &pindexRet) const
int CMerkleTx::GetTransactionLockSignatures() const
{
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound) return -2;
if(!IsSporkActive(SPORK_2_INSTANTX)) return -3;
if(nInstantXDepth == 0) return -1;
//compile consessus vote
@ -2827,23 +2828,27 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
// ----------- instantX transaction scanning -----------
if(!fLargeWorkForkFound && !fLargeWorkInvalidChainFound){
BOOST_FOREACH(const CTransaction& tx, block.vtx){
if (!tx.IsCoinBase()){
//only reject blocks when it's based on complete consensus
BOOST_FOREACH(const CTxIn& in, tx.vin){
if(mapLockedInputs.count(in.prevout)){
if(mapLockedInputs[in.prevout] != tx.GetHash()){
LogPrintf("CheckBlock() : found conflicting transaction with transaction lock %s %s\n", mapLockedInputs[in.prevout].ToString().c_str(), tx.GetHash().ToString().c_str());
return state.DoS(0, error("CheckBlock() : found conflicting transaction with transaction lock"),
REJECT_INVALID, "conflicting-tx-ix");
if(IsSporkActive(SPORK_3_INSTANTX_BLOCK_FILTERING)){
if(!fLargeWorkForkFound && !fLargeWorkInvalidChainFound){
BOOST_FOREACH(const CTransaction& tx, block.vtx){
if (!tx.IsCoinBase()){
//only reject blocks when it's based on complete consensus
BOOST_FOREACH(const CTxIn& in, tx.vin){
if(mapLockedInputs.count(in.prevout)){
if(mapLockedInputs[in.prevout] != tx.GetHash()){
LogPrintf("CheckBlock() : found conflicting transaction with transaction lock %s %s\n", mapLockedInputs[in.prevout].ToString().c_str(), tx.GetHash().ToString().c_str());
return state.DoS(0, error("CheckBlock() : found conflicting transaction with transaction lock"),
REJECT_INVALID, "conflicting-tx-ix");
}
}
}
}
}
} else {
LogPrintf("CheckBlock() : fork detected, skipping transaction locking checks\n");
}
} else {
LogPrintf("CheckBlock() : fork detected, skipping transaction locking checks\n");
if(fDebug) LogPrintf("CheckBlock() : InstantX block filtering is off\n");
}
@ -2857,6 +2862,10 @@ bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bo
if(block.nTime > START_MASTERNODE_PAYMENTS) MasternodePayments = true;
}
if(!IsSporkActive(SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT)){
MasternodePayments = false;
if(fDebug) LogPrintf("CheckBlock() : Masternode payment enforcement is off\n");
}
if(MasternodePayments && !fLargeWorkForkFound && !fLargeWorkInvalidChainFound)
{
@ -3175,8 +3184,8 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
// Ask this guy to fill in what we're missing
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(hash));
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound){
// Move backwards to tigger reprocessing both chains
// Move backwards to tigger reprocessing both chains
if(fLargeWorkForkFound || fLargeWorkInvalidChainFound || IsSporkActive(SPORK_4_RECONVERGE)){
CValidationState state;
DisconnectTip(state);
}
@ -3875,6 +3884,8 @@ bool static AlreadyHave(const CInv& inv)
mapTxLockReqRejected.count(inv.hash);
case MSG_TXLOCK_VOTE:
return mapTxLockVote.count(inv.hash);
case MSG_SPORK:
return mapSporks.count(inv.hash);
}
// Don't know what it is, just say we already got one
return true;
@ -4017,6 +4028,16 @@ void static ProcessGetData(CNode* pfrom)
pushed = true;
}
}
if (!pushed && inv.type == MSG_SPORK) {
if(mapSporks.count(inv.hash)){
printf("have %s\n", inv.hash.ToString().c_str() );
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mapSporks[inv.hash];
pfrom->PushMessage("spork", ss);
pushed = true;
}
}
if (!pushed) {
vNotFound.push_back(inv);
@ -4770,13 +4791,13 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
LogPrint("net", "Reject %s\n", SanitizeString(ss.str()));
}
}
else
{
//probably one the extensions
ProcessMessageDarksend(pfrom, strCommand, vRecv);
ProcessMessageMasternode(pfrom, strCommand, vRecv);
ProcessMessageInstantX(pfrom, strCommand, vRecv);
ProcessSpork(pfrom, strCommand, vRecv);
}

View File

@ -18,7 +18,8 @@ static const char* ppszTypeName[] =
"block",
"filtered block",
"tx lock request",
"tx lock vote"
"tx lock vote",
"spork"
};
CMessageHeader::CMessageHeader()

View File

@ -137,6 +137,7 @@ enum
MSG_FILTERED_BLOCK,
MSG_TXLOCK_REQUEST,
MSG_TXLOCK_VOTE,
MSG_SPORK
};
#endif // __INCLUDED_PROTOCOL_H__

View File

@ -178,6 +178,7 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector<std::stri
if (strMethod == "verifychain" && n > 1) ConvertTo<int64_t>(params[1]);
if (strMethod == "keypoolrefill" && n > 0) ConvertTo<int64_t>(params[0]);
if (strMethod == "getrawmempool" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "spork" && n > 1) ConvertTo<int64_t>(params[1]);
return params;
}

View File

@ -11,6 +11,7 @@
#include "netbase.h"
#include "rpcserver.h"
#include "util.h"
#include "spork.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#include "walletdb.h"
@ -129,6 +130,45 @@ public:
};
#endif
/*
Used for updating/reading spork settings on the network
*/
Value spork(const Array& params, bool fHelp)
{
if(params.size() == 1 && params[0].get_str() == "show"){
std::map<int, CSporkMessage>::iterator it = mapSporksActive.begin();
Object ret;
while(it != mapSporksActive.end()) {
ret.push_back(Pair(sporkManager.GetSporkNameByID(it->second.nSporkID), it->second.nTimeStart));
it++;
}
return ret;
} else if (params.size() == 2){
int nSporkID = sporkManager.GetSporkIDByName(params[0].get_str());
if(nSporkID == -1){
return "Invalid spork name";
}
// EPOCH VALUE
int64_t nEpochStart = params[1].get_int();
//broadcast new spork
if(sporkManager.UpdateSpork(nSporkID, nEpochStart)){
return "success";
} else {
return "failure";
}
}
throw runtime_error(
"spork <name> [<value>]\n"
"<name> is the corresponding spork name, or 'show' to show all current spork settings"
"<value> is a epoch datetime to enable or disable spork"
+ HelpRequiringPassphrase());
}
Value validateaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)

View File

@ -271,6 +271,7 @@ static const CRPCCommand vRPCCommands[] =
/* Darkcoin features */
{ "darksend", &darksend, false, false, true },
{ "spork", &spork, true, false, false },
{ "masternode", &masternode, true, false, true },
#ifdef ENABLE_WALLET

View File

@ -191,6 +191,7 @@ extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHe
extern json_spirit::Value darksend(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value spork(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value masternode(const json_spirit::Array& params, bool fHelp);