-// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2011 Satoshi Nakamoto
// Copyright (c) 2011 The Bitcoin 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;
}
-bool CWallet::Unlock(const string& strWalletPassphrase)
+bool CWallet::Unlock(const SecureString& strWalletPassphrase)
{
if (!IsLocked())
return false;
return false;
}
-bool CWallet::ChangeWalletPassphrase(const string& strOldWalletPassphrase, const string& strNewWalletPassphrase)
+bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
{
bool fWasLocked = IsLocked();
)
};
-bool CWallet::EncryptWallet(const string& strWalletPassphrase)
+bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
{
if (IsCrypted())
return false;
// Need to completely rewrite the wallet file; if we don't, bdb might keep
// bits of the unencrypted private key in slack space in the database file.
- if (CDB::Rewrite(strWalletFile))
- RemoveLogFilesOnShutdown(true);
+ CDB::Rewrite(strWalletFile);
}
return true;
CWalletTx& wtx = (*mi).second;
if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
{
- printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ printf("WalletUpdateSpent found spent coin %sppc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkSpent(txin.prevout.n);
wtx.WriteToDisk();
vWalletUpdated.push_back(txin.prevout.hash);
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;
}
if (fUpdated)
{
- printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ printf("ReacceptWalletTransactions found spent coin %sppc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkDirty();
wtx.WriteToDisk();
}
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))
return nTotal;
}
-bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
+// ppcoin: total coins staked (non-spendable until maturity)
+int64 CWallet::GetStake() const
+{
+ int64 nTotal = 0;
+ CRITICAL_BLOCK(cs_wallet)
+ {
+ for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+ {
+ const CWalletTx* pcoin = &(*it).second;
+ if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)
+ nTotal += CWallet::GetCredit(*pcoin);
+ }
+ }
+ return nTotal;
+}
+
+bool CWallet::SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
setCoinsRet.clear();
nValueRet = 0;
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();
if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
continue;
+ if (pcoin->nTime > nSpendTime)
+ continue; // ppcoin: timestamp must not exceed spend time
+
int64 n = pcoin->vout[i].nValue;
if (n <= 0)
return true;
}
-bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
+bool CWallet::SelectCoins(int64 nTargetValue, unsigned int nSpendTime, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{
- return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
- SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
- SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
+ return (SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 6, setCoinsRet, nValueRet) ||
+ SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 1, setCoinsRet, nValueRet) ||
+ SelectCoinsMinConf(nTargetValue, nSpendTime, 0, 1, setCoinsRet, nValueRet));
}
// Choose coins to use
set<pair<const CWalletTx*,unsigned int> > setCoins;
int64 nValueIn = 0;
- if (!SelectCoins(nTotalValue, setCoins, nValueIn))
+ if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn))
return false;
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
{
// Check that enough fee is included
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
- bool fAllowFree = CTransaction::AllowFree(dPriority);
- int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree);
+ int64 nMinFee = wtxNew.GetMinFee(1, false);
if (nFeeRet < max(nPayFee, nMinFee))
{
nFeeRet = max(nPayFee, nMinFee);
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
+ 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;
+ 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)
{
{
if (CDB::Rewrite(strWalletFile, "\x04pool"))
{
- RemoveLogFilesOnShutdown(true);
setKeyPool.clear();
// Note: can't top-up keypool here, because wallet is locked.
// User will be prompted to unlock wallet the next operation