nStart = GetTime();
// Create new block
- pblock = CreateNewBlock(reservekey, pwalletMain);
+ pblock = CreateNewBlock(pwalletMain);
if (!pblock)
throw JSONRPCError(-7, "Out of memory");
vNewBlock.push_back(pblock);
// Create new block
if(pblock)
delete pblock;
- pblock = CreateNewBlock(reservekey, pwalletMain);
+ pblock = CreateNewBlock(pwalletMain);
if (!pblock)
throw JSONRPCError(-7, "Out of memory");
}
if (IsCoinStake())
{
// ppcoin: coin stake tx earns reward instead of paying fee
- uint64 nCoinAge = 0;
- if (!GetCoinAge(nCoinAge))
+ uint64 nCoinAge;
+ if (!GetCoinAge(txdb, nCoinAge))
return error("ConnectInputs() : %s unable to get coin age for coinstake", GetHash().ToString().substr(0,10).c_str());
int64 nStakeReward = GetValueOut() - nValueIn;
if (nStakeReward > GetProofOfStakeReward(nCoinAge))
// guaranteed to be in main chain by auto checkpoint. This rule is
// introduced to help nodes establish a consistent view of the coin
// age (trust score) of competing branches.
-bool CTransaction::GetCoinAge(uint64& nCoinAge) const
+bool CTransaction::GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const
{
CBigNum bnCentSecond = 0; // coin age in the unit of cent-seconds
nCoinAge = 0;
BOOST_FOREACH(const CTxIn& txin, vin)
{
// First try finding the previous transaction in database
- CTxDB txdb("r");
CTransaction txPrev;
CTxIndex txindex;
if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
printf("coin age nValueIn=%-12I64d nTimeDiff=%d bnCentSecond=%s\n", nValueIn, nTime - txPrev.nTime, bnCentSecond.ToString().c_str());
}
- CBigNum bnCoinAge = bnCentSecond * CENT / COIN / (24 * 60 * 60);
+ CBigNum bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60);
if (fDebug && GetBoolArg("-printcoinage"))
- printf("coin age nCoinDays=%s\n", bnCoinAge.ToString().c_str());
- nCoinAge = bnCoinAge.getuint64();
+ printf("coin age bnCoinDay=%s\n", bnCoinDay.ToString().c_str());
+ nCoinAge = bnCoinDay.getuint64();
return true;
}
// ppcoin: total coin age spent in block, in the unit of coin-days.
bool CBlock::GetCoinAge(uint64& nCoinAge) const
{
- CBigNum bnCentSecond = 0;
nCoinAge = 0;
+ CTxDB txdb("r");
BOOST_FOREACH(const CTransaction& tx, vtx)
{
- uint64 nTxCoinAge = 0;
- if (tx.GetCoinAge(nTxCoinAge))
+ uint64 nTxCoinAge;
+ if (tx.GetCoinAge(txdb, nTxCoinAge))
nCoinAge += nTxCoinAge;
else
return false;
}
// ppcoin: compute chain trust score
- uint64 nCoinAge = 0;
+ uint64 nCoinAge;
if (!GetCoinAge(nCoinAge))
return error("AddToBlockIndex() : invalid transaction in block");
pindexNew->nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + nCoinAge;
};
-CBlock* CreateNewBlock(CReserveKey& reservekey, CWallet* pwallet)
+CBlock* CreateNewBlock(CWallet* pwallet)
{
CBlockIndex* pindexPrev = pindexBest;
+ CReserveKey reservekey(pwallet);
// Create new block
auto_ptr<CBlock> pblock(new CBlock());
CTransaction txCoinStake;
if (pwallet->CreateCoinStake(txNew.vout[0].scriptPubKey, txCoinStake))
pblock->vtx.push_back(txCoinStake);
- else
- printf("CreateNewBlock: unable to find coins to stake\n");
// Collect memory pool transactions into the block
int64 nFees = 0;
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
CBlockIndex* pindexPrev = pindexBest;
- auto_ptr<CBlock> pblock(CreateNewBlock(reservekey, pwallet));
+ auto_ptr<CBlock> pblock(CreateNewBlock(pwallet));
if (!pblock.get())
return;
IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce);
bool ProcessMessages(CNode* pfrom);
bool SendMessages(CNode* pto, bool fSendTrickle);
void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
-CBlock* CreateNewBlock(CReserveKey& reservekey, CWallet* pwallet);
+CBlock* CreateNewBlock(CWallet* pwallet);
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
bool AddToMemoryPoolUnchecked();
public:
bool RemoveFromMemoryPool();
- bool GetCoinAge(uint64& nCoinAge) const; // ppcoin: get transaction coin age
+ bool GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const; // ppcoin: get transaction coin age
};
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{
CWalletTx& wtx = item.second;
- if ((wtx.IsCoinBase() || wtx.IsCoinStake()) && wtx.IsSpent(0))
+ if ((wtx.IsCoinBase() && wtx.IsSpent(0)) || (wtx.IsCoinStake() && wtx.IsSpent(1)))
continue;
CTxIndex txindex;
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_wallet)
{
- // txdb must be opened before the mapWallet lock
- CTxDB txdb("r");
+ txNew.vin.clear();
+ txNew.vout.clear();
+ // Mark coin stake transaction
+ CScript scriptEmpty;
+ scriptEmpty.clear();
+ txNew.vout.push_back(CTxOut(0, scriptEmpty));
+ // Choose coins to use
+ set<pair<const CWalletTx*,unsigned int> > setCoins;
+ int64 nValueIn = 0;
+ if (!SelectCoins(GetBalance(), txNew.nTime, setCoins, nValueIn))
+ return false;
+ int64 nCredit = 0;
+ BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
+ {
+ nCredit += pcoin.first->vout[pcoin.second].nValue;
+ // Only spend one tx for now
+ break;
+ }
+ // Fill vin
+ BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
+ {
+ txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
+ // Only spend one tx for now
+ break;
+ }
+ // Calculate coin age reward
{
- txNew.vin.clear();
- txNew.vout.clear();
- // Mark coin stake transaction
- CScript scriptEmpty;
- scriptEmpty.clear();
- txNew.vout.push_back(CTxOut(0, scriptEmpty));
- // Choose coins to use
- set<pair<const CWalletTx*,unsigned int> > setCoins;
- int64 nValueIn = 0;
- if (!SelectCoins(GetBalance(), txNew.nTime, setCoins, nValueIn))
- return false;
- int64 nCredit = 0;
- BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
- {
- nCredit += pcoin.first->vout[pcoin.second].nValue;
- // Only spend one tx for now
- break;
- }
- // Fill vin
- BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
- {
- txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
- // Only spend one tx for now
- break;
- }
- // Calculate coin age reward
uint64 nCoinAge;
- if (!txNew.GetCoinAge(nCoinAge))
+ CTxDB txdb("r");
+ if (!txNew.GetCoinAge(txdb, nCoinAge))
return false;
nCredit += GetProofOfStakeReward(nCoinAge);
- // Fill vout
- txNew.vout.push_back(CTxOut(nCredit, scriptPubKey));
+ }
+ // Fill vout
+ txNew.vout.push_back(CTxOut(nCredit, scriptPubKey));
- // Sign
- int nIn = 0;
- BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
- {
- if (!SignSignature(*this, *coin.first, txNew, nIn++))
- return false;
- // Only spend one tx for now
- break;
- }
+ // Sign
+ int nIn = 0;
+ BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
+ {
+ if (!SignSignature(*this, *coin.first, txNew, nIn++))
+ return false;
+ // Only spend one tx for now
+ break;
}
}
return true;