X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fwallet.cpp;h=1e769d7e615c1f5aa48702a54bbdf58d37c6539a;hb=882164196e5b1971313493f95a6d027f05e2ec92;hp=28babdb3e2c8a778a7d63771e0557e2bec86a7eb;hpb=94f778bdebe1438fbe0206621ce44b4e25196e59;p=novacoin.git diff --git a/src/wallet.cpp b/src/wallet.cpp index 28babdb..1e769d7 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1,5 +1,5 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2011 The Bitcoin developers +// Copyright (c) 2009-2012 The Bitcoin developers // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. @@ -42,6 +42,15 @@ bool CWallet::AddCryptedKey(const vector &vchPubKey, const vector return false; } +bool CWallet::AddCScript(const CScript& redeemScript) +{ + if (!CCryptoKeyStore::AddCScript(redeemScript)) + return false; + if (!fFileBacked) + return true; + return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript); +} + bool CWallet::Unlock(const SecureString& strWalletPassphrase) { if (!IsLocked()) @@ -224,6 +233,15 @@ void CWallet::WalletUpdateSpent(const CTransaction &tx) } } +void CWallet::MarkDirty() +{ + CRITICAL_BLOCK(cs_wallet) + { + BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet) + item.second.MarkDirty(); + } +} + bool CWallet::AddToWallet(const CWalletTx& wtxIn) { uint256 hash = wtxIn.GetHash(); @@ -232,7 +250,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) // Inserts only if not already there, returns tx inserted or tx found pair::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn)); CWalletTx& wtx = (*ret.first).second; - wtx.pwallet = this; + wtx.BindWallet(this); bool fInsertedNew = ret.second; if (fInsertedNew) wtx.nTimeReceived = GetAdjustedTime(); @@ -299,7 +317,7 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn) // Add a transaction to the wallet, or update it. // pblock is optional, but should be provided if the transaction is known to be in a block. // If fUpdate is true, existing transactions will be updated. -bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate) +bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock) { uint256 hash = tx.GetHash(); CRITICAL_BLOCK(cs_wallet) @@ -365,6 +383,24 @@ int64 CWallet::GetDebit(const CTxIn &txin) const return 0; } +bool CWallet::IsChange(const CTxOut& txout) const +{ + CBitcoinAddress address; + + // TODO: fix handling of 'change' outputs. The assumption is that any + // payment to a TX_PUBKEYHASH that is mine but isn't in the address book + // is change. That assumption is likely to break when we implement multisignature + // wallets that return change back into a multi-signature-protected address; + // a better way of identifying which outputs are 'the send' and which are + // 'the change' will need to be implemented (maybe extend CWalletTx to remember + // which output, if any, was change). + if (ExtractAddress(txout.scriptPubKey, address) && HaveKey(address)) + CRITICAL_BLOCK(cs_wallet) + if (!mapAddressBook.count(address)) + return true; + return false; +} + int64 CWalletTx::GetTxTime() const { return nTimeReceived; @@ -434,13 +470,12 @@ void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, l nFee = nDebit - nValueOut; } - // Sent/received. Standard client will never generate a send-to-multiple-recipients, - // but non-standard clients might (so return a list of address/amount pairs) + // Sent/received. BOOST_FOREACH(const CTxOut& txout, vout) { CBitcoinAddress address; vector vchPubKey; - if (!ExtractAddress(txout.scriptPubKey, NULL, address)) + if (!ExtractAddress(txout.scriptPubKey, address)) { printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n", this->GetHash().ToString().c_str()); @@ -586,6 +621,15 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate) return ret; } +int CWallet::ScanForWalletTransaction(const uint256& hashTx) +{ + CTransaction tx; + tx.ReadFromDisk(COutPoint(hashTx, 0)); + if (AddToWalletIfInvolvingMe(tx, NULL, true, true)) + return 1; + return 0; +} + void CWallet::ReacceptWalletTransactions() { CTxDB txdb("r"); @@ -764,7 +808,7 @@ bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfThe // List of values less than target pair > coinLowestLarger; - coinLowestLarger.first = INT64_MAX; + coinLowestLarger.first = std::numeric_limits::max(); coinLowestLarger.second.first = NULL; vector > > vValue; int64 nTotalLower = 0; @@ -924,7 +968,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW if (vecSend.empty() || nValue < 0) return false; - wtxNew.pwallet = this; + wtxNew.BindWallet(this); CRITICAL_BLOCK(cs_main) CRITICAL_BLOCK(cs_wallet) @@ -959,6 +1003,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW int64 nChange = nValueIn - nValue - nFeeRet; // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE // or until nChange becomes zero + // NOTE: this depends on the exact behaviour of GetMinFee if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT) { int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet); @@ -979,12 +1024,11 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW vector vchPubKey = reservekey.GetReservedKey(); // assert(mapKeys.count(vchPubKey)); - // Fill a vout to ourself, using same address type as the payment + // Fill a vout to ourself + // TODO: pass in scriptChange instead of reservekey so + // change transaction isn't always pay-to-bitcoin-address CScript scriptChange; - if (vecSend[0].first.GetBitcoinAddress().IsValid()) - scriptChange.SetBitcoinAddress(vchPubKey); - else - scriptChange << vchPubKey << OP_CHECKSIG; + scriptChange.SetBitcoinAddress(vchPubKey); // Insert change txn at random position: vector::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()); @@ -1012,7 +1056,7 @@ bool CWallet::CreateTransaction(const vector >& vecSend, CW // 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, fAllowFree, GMF_SEND); if (nFeeRet < max(nPayFee, nMinFee)) { nFeeRet = max(nPayFee, nMinFee); @@ -1062,7 +1106,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) BOOST_FOREACH(const CTxIn& txin, wtxNew.vin) { CWalletTx &coin = mapWallet[txin.prevout.hash]; - coin.pwallet = this; + coin.BindWallet(this); coin.MarkSpent(txin.prevout.n); coin.WriteToDisk(); vWalletUpdated.push_back(coin.GetHash()); @@ -1325,6 +1369,22 @@ void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool) } } +int64 CWallet::AddReserveKey(const CKeyPool& keypool) +{ + CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(cs_wallet) + { + CWalletDB walletdb(strWalletFile); + + int64 nIndex = 1 + *(--setKeyPool.end()); + if (!walletdb.WritePool(nIndex, keypool)) + throw runtime_error("AddReserveKey() : writing added key failed"); + setKeyPool.insert(nIndex); + return nIndex; + } + return -1; +} + void CWallet::KeepKey(int64 nIndex) { // Remove from key pool @@ -1413,3 +1473,23 @@ void CReserveKey::ReturnKey() vchPubKey.clear(); } +void CWallet::GetAllReserveAddresses(set& setAddress) +{ + setAddress.clear(); + + CWalletDB walletdb(strWalletFile); + + CRITICAL_BLOCK(cs_main) + CRITICAL_BLOCK(cs_wallet) + BOOST_FOREACH(const int64& id, setKeyPool) + { + CKeyPool keypool; + if (!walletdb.ReadPool(id, keypool)) + throw runtime_error("GetAllReserveKeyHashes() : read failed"); + CBitcoinAddress address(keypool.vchPubKey); + assert(!keypool.vchPubKey.empty()); + if (!HaveKey(address)) + throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool"); + setAddress.insert(address); + } +}