// Copyright (c) 2009-2011 Satoshi Nakamoto
// Copyright (c) 2011 The Bitcoin developers
-// Copyright (c) 2011 The PPCoin developers
+// Copyright (c) 2011-2012 The PPCoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
return false;
}
+// ppcoin: optional setting to create coinstake only when unlocked;
+// serves to disable the trivial sendmoney when OS account compromised
+bool fWalletUnlockStakeOnly = false;
+
bool CWallet::Unlock(const SecureString& strWalletPassphrase)
{
if (!IsLocked())
int nRequests = -1;
CRITICAL_BLOCK(pwallet->cs_wallet)
{
- if (IsCoinBase())
+ if (IsCoinBase() || IsCoinStake())
{
// Generated block
if (hashBlock != 0)
listSent.clear();
strSentAccount = strFromAccount;
- if (IsCoinBase())
+ if (IsCoinBase() || IsCoinStake())
{
if (GetBlocksToMaturity() > 0)
nGeneratedImmature = pwallet->GetCredit(*this);
BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{
CWalletTx& wtx = item.second;
- if (wtx.IsCoinBase() && wtx.IsSpent(0))
+ if ((wtx.IsCoinBase() && wtx.IsSpent(0)) || (wtx.IsCoinStake() && wtx.IsSpent(1)))
continue;
CTxIndex txindex;
else
{
// Reaccept any txes of ours that aren't already in a block
- if (!wtx.IsCoinBase())
+ if (!(wtx.IsCoinBase() || wtx.IsCoinStake()))
wtx.AcceptWalletTransaction(txdb, false);
}
}
{
BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
{
- if (!tx.IsCoinBase())
+ if (!(tx.IsCoinBase() || tx.IsCoinStake()))
{
uint256 hash = tx.GetHash();
if (!txdb.ContainsTx(hash))
RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
}
}
- if (!IsCoinBase())
+ if (!(IsCoinBase() || IsCoinStake()))
{
uint256 hash = GetHash();
if (!txdb.ContainsTx(hash))
for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
{
const CWalletTx* pcoin = &(*it).second;
- if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+ if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)
nTotal += CWallet::GetCredit(*pcoin);
}
}
if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
continue;
- if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+ if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0)
continue;
int nDepth = pcoin->GetDepthInMainChain();
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
}
+// ppcoin: create coin stake transaction
+bool CWallet::CreateCoinStake(CScript scriptPubKey, CTransaction& txNew)
+{
+ CRITICAL_BLOCK(cs_main)
+ CRITICAL_BLOCK(cs_wallet)
+ {
+ 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
+ int64 nBalance = GetBalance();
+ if (nBalance <= nBalanceReserve)
+ return false;
+ set<pair<const CWalletTx*,unsigned int> > setCoins;
+ int64 nValueIn = 0;
+ if (!SelectCoins(nBalance - nBalanceReserve, txNew.nTime, setCoins, nValueIn))
+ return false;
+ if (setCoins.empty())
+ 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;
+ }
+ if (nCredit > nBalance - nBalanceReserve)
+ return false;
+ // 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;
+ CTxDB txdb("r");
+ if (!txNew.GetCoinAge(txdb, nCoinAge))
+ return false;
+ nCredit += GetProofOfStakeReward(nCoinAge);
+ }
+ // 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;
+ }
+ }
+ return true;
+}
+
// Call after CreateTransaction unless you want to abort
bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
{
printf("SendMoney() : %s", strError.c_str());
return strError;
}
+ if (fWalletUnlockStakeOnly)
+ {
+ string strError = _("Error: Wallet unlocked for coinstake only, unable to create transaction.");
+ printf("SendMoney() : %s", strError.c_str());
+ return strError;
+ }
if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
{
string strError;