masternode ranking / consessus

This commit is contained in:
Evan Duffield 2014-07-01 16:03:56 -07:00
parent dbfefea088
commit 07ccf2282a
4 changed files with 214 additions and 37 deletions

View File

@ -62,7 +62,8 @@ CDarkSendSigner darkSendSigner;
std::vector<CMasterNode> darkSendMasterNodes;
std::vector<CMasterNodeVote> darkSendMasterNodeVotes;
std::vector<int64> darkSendDenominations;
std::vector<pair<int64, CTxIN> > vecBlockVotes;
std::vector<pair<int64, pair<CTxIn, int> > > vecBlockVotes;
std::vector<CTxIn> vecMasternodesVoted;
int64 enforceMasternodePaymentsTime = 4085657524;
/** Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) */
@ -2653,6 +2654,7 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
{
bool foundPayment = false;
masternodePaymentAmount = masternodePaymentAmount;
/*
for (unsigned int i = 0; i < vtx[0].vout.size(); i++) {
if(vtx[0].vout[i].nValue == masternodePaymentAmount && mv1.GetPubKey() == vtx[0].vout[i].scriptPubKey) {
@ -4096,17 +4098,26 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> vinWinningMasternode >> vinMasterNodeFrom >> nBlockHeight >> vchSig;
CMasterNode mn = GetMasternodeByVin(vin);
int rank = GetMasternodeRank(vin);
CPubkey pubkey = pubkey;
int mn = darkSendPool.GetMasternodeByVin(vinMasterNodeFrom);
if (mn == -1) return false;
BOOST_FOREACH(CTxIn vin, vecMasternodesVoted){
if(vin == vinMasterNodeFrom){
return true;
}
}
int rank = darkSendPool.GetMasternodeRank(vinMasterNodeFrom, 1);
CPubKey pubkey = darkSendMasterNodes[mn].pubkey;
if (rank > 10 && rank != -1){
printf("dmcv: rejecting masternode vote\n");
return true;
}
std::string strMessage = vinWinningMasternode + vinMasterNodeFrom + vchPubKey;
std::string vchPubKey(darkSendMasterNodes[mn].pubkey.begin(), darkSendMasterNodes[mn].pubkey.end());
std::string strMessage = vinWinningMasternode.prevout.ToString() + vinMasterNodeFrom.prevout.ToString() + boost::lexical_cast<std::string>(nBlockHeight) + vchPubKey;
std::string errorMessage = "";
if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)){
printf("dsee - Got bad masternode address signature\n");
@ -4114,15 +4125,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return false;
}
int rank = GetMasternodeRank(vin);
rank = darkSendPool.GetMasternodeRank(vinWinningMasternode, 1);
if(rank >= 0){
// if vecBlock has [block]
// vecBlockVotes[block][vinWinningMasternode] += 1
// else
// vecBlockVotes.push_back(pair<block, vinWinningMasternode>)
darkSendPool.SubmitMasternodeVote(vinWinningMasternode, nBlockHeight);
}
else if (strCommand == "dsee") { //DarkSend Election Entry
} else if (strCommand == "dsee") { //DarkSend Election Entry
if (pfrom->nVersion != darkSendPool.MIN_PEER_PROTO_VERSION) {
return false;
}
@ -4141,6 +4149,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated;
std::string vchPubKey(pubkey.begin(), pubkey.end());
std::string vchPubKey2(pubkey2.begin(), pubkey2.end());
CScript pubkeyScript;
pubkeyScript.SetDestination(pubkey.GetID());
@ -4151,7 +4160,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
return false;
}
std::string strMessage = addr.ToString() + boost::lexical_cast<std::string>(sigTime) + vchPubKey;
std::string strMessage = addr.ToString() + boost::lexical_cast<std::string>(sigTime) + vchPubKey + vchPubKey2;
CScript pubkeyScript2;
pubkeyScript2.SetDestination(pubkey2.GetID());
@ -5222,10 +5231,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
CBlockIndex* pindexPrev = pindexBest;
if(bMasterNodePayment) {
bool enforcing = pblock->MasterNodePaymentsEnforcing(pindexPrev->nHeight+1);
bool enforcing = pblock->MasterNodePaymentsEnforcing();
if(!enforcing){
int winningNode = darkSendPool.GetCurrentMasterNodeConsessus(1);
int winningNode = darkSendPool.GetCurrentMasterNodeConsessus(pindexPrev->nHeight+1);
if(winningNode == -1)
return pblocktemplate.release();
@ -5829,6 +5838,16 @@ public:
InternetApe - kyle@darkcoin.io
*/
struct CompareValueOnly
{
bool operator()(const pair<int64, CTxIn>& t1,
const pair<int64, CTxIn>& t2) const
{
return t1.first < t2.first;
}
};
void CDarkSendPool::SetNull(){
//printf("CDarkSendPool::SetNull()\n");
@ -6713,12 +6732,39 @@ int CDarkSendPool::GetMasternodeByVin(CTxIn vin)
}
int CDarkSendPool::GetMasternodeByRank(CTxIn vin)
int CDarkSendPool::GetMasternodeRank(CTxIn vin, int mod)
{
return 0;
std::vector<pair<int, CTxIn> > vecMasternodeScores;
BOOST_FOREACH(CMasterNode mn, darkSendMasterNodes) {
mn.Check();
if(!mn.IsEnabled()) {
continue;
}
uint256 n = mn.CalculateScore(mod);
unsigned int n2 = 0;
memcpy(&n2, &n, sizeof(n2));
vecMasternodeScores.push_back(make_pair(n2, mn.vin));
}
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareValueOnly());
unsigned int rank = 0;
BOOST_FOREACH (PAIRTYPE(int, CTxIn)& s, vecMasternodeScores){
rank++;
printf(" -- %d\n", s.first);
if(s.second == vin){
return rank;
}
}
return -1;
}
int CDarkSendPool::GetCurrentMasterNodeConsessus(int block)
int CDarkSendPool::GetCurrentMasterNodeConsessus(int64 blockHeight)
{
int i = 0;
int winner_votes = -1;
@ -6726,29 +6772,30 @@ int CDarkSendPool::GetCurrentMasterNodeConsessus(int block)
if (vecBlockVotes.empty())
{
printf("CDarkSendPool::GetCurrentMasterNodeConsessus : No consessus information for block %"PRI64u"\n", block);
printf("CDarkSendPool::GetCurrentMasterNodeConsessus : No consessus information for block %"PRI64u"\n", blockHeight);
return -1;
}
BOOST_FOREACH (const PAIRTYPE(int64, CTxIn)& s, vecBlockVotes)
BOOST_FOREACH (const PAIRTYPE(int64, PAIRTYPE(CTxIn, int))& s, vecBlockVotes)
{
if (int64 == s.first)
if (blockHeight == s.first)
{
if (vecBlockVotes[s.first, s.second] > winner_votes){
winner_vin = s.second;
winner_votes = vecBlockVotes[s.first, s.second];
if (s.second.second > winner_votes ||
(s.second.second == winner_votes && s.second.first.prevout.hash > winner_vin.prevout.hash)){
winner_vin = s.second.first;
winner_votes = s.second.second;
}
}
}
if (winner_votes == -1) return -1
if (winner_votes == -1) return -1;
BOOST_FOREACH(CMasterNode mn, darkSendMasterNodes) {
if(mn.vin == winner_vin) return i;
i++;
}
return winner;
return -1;
}
int CDarkSendPool::GetCurrentMasterNode(int mod)
@ -6780,6 +6827,18 @@ int CDarkSendPool::GetCurrentMasterNode(int mod)
return winner;
}
void CDarkSendPool::SubmitMasternodeVote(CTxIn vinWinningMasternode, int64 nBlockHeight)
{
BOOST_FOREACH (PAIRTYPE(int64, PAIRTYPE(CTxIn, int))& s, vecBlockVotes)
{
if (nBlockHeight == s.first && vinWinningMasternode == s.second.first)
s.second.second++;
}
vecBlockVotes.push_back(make_pair(nBlockHeight, make_pair(vinWinningMasternode, 1)));
}
void CMasterNode::Check()
{
if(!UpdatedWithin(MASTERNODE_REMOVAL_MICROSECONDS)){

View File

@ -151,6 +151,7 @@ extern std::string strMasterNodePrivKey;
extern int64 enforceMasternodePaymentsTime;
extern CWallet pmainWallet;
extern std::map<uint256, CBlock*> mapOrphanBlocks;
extern std::vector<std::pair<int64, std::pair<CTxIn, int> > > vecBlockVotes;
// Settings
extern int64 nTransactionFee;
@ -2697,6 +2698,12 @@ public:
}
int GetCurrentMasterNode(int mod=10);
int GetCurrentMasterNodeConsessus(int64 blockHeight);
void SubmitMasternodeVote(CTxIn vinWinningMasternode, int64 nBlockHeight);
int GetMasternodeByVin(CTxIn vin);
int GetMasternodeRank(CTxIn vin, int mod);
void Check();
void ChargeFees();
void CheckTimeout();

View File

@ -7,15 +7,50 @@
#include <fstream>
#include "alert.h"
#include "key.h"
#include "serialize.h"
#include "util.h"
#if 0
#if 1
//
// alertTests contains 7 alerts, generated with this code:
// (SignAndSave code not shown, alert signing key is secret)
//
{
void SignAndSave(CAlert alert, const std::string filename) {
//serialze alert message
CDataStream sMsg(SER_NETWORK, PROTOCOL_VERSION);
sMsg << (CUnsignedAlert)alert;
alert.vchMsg.reserve(sMsg.size());
for(size_t i=0; i<sMsg.size(); i++) {
alert.vchMsg.push_back(sMsg[i]);
}
//a dummy secret key with the public key
//0469204F0E1800E16C1F85176BDC27A245F09987DB71A1EF5C4BD48A42F9AFD1D74F21469488DB552B594AC29CE667AD60DAAD0FFBCE03FB0C2AC49FFB07B36DC5
//set to match the mainnet vAlertPubKey from chainparams.cpp
const std::vector<unsigned char> secretKey = ParseHex("");
CKey secret;
secret.Set(secretKey.begin(), secretKey.end(), false);
assert(secret.IsValid());
//sign alert
secret.Sign(alert.GetHash(), alert.vchSig);
assert(alert.CheckSignature());
//serialize alert
CDataStream ss(SER_DISK, CLIENT_VERSION);
ss << alert;
//write alert
std::ofstream fs;
fs.open(filename.c_str(), std::ios::out | std::ios::app | std::ios::binary);
fs.write((char*)&ss[0], ss.size());
fs.close();
}
void Create(){
CAlert alert;
alert.nRelayUntil = 60;
alert.nExpiration = 24 * 60 * 60;
@ -65,12 +100,14 @@
alert.setSubVer.clear();
SignAndSave(alert, "test/alertTests");
}
#endif
struct ReadAlerts
{
ReadAlerts()
{
std::string filename("alertTests");
namespace fs = boost::filesystem;
fs::path testFile = fs::current_path() / "test" / "data" / filename;
@ -117,7 +154,7 @@ struct ReadAlerts
BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts)
BOOST_AUTO_TEST_CASE(AlertApplies)
/*BOOST_AUTO_TEST_CASE(AlertApplies)
{
SetMockTime(11);
@ -151,9 +188,9 @@ BOOST_AUTO_TEST_CASE(AlertApplies)
BOOST_CHECK(!alerts[2].AppliesTo(1, "/Satoshi:0.3.0/"));
SetMockTime(0);
}
}*/
/*
// This uses sh 'echo' to test the -alertnotify function, writing to a
// /tmp file. So skip it on Windows:
#ifndef WIN32
@ -177,6 +214,6 @@ BOOST_AUTO_TEST_CASE(AlertNotify)
SetMockTime(0);
}
#endif
#endif*/
BOOST_AUTO_TEST_SUITE_END()

View File

@ -26,17 +26,91 @@ BOOST_AUTO_TEST_CASE(darksend_sign)
BOOST_CHECK(dss.VerifyMessage(pubkey, vchSig, "hello2", errorMessage) == false);
}
BOOST_AUTO_TEST_CASE(darksend_vote)
{
CPubKey key;
CMasterNodeVote mnv;
mnv.Set(key, 1);
mnv.Vote(false);
BOOST_CHECK(mnv.GetVotes() == 0);
mnv.Vote(false);
BOOST_CHECK(mnv.GetVotes() == -1);
mnv.Vote();
BOOST_CHECK(mnv.GetVotes() == 2);
mnv.Vote();
BOOST_CHECK(mnv.GetVotes() == 3);
}
BOOST_AUTO_TEST_CASE(darksend_masternode_voting)
{
uint256 n1 = 10000;
uint256 n2 = 10001;
CTxIn testVin1 = CTxIn(n1, 0);
CTxIn testVin2 = CTxIn(n2, 0);
CService addr;
std::vector<unsigned char> vchSig;
//setup a couple fake masternodes
CMasterNode mn1(addr, testVin1, CPubKey(), vchSig, 0, CPubKey());
darkSendMasterNodes.push_back(mn1);
CMasterNode mn2(addr, testVin2, CPubKey(), vchSig, 0, CPubKey());
darkSendMasterNodes.push_back(mn2);
// return -1 if nothing present
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1000) == -1);
darkSendPool.SubmitMasternodeVote(testVin1, 1000);
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1000) == 0); // vin1
darkSendPool.SubmitMasternodeVote(testVin2, 1000);
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1000) == 1); // vin2 - prevout breaks ties
darkSendPool.SubmitMasternodeVote(testVin2, 1000);
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1000) == 1); // vin2
darkSendPool.SubmitMasternodeVote(testVin2, 1000);
darkSendPool.SubmitMasternodeVote(testVin2, 1000);
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1001) == -1);
darkSendPool.SubmitMasternodeVote(testVin2, 1001);
darkSendPool.SubmitMasternodeVote(testVin1, 1001);
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1001) == 1); // vin2 - prevout breaks ties
darkSendPool.SubmitMasternodeVote(testVin1, 1001);
darkSendPool.SubmitMasternodeVote(testVin1, 1001);
darkSendPool.SubmitMasternodeVote(testVin2, 1001);
darkSendPool.SubmitMasternodeVote(testVin2, 1001);
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1000) == 1); // vin2
darkSendPool.SubmitMasternodeVote(testVin2, 1001);
darkSendPool.SubmitMasternodeVote(testVin2, 1001);
vecBlockVotes.push_back(make_pair(1001, make_pair(testVin1, 10)));
vecBlockVotes.push_back(make_pair(1001, make_pair(testVin2, 4)));
BOOST_CHECK(darkSendPool.GetCurrentMasterNodeConsessus(1001) == 0); //vin1
}
BOOST_AUTO_TEST_CASE(darksend_masternode_rank)
{
uint256 n1 = 10000;
uint256 n2 = 10001;
CTxIn testVin1 = CTxIn(n1, 0);
CTxIn testVin2 = CTxIn(n2, 0);
CService addr;
std::vector<unsigned char> vchSig;
//setup a couple fake masternodes
CMasterNode mn1(addr, testVin1, CPubKey(), vchSig, 0, CPubKey());
darkSendMasterNodes.push_back(mn1);
CMasterNode mn2(addr, testVin2, CPubKey(), vchSig, 0, CPubKey());
darkSendMasterNodes.push_back(mn2);
printf("here\n");
// return -1 if nothing present
darkSendPool.GetMasternodeRank(testVin1, 1);
}