diff --git a/README.md b/README.md index edf22555..1aef4181 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ DigitalNote uses libsecp256k1, libgmp, Boost1.68, OR Boost1.58, - Openssl1.02o, + Openssl1.02r, Berkeley DB 6.2.32, - QT5.11, + QT5.12.1, to compile @@ -139,7 +139,6 @@ The developer [mailing list](https://lists.linuxfoundation.org/mailman/listinfo/ should be used to discuss complicated or controversial changes before working on a patch set. -<< Developer Discord can be found at https://discord.gg/eSb7nEx. Testing diff --git a/src/activemasternode.cpp b/src/activemasternode.cpp index 9715836b..c5d8a270 100644 --- a/src/activemasternode.cpp +++ b/src/activemasternode.cpp @@ -9,7 +9,7 @@ #include "clientversion.h" // -// Bootup the masternode, look for a 10,000 XDN input and register on the network +// Bootup the masternode, look for a 2,000,000 XDN input and register on the network // void CActiveMasternode::ManageStatus() { diff --git a/src/activemasternode.h b/src/activemasternode.h index d53ca1b8..a829a056 100644 --- a/src/activemasternode.h +++ b/src/activemasternode.h @@ -49,7 +49,7 @@ class CActiveMasternode /// Register any Masternode bool Register(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, CScript donationAddress, int donationPercentage, std::string &retErrorMessage); - // get 10,000 XDN input that can be used for the masternode + // get 2,000,000 XDN input that can be used for the masternode bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey); bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex); bool GetMasterNodeVinForPubKey(std::string collateralAddress, CTxIn& vin, CPubKey& pubkey, CKey& secretKey); diff --git a/src/blockparams.cpp b/src/blockparams.cpp index fd61329f..8ba178b6 100644 --- a/src/blockparams.cpp +++ b/src/blockparams.cpp @@ -15,6 +15,8 @@ #include "txdb.h" #include "velocity.h" #include "main.h" +#include "mnengine.h" +#include "masternodeman.h" #include #include @@ -75,6 +77,7 @@ uint64_t cntTime = 0; uint64_t prvTime = 0; uint64_t difTimePoS = 0; uint64_t difTimePoW = 0; +string loggedpayee = ""; ////////////////////////////////////////////////////////////////////////////// @@ -312,6 +315,17 @@ unsigned int VRX_Retarget(const CBlockIndex* pindexLast, bool fProofOfStake) if (pindexLast->nHeight < scanheight+124) return bnVelocity.GetCompact(); // can't index prevblock + // Live fork toggle diff reset + if(nLiveForkToggle > 0) + { + if(pindexLast->nHeight > nLiveForkToggle) // Selectable toggle + { + if(pindexLast->nHeight < nLiveForkToggle+5) { + return bnVelocity.GetCompact(); // diff reset + } + } + } + // Differentiate PoW/PoS prev block BlockVelocityType = GetLastBlockIndex(pindexLast, fProofOfStake); @@ -465,7 +479,7 @@ int64_t GetMasternodePayment(int nHeight, int64_t blockValue) { // Define values int64_t ret = 0; - int64_t swingSubsidy = blockValue - (50 * COIN); // 200 XDN ceiling + int64_t swingSubsidy = blockValue - (100 * COIN); // 200 XDN ceiling int64_t seesawHeight = nHeight; int64_t seesawInterval = seesawHeight / 30; int64_t seesawEpoch = seesawInterval / 15; @@ -480,11 +494,19 @@ int64_t GetMasternodePayment(int nHeight, int64_t blockValue) double seesawCeiling = 1; // Set bottom of seesaw arc seesawBase = seesawMidIncrmt; + LogPrint("creation", "GetMasternodePayment(): seesawEpoch=%lu\n", seesawEpoch); // Adjust for arc epochs if(seesawEpoch >= 1) { seesawRollover = seesawArcend * seesawEpoch; + LogPrint("creation", "GetMasternodePayment(): seesawRollover=%lu\n", seesawRollover); seesawInterval =- seesawRollover; + LogPrint("creation", "GetMasternodePayment(): seesawInterval=%lu\n", seesawInterval); + } + else + { + LogPrint("creation", "GetMasternodePayment(): seesawRollover=%lu\n", seesawRollover); + LogPrint("creation", "GetMasternodePayment(): seesawInterval=%lu\n", seesawInterval); } // Seesaw downswing (first for logic order) if(seesawInterval > seesawArc) @@ -492,10 +514,12 @@ int64_t GetMasternodePayment(int nHeight, int64_t blockValue) if(seesawInterval <= seesawArcend) { seesawBase = seesawCeiling - ((seesawIncrement * seesawInterval) - 1); + LogPrint("creation", "GetMasternodePayment(): seesawBase_1=%lu\n", seesawBase); // Limit seesaw arc if(seesawBase < seesawMidIncrmt) { seesawBase = seesawMidIncrmt; + LogPrint("creation", "GetMasternodePayment(): seesawBase_2=%lu\n", seesawBase); } } } @@ -505,15 +529,28 @@ int64_t GetMasternodePayment(int nHeight, int64_t blockValue) if(seesawInterval <= seesawArc) { seesawBase = seesawIncrement * seesawInterval; + LogPrint("creation", "GetMasternodePayment(): seesawBase_3=%lu\n", seesawBase); // Limit seesaw arc if(seesawBase > seesawCeiling) { seesawBase = seesawCeiling; + LogPrint("creation", "GetMasternodePayment(): seesawBase_4=%lu\n", seesawBase); } } } // Set calculated position of seesaw arc retDouble = swingSubsidy * seesawBase; + // v1.1 payment subsidy patch + if(nLiveForkToggle > 0) + { + if(pindexBest->nHeight > nLiveForkToggle) // Selectable toggle + { + // set returned value to calculated value + ret = retDouble; + LogPrint("creation", "GetMasternodePayment(): Value=%lu\n\n", ret); + + } + } // Return our seesaw arc value (reward in current position of arc) return ret; } diff --git a/src/blockparams.h b/src/blockparams.h index 2f01165b..630f2a2c 100644 --- a/src/blockparams.h +++ b/src/blockparams.h @@ -10,6 +10,7 @@ #include "net.h" #include "chain.h" #include "bignum.h" +#include "base58.h" #define START_MASTERNODE_PAYMENTS_TESTNET 9993058800 // OFF (NOT TOGGLED) #define START_MASTERNODE_PAYMENTS 1554494400 // OFF (Friday, April 5, 2019 1:00:00 PM GMT-07:00 | PDT) @@ -43,5 +44,4 @@ int64_t GetProofOfStakeReward(const CBlockIndex* pindexPrev, int64_t nCoinAge, i int64_t GetMasternodePayment(int nHeight, int64_t blockValue); int64_t GetDevOpsPayment(int nHeight, int64_t blockValue); - #endif // BITCOIN_BLOCKPARAMS_H diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5f66f646..b2fb697c 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -102,6 +102,9 @@ class CMainParams : public CChainParams { nPoolMaxTransactions = 9; strMNenginePoolDummyAddress = "dUnVN6zz2apaoWkb5krGoBCwwo8ZD3axue"; + // TODO: Verify upgrade + strDevOpsAddress = "dSCXLHTZJJqTej8ZRszZxbLrS6dDGVJhw7"; + strDevOpsScriptPubKey = "76a9148c2fad4e8bdfdc047ad5ad5378084de415e1538988ac"; nEndPoWBlock = 0x7fffffff; nStartPoSBlock = 0; } diff --git a/src/chainparams.h b/src/chainparams.h index 034c8bdc..302e429e 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -72,6 +72,9 @@ class CChainParams int StartPoSBlock() const { return nStartPoSBlock; } int PoolMaxTransactions() const { return nPoolMaxTransactions; } std::string MNenginePoolDummyAddress() const { return strMNenginePoolDummyAddress; } + // TODO: Verify upgrade + std::string DevOpsAddress() const { return strDevOpsAddress; } + std::string DevOpsPubKey() const { return strDevOpsScriptPubKey; } protected: CChainParams() {}; @@ -90,6 +93,9 @@ class CChainParams int nStartPoSBlock; int nPoolMaxTransactions; std::string strMNenginePoolDummyAddress; + // TODO: Verify upgrade + std::string strDevOpsAddress; + std::string strDevOpsScriptPubKey; }; /** diff --git a/src/init.cpp b/src/init.cpp index 2deb8508..b5a0b224 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -297,6 +297,7 @@ std::string HelpMessage() " -debugsmsg " + _("Log extra debug messages.") + "\n" + " -smsgscanchain " + _("Scan the block chain for public key addresses on startup.") + "\n"; strUsage += " -stakethreshold= " + _("This will set the output size of your stakes to never be below this number (default: 100)") + "\n"; + strUsage += " -liveforktoggle= " + _("Toggle experimental features via block height testing fork, (example: -command=)") + "\n"; return strUsage; } @@ -987,6 +988,32 @@ bool AppInit2(boost::thread_group& threadGroup) if (!strErrors.str().empty()) return InitError(strErrors.str()); + // Check toggle switch for experimental feature testing fork + uiInterface.InitMessage(_("Checking experimental feature toggle...")); + strLiveForkToggle = GetArg("-liveforktoggle", ""); + LogPrintf("Checking for experimental testing feature fork toggle...\n"); + if(!strLiveForkToggle.empty()){ + LogPrintf("Verifying height selection for experimental testing feature fork toggle...\n"); + std::istringstream(strLiveForkToggle) >> nLiveForkToggle; + if(nLiveForkToggle == 0) + { + LogPrintf("Continuing with fork toggle manually disabled by user...\n"); + } + else if(nLiveForkToggle < nBestHeight) + { + return InitError(_("Invalid experimental testing feature fork toggle, please select a higher block than currently sync'd height\n")); + } + else + { + LogPrintf("Continuing with fork toggle set for block: %s | Happy testing!\n", strLiveForkToggle.c_str()); + } + + } + else { + nLiveForkToggle = 0; + LogPrintf("No experimental testing feature fork toggle detected... skipping...\n"); + } + uiInterface.InitMessage(_("Loading masternode cache...")); CMasternodeDB mndb; diff --git a/src/main.cpp b/src/main.cpp index 44facfd7..1b67b65e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2488,99 +2488,13 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c for (unsigned int i = 2; i < vtx.size(); i++) if (vtx[i].IsCoinStake()) return DoS(100, error("CheckBlock() : more than one coinstake")); - - // Verify coin stake tx includes devops payment - - // first check for start of devops payments - bool bDevOpsPayment = false; - - if ( Params().NetworkID() == CChainParams::TESTNET ){ - if (GetTime() > START_DEVOPS_PAYMENTS_TESTNET ){ - bDevOpsPayment = true; - } - }else{ - if (GetTime() > START_DEVOPS_PAYMENTS){ - bDevOpsPayment = true; - } - } - // stop devops payments (for testing) - if ( Params().NetworkID() == CChainParams::TESTNET ){ - if (GetTime() > STOP_DEVOPS_PAYMENTS_TESTNET ){ - bDevOpsPayment = false; - } - }else{ - if (GetTime() > STOP_DEVOPS_PAYMENTS){ - bDevOpsPayment = false; - } - } - - bool fIsInitialDownload = IsInitialBlockDownload(); - if (!fIsInitialDownload) - { - if(bDevOpsPayment && Params().NetworkID() == CChainParams::TESTNET) - { - LOCK2(cs_main, mempool.cs); - - CBlockIndex *pindex = pindexBest; - if(pindex != NULL){ - if(pindex->GetBlockHash() == hashPrevBlock){ - // If we don't already have its previous block, skip devops payment step - // TODO: elaborate on payment catch, currently unused and throws warning - CAmount blockPayment; - for (int i = vtx[1].vout.size(); i--> 0; ) { - blockPayment = vtx[1].vout[i].nValue; - break; - } - - // Set values - CBitcoinAddress devopaddress; - CScript devpayee; - if (Params().NetworkID() == CChainParams::MAIN) - devopaddress = CBitcoinAddress("dSCXLHTZJJqTej8ZRszZxbLrS6dDGVJhw7 "); - - int64_t devopsPayment = GetDevOpsPayment(pindexBest->nHeight+1, nPoSageReward); - bool foundDevOpspayment = false; - bool foundDevOpspayee = false; - - // verify address - if(devopaddress.IsValid()) - { - //spork - if(pindexBest->GetBlockTime() > 1546123500) { // ON (Saturday, December 29, 2018 10:45 PM) - devpayee = GetScriptForDestination(devopaddress.Get()); - } - else { - foundDevOpspayment = true; - foundDevOpspayee = true; - } - } - else { - return DoS(100, error("CheckBlock() : coinstake failed to include devops recipient")); - } - // Search for devops payment - for (unsigned int i = 0; i < vtx[1].vout.size(); i++) { - if(vtx[1].vout[i].nValue == devopsPayment ) - foundDevOpspayment = true; - if(vtx[1].vout[i].scriptPubKey == devpayee ) - foundDevOpspayee = true; - } - - // velocity: reject if illogical - if (!foundDevOpspayment) - return DoS(100, error("CheckBlock() : coinstake failed to include devops payment")); - if (!foundDevOpspayee) - return DoS(100, error("CheckBlock() : coinstake failed to include devops recipient")); - } - } - } - } } // Check proof-of-stake block signature if (fCheckSig && !CheckBlockSignature()) return DoS(100, error("CheckBlock() : bad proof-of-stake block signature")); - -// ----------- instantX transaction scanning ----------- + // ----------- instantX transaction scanning ----------- if(IsSporkActive(SPORK_3_INSTANTX_BLOCK_FILTERING)){ BOOST_FOREACH(const CTransaction& tx, vtx){ @@ -2600,9 +2514,7 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c if(fDebug) { LogPrintf("CheckBlock() : skipping transaction locking checks\n"); } } - - - // ----------- masternode payments ----------- + // ----------- masternode / devops - payments ----------- bool MasternodePayments = false; bool fIsInitialDownload = IsInitialBlockDownload(); @@ -2670,7 +2582,171 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot, bool fCheckSig) c if(fDebug) { LogPrintf("CheckBlock() : Is initial download, skipping masternode payment check %d\n", pindexBest->nHeight+1); } } + // Verify coinbase/coinstake tx includes devops payment - + // first check for start of devops payments + bool bDevOpsPayment = false; + if ( Params().NetworkID() == CChainParams::TESTNET ){ + if (GetTime() > START_DEVOPS_PAYMENTS_TESTNET ){ + bDevOpsPayment = true; + } + }else{ + if (GetTime() > START_DEVOPS_PAYMENTS){ + bDevOpsPayment = true; + } + } + // stop devops payments (for testing) + if ( Params().NetworkID() == CChainParams::TESTNET ){ + if (GetTime() > STOP_DEVOPS_PAYMENTS_TESTNET ){ + bDevOpsPayment = false; + } + }else{ + if (GetTime() > STOP_DEVOPS_PAYMENTS){ + bDevOpsPayment = false; + } + } + // Live fork toggle for upgrade testing + if(nLiveForkToggle > 0) + { + if(pindexBest->nHeight > nLiveForkToggle) + { + bDevOpsPayment = true; + } + else + { + bDevOpsPayment = false; + } + } + else + { + bDevOpsPayment = false; + } + // TODO: verify upgrade + if(bDevOpsPayment) + { + int64_t nStandardPayment = 0; + int64_t nMasternodePayment = 0; + int64_t nDevopsPayment = 0; + int64_t nProofOfIndexMasternode = 0; + int64_t nProofOfIndexDevops = 0; + const CBlockIndex* pindexPrev = pindexBest->pprev; + bool isProofOfStake = !IsProofOfWork(); + bool fBlockHasPayments = true; + if (isProofOfStake) { + nProofOfIndexMasternode = 2; + nProofOfIndexDevops = 3; + if (vtx[isProofOfStake].vout.size() != 4) { + if (vtx[isProofOfStake].vout.size() != 5) { + LogPrintf("CheckBlock() : PoS submission doesn't include devops and/or masternode payment\n"); + fBlockHasPayments = false; + } else { + nProofOfIndexMasternode = 3; + nProofOfIndexDevops = 4; + } + } + nStandardPayment = GetProofOfStakeReward(pindexPrev, 0, 0); + } else { + nProofOfIndexMasternode = 1; + nProofOfIndexDevops = 2; + if (vtx[isProofOfStake].vout.size() != 3) { + LogPrintf("CheckBlock() : PoW submission doesn't include devops and/or masternode payment\n"); + fBlockHasPayments = false; + } + nStandardPayment = GetProofOfWorkReward(nBestHeight, 0); + } + nMasternodePayment = GetMasternodePayment(pindexBest->nHeight, nStandardPayment) / COIN; + nDevopsPayment = GetDevOpsPayment(pindexBest->nHeight, nStandardPayment) / COIN; + LogPrintf("Hardset MasternodePayment: %lu | Hardset DevOpsPayment: %lu \n", nMasternodePayment, nDevopsPayment); + // Check PoW or PoS payments for current block + for (unsigned int i=0; i < vtx[isProofOfStake].vout.size(); i++) { + // Define values + CScript rawPayee = vtx[isProofOfStake].vout[i].scriptPubKey; + CTxDestination address; + ExtractDestination(vtx[isProofOfStake].vout[i].scriptPubKey, address); + CBitcoinAddress addressOut(address); + int64_t nAmount = vtx[isProofOfStake].vout[i].nValue / COIN; + int64_t nIndexedMasternodePayment = vtx[isProofOfStake].vout[nProofOfIndexMasternode].nValue / COIN; + int64_t nIndexedDevopsPayment = vtx[isProofOfStake].vout[nProofOfIndexDevops].nValue / COIN; + LogPrintf(" - vtx[%d].vout[%d] Address: %s Amount: %lu \n", isProofOfStake, i, addressOut.ToString(), nAmount); + // PoS Checks + if (isProofOfStake) { + // Check for PoS masternode payment + if (i == nProofOfIndexMasternode) { + if (mnodeman.IsPayeeAValidMasternode(rawPayee)) { + LogPrintf("CheckBlock() : PoS Recipient masternode address validity succesfully verified\n"); + } else if (addressOut.ToString() == Params().DevOpsAddress()) { + LogPrintf("CheckBlock() : PoS Recipient masternode address validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoS Recipient masternode address validity could not be verified\n"); + fBlockHasPayments = false; + } + if (nIndexedMasternodePayment == nMasternodePayment) { + LogPrintf("CheckBlock() : PoS Recipient masternode amount validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoS Recipient masternode amount validity could not be verified\n"); + fBlockHasPayments = false; + } + } + // Check for PoS devops payment + if (i == nProofOfIndexDevops) { + if (addressOut.ToString() == Params().DevOpsAddress()) { + LogPrintf("CheckBlock() : PoS Recipient devops address validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoS Recipient devops address validity could not be verified\n"); + fBlockHasPayments = false; + } + if (nIndexedDevopsPayment == nDevopsPayment) { + LogPrintf("CheckBlock() : PoS Recipient devops amount validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoS Recipient devops amount validity could not be verified\n"); + fBlockHasPayments = false; + } + } + } + // PoW Checks + else if (!isProofOfStake) { + // Check for PoW masternode payment + if (i == nProofOfIndexMasternode) { + if (mnodeman.IsPayeeAValidMasternode(rawPayee)) { + LogPrintf("CheckBlock() : PoW Recipient masternode address validity succesfully verified\n"); + } else if (addressOut.ToString() == Params().DevOpsAddress()) { + LogPrintf("CheckBlock() : PoS Recipient masternode address validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoW Recipient masternode address validity could not be verified\n"); + fBlockHasPayments = false; + } + if (nAmount == nMasternodePayment) { + LogPrintf("CheckBlock() : PoW Recipient masternode amount validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoW Recipient masternode amount validity could not be verified\n"); + fBlockHasPayments = false; + } + } + // Check for PoW devops payment + if (i == nProofOfIndexDevops) { + if (addressOut.ToString() == Params().DevOpsAddress()) { + LogPrintf("CheckBlock() : PoW Recipient devops address validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoW Recipient devops address validity could not be verified\n"); + fBlockHasPayments = false; + } + if (nAmount == nDevopsPayment) { + LogPrintf("CheckBlock() : PoW Recipient devops amount validity succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoW Recipient devops amount validity could not be verified\n"); + fBlockHasPayments = false; + } + } + } + } + // Final checks (DevOps/Masternode payments) + if (fBlockHasPayments) { + LogPrintf("CheckBlock() : PoW/PoS non-miner reward payments succesfully verified\n"); + } else { + LogPrintf("CheckBlock() : PoW/PoS non-miner reward payments could not be verified\n"); + return DoS(100, error("CheckBlock() : PoW/PoS invalid payments in current block\n")); + } + } // Check transactions BOOST_FOREACH(const CTransaction& tx, vtx) @@ -4607,8 +4683,8 @@ bool SendMessages(CNode* pto, bool fSendTrickle) // in flight for over two minutes, since we first had a chance to // process an incoming block. int64_t nNow = GetTimeMicros(); - if (!pto->fDisconnect && state.nBlocksInFlight && - state.nLastBlockReceive < state.nLastBlockProcess - BLOCK_DOWNLOAD_TIMEOUT*1000000 && + if (!pto->fDisconnect && state.nBlocksInFlight && + state.nLastBlockReceive < state.nLastBlockProcess - BLOCK_DOWNLOAD_TIMEOUT*1000000 && state.vBlocksInFlight.front().nTime < state.nLastBlockProcess - 2*BLOCK_DOWNLOAD_TIMEOUT*1000000) { LogPrintf("Peer %s is stalling block download, disconnecting\n", state.name.c_str()); pto->fDisconnect = true; diff --git a/src/masternode.h b/src/masternode.h index 963f836c..53448520 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -44,7 +44,7 @@ extern map mapCacheBlockHashes; bool GetBlockHash(uint256& hash, int nBlockHeight); // -// The Masternode Class. For managing the mnengine process. It contains the input of the 10,000 XDN, signature to prove +// The Masternode Class. For managing the mnengine process. It contains the input of the 2,000,000 XDN, signature to prove // it's the one who own that ip address and code for calculating the payment election. // class CMasternode diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 268519d5..5fb0da36 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -459,6 +459,26 @@ CMasternode* CMasternodeMan::GetCurrentMasterNode(int mod, int64_t nBlockHeight, return winner; } +bool CMasternodeMan::IsPayeeAValidMasternode(CScript payee) +{ + if(!mnEnginePool.IsBlockchainSynced()) return true; + + int mnCount = 0; + bool fValid = false; + BOOST_FOREACH(CMasternode& mn, vMasternodes) { + + mn.Check(); + mnCount++; + if(!mn.IsEnabled()) continue; + + CScript currentMasternode = GetScriptForDestination(mn.pubkey.GetID()); + LogPrintf("* Masternode %d - testing %s\n", mnCount, currentMasternode.ToString().c_str()); + if(payee == currentMasternode) + fValid = true; + } + return fValid; +} + int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, int minProtocol, bool fOnlyActive) { std::vector > vecMasternodeScores; @@ -735,13 +755,13 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData } // verify that sig time is legit in past - // should be at least not earlier than block when 10,000 DigitalNote tx got MASTERNODE_MIN_CONFIRMATIONS + // should be at least not earlier than block when 2,000,000 DigitalNote tx got MASTERNODE_MIN_CONFIRMATIONS uint256 hashBlock = 0; GetTransaction(vin.prevout.hash, tx, hashBlock); map::iterator mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end() && (*mi).second) { - CBlockIndex* pMNIndex = (*mi).second; // block for 10,000 DigitalNote tx -> 1 confirmation + CBlockIndex* pMNIndex = (*mi).second; // block for 2,000,000 DigitalNote tx -> 1 confirmation CBlockIndex* pConfIndex = FindBlockByHeight((pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1)); // block where tx got MASTERNODE_MIN_CONFIRMATIONS if(pConfIndex->GetBlockTime() > sigTime) { diff --git a/src/masternodeman.h b/src/masternodeman.h index 60c2901e..ee226141 100644 --- a/src/masternodeman.h +++ b/src/masternodeman.h @@ -126,6 +126,8 @@ class CMasternodeMan // Get the current winner for this block CMasternode* GetCurrentMasterNode(int mod=1, int64_t nBlockHeight=0, int minProtocol=0); + bool IsPayeeAValidMasternode(CScript payee); + std::vector GetFullMasternodeVector() { Check(); return vMasternodes; } std::vector > GetMasternodeRanks(int64_t nBlockHeight, int minProtocol=0); diff --git a/src/miner.cpp b/src/miner.cpp index ba93f3cb..67353d74 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -8,6 +8,7 @@ #include "txdb.h" #include "miner.h" #include "kernel.h" +#include "masternode.h" #include "masternodeman.h" #include "masternode-payments.h" @@ -366,10 +367,97 @@ CBlock* CreateNewBlock(CReserveKey& reservekey, bool fProofOfStake, int64_t* pFe if (fDebug && GetBoolArg("-printpriority", false)) LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize); -// > XDN < - if (!fProofOfStake) + // > XDN < + if (!fProofOfStake){ pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(pindexPrev->nHeight + 1, nFees); + // TODO: Verify upgrade + if(nLiveForkToggle > 0){ + if(pindexPrev->nHeight + 1 > nLiveForkToggle){ + // masternode/devops payment + int64_t blockReward = GetProofOfWorkReward(pindexPrev->nHeight + 1, nFees); + bool hasPayment = true; + bool bMasterNodePayment = true;// TODO: Setup proper network toggle + CScript mn_payee; + CScript do_payee; + CTxIn vin; + + // Determine our payment address for devops + // + // OLD IMPLEMENTATION COMMNETED OUT + // CScript devopsScript; + // devopsScript << OP_DUP << OP_HASH160 << ParseHex(Params().DevOpsPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG; + // do_payee = devopsScript; + // + // Define Address + // + // TODO: Clean this up, it's a mess (could be done much more cleanly) + // Not an issue otherwise, merely a pet peev. Done in a rush... + // + CBitcoinAddress devopaddress; + if (Params().NetworkID() == CChainParams::MAIN) + devopaddress = CBitcoinAddress("dSCXLHTZJJqTej8ZRszZxbLrS6dDGVJhw7"); // TODO: nothing, already set to a valid DigitalNote address + else if (Params().NetworkID() == CChainParams::TESTNET) + devopaddress = CBitcoinAddress(""); + else if (Params().NetworkID() == CChainParams::REGTEST) + devopaddress = CBitcoinAddress(""); + + // verify address + if(devopaddress.IsValid()) + { + //spork + if(pindexBest->GetBlockTime() > 1546123500) { // ON (Saturday, December 29, 2018 10:45 PM) + do_payee = GetScriptForDestination(devopaddress.Get()); + } + else { + hasPayment = false; + } + } + else + { + LogPrintf("CreateNewBlock(): Failed to detect dev address to pay\n"); + } + + if(bMasterNodePayment) { + //spork + if(!masternodePayments.GetBlockPayee(pindexPrev->nHeight+1, mn_payee, vin)){ + CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1); + if(winningNode){ + mn_payee = GetScriptForDestination(winningNode->pubkey.GetID()); + } else { + mn_payee = do_payee; + } + } + } else { + hasPayment = false; + } + + CAmount masternodePayment = GetMasternodePayment(nHeight, blockReward); + CAmount devopsPayment = GetDevOpsPayment(nHeight, blockReward); + + if (hasPayment) { + pblock->vtx[0].vout.resize(3); + pblock->vtx[0].vout[1].scriptPubKey = mn_payee; + pblock->vtx[0].vout[1].nValue = masternodePayment; + pblock->vtx[0].vout[2].scriptPubKey = do_payee; + pblock->vtx[0].vout[2].nValue = devopsPayment; + pblock->vtx[0].vout[0].nValue = blockReward - (masternodePayment + devopsPayment); + } + + CTxDestination address1; + CTxDestination address3; + ExtractDestination(mn_payee, address1); + ExtractDestination(do_payee, address3); + CBitcoinAddress address2(address1); + CBitcoinAddress address4(address3); + LogPrintf("CreateNewBlock(): Masternode payment %lld to %s\n", + masternodePayment, address2.ToString().c_str()); + LogPrintf("CreateNewBlock(): Devops payment %lld to %s\n", + devopsPayment, address4.ToString().c_str()); + } + } // + } + if (pFees) *pFees = nFees; diff --git a/src/qt/addeditadrenalinenode.cpp b/src/qt/addeditadrenalinenode.cpp index 2cf4b562..8027be31 100644 --- a/src/qt/addeditadrenalinenode.cpp +++ b/src/qt/addeditadrenalinenode.cpp @@ -28,7 +28,7 @@ AddEditAdrenalineNode::AddEditAdrenalineNode(QWidget *parent) : ui->aliasLineEdit->setPlaceholderText("Enter your Masternode alias"); ui->addressLineEdit->setPlaceholderText("Enter your IP & port"); ui->privkeyLineEdit->setPlaceholderText("Enter your Masternode private key"); - ui->txhashLineEdit->setPlaceholderText("Enter your 10,000 XDN TXID"); + ui->txhashLineEdit->setPlaceholderText("Enter your 2,000,000 XDN TXID"); ui->outputindexLineEdit->setPlaceholderText("Enter your transaction output index"); // ui->donationaddressLineEdit->setPlaceholderText("Enter a donation recive address"); // ui->donationpercentageLineEdit->setPlaceholderText("Input the % for the donation"); @@ -66,7 +66,7 @@ void AddEditAdrenalineNode::on_okButton_clicked() else if(ui->txhashLineEdit->text() == "") { QMessageBox msg; - msg.setText("Please enter the transaction hash for the transaction that has 10,000 coins"); + msg.setText("Please enter the transaction hash for the transaction that has 2,000,000 coins"); msg.exec(); return; } diff --git a/src/qt/forms/addeditadrenalinenode.ui b/src/qt/forms/addeditadrenalinenode.ui index 3b0d0c1a..aec6c05d 100644 --- a/src/qt/forms/addeditadrenalinenode.ui +++ b/src/qt/forms/addeditadrenalinenode.ui @@ -29,7 +29,7 @@ - <html><head/><body><p>Enter an Alias (friendly name) for your Master Node and its address (either clearnet IP and port or Tor onion address and port). The address should be in the format 123.456.789.123:51441 or akjdsafxjkhasdf.onion:51441. You must send exactly 10,000 XDN to the collateral address.</p></body></html> + <html><head/><body><p>Enter an Alias (friendly name) for your Master Node and its address (either clearnet IP and port or Tor onion address and port). The address should be in the format 123.456.789.123:51441 or akjdsafxjkhasdf.onion:51441. You must send exactly 2,000,000 XDN to the collateral address.</p></body></html> true diff --git a/src/qt/qcustomplot.cpp b/src/qt/qcustomplot.cpp index 6e3cef9c..caf6fa9f 100644 --- a/src/qt/qcustomplot.cpp +++ b/src/qt/qcustomplot.cpp @@ -15110,7 +15110,7 @@ void QCPGraph::setChannelFillGraph(QCPGraph *targetGraph) /*! Sets whether adaptive sampling shall be used when plotting this graph. QCustomPlot's adaptive sampling technique can drastically improve the replot performance for graphs with a larger number - of points (e.g. above 10,000), without notably changing the appearance of the graph. + of points (e.g. above 2,000,000), without notably changing the appearance of the graph. By default, adaptive sampling is enabled. Even if enabled, QCustomPlot decides whether adaptive sampling shall actually be used on a per-graph basis. So leaving adaptive sampling enabled has no diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp index 714ff5e8..aaceec37 100644 --- a/src/rpcmining.cpp +++ b/src/rpcmining.cpp @@ -7,6 +7,8 @@ #include "blockparams.h" #include "chainparams.h" #include "main.h" +#include "masternodeman.h" +#include "masternode-payments.h" #include "db.h" #include "txdb.h" #include "init.h" @@ -154,7 +156,7 @@ Value getstakinginfo(const Array& params, bool fHelp) obj.push_back(Pair("expectedtime", nExpectedTime)); obj.push_back(Pair("stakethreshold", GetStakeCombineThreshold() / COIN)); - + return obj; } @@ -653,6 +655,8 @@ Value getblocktemplate(const Array& params, bool fHelp) aMutable.push_back("version/force"); } + Array aVotes; + Object result; result.push_back(Pair("version", pblock->nVersion)); result.push_back(Pair("previousblockhash", pblock->hashPrevBlock.GetHex())); @@ -668,6 +672,43 @@ Value getblocktemplate(const Array& params, bool fHelp) result.push_back(Pair("curtime", (int64_t)pblock->nTime)); result.push_back(Pair("bits", strprintf("%08x", pblock->nBits))); result.push_back(Pair("height", (int64_t)(pindexPrev->nHeight+1))); + result.push_back(Pair("votes", aVotes)); + + // TODO: Verify upgrade + if (nLiveForkToggle > 0) + { + if (pindexBest->nHeight > nLiveForkToggle) + { + // Set Masternode / DevOps payments + int64_t masternodePayment = GetMasternodePayment(pindexPrev->nHeight+1, (int64_t)pblock->vtx[0].vout[0].nValue); + int64_t devopsPayment = GetDevOpsPayment(pindexPrev->nHeight+1, (int64_t)pblock->vtx[0].vout[0].nValue); + + // Include DevOps payments + CAmount devopsSplit = devopsPayment; + Object devopsReward; + devopsReward.push_back(Pair("devopspayee", Params().DevOpsAddress())); + devopsReward.push_back(Pair("amount", devopsSplit)); + result.push_back(Pair("devopsreward", devopsReward)); + result.push_back(Pair("devops_reward_enforced", true)); + + // Include Masternode payments + CAmount masternodeSplit = masternodePayment; + CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1); + + if (winningNode) { + CScript payee = GetScriptForDestination(winningNode->pubkey.GetID()); + CTxDestination address1; + ExtractDestination(payee, address1); + CBitcoinAddress address2(address1); + result.push_back(Pair("payee", address2.ToString().c_str())); + } else { + result.push_back(Pair("payee", Params().DevOpsAddress().c_str())); + } + result.push_back(Pair("payee_amount", (int64_t)masternodeSplit)); + result.push_back(Pair("masternode_payments", true)); + result.push_back(Pair("enforce_masternode_payments", true)); + } + } return result; } diff --git a/src/util.cpp b/src/util.cpp index 91c9bbdc..10e74bf0 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -106,6 +106,10 @@ bool fNoListen = false; bool fLogTimestamps = false; volatile bool fReopenDebugLog = false; +//Live fork toggle +string strLiveForkToggle = ""; +int64_t nLiveForkToggle = 0; + // Init OpenSSL library multithreading support static CCriticalSection** ppmutexOpenSSL; void locking_callback(int mode, int i, const char* file, int line) diff --git a/src/util.h b/src/util.h index 61faedec..802eeb9c 100644 --- a/src/util.h +++ b/src/util.h @@ -115,7 +115,6 @@ inline void MilliSleep(int64_t n) } //Dark features - extern bool fMasterNode; extern bool fLiteMode; extern bool fEnableInstantX; @@ -143,6 +142,9 @@ extern std::string strMiscWarning; extern bool fNoListen; extern bool fLogTimestamps; extern volatile bool fReopenDebugLog; +//Live fork toggle +extern std::string strLiveForkToggle; +extern int64_t nLiveForkToggle; void RandAddSeed(); void RandAddSeedPerfmon(); diff --git a/src/wallet.cpp b/src/wallet.cpp index cfe6ff61..1b35d601 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -2887,6 +2887,10 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int txNew.vin.clear(); txNew.vout.clear(); + // Determine our payment script for devops + CScript devopsScript; + devopsScript << OP_DUP << OP_HASH160 << ParseHex(Params().DevOpsPubKey()) << OP_EQUALVERIFY << OP_CHECKSIG; + // Mark coin stake transaction CScript scriptEmpty; scriptEmpty.clear(); @@ -3077,7 +3081,7 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int if(winningNode){ payee = GetScriptForDestination(winningNode->pubkey.GetID()); } else { - return error("CreateCoinStake: Failed to detect masternode to pay\n"); + payee = devopsScript; } } } else { @@ -3098,7 +3102,9 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int LogPrintf("Masternode payment to %s\n", address2.ToString().c_str()); } - // TODO: Activate devops + // TODO: Clean this up, it's a mess (could be done much more cleanly) + // Not an issue otherwise, merely a pet peev. Done in a rush... + // // DevOps Payments int devoppay = 1; // start devops payments @@ -3130,10 +3136,10 @@ bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int CBitcoinAddress devopaddress; if (Params().NetworkID() == CChainParams::MAIN) devopaddress = CBitcoinAddress("dSCXLHTZJJqTej8ZRszZxbLrS6dDGVJhw7"); // TODO: nothing, already set to a valid DigitalNote address - // else if (Params().NetworkIDString() == CBaseChainParams::TESTNET) - // address = CBitcoinAddress(" "); - // else if (Params().NetworkIDString() == CBaseChainParams::REGTEST) - // address = CBitcoinAddress(" "); + else if (Params().NetworkID() == CChainParams::TESTNET) + devopaddress = CBitcoinAddress(""); + else if (Params().NetworkID() == CChainParams::REGTEST) + devopaddress = CBitcoinAddress(""); // verify address if(devopaddress.IsValid())