From 2ced0cb33591a845f9609f981e0615775d5e5f0e Mon Sep 17 00:00:00 2001 From: Sunny King Date: Fri, 24 Aug 2012 22:34:23 +0100 Subject: [PATCH] PPCoin: Fix coinstake generation for pay-to-address coins --- src/main.cpp | 2 +- src/wallet.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++----- src/wallet.h | 2 +- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 2b0bef8..c4d7404 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3631,7 +3631,7 @@ CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake) nLastCoinStakeCheckTime = max(nLastCoinStakeCheckTime, (unsigned int) (GetAdjustedTime() - nMaxClockDrift / 2)); txCoinStake.nTime = nLastCoinStakeCheckTime; } - if (pwallet->CreateCoinStake(pblock->nBits, txCoinStake)) + if (pwallet->CreateCoinStake(*pwallet, pblock->nBits, txCoinStake)) { pblock->vtx.push_back(txCoinStake); pblock->vtx[0].vout[0].SetEmpty(); diff --git a/src/wallet.cpp b/src/wallet.cpp index b740c8a..c5178d2 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1203,7 +1203,7 @@ bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& w } // ppcoin: create coin stake transaction -bool CWallet::CreateCoinStake(unsigned int nBits, CTransaction& txNew) +bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, CTransaction& txNew) { CBigNum bnTargetPerCoinDay; bnTargetPerCoinDay.SetCompact(nBits); @@ -1230,6 +1230,7 @@ bool CWallet::CreateCoinStake(unsigned int nBits, CTransaction& txNew) if (setCoins.empty()) return false; int64 nCredit = 0; + CScript scriptPubKeyKernel; BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) { CTxDB txdb("r"); @@ -1251,11 +1252,48 @@ bool CWallet::CreateCoinStake(unsigned int nBits, CTransaction& txNew) ss << nBits << block.nTime << (txindex.pos.nTxPos - txindex.pos.nBlockPos) << pcoin.first->nTime << pcoin.second << txNew.nTime; if (CBigNum(Hash(ss.begin(), ss.end())) <= bnCoinDay * bnTargetPerCoinDay) { + // Found a kernel + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : kernel found\n"); + vector vSolutions; + txnouttype whichType; + CScript scriptPubKeyOut; + scriptPubKeyKernel = pcoin.first->vout[pcoin.second].scriptPubKey; + if (!Solver(scriptPubKeyKernel, whichType, vSolutions)) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : failed to parse kernel\n", whichType); + continue; + } + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : parsed kernel type=%d\n", whichType); + if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : no support for kernel type=%d\n", whichType); + continue; // only support pay to public key and pay to address + } + if (whichType == TX_PUBKEYHASH) // pay to address type + { + // convert to pay to public key type + CKey key; + if (!keystore.GetKey(uint160(vSolutions[0]), key)) + { + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : failed to get key for kernel type=%d\n", whichType); + continue; // unable to find corresponding public key + } + scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG; + } + else + scriptPubKeyOut = scriptPubKeyKernel; + txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second)); nCredit += pcoin.first->vout[pcoin.second].nValue; vwtxPrev.push_back(pcoin.first); - // Set output scriptPubKey - txNew.vout.push_back(CTxOut(0, pcoin.first->vout[pcoin.second].scriptPubKey)); + txNew.vout.push_back(CTxOut(0, scriptPubKeyOut)); + if (fDebug && GetBoolArg("-printcoinstake")) + printf("CreateCoinStake : added kernel type=%d\n", whichType); break; } } @@ -1263,8 +1301,9 @@ bool CWallet::CreateCoinStake(unsigned int nBits, CTransaction& txNew) return false; BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins) { - // Attempt to add more inputs of the same key - if (pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey && pcoin.first->GetHash() != txNew.vin[0].prevout.hash) + // Attempt to add more inputs + // Only add coins of the same key/address as kernel + if (pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel && pcoin.first->GetHash() != txNew.vin[0].prevout.hash) { // Stop adding more inputs if value is already pretty significant if (nCredit > MAX_MINT_PROOF_OF_WORK) diff --git a/src/wallet.h b/src/wallet.h index 9229d30..c7380e3 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -152,7 +152,7 @@ public: int64 GetNewMint() const; bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet); - bool CreateCoinStake(unsigned int nBits, CTransaction& txNew); + bool CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, CTransaction& txNew); bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); std::string SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false); -- 1.7.1