// ppcoin: create coin stake transaction
bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, CTransaction& txNew)
{
+ // The following split & combine thresholds are important to security
+ // Should not be adjusted if you don't understand the consequences
+ static unsigned int nStakeSplitAge = (60 * 60 * 24 * 90);
+ int64 nCombineThreshold = GetProofOfWorkReward(GetLastBlockIndex(pindexBest, false)->nBits) / 3;
+
CBigNum bnTargetPerCoinDay;
bnTargetPerCoinDay.SetCompact(nBits);
CBlock block;
if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
continue;
- if (block.GetBlockTime() + STAKE_MIN_AGE > txNew.nTime)
+ if (block.GetBlockTime() + nStakeMinAge > txNew.nTime)
continue; // only count coins meeting min age requirement
int64 nValueIn = pcoin.first->vout[pcoin.second].nValue;
- CBigNum bnCoinDay = CBigNum(nValueIn) * (txNew.nTime-pcoin.first->nTime) / COIN / (24 * 60 * 60);
+ CBigNum bnCoinDay = CBigNum(nValueIn) * min(txNew.nTime-pcoin.first->nTime, (unsigned int)STAKE_MAX_AGE) / COIN / (24 * 60 * 60);
// Calculate hash
CDataStream ss(SER_GETHASH, 0);
ss << nBits << block.nTime << (txindex.pos.nTxPos - txindex.pos.nBlockPos) << pcoin.first->nTime << pcoin.second << txNew.nTime;
nCredit += pcoin.first->vout[pcoin.second].nValue;
vwtxPrev.push_back(pcoin.first);
txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
+ if (block.GetBlockTime() + nStakeSplitAge > txNew.nTime)
+ txNew.vout.push_back(CTxOut(0, scriptPubKeyOut)); //split stake
if (fDebug && GetBoolArg("-printcoinstake"))
printf("CreateCoinStake : added kernel type=%d\n", whichType);
break;
}
if (nCredit == 0 || nCredit > nBalance - nReserveBalance)
return false;
- // The following combine threshold is important to network security
- // Should not be adjusted if you don't understand the consequences
- int64 nCombineThreshold = GetProofOfWorkReward(GetLastBlockIndex(pindexBest, false)->nBits);
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
// 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->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey)
+ if (txNew.vout.size() == 2 && ((pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey))
&& pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
{
// Stop adding more inputs if value is already pretty significant
loop
{
// Set output amount
- txNew.vout[1].nValue = nCredit - nMinFee;
+ if (txNew.vout.size() == 3)
+ {
+ txNew.vout[1].nValue = ((nCredit - nMinFee) / 2 / CENT) * CENT;
+ txNew.vout[2].nValue = nCredit - nMinFee - txNew.vout[1].nValue;
+ }
+ else
+ txNew.vout[1].nValue = nCredit - nMinFee;
// Sign
int nIn = 0;
continue;
for (int n=0; n < pcoin->vout.size(); n++)
{
- if (pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
+ if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
{
- printf("CheckSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
+ printf("CheckSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n);
nMismatchFound++;
nBalanceInQuestion += pcoin->vout[n].nValue;
}
- else if (!pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
+ else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
{
- printf("CheckSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
+ printf("CheckSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n);
nMismatchFound++;
nBalanceInQuestion += pcoin->vout[n].nValue;
}
continue;
for (int n=0; n < pcoin->vout.size(); n++)
{
- if (pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
+ if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
{
- printf("FixSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
+ printf("FixSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n);
nMismatchFound++;
nBalanceInQuestion += pcoin->vout[n].nValue;
pcoin->MarkUnspent(n);
pcoin->WriteToDisk();
}
- else if (!pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
+ else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
{
- printf("FixSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
+ printf("FixSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n);
nMismatchFound++;
nBalanceInQuestion += pcoin->vout[n].nValue;
pcoin->MarkSpent(n);