diff --git a/gridcoinresearch.pro b/gridcoinresearch.pro index ba5b1bd58d..afa72a21bf 100755 --- a/gridcoinresearch.pro +++ b/gridcoinresearch.pro @@ -6,10 +6,15 @@ DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE CONFIG += no_include_pwd thread c++11 exceptions concurrent QT += core gui network -win32 { - lessThan(QT_VERSION, 5.0.0) { +win32 +{ + DEFINES += _WIN32_WINNT=0x0501 WINVER=0x0501 + lessThan(QT_VERSION, 5.0.0) + { CONFIG += qaxcontainer - } else { + } + else + { QT += axcontainer } } @@ -73,7 +78,6 @@ contains(RELEASE, 1) { QMAKE_LFLAGS *= -Wl,--large-address-aware } - # use: qmake "USE_QRCODE=1" # libqrencode (http://fukuchi.org/works/qrencode/index.en.html) must be installed for support contains(USE_QRCODE, 1) { @@ -441,6 +445,7 @@ isEmpty(BOOST_INCLUDE_PATH) { windows:DEFINES += WIN32 windows:RC_FILE = src/qt/res/bitcoin-qt.rc + windows:!contains(MINGW_THREAD_BUGFIX, 0) { # At least qmake's win32-g++-cross profile is missing the -lmingwthrd # thread-safety flag. GCC has -mthreads to enable this, but it doesn't diff --git a/src/clientversion.h b/src/clientversion.h index c5f9014e63..3383717a27 100644 --- a/src/clientversion.h +++ b/src/clientversion.h @@ -8,8 +8,8 @@ // These need to be macros, as version.cpp's and bitcoin-qt.rc's voodoo requires it #define CLIENT_VERSION_MAJOR 3 #define CLIENT_VERSION_MINOR 5 -#define CLIENT_VERSION_REVISION 8 -#define CLIENT_VERSION_BUILD 9 +#define CLIENT_VERSION_REVISION 9 +#define CLIENT_VERSION_BUILD 0 // Converts the parameter X to a string after macro replacement on X has been performed. // Don't merge these into one macro! diff --git a/src/main.cpp b/src/main.cpp index 239fe18605..79eb060271 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,7 +86,7 @@ extern std::string getCpuHash(); std::string getMacAddress(); std::string TimestampToHRDate(double dtm); bool CPIDAcidTest2(std::string bpk, std::string externalcpid); - +extern std::string VectorToString(std::vector v); bool HasActiveBeacon(const std::string& cpid); extern bool BlockNeedsChecked(int64_t BlockTime); extern void FixInvalidResearchTotals(std::vector vDisconnect, std::vector vConnect); @@ -512,6 +512,19 @@ bool PushGridcoinDiagnostics() return false; } + +vector StringToVector(std::string sData) +{ + vector v(sData.begin(), sData.end()); + return v; +} + +std::string VectorToString(vector v) +{ + std::string s(v.begin(), v.end()); + return s; +} + bool FullSyncWithDPORNodes() { #if defined(WIN32) && defined(QT_GUI) @@ -3998,7 +4011,14 @@ bool CBlock::CheckBlock(std::string sCaller, int height1, int64_t Mint, bool fCh if (bb.cpid != "INVESTOR" && IsProofOfStake() && height1 > nGrandfather && IsResearchAgeEnabled(height1) && BlockNeedsChecked(nTime) && !fLoadingIndex) { - int64_t nCalculatedResearch = GetProofOfStakeReward(nCoinAge, nFees, bb.cpid, true, 1, nTime, + // 6-4-2017 - Verify researchers stored block magnitude + double dNeuralNetworkMagnitude = CalculatedMagnitude2(bb.cpid, nTime, false); + if (bb.Magnitude > 0 && bb.Magnitude > (dNeuralNetworkMagnitude*1.25) && (fTestNet || height1 > 947000)) + { + return error("CheckBlock[ResearchAge] : Researchers block magnitude > neural network magnitude: Block Magnitude %f, Neural Network Magnitude %f, CPID %s ", + (double)bb.Magnitude,(double)dNeuralNetworkMagnitude,bb.cpid.c_str()); + } + int64_t nCalculatedResearch = GetProofOfStakeReward(nCoinAge, nFees, bb.cpid, true, 1, nTime, pindexBest, sCaller + "_checkblock_researcher", OUT_POR, OUT_INTEREST, dAccrualAge, dMagnitudeUnit, dAvgMagnitude); if (bb.ResearchSubsidy > ((OUT_POR*1.25)+1)) { @@ -5588,8 +5608,8 @@ bool GetEarliestStakeTime(std::string grcaddress, std::string cpid) return true; } - if (IsLockTimeWithinMinutes(nLastGRCtallied,100)) - return true; + if (IsLockTimeWithinMinutes(nLastGRCtallied,100) && (mvApplicationCacheTimestamp["nGRCTime"] > 0 || + mvApplicationCacheTimestamp["nCPIDTime"] > 0)) return true; nLastGRCtallied = GetAdjustedTime(); int64_t nGRCTime = 0; @@ -5621,9 +5641,9 @@ bool GetEarliestStakeTime(std::string grcaddress, std::string cpid) } else { - myCPID = pblockindex->GetCPID(); + myCPID = pblockindex->GetCPID(); } - if (cpid == myCPID && nCPIDTime==0) + if (cpid == myCPID && nCPIDTime==0 && myCPID != "INVESTOR") { nCPIDTime = pblockindex->nTime; nGRCTime = pblockindex->nTime; @@ -5633,6 +5653,7 @@ bool GetEarliestStakeTime(std::string grcaddress, std::string cpid) } int64_t EarliestStakedWalletTx = GetEarliestWalletTransaction(); if (EarliestStakedWalletTx > 0 && EarliestStakedWalletTx < nGRCTime) nGRCTime = EarliestStakedWalletTx; + if (cpid=="INVESTOR" && EarliestStakedWalletTx > 0) nGRCTime = EarliestStakedWalletTx; if (fTestNet) nGRCTime -= (86400*30); if (nGRCTime <= 0) nGRCTime = GetAdjustedTime(); if (nCPIDTime <= 0) nCPIDTime = GetAdjustedTime(); diff --git a/src/miner.cpp b/src/miner.cpp index 8341e9ef42..5a7351c53f 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -34,6 +34,8 @@ bool OutOfSyncByAgeWithChanceOfMining(); MiningCPID DeserializeBoincBlock(std::string block); std::string SerializeBoincBlock(MiningCPID mcpid); bool LessVerbose(int iMax1000); +std::string PubKeyToAddress(const CScript& scriptPubKey); + bool IsCPIDValidv2(MiningCPID& mc,int height); int static FormatHashBlocks(void* pbuffer, unsigned int len) diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 4eb467168d..0409728546 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -192,7 +192,7 @@ WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList vCoins; - wallet->AvailableCoins(vCoins, true, coinControl); + wallet->AvailableCoins(vCoins, true, coinControl,false); BOOST_FOREACH(const COutput& out, vCoins) nBalance += out.tx->vout[out.i].nValue; @@ -503,7 +503,7 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect void WalletModel::listCoins(std::map >& mapCoins) const { std::vector vCoins; - wallet->AvailableCoins(vCoins); + wallet->AvailableCoins(vCoins,true,NULL,false); LOCK2(cs_main, wallet->cs_wallet); // ListLockedCoins, mapWallet std::vector vLockedCoins; diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index d29d7cfcdf..65e37e4419 100755 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -24,8 +24,14 @@ std::string getHardDriveSerial(); int64_t GetRSAWeightByCPIDWithRA(std::string cpid); extern double DoubleFromAmount(int64_t amount); double ReturnTotalRacByCPID(std::string cpid); +std::string VectorToString(std::vector v); +std::string PubKeyToAddress(const CScript& scriptPubKey); +CBlockIndex* GetHistoricalMagnitude(std::string cpid); std::string UnpackBinarySuperblock(std::string sBlock); std::string PackBinarySuperblock(std::string sBlock); +extern std::string GetProvableVotingWeightXML(); +extern double ReturnVerifiedVotingBalance(std::string sXML, bool bCreatedAfterSecurityUpgrade); +extern double ReturnVerifiedVotingMagnitude(std::string sXML, bool bCreatedAfterSecurityUpgrade); int DetermineCPIDType(std::string cpid); extern void GetBeaconElements(std::string sBeacon,std::string& out_cpid, std::string& out_address, std::string& out_publickey); bool AskForOutstandingBlocks(uint256 hashStart); @@ -99,6 +105,7 @@ Array GetJSONNeuralNetworkReport(); Array GetJSONCurrentNeuralNetworkReport(); extern Array GetJSONVersionReport(); +extern Array GetJsonUnspentReport(); extern bool PollExists(std::string pollname); extern bool PollExpired(std::string pollname); @@ -1998,6 +2005,11 @@ Value execute(const Array& params, bool fHelp) Array myBeaconJSONReport = GetJSONBeaconReport(); results.push_back(myBeaconJSONReport); } + else if (sItem == "unspentreport") + { + Array aUnspentReport = GetJsonUnspentReport(); + results.push_back(aUnspentReport); + } else if (sItem == "upgradedbeaconreport") { Array aUpgBR = GetUpgradedBeaconReport(); @@ -2477,15 +2489,17 @@ Value execute(const Array& params, bool fHelp) else { std::string voter = ""+GlobalCPUMiningCPID.cpidv2 + "" - + GlobalCPUMiningCPID.cpid + "" + GRCAddress + "" - + hashRand.GetHex() + "" + RoundToString(nBalance,2) - + "" + RoundToString(dmag,0) + ""; - std::string pk = Title+";"+GRCAddress+";"+GlobalCPUMiningCPID.cpid; - std::string contract = "" + Title + "" + Answer + "" + voter; - std::string result = AddContract("vote",pk,contract); - std::string narr = "Your CPID weight is " + RoundToString(dmag,0) + " and your Balance weight is " + RoundToString(nBalance,0) + "."; - entry.push_back(Pair("Success",narr + " " + "Your vote has been cast for topic " + Title + ": With an Answer of " + Answer + ": " + result.c_str())); - results.push_back(entry); + + GlobalCPUMiningCPID.cpid + "" + GRCAddress + "" + + hashRand.GetHex() + "" + RoundToString(nBalance,2) + + "" + RoundToString(dmag,0) + ""; + // Add the provable balance and the provable magnitude - this goes into effect July 1 2017 + voter += GetProvableVotingWeightXML(); + std::string pk = Title + ";" + GRCAddress + ";" + GlobalCPUMiningCPID.cpid; + std::string contract = "" + Title + "" + Answer + "" + voter; + std::string result = AddContract("vote",pk,contract); + std::string narr = "Your CPID weight is " + RoundToString(dmag,0) + " and your Balance weight is " + RoundToString(nBalance,0) + "."; + entry.push_back(Pair("Success",narr + " " + "Your vote has been cast for topic " + Title + ": With an Answer of " + Answer + ": " + result.c_str())); + results.push_back(entry); } } } @@ -2650,7 +2664,6 @@ Value execute(const Array& params, bool fHelp) } else if (sItem=="netexec") { - std::string myresponse = ExecuteRPCCommand("vote","gender_poll","male"); entry.push_back(Pair("Response",myresponse.c_str())); results.push_back(entry); @@ -2658,7 +2671,6 @@ Value execute(const Array& params, bool fHelp) } else if (sItem=="staketime") { - std::string cpid = GlobalCPUMiningCPID.cpid; std::string GRCAddress = DefaultWalletAddress(); GetEarliestStakeTime(GRCAddress,cpid); @@ -3745,6 +3757,16 @@ bool PollExpired(std::string pollname) return (expiration < (double)GetAdjustedTime()) ? true : false; } + +bool PollCreatedAfterSecurityUpgrade(std::string pollname) +{ + // If the expiration is after July 1 2017, use the new security features. + std::string contract = GetPollContractByTitle("poll",pollname); + double expiration = cdbl(ExtractXML(contract,"",""),0); + return (expiration > 1498867200) ? true : false; +} + + double PollDuration(std::string pollname) { std::string contract = GetPollContractByTitle("poll",pollname); @@ -3776,11 +3798,12 @@ double PollCalculateShares(std::string contract, double sharetype, double MoneyS { std::string address = ExtractXML(contract,"",""); std::string cpid = ExtractXML(contract,"",""); - double magnitude = cdbl(ExtractXML(contract,"",""),0); - double balance = cdbl(ExtractXML(contract,"",""),0); - if (VoteAnswerCount < 1) VoteAnswerCount=1; + double magnitude = ReturnVerifiedVotingMagnitude(contract,PollCreatedAfterSecurityUpgrade(contract)); + double balance = ReturnVerifiedVotingBalance(contract,PollCreatedAfterSecurityUpgrade(contract)); + if (VoteAnswerCount < 1) VoteAnswerCount=1; if (sharetype==1) return magnitude/VoteAnswerCount; if (sharetype==2) return balance/VoteAnswerCount; + if (sharetype==3) { // https://github.com/gridcoin/Gridcoin-Research/issues/87#issuecomment-253999878 @@ -3897,6 +3920,379 @@ std::string GetShareType(double dShareType) } + + + +std::string GetProvableVotingWeightXML() +{ + std::string sXML = ""; + //Retrieve the historical magnitude + if (!msPrimaryCPID.empty() && msPrimaryCPID != "INVESTOR") + { + StructCPID st1 = GetLifetimeCPID(msPrimaryCPID,"ProvableMagnitude()"); + CBlockIndex* pHistorical = GetHistoricalMagnitude(msPrimaryCPID); + if (pHistorical->nHeight > 1 && pHistorical->nMagnitude > 0) + { + std::string sBlockhash = pHistorical->GetBlockHash().GetHex(); + std::string sSignature = SignBlockWithCPID(msPrimaryCPID,pHistorical->GetBlockHash().GetHex()); + // Find the Magnitude from the last staked block, within the last 6 months, and ensure researcher has a valid current beacon (if the beacon is expired, the signature contain an error message) + sXML += "" + msPrimaryCPID + "" + + RoundToString(pHistorical->nMagnitude,2) + "" + + "" + RoundToString(pHistorical->nHeight,0) + + "" + sBlockhash + "" + sSignature + ""; + } + } + sXML += ""; + + vector vecOutputs; + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + std::string sRow = ""; + double dTotal = 0; + double dBloatThreshhold = 100; + double dCurrentItemCount = 0; + double dItemBloatThreshhold = 50; + // Iterate unspent coins from transactions owned by me that total over 100GRC (this prevents XML bloat) + sXML += ""; + BOOST_FOREACH(const COutput& out, vecOutputs) + { + int64_t nValue = out.tx->vout[out.i].nValue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + Object entry; + CTxDestination address; + if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + { + if (CoinToDouble(nValue) > dBloatThreshhold) + { + std::string sScriptPubKey1 = HexStr(pk.begin(), pk.end()); + std::string strAddress=CBitcoinAddress(address).ToString(); + CKeyID keyID; + const CBitcoinAddress& bcAddress = CBitcoinAddress(address); + if (bcAddress.GetKeyID(keyID)) + { + bool IsCompressed; + CKey vchSecret; + if (pwalletMain->GetKey(keyID, vchSecret)) + { + // Here we use the secret key to sign the coins, then we abandon the key. + CSecret csKey = vchSecret.GetSecret(IsCompressed); + CKey keyInner; + keyInner.SetSecret(csKey,IsCompressed); + std::string private_key = CBitcoinSecret(csKey,IsCompressed).ToString(); + std::string public_key = HexStr(keyInner.GetPubKey().Raw()); + std::vector vchSig; + keyInner.Sign(out.tx->GetHash(), vchSig); + // Sign the coins we own + std::string sSig = EncodeBase64(VectorToString(vchSig)); + // Increment the total balance weight voting ability + dTotal += CoinToDouble(nValue); + sRow = "" + out.tx->GetHash().GetHex() + "" + RoundToString(CoinToDouble(nValue),2) + + "" + RoundToString((double)out.i,0) + "" + + public_key + "" + sScriptPubKey1 + "" + sSig + ""; + sXML += sRow; + dCurrentItemCount++; + if (dCurrentItemCount >= dItemBloatThreshhold) break; + } + + } + } + } + } + + + sXML += "" + RoundToString(dTotal,2) + ""; + sXML += ""; + return sXML; + +} + + +double ReturnVerifiedVotingBalance(std::string sXML, bool bCreatedAfterSecurityUpgrade) +{ + std::string sPayload = ExtractXML(sXML,"",""); + double dTotalVotedBalance = cdbl(ExtractXML(sPayload,"",""),2); + double dLegacyBalance = cdbl(ExtractXML(sXML,"",""),0); + + if (fDebug10) printf(" \r\n Total Voted Balance %f, Legacy Balance %f \r\n",(float)dTotalVotedBalance,(float)dLegacyBalance); + + if (!bCreatedAfterSecurityUpgrade) return dLegacyBalance; + + double dCounted = 0; + std::vector vXML= split(sPayload.c_str(),""); + for (unsigned int x = 0; x < vXML.size(); x++) + { + // Prove the contents of the XML as a 3rd party + CTransaction tx2; + uint256 hashBlock = 0; + uint256 uTXID(ExtractXML(vXML[x],"","")); + std::string sAmt = ExtractXML(vXML[x],"",""); + std::string sPos = ExtractXML(vXML[x],"",""); + std::string sXmlSig = ExtractXML(vXML[x],"",""); + std::string sXmlMsg = ExtractXML(vXML[x],"",""); + std::string sScriptPubKeyXml = ExtractXML(vXML[x],"",""); + int iPos = (int)cdbl(sPos,0); + std::string sPubKey = ExtractXML(vXML[x],"",""); + if (!sPubKey.empty() && !sAmt.empty() && !sPos.empty() && uTXID > 0) + { + if (GetTransaction(uTXID, tx2, hashBlock)) + { + if (iPos >= 0 && iPos < (unsigned int)tx2.vout.size()) + { + int64_t nValue2 = tx2.vout[iPos].nValue; + const CScript& pk2 = tx2.vout[iPos].scriptPubKey; + CTxDestination address2; + std::string sVotedPubKey = HexStr(pk2.begin(), pk2.end()); + std::string sVotedGRCAddress = CBitcoinAddress(address2).ToString(); + std::string sCoinOwnerAddress = PubKeyToAddress(pk2); + double dAmount = CoinToDouble(nValue2); + if (ExtractDestination(tx2.vout[iPos].scriptPubKey, address2)) + { + if (sScriptPubKeyXml == sVotedPubKey && RoundToString(dAmount,2) == sAmt) + { + Object entry; + entry.push_back(Pair("Audited Amount",ValueFromAmount(nValue2))); + std::string sDecXmlSig = DecodeBase64(sXmlSig); + CKey keyVerify; + if (keyVerify.SetPubKey(ParseHex(sPubKey))) + { + std::vector vchMsg1 = vector(sXmlMsg.begin(), sXmlMsg.end()); + std::vector vchSig1 = vector(sDecXmlSig.begin(), sDecXmlSig.end()); + bool bValid = keyVerify.Verify(uTXID,vchSig1); + // Unspent Balance is proven to be owned by the voters public key, count the vote + if (bValid) dCounted += dAmount; + } + + } + } + } + } + } + } + + return dCounted; +} + +double ReturnVerifiedVotingMagnitude(std::string sXML, bool bCreatedAfterSecurityUpgrade) +{ + double dLegacyMagnitude = cdbl(ExtractXML(sXML,"",""),2); + if (!bCreatedAfterSecurityUpgrade) return dLegacyMagnitude; + + std::string sMagXML = ExtractXML(sXML,"",""); + std::string sMagnitude = ExtractXML(sMagXML,"",""); + std::string sXmlSigned = ExtractXML(sMagXML,"",""); + std::string sXmlBlockHash = ExtractXML(sMagXML,"",""); + std::string sXmlCPID = ExtractXML(sMagXML,"",""); + if (!sXmlBlockHash.empty() && !sMagnitude.empty() && !sXmlSigned.empty()) + { + CBlockIndex* pblockindexMagnitude = mapBlockIndex[uint256(sXmlBlockHash)]; + if (pblockindexMagnitude) + { + bool fResult = VerifyCPIDSignature(sXmlCPID, sXmlBlockHash, sXmlSigned); + bool fAudited = (cdbl(RoundToString(pblockindexMagnitude->nMagnitude,2),0)==cdbl(sMagnitude,0) && fResult); + if (fAudited) return (double)pblockindexMagnitude->nMagnitude; + } + } + return 0; +} + + + + +Array GetJsonUnspentReport() +{ + // The purpose of this report is to list the details of unspent coins in the wallet, create a signed XML payload and then audit those coins as a third party + // Written on 5-28-2017 - R HALFORD + // We can use this as the basis for proving the total coin balance, and the current researcher magnitude in the voting system. + Array results; + + //Retrieve the historical magnitude + if (!msPrimaryCPID.empty() && msPrimaryCPID != "INVESTOR") + { + StructCPID st1 = GetLifetimeCPID(msPrimaryCPID,"GetUnspentReport()"); + CBlockIndex* pHistorical = GetHistoricalMagnitude(msPrimaryCPID); + Object entry1; + entry1.push_back(Pair("Researcher Magnitude",pHistorical->nMagnitude)); + results.push_back(entry1); + + // Create the XML Magnitude Payload + if (pHistorical->nHeight > 1 && pHistorical->nMagnitude > 0) + { + std::string sBlockhash = pHistorical->GetBlockHash().GetHex(); + std::string sSignature = SignBlockWithCPID(msPrimaryCPID,pHistorical->GetBlockHash().GetHex()); + // Find the Magnitude from the last staked block, within the last 6 months, and ensure researcher has a valid current beacon (if the beacon is expired, the signature contain an error message) + + std::string sMagXML = "" + msPrimaryCPID + "" + RoundToString(pHistorical->nMagnitude,2) + "" + + "" + RoundToString(pHistorical->nHeight,0) + "" + sBlockhash + "" + sSignature + ""; + std::string sMagnitude = ExtractXML(sMagXML,"",""); + std::string sXmlSigned = ExtractXML(sMagXML,"",""); + std::string sXmlBlockHash = ExtractXML(sMagXML,"",""); + std::string sXmlCPID = ExtractXML(sMagXML,"",""); + Object entry; + entry.push_back(Pair("CPID Signature", sSignature)); + entry.push_back(Pair("Historical Magnitude Block #", pHistorical->nHeight)); + entry.push_back(Pair("Historical Blockhash", sBlockhash)); + // Prove the magnitude from a 3rd party standpoint: + if (!sXmlBlockHash.empty() && !sMagnitude.empty() && !sXmlSigned.empty()) + { + CBlockIndex* pblockindexMagnitude = mapBlockIndex[uint256(sXmlBlockHash)]; + if (pblockindexMagnitude) + { + bool fResult = VerifyCPIDSignature(sXmlCPID, sXmlBlockHash, sXmlSigned); + entry.push_back(Pair("Historical Magnitude",pblockindexMagnitude->nMagnitude)); + entry.push_back(Pair("Signature Valid",fResult)); + bool fAudited = (cdbl(RoundToString(pblockindexMagnitude->nMagnitude,2),0)==cdbl(sMagnitude,0) && fResult); + entry.push_back(Pair("Magnitude Audited",fAudited)); + results.push_back(entry); + + } + } + + + } + + + } + + // Now we move on to proving the coins we own are ours + + vector vecOutputs; + pwalletMain->AvailableCoins(vecOutputs, false, NULL, true); + std::string sXML = ""; + std::string sRow = ""; + double dTotal = 0; + double dBloatThreshhold = 100; + double dCurrentItemCount = 0; + double dItemBloatThreshhold = 50; + // Iterate unspent coins from transactions owned by me that total over 100GRC (this prevents XML bloat) + BOOST_FOREACH(const COutput& out, vecOutputs) + { + int64_t nValue = out.tx->vout[out.i].nValue; + const CScript& pk = out.tx->vout[out.i].scriptPubKey; + Object entry; + CTxDestination address; + if (ExtractDestination(out.tx->vout[out.i].scriptPubKey, address)) + { + if (CoinToDouble(nValue) > dBloatThreshhold) + { + entry.push_back(Pair("TXID", out.tx->GetHash().GetHex())); + entry.push_back(Pair("Address", CBitcoinAddress(address).ToString())); + std::string sScriptPubKey1 = HexStr(pk.begin(), pk.end()); + entry.push_back(Pair("Amount",ValueFromAmount(nValue))); + std::string strAddress=CBitcoinAddress(address).ToString(); + CKeyID keyID; + const CBitcoinAddress& bcAddress = CBitcoinAddress(address); + if (bcAddress.GetKeyID(keyID)) + { + bool IsCompressed; + CKey vchSecret; + if (pwalletMain->GetKey(keyID, vchSecret)) + { + // Here we use the secret key to sign the coins, then we abandon the key. + CSecret csKey = vchSecret.GetSecret(IsCompressed); + CKey keyInner; + keyInner.SetSecret(csKey,IsCompressed); + std::string private_key = CBitcoinSecret(csKey,IsCompressed).ToString(); + std::string public_key = HexStr(keyInner.GetPubKey().Raw()); + std::vector vchSig; + keyInner.Sign(out.tx->GetHash(), vchSig); + // Sign the coins we own + std::string sSig = EncodeBase64(VectorToString(vchSig)); + // Increment the total balance weight voting ability + dTotal += CoinToDouble(nValue); + sRow = "" + out.tx->GetHash().GetHex() + "" + RoundToString(CoinToDouble(nValue),2) + + "" + RoundToString((double)out.i,0) + "" + + public_key + "" + sScriptPubKey1 + "" + sSig + ""; + sXML += sRow; + dCurrentItemCount++; + if (dCurrentItemCount >= dItemBloatThreshhold) break; + } + + } + results.push_back(entry); + } + } + } + + // Now we will need to go back through the XML and Audit the claimed vote weight balance as a 3rd party + + double dCounted = 0; + + std::vector vXML= split(sXML.c_str(),""); + for (unsigned int x = 0; x < vXML.size(); x++) + { + // Prove the contents of the XML as a 3rd party + CTransaction tx2; + uint256 hashBlock = 0; + uint256 uTXID(ExtractXML(vXML[x],"","")); + std::string sAmt = ExtractXML(vXML[x],"",""); + std::string sPos = ExtractXML(vXML[x],"",""); + std::string sXmlSig = ExtractXML(vXML[x],"",""); + std::string sXmlMsg = ExtractXML(vXML[x],"",""); + std::string sScriptPubKeyXml = ExtractXML(vXML[x],"",""); + + int iPos = (int)cdbl(sPos,0); + std::string sPubKey = ExtractXML(vXML[x],"",""); + + if (!sPubKey.empty() && !sAmt.empty() && !sPos.empty() && uTXID > 0) + { + + if (GetTransaction(uTXID, tx2, hashBlock)) + { + if (iPos >= 0 && iPos < (unsigned int)tx2.vout.size()) + { + int64_t nValue2 = tx2.vout[iPos].nValue; + const CScript& pk2 = tx2.vout[iPos].scriptPubKey; + CTxDestination address2; + std::string sVotedPubKey = HexStr(pk2.begin(), pk2.end()); + std::string sVotedGRCAddress = CBitcoinAddress(address2).ToString(); + std::string sCoinOwnerAddress = PubKeyToAddress(pk2); + double dAmount = CoinToDouble(nValue2); + if (ExtractDestination(tx2.vout[iPos].scriptPubKey, address2)) + { + if (sScriptPubKeyXml == sVotedPubKey && RoundToString(dAmount,2) == sAmt) + { + Object entry; + entry.push_back(Pair("Audited Amount",ValueFromAmount(nValue2))); + std::string sDecXmlSig = DecodeBase64(sXmlSig); + CKey keyVerify; + if (keyVerify.SetPubKey(ParseHex(sPubKey))) + { + std::vector vchMsg1 = vector(sXmlMsg.begin(), sXmlMsg.end()); + std::vector vchSig1 = vector(sDecXmlSig.begin(), sDecXmlSig.end()); + bool bValid = keyVerify.Verify(uTXID,vchSig1); + // Unspent Balance is proven to be owned by the voters public key, count the vote + if (bValid) dCounted += dAmount; + entry.push_back(Pair("Verified",bValid)); + } + + results.push_back(entry); + } + } + } + } + } + } + + Object entry; + // Note that the voter needs to have the wallet at least unlocked for staking in order for the coins to be signed, otherwise the coins-owned portion of the vote balance will be 0. + // In simpler terms: The wallet must be unlocked to cast a provable vote. + + entry.push_back(Pair("Total Voting Balance Weight", dTotal)); + entry.push_back(Pair("Grand Verified Amount",dCounted)); + + std::string sBalCheck2 = GetProvableVotingWeightXML(); + double dVerifiedBalance = ReturnVerifiedVotingBalance(sBalCheck2,true); + double dVerifiedMag = ReturnVerifiedVotingMagnitude(sBalCheck2, true); + entry.push_back(Pair("Balance check",dVerifiedBalance)); + entry.push_back(Pair("Mag check",dVerifiedMag)); + results.push_back(entry); + + return results; +} + + + + + Array GetJsonVoteDetailsReport(std::string pollname) { diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 4d4cc73c8c..78f86a706c 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -363,7 +363,7 @@ Value listunspent(const Array& params, bool fHelp) Array results; vector vecOutputs; - pwalletMain->AvailableCoins(vecOutputs, false); + pwalletMain->AvailableCoins(vecOutputs, false,NULL,false); BOOST_FOREACH(const COutput& out, vecOutputs) { if (out.nDepth < nMinDepth || out.nDepth > nMaxDepth) diff --git a/src/wallet.cpp b/src/wallet.cpp index 2b1ce25405..5fd19f8027 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1299,7 +1299,7 @@ int64_t CWallet::GetImmatureBalance() const } // populate vCoins with vector of spendable COutputs -void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const +void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl, bool fIncludeStakedCoins) const { vCoins.clear(); @@ -1308,27 +1308,39 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) { const CWalletTx* pcoin = &(*it).second; - - if (!IsFinalTx(*pcoin)) - continue; - - if (fOnlyConfirmed && !pcoin->IsTrusted()) - continue; - - if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) - continue; - - if(pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0) - continue; - - int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < 0) - continue; + int nDepth = pcoin->GetDepthInMainChain(); + + if (!fIncludeStakedCoins) + { + if (!IsFinalTx(*pcoin)) + continue; + + if (fOnlyConfirmed && !pcoin->IsTrusted()) + continue; + + if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0) + continue; + + if(pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0) + continue; + + if (nDepth < 0) + continue; + } + else + { + if (nDepth < 1) continue; + } for (unsigned int i = 0; i < pcoin->vout.size(); i++) - if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue >= nMinimumInputValue && - (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) - vCoins.push_back(COutput(pcoin, i, nDepth)); + { + if ((!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue >= nMinimumInputValue && + (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) + || (fIncludeStakedCoins && pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)) + { + vCoins.push_back(COutput(pcoin, i, nDepth)); + } + } } } @@ -1544,7 +1556,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, bool CWallet::SelectCoins(int64_t nTargetValue, unsigned int nSpendTime, set >& setCoinsRet, int64_t& nValueRet, const CCoinControl* coinControl) const { vector vCoins; - AvailableCoins(vCoins, true, coinControl); + AvailableCoins(vCoins, true, coinControl, false); // coin control -> return all selected outputs (we want all selected to go into the transaction for sure) if (coinControl && coinControl->HasSelected()) diff --git a/src/wallet.h b/src/wallet.h index 515903eb7f..ffc4cb9e3a 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -129,8 +129,8 @@ class CWallet : public CCryptoKeyStore // check whether we are allowed to upgrade (or already support) to the named feature bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; } - void AvailableCoinsForStaking(std::vector& vCoins, unsigned int nSpendTime) const; - void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=NULL) const; + void AvailableCoinsForStaking(std::vector& vCoins, unsigned int nSpendTime) const; + void AvailableCoins(std::vector& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=NULL, bool fIncludeStakingCoins=false) const; bool SelectCoinsMinConf(int64_t nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, std::vector vCoins, std::set >& setCoinsRet, int64_t& nValueRet) const; // keystore implementation