From c8988460a2865b99ee96da6799d37ac6ccb79d4d Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 26 Jul 2013 01:06:01 +0200 Subject: Add support for watch-only addresses Changes: * Add Add/Have WatchOnly methods to CKeyStore, and implementations in CBasicKeyStore. * Add similar methods to CWallet, and support entries for it in CWalletDB. * Make IsMine in script/wallet return a new enum 'isminetype', rather than a boolean. This allows distinguishing between spendable and unspendable coins. * Add a field fSpendable to COutput (GetAvailableCoins' return type). * Mark watchonly coins in listunspent as 'watchonly': true. * Add 'watchonly' to validateaddress, suppressing script/pubkey/... in this case. Based on a patch by Eric Lombrozo. Conflicts: src/qt/walletmodel.cpp src/rpcserver.cpp src/wallet.cpp --- src/keystore.cpp | 12 +++++++++++ src/keystore.h | 19 +++++++++++++++++ src/qt/walletmodel.cpp | 6 +++--- src/rpcclient.cpp | 1 + src/rpcdump.cpp | 45 ++++++++++++++++++++++++++++++++++++++++ src/rpcmisc.cpp | 52 ++++++++++++++++++++++++++++------------------- src/rpcrawtransaction.cpp | 1 + src/rpcserver.cpp | 1 + src/rpcserver.h | 1 + src/script.cpp | 52 +++++++++++++++++++++++++++++++++++------------ src/script.h | 12 +++++++++-- src/test/wallet_tests.cpp | 2 +- src/wallet.cpp | 35 +++++++++++++++++++++++-------- src/wallet.h | 14 +++++++++---- src/walletdb.cpp | 19 +++++++++++++++++ src/walletdb.h | 3 +++ 16 files changed, 223 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/keystore.cpp b/src/keystore.cpp index 594e0c61da..c2ea1ce5a9 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -59,3 +59,15 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) return false; } +bool CBasicKeyStore::AddWatchOnly(const CTxDestination &dest) +{ + LOCK(cs_KeyStore); + setWatchOnly.insert(dest); + return true; +} + +bool CBasicKeyStore::HaveWatchOnly(const CTxDestination &dest) const +{ + LOCK(cs_KeyStore); + return setWatchOnly.count(dest) > 0; +} diff --git a/src/keystore.h b/src/keystore.h index 79d8661aca..90fc3a4c7b 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -8,11 +8,21 @@ #include "key.h" #include "sync.h" +#include "script.h" // for CNoDestination #include +#include class CScript; +/** A txout script template with a specific destination. It is either: + * * CNoDestination: no destination set + * * CKeyID: TX_PUBKEYHASH destination + * * CScriptID: TX_SCRIPTHASH destination + * A CTxDestination is the internal data type encoded in a CBitcoinAddress + */ +typedef boost::variant CTxDestination; + /** A virtual base class for key stores */ class CKeyStore { @@ -36,10 +46,15 @@ public: virtual bool AddCScript(const CScript& redeemScript) =0; virtual bool HaveCScript(const CScriptID &hash) const =0; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; + + // Support for Watch-only addresses + virtual bool AddWatchOnly(const CTxDestination &dest) =0; + virtual bool HaveWatchOnly(const CTxDestination &dest) const =0; }; typedef std::map KeyMap; typedef std::map ScriptMap; +typedef std::set WatchOnlySet; /** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore @@ -47,6 +62,7 @@ class CBasicKeyStore : public CKeyStore protected: KeyMap mapKeys; ScriptMap mapScripts; + WatchOnlySet setWatchOnly; public: bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey); @@ -88,6 +104,9 @@ public: virtual bool AddCScript(const CScript& redeemScript); virtual bool HaveCScript(const CScriptID &hash) const; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const; + + virtual bool AddWatchOnly(const CTxDestination &dest); + virtual bool HaveWatchOnly(const CTxDestination &dest) const; }; typedef std::vector > CKeyingMaterial; diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index defc815def..d32e74b78a 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -543,7 +543,7 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); if (nDepth < 0) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); vOutputs.push_back(out); } } @@ -570,7 +570,7 @@ void WalletModel::listCoins(std::map >& mapCoins) if (!wallet->mapWallet.count(outpoint.hash)) continue; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain(); if (nDepth < 0) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); vCoins.push_back(out); } @@ -581,7 +581,7 @@ void WalletModel::listCoins(std::map >& mapCoins) while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0])) { if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break; - cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0); + cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true); } CTxDestination address; diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 501940a730..76c99e7c9f 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -72,6 +72,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "lockunspent", 0 }, { "lockunspent", 1 }, { "importprivkey", 2 }, + { "importaddress", 2 }, { "verifychain", 0 }, { "verifychain", 1 }, { "keypoolrefill", 0 }, diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 593e0d2b6b..5b325c46ee 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -133,6 +133,51 @@ Value importprivkey(const Array& params, bool fHelp) return Value::null; } +Value importaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 3) + throw runtime_error( + "importaddress
[label] [rescan=true]\n" + "Adds an address that can be watched as if it were in your wallet but cannot be used to spend."); + + CBitcoinAddress address(params[0].get_str()); + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); + CTxDestination dest; + dest = address.Get(); + + string strLabel = ""; + if (params.size() > 1) + strLabel = params[1].get_str(); + + // Whether to perform rescan after import + bool fRescan = true; + if (params.size() > 2) + fRescan = params[2].get_bool(); + + { + LOCK2(cs_main, pwalletMain->cs_wallet); + + // Don't throw error in case an address is already there + if (pwalletMain->HaveWatchOnly(dest)) + return Value::null; + + pwalletMain->MarkDirty(); + pwalletMain->SetAddressBook(dest, strLabel, "receive"); + + if (!pwalletMain->AddWatchOnly(dest)) + throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); + + if (fRescan) + { + pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true); + pwalletMain->ReacceptWalletTransactions(); + } + } + + return Value::null; +} + Value importwallet(const Array& params, bool fHelp) { if (fHelp || params.size() != 1) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 5b470516a1..e2de2dbcdb 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -92,36 +92,45 @@ Value getinfo(const Array& params, bool fHelp) #ifdef ENABLE_WALLET class DescribeAddressVisitor : public boost::static_visitor { +private: + isminetype mine; + public: + DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {} + Object operator()(const CNoDestination &dest) const { return Object(); } Object operator()(const CKeyID &keyID) const { Object obj; CPubKey vchPubKey; - pwalletMain->GetPubKey(keyID, vchPubKey); obj.push_back(Pair("isscript", false)); - obj.push_back(Pair("pubkey", HexStr(vchPubKey))); - obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); + if (mine == MINE_SPENDABLE) { + pwalletMain->GetPubKey(keyID, vchPubKey); + obj.push_back(Pair("pubkey", HexStr(vchPubKey))); + obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); + } return obj; } Object operator()(const CScriptID &scriptID) const { Object obj; obj.push_back(Pair("isscript", true)); - CScript subscript; - pwalletMain->GetCScript(scriptID, subscript); - std::vector addresses; - txnouttype whichType; - int nRequired; - ExtractDestinations(subscript, whichType, addresses, nRequired); - obj.push_back(Pair("script", GetTxnOutputType(whichType))); - obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); - Array a; - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); - obj.push_back(Pair("addresses", a)); - if (whichType == TX_MULTISIG) - obj.push_back(Pair("sigsrequired", nRequired)); + if (mine == MINE_SPENDABLE) { + CScript subscript; + pwalletMain->GetCScript(scriptID, subscript); + std::vector addresses; + txnouttype whichType; + int nRequired; + ExtractDestinations(subscript, whichType, addresses, nRequired); + obj.push_back(Pair("script", GetTxnOutputType(whichType))); + obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); + Array a; + BOOST_FOREACH(const CTxDestination& addr, addresses) + a.push_back(CBitcoinAddress(addr).ToString()); + obj.push_back(Pair("addresses", a)); + if (whichType == TX_MULTISIG) + obj.push_back(Pair("sigsrequired", nRequired)); + } return obj; } }; @@ -161,10 +170,11 @@ Value validateaddress(const Array& params, bool fHelp) string currentAddress = address.ToString(); ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET - bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false; - ret.push_back(Pair("ismine", fMine)); - if (fMine) { - Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest); + isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; + ret.push_back(Pair("ismine", mine != MINE_NO)); + if (mine != MINE_NO) { + ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY)); + Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); ret.insert(ret.end(), detail.begin(), detail.end()); } if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) diff --git a/src/rpcrawtransaction.cpp b/src/rpcrawtransaction.cpp index 9771f8e685..da4bde3975 100644 --- a/src/rpcrawtransaction.cpp +++ b/src/rpcrawtransaction.cpp @@ -304,6 +304,7 @@ Value listunspent(const Array& params, bool fHelp) } entry.push_back(Pair("amount",ValueFromAmount(nValue))); entry.push_back(Pair("confirmations",out.nDepth)); + entry.push_back(Pair("spendable", out.fSpendable)); results.push_back(entry); } diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index f47b3385da..363403c69e 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -282,6 +282,7 @@ static const CRPCCommand vRPCCommands[] = { "getwalletinfo", &getwalletinfo, true, false, true }, { "importprivkey", &importprivkey, false, false, true }, { "importwallet", &importwallet, false, false, true }, + { "importaddress", &importaddress, false, false, true }, { "keypoolrefill", &keypoolrefill, true, false, true }, { "listaccounts", &listaccounts, false, false, true }, { "listaddressgroupings", &listaddressgroupings, false, false, true }, diff --git a/src/rpcserver.h b/src/rpcserver.h index 01e77163c4..e32eb975a1 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -131,6 +131,7 @@ extern json_spirit::Value getnettotals(const json_spirit::Array& params, bool fH extern json_spirit::Value dumpprivkey(const json_spirit::Array& params, bool fHelp); // in rpcdump.cpp extern json_spirit::Value importprivkey(const json_spirit::Array& params, bool fHelp); +extern json_spirit::Value importaddress(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value dumpwallet(const json_spirit::Array& params, bool fHelp); extern json_spirit::Value importwallet(const json_spirit::Array& params, bool fHelp); diff --git a/src/script.cpp b/src/script.cpp index e1b6985408..0ef0126255 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1456,36 +1456,57 @@ public: bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); } }; -bool IsMine(const CKeyStore &keystore, const CTxDestination &dest) +isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest) { - return boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest); + if (boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest)) + return MINE_SPENDABLE; + if (keystore.HaveWatchOnly(dest)) + return MINE_WATCH_ONLY; + return MINE_NO; } -bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) +isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) { vector vSolutions; txnouttype whichType; - if (!Solver(scriptPubKey, whichType, vSolutions)) - return false; + if (!Solver(scriptPubKey, whichType, vSolutions)) { + if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + return MINE_WATCH_ONLY; + return MINE_NO; + } CKeyID keyID; switch (whichType) { case TX_NONSTANDARD: case TX_NULL_DATA: - return false; + break; case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); - return keystore.HaveKey(keyID); + if (keystore.HaveKey(keyID)) + return MINE_SPENDABLE; + if (keystore.HaveWatchOnly(keyID)) + return MINE_WATCH_ONLY; + break; case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); - return keystore.HaveKey(keyID); + if (keystore.HaveKey(keyID)) + return MINE_SPENDABLE; + if (keystore.HaveWatchOnly(keyID)) + return MINE_WATCH_ONLY; + break; case TX_SCRIPTHASH: { + CScriptID scriptID = CScriptID(uint160(vSolutions[0])); CScript subscript; - if (!keystore.GetCScript(CScriptID(uint160(vSolutions[0])), subscript)) - return false; - return IsMine(keystore, subscript); + if (keystore.GetCScript(scriptID, subscript)) { + isminetype ret = IsMine(keystore, subscript); + if (ret) + return ret; + } + if (keystore.HaveWatchOnly(scriptID)) + return MINE_WATCH_ONLY; + break; } case TX_MULTISIG: { @@ -1495,10 +1516,15 @@ bool IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) // them) enable spend-out-from-under-you attacks, especially // in shared-wallet situations. vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); - return HaveKeys(keys, keystore) == keys.size(); + if (HaveKeys(keys, keystore) == keys.size()) + return MINE_SPENDABLE; + break; } } - return false; + + if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + return MINE_WATCH_ONLY; + return MINE_NO; } bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) diff --git a/src/script.h b/src/script.h index 7ab471f6e6..1db758094e 100644 --- a/src/script.h +++ b/src/script.h @@ -194,6 +194,14 @@ enum SCRIPT_VERIFY_NULLDUMMY = (1U << 4), // verify dummy stack item consumed by CHECKMULTISIG is of zero-length }; +/** IsMine() return codes */ +enum isminetype +{ + MINE_NO = 0, + MINE_WATCH_ONLY = 1, + MINE_SPENDABLE = 2, +}; + // Mandatory script verification flags that all new blocks must comply with for // them to be valid. (but old blocks may not comply with) Currently just P2SH, // but in the future other flags may be added, such as a soft-fork to enforce @@ -801,8 +809,8 @@ bool EvalScript(std::vector >& stack, const CScript& bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutionsRet); int ScriptSigArgsExpected(txnouttype t, const std::vector >& vSolutions); bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); -bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); -bool IsMine(const CKeyStore& keystore, const CTxDestination &dest); +isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); +isminetype IsMine(const CKeyStore& keystore, const CTxDestination &dest); void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector &vKeys); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet); diff --git a/src/test/wallet_tests.cpp b/src/test/wallet_tests.cpp index 86a83f5163..3887efbd0d 100644 --- a/src/test/wallet_tests.cpp +++ b/src/test/wallet_tests.cpp @@ -46,7 +46,7 @@ static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, in wtx->fDebitCached = true; wtx->nDebitCached = 1; } - COutput output(wtx, nInput, nAge); + COutput output(wtx, nInput, nAge, true); vCoins.push_back(output); } diff --git a/src/wallet.cpp b/src/wallet.cpp index daca7ac04b..3d679f4c56 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -145,6 +145,22 @@ bool CWallet::LoadCScript(const CScript& redeemScript) return CCryptoKeyStore::AddCScript(redeemScript); } +bool CWallet::AddWatchOnly(const CTxDestination &dest) +{ + if (!CCryptoKeyStore::AddWatchOnly(dest)) + return false; + nTimeFirstKey = 1; // No birthday information for watch-only keys. + if (!fFileBacked) + return true; + return CWalletDB(strWalletFile).WriteWatchOnly(dest); +} + +bool CWallet::LoadWatchOnly(const CTxDestination &dest) +{ + LogPrintf("Loaded %s!\n", CBitcoinAddress(dest).ToString().c_str()); + return CCryptoKeyStore::AddWatchOnly(dest); +} + bool CWallet::Unlock(const SecureString& strWalletPassphrase) { CCrypter crypter; @@ -680,7 +696,7 @@ void CWallet::EraseFromWallet(const uint256 &hash) } -bool CWallet::IsMine(const CTxIn &txin) const +isminetype CWallet::IsMine(const CTxIn &txin) const { { LOCK(cs_wallet); @@ -689,11 +705,10 @@ bool CWallet::IsMine(const CTxIn &txin) const { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.vout.size()) - if (IsMine(prev.vout[txin.prevout.n])) - return true; + return IsMine(prev.vout[txin.prevout.n]); } } - return false; + return MINE_NO; } int64_t CWallet::GetDebit(const CTxIn &txin) const @@ -1051,7 +1066,7 @@ int64_t CWallet::GetImmatureBalance() const return nTotal; } -// populate vCoins with vector of spendable COutputs +// populate vCoins with vector of available COutputs. void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const { vCoins.clear(); @@ -1077,10 +1092,11 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) { - if (!(IsSpent(wtxid, i)) && IsMine(pcoin->vout[i]) && + isminetype mine = IsMine(pcoin->vout[i]); + if (!(IsSpent(wtxid, i)) && mine != MINE_NO && !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) - vCoins.push_back(COutput(pcoin, i, nDepth)); + vCoins.push_back(COutput(pcoin, i, nDepth, mine & MINE_SPENDABLE)); } } } @@ -1147,8 +1163,11 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt); - BOOST_FOREACH(COutput output, vCoins) + BOOST_FOREACH(const COutput &output, vCoins) { + if (!output.fSpendable) + continue; + const CWalletTx *pcoin = output.tx; if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) diff --git a/src/wallet.h b/src/wallet.h index 1c2512d678..ff6af3a6a8 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -226,6 +226,11 @@ public: /// Look up a destination data tuple in the store, return true if found false otherwise bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const; + // Adds a watch-only address to the store, and saves it to disk. + bool AddWatchOnly(const CTxDestination &dest); + // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) + bool LoadWatchOnly(const CTxDestination &dest); + bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); bool EncryptWallet(const SecureString& strWalletPassphrase); @@ -279,9 +284,9 @@ public: std::set GetAccountAddresses(std::string strAccount) const; - bool IsMine(const CTxIn& txin) const; + isminetype IsMine(const CTxIn& txin) const; int64_t GetDebit(const CTxIn& txin) const; - bool IsMine(const CTxOut& txout) const + isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } @@ -722,10 +727,11 @@ public: const CWalletTx *tx; int i; int nDepth; + bool fSpendable; - COutput(const CWalletTx *txIn, int iIn, int nDepthIn) + COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn) { - tx = txIn; i = iIn; nDepth = nDepthIn; + tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn; } std::string ToString() const diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 3ce2ef019c..9338d57097 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -112,6 +112,12 @@ bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false); } +bool CWalletDB::WriteWatchOnly(const CTxDestination &dest) +{ + nWalletDBUpdated++; + return Write(std::make_pair(std::string("watch"), CBitcoinAddress(dest).ToString()), '1'); +} + bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) { nWalletDBUpdated++; @@ -404,6 +410,19 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; } } + else if (strType == "watch") + { + std::string strAddress; + ssKey >> strAddress; + char fYes; + ssValue >> fYes; + if (fYes == '1') + pwallet->LoadWatchOnly(CBitcoinAddress(strAddress).Get()); + + // Watch-only addresses have no birthday information for now, + // so set the wallet birthday to the beginning of time. + pwallet->nTimeFirstKey = 1; + } else if (strType == "key" || strType == "wkey") { CPubKey vchPubKey; diff --git a/src/walletdb.h b/src/walletdb.h index 8eb716acbb..3a6cb152a1 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -7,6 +7,7 @@ #include "db.h" #include "key.h" +#include "keystore.h" #include #include @@ -93,6 +94,8 @@ public: bool WriteCScript(const uint160& hash, const CScript& redeemScript); + bool WriteWatchOnly(const CTxDestination &dest); + bool WriteBestBlock(const CBlockLocator& locator); bool ReadBestBlock(CBlockLocator& locator); -- cgit v1.2.3 From 2935b211033610d7ef0deef9bf1b344a5bac029f Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 10 Dec 2013 15:27:53 +0100 Subject: qt: Hide unspendable outputs in coin control --- src/qt/walletmodel.cpp | 6 ++++-- src/wallet.cpp | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index d32e74b78a..098d39e8a7 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -60,7 +60,8 @@ qint64 WalletModel::getBalance(const CCoinControl *coinControl) const std::vector vCoins; wallet->AvailableCoins(vCoins, true, coinControl); BOOST_FOREACH(const COutput& out, vCoins) - nBalance += out.tx->vout[out.i].nValue; + if(out.fSpendable) + nBalance += out.tx->vout[out.i].nValue; return nBalance; } @@ -585,7 +586,8 @@ void WalletModel::listCoins(std::map >& mapCoins) } CTxDestination address; - if(!ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) continue; + if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address)) + continue; mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out); } } diff --git a/src/wallet.cpp b/src/wallet.cpp index 3d679f4c56..40ace9c40b 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1259,6 +1259,8 @@ bool CWallet::SelectCoins(int64_t nTargetValue, setvout[out.i].nValue; setCoinsRet.insert(make_pair(out.tx, out.i)); } -- cgit v1.2.3 From ffd40da361639faeef405c7e4a504a340d77aa5b Mon Sep 17 00:00:00 2001 From: JaSK Date: Sat, 29 Mar 2014 05:15:28 +0100 Subject: Watchonly balances are shown separately in gui. --- src/qt/forms/overviewpage.ui | 533 ++++++++++++++++++++++++++++--------------- src/qt/overviewpage.cpp | 34 ++- src/qt/overviewpage.h | 6 +- src/qt/sendcoinsdialog.cpp | 13 +- src/qt/sendcoinsdialog.h | 3 +- src/qt/transactiondesc.cpp | 64 ++++-- src/qt/transactionrecord.cpp | 17 +- src/qt/walletmodel.cpp | 27 ++- src/qt/walletmodel.h | 9 +- src/rpcdump.cpp | 4 +- src/rpcmisc.cpp | 2 +- src/script.h | 2 + src/wallet.cpp | 53 ++++- src/wallet.h | 71 +++++- 14 files changed, 601 insertions(+), 237 deletions(-) (limited to 'src') diff --git a/src/qt/forms/overviewpage.ui b/src/qt/forms/overviewpage.ui index e662912781..8784da5f3e 100644 --- a/src/qt/forms/overviewpage.ui +++ b/src/qt/forms/overviewpage.ui @@ -6,7 +6,7 @@ 0 0 - 573 + 596 342 @@ -46,204 +46,369 @@ - - - - 75 - true - - - - Wallet - - - - - - - The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. - - - QLabel { color: red; } - - - (out of sync) - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - + + + + + + 75 + true + + + + Wallet + + + + + + + The displayed information may be out of date. Your wallet automatically synchronizes with the Bitcoin network after a connection is established, but this process has not completed yet. + + + QLabel { color: red; } + + + (out of sync) + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + + 75 + true + + + + Watchonly: + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + - - - - - QFormLayout::AllNonFixedFieldsGrow - - - 12 - - - 12 - - - - - Available: - - - - - - - - 75 - true - - - - IBeamCursor - - - Your current spendable balance - - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Pending: - - - - - - - - 75 - true - - - - IBeamCursor - - - Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance - - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Immature: - - - - - - - - 75 - true - - - - Mined balance that has not yet matured - - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - Total: - - - - - - - - 75 - true - - - - IBeamCursor - - - Your current total balance - - - 0 BTC - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - + + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + 12 + + + + + Available: + + + + + + + + 75 + true + + + + IBeamCursor + + + Your current spendable balance + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Pending: + + + + + + + + 75 + true + + + + IBeamCursor + + + Total of transactions that have yet to be confirmed, and do not yet count toward the spendable balance + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Immature: + + + + + + + + 75 + true + + + + IBeamCursor + + + Mined balance that has not yet matured + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + Qt::Horizontal + + + + + + + Total: + + + + + + + + 75 + true + + + + IBeamCursor + + + Your current total balance + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + - - - - Qt::Horizontal - - + + + + QFormLayout::AllNonFixedFieldsGrow + + + 12 + + + 12 + + + + + + 75 + true + + + + IBeamCursor + + + Your current balance in watchonly addresses + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 75 + true + + + + IBeamCursor + + + Unconfirmed transactions to watchonly addresses + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 75 + true + + + + IBeamCursor + + + Mined balance in watchonly addresses that has not yet matured + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + + 140 + 0 + + + + Qt::Horizontal + + + + + + + + 75 + true + + + + IBeamCursor + + + Current total balance in watchonly addresses + + + 0 BTC + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + - - Qt::Horizontal + + QSizePolicy::Expanding + - 40 + 20 20 diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 1a9d1de571..1278f368cf 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -103,6 +103,9 @@ OverviewPage::OverviewPage(QWidget *parent) : currentBalance(-1), currentUnconfirmedBalance(-1), currentImmatureBalance(-1), + currentWatchOnlyBalance(-1), + currentWatchUnconfBalance(-1), + currentWatchImmatureBalance(-1), txdelegate(new TxViewDelegate()), filter(0) { @@ -135,22 +138,39 @@ OverviewPage::~OverviewPage() delete ui; } -void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance) +void OverviewPage::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance) { int unit = walletModel->getOptionsModel()->getDisplayUnit(); currentBalance = balance; currentUnconfirmedBalance = unconfirmedBalance; currentImmatureBalance = immatureBalance; + currentWatchOnlyBalance = watchOnlyBalance; + currentWatchUnconfBalance = watchUnconfBalance; + currentWatchImmatureBalance = watchImmatureBalance; ui->labelBalance->setText(BitcoinUnits::formatWithUnit(unit, balance)); ui->labelUnconfirmed->setText(BitcoinUnits::formatWithUnit(unit, unconfirmedBalance)); ui->labelImmature->setText(BitcoinUnits::formatWithUnit(unit, immatureBalance)); ui->labelTotal->setText(BitcoinUnits::formatWithUnit(unit, balance + unconfirmedBalance + immatureBalance)); + ui->labelWatchAvailable->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance)); + ui->labelWatchPending->setText(BitcoinUnits::formatWithUnit(unit, watchUnconfBalance)); + ui->labelWatchImmature->setText(BitcoinUnits::formatWithUnit(unit, watchImmatureBalance)); + ui->labelWatchTotal->setText(BitcoinUnits::formatWithUnit(unit, watchOnlyBalance + watchUnconfBalance + watchImmatureBalance)); // only show immature (newly mined) balance if it's non-zero, so as not to complicate things // for the non-mining users bool showImmature = immatureBalance != 0; - ui->labelImmature->setVisible(showImmature); - ui->labelImmatureText->setVisible(showImmature); + bool showWatchOnlyImmature = watchImmatureBalance != 0; + bool showWatchOnly = (watchOnlyBalance != 0 || watchUnconfBalance != 0 || showWatchOnlyImmature); + + // for symmetry reasons also show immature label when the watchonly one is shown + ui->labelImmature->setVisible(showImmature || showWatchOnlyImmature); + ui->labelImmatureText->setVisible(showImmature || showWatchOnlyImmature); + ui->labelWatchonly->setVisible(showWatchOnly); // show Watchonly label + ui->lineWatchBalance->setVisible(showWatchOnly); // show watchonly balance separator line + ui->labelWatchAvailable->setVisible(showWatchOnly); // show watchonly available balance + ui->labelWatchImmature->setVisible(showWatchOnlyImmature); // show watchonly immature balance + ui->labelWatchPending->setVisible(showWatchOnly); // show watchonly pending balance + ui->labelWatchTotal->setVisible(showWatchOnly); // show watchonly total balance } void OverviewPage::setClientModel(ClientModel *model) @@ -182,8 +202,9 @@ void OverviewPage::setWalletModel(WalletModel *model) ui->listTransactions->setModelColumn(TransactionTableModel::ToAddress); // Keep up to date with wallet - setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64))); + setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), + model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); } @@ -197,7 +218,8 @@ void OverviewPage::updateDisplayUnit() if(walletModel && walletModel->getOptionsModel()) { if(currentBalance != -1) - setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance); + setBalance(currentBalance, currentUnconfirmedBalance, currentImmatureBalance, + currentWatchOnlyBalance, currentWatchUnconfBalance, currentWatchImmatureBalance); // Update txdelegate->unit with the current unit txdelegate->unit = walletModel->getOptionsModel()->getDisplayUnit(); diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 2507a3fb31..fe00106770 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -34,7 +34,8 @@ public: void showOutOfSyncWarning(bool fShow); public slots: - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); + void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); signals: void transactionClicked(const QModelIndex &index); @@ -46,6 +47,9 @@ private: qint64 currentBalance; qint64 currentUnconfirmedBalance; qint64 currentImmatureBalance; + qint64 currentWatchOnlyBalance; + qint64 currentWatchUnconfBalance; + qint64 currentWatchImmatureBalance; TxViewDelegate *txdelegate; TransactionFilterProxy *filter; diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index b7d74d7039..6f10ed5b0b 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -90,8 +90,9 @@ void SendCoinsDialog::setModel(WalletModel *model) } } - setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance()); - connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64))); + setBalance(model->getBalance(), model->getUnconfirmedBalance(), model->getImmatureBalance(), + model->getWatchBalance(), model->getWatchUnconfirmedBalance(), model->getWatchImmatureBalance()); + connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64, qint64, qint64))); connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit())); // Coin Control @@ -383,10 +384,14 @@ bool SendCoinsDialog::handlePaymentRequest(const SendCoinsRecipient &rv) return true; } -void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance) +void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchBalance, qint64 watchUnconfirmedBalance, qint64 watchImmatureBalance) { Q_UNUSED(unconfirmedBalance); Q_UNUSED(immatureBalance); + Q_UNUSED(watchBalance); + Q_UNUSED(watchUnconfirmedBalance); + Q_UNUSED(watchImmatureBalance); if(model && model->getOptionsModel()) { @@ -396,7 +401,7 @@ void SendCoinsDialog::setBalance(qint64 balance, qint64 unconfirmedBalance, qint void SendCoinsDialog::updateDisplayUnit() { - setBalance(model->getBalance(), 0, 0); + setBalance(model->getBalance(), 0, 0, 0, 0, 0); } void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn &sendCoinsReturn, const QString &msgArg) diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index fcae26c720..6cdf4a00c8 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -47,7 +47,8 @@ public slots: void accept(); SendCoinsEntry *addEntry(); void updateTabsAndLabels(); - void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); + void setBalance(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); private: Ui::SendCoinsDialog *ui; diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index e48dbcac9d..76dc47318d 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -89,19 +89,27 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (nNet > 0) { // Credit - if (CBitcoinAddress(rec->address).IsValid()) + BOOST_FOREACH(const CTxOut& txout, wtx.vout) { - CTxDestination address = CBitcoinAddress(rec->address).Get(); - if (wallet->mapAddressBook.count(address)) + if (wallet->IsMine(txout)) { - strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; - strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(rec->address); - if (!wallet->mapAddressBook[address].name.empty()) - strHTML += " (" + tr("own address") + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; - else - strHTML += " (" + tr("own address") + ")"; - strHTML += "
"; + if (CBitcoinAddress(rec->address).IsValid()) + { + CTxDestination address = CBitcoinAddress(rec->address).Get(); + if (wallet->mapAddressBook.count(address)) + { + strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; + strHTML += "" + tr("To") + ": "; + strHTML += GUIUtil::HtmlEscape(rec->address); + std::string addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? "own address" : "watch-only"; + if (!wallet->mapAddressBook[address].name.empty()) + strHTML += " (" + tr(addressOwned.c_str()) + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; + else + strHTML += " (" + tr(addressOwned.c_str()) + ")"; + strHTML += "
"; + } + } + break; } } } @@ -148,22 +156,33 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco } else { - bool fAllFromMe = true; + isminetype fAllFromMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) - fAllFromMe = fAllFromMe && wallet->IsMine(txin); + { + isminetype mine = wallet->IsMine(txin); + if(fAllFromMe > mine) fAllFromMe = mine; + } - bool fAllToMe = true; + isminetype fAllToMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - fAllToMe = fAllToMe && wallet->IsMine(txout); + { + isminetype mine = wallet->IsMine(txout); + if(fAllToMe > mine) fAllToMe = mine; + } if (fAllFromMe) { + if(fAllFromMe == MINE_WATCH_ONLY) + strHTML += "" + tr("From") + ": " + tr("watch-only") + "
"; + // // Debit // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { - if (wallet->IsMine(txout)) + // Ignore change + isminetype toSelf = wallet->IsMine(txout); + if ((toSelf == MINE_SPENDABLE) && (fAllFromMe == MINE_SPENDABLE)) continue; if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) @@ -176,11 +195,17 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); + if(toSelf == MINE_SPENDABLE) + strHTML += " (own address)"; + else if(toSelf == MINE_WATCH_ONLY) + strHTML += " (watch-only)"; strHTML += "
"; } } strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -txout.nValue) + "
"; + if(toSelf) + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, txout.nValue) + "
"; } if (fAllToMe) @@ -188,8 +213,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // Payment to self int64_t nChange = wtx.GetChange(); int64_t nValue = nCredit - nChange; - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -nValue) + "
"; - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, nValue) + "
"; + strHTML += "" + tr("Total debit") + ": " + BitcoinUnits::formatWithUnit(unit, -nValue) + "
"; + strHTML += "" + tr("Total credit") + ": " + BitcoinUnits::formatWithUnit(unit, nValue) + "
"; } int64_t nTxFee = nDebit - wtx.GetValueOut(); @@ -286,7 +311,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); } strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue); - strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & MINE_SPENDABLE ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & MINE_WATCH_ONLY ? tr("true") : tr("false")) + ""; } } } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 21f1b7356f..3d77d39893 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -45,7 +45,8 @@ QList TransactionRecord::decomposeTransaction(const CWallet * // BOOST_FOREACH(const CTxOut& txout, wtx.vout) { - if(wallet->IsMine(txout)) + isminetype mine = wallet->IsMine(txout); + if(mine) { TransactionRecord sub(hash, nTime); CTxDestination address; @@ -75,13 +76,19 @@ QList TransactionRecord::decomposeTransaction(const CWallet * } else { - bool fAllFromMe = true; + isminetype fAllFromMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) - fAllFromMe = fAllFromMe && wallet->IsMine(txin); + { + isminetype mine = wallet->IsMine(txin); + if(fAllFromMe > mine) fAllFromMe = mine; + } - bool fAllToMe = true; + isminetype fAllToMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - fAllToMe = fAllToMe && wallet->IsMine(txout); + { + isminetype mine = wallet->IsMine(txout); + if(fAllToMe > mine) fAllToMe = mine; + } if (fAllFromMe && fAllToMe) { diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 098d39e8a7..7317c32766 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -79,6 +79,21 @@ qint64 WalletModel::getImmatureBalance() const return wallet->GetImmatureBalance(); } +qint64 WalletModel::getWatchBalance() const +{ + return wallet->GetWatchOnlyBalance(); +} + +qint64 WalletModel::getWatchUnconfirmedBalance() const +{ + return wallet->GetUnconfirmedWatchOnlyBalance(); +} + +qint64 WalletModel::getWatchImmatureBalance() const +{ + return wallet->GetImmatureWatchOnlyBalance(); +} + int WalletModel::getNumTransactions() const { int numTransactions = 0; @@ -127,13 +142,21 @@ void WalletModel::checkBalanceChanged() qint64 newBalance = getBalance(); qint64 newUnconfirmedBalance = getUnconfirmedBalance(); qint64 newImmatureBalance = getImmatureBalance(); + qint64 newWatchOnlyBalance = getWatchBalance(); + qint64 newWatchUnconfBalance = getWatchUnconfirmedBalance(); + qint64 newWatchImmatureBalance = getWatchImmatureBalance(); - if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance) + if(cachedBalance != newBalance || cachedUnconfirmedBalance != newUnconfirmedBalance || cachedImmatureBalance != newImmatureBalance || + cachedWatchOnlyBalance != newWatchOnlyBalance || cachedWatchUnconfBalance != newWatchUnconfBalance || cachedWatchImmatureBalance != newWatchImmatureBalance) { cachedBalance = newBalance; cachedUnconfirmedBalance = newUnconfirmedBalance; cachedImmatureBalance = newImmatureBalance; - emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance); + cachedWatchOnlyBalance = newWatchOnlyBalance; + cachedWatchUnconfBalance = newWatchUnconfBalance; + cachedWatchImmatureBalance = newWatchImmatureBalance; + emit balanceChanged(newBalance, newUnconfirmedBalance, newImmatureBalance, + newWatchOnlyBalance, newWatchUnconfBalance, newWatchImmatureBalance); } } diff --git a/src/qt/walletmodel.h b/src/qt/walletmodel.h index ccf590aaed..7ad54ff8e6 100644 --- a/src/qt/walletmodel.h +++ b/src/qt/walletmodel.h @@ -128,6 +128,9 @@ public: qint64 getBalance(const CCoinControl *coinControl = NULL) const; qint64 getUnconfirmedBalance() const; qint64 getImmatureBalance() const; + qint64 getWatchBalance() const; + qint64 getWatchUnconfirmedBalance() const; + qint64 getWatchImmatureBalance() const; int getNumTransactions() const; EncryptionStatus getEncryptionStatus() const; @@ -206,6 +209,9 @@ private: qint64 cachedBalance; qint64 cachedUnconfirmedBalance; qint64 cachedImmatureBalance; + qint64 cachedWatchOnlyBalance; + qint64 cachedWatchUnconfBalance; + qint64 cachedWatchImmatureBalance; qint64 cachedNumTransactions; EncryptionStatus cachedEncryptionStatus; int cachedNumBlocks; @@ -218,7 +224,8 @@ private: signals: // Signal that balance in wallet changed - void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance); + void balanceChanged(qint64 balance, qint64 unconfirmedBalance, qint64 immatureBalance, + qint64 watchOnlyBalance, qint64 watchUnconfBalance, qint64 watchImmatureBalance); // Number of transactions in wallet changed void numTransactionsChanged(int count); diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 5b325c46ee..98af4695d6 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -158,12 +158,14 @@ Value importaddress(const Array& params, bool fHelp) { LOCK2(cs_main, pwalletMain->cs_wallet); + // add to address book or update label + pwalletMain->SetAddressBook(dest, strLabel, "receive"); + // Don't throw error in case an address is already there if (pwalletMain->HaveWatchOnly(dest)) return Value::null; pwalletMain->MarkDirty(); - pwalletMain->SetAddressBook(dest, strLabel, "receive"); if (!pwalletMain->AddWatchOnly(dest)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index e2de2dbcdb..3245f7d713 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -171,7 +171,7 @@ Value validateaddress(const Array& params, bool fHelp) ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; - ret.push_back(Pair("ismine", mine != MINE_NO)); + ret.push_back(Pair("ismine", mine == MINE_SPENDABLE)); if (mine != MINE_NO) { ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY)); Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); diff --git a/src/script.h b/src/script.h index 1db758094e..56c7d01d4e 100644 --- a/src/script.h +++ b/src/script.h @@ -201,6 +201,8 @@ enum isminetype MINE_WATCH_ONLY = 1, MINE_SPENDABLE = 2, }; +/** used for bitflags of isminetype */ +typedef uint8_t isminefilter; // Mandatory script verification flags that all new blocks must comply with for // them to be valid. (but old blocks may not comply with) Currently just P2SH, diff --git a/src/wallet.cpp b/src/wallet.cpp index 40ace9c40b..d4e9fe9d18 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -738,7 +738,7 @@ bool CWallet::IsChange(const CTxOut& txout) const // 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 (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address)) + if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address) == MINE_SPENDABLE) { LOCK(cs_wallet); if (!mapAddressBook.count(address)) @@ -793,7 +793,7 @@ int CWalletTx::GetRequestCount() const } void CWalletTx::GetAmounts(list >& listReceived, - list >& listSent, int64_t& nFee, string& strSentAccount) const + list >& listSent, int64_t& nFee, string& strSentAccount, const isminefilter& filter) const { nFee = 0; listReceived.clear(); @@ -820,9 +820,9 @@ void CWalletTx::GetAmounts(list >& listReceived, // Don't report 'change' txouts if (pwallet->IsChange(txout)) continue; - fIsMine = pwallet->IsMine(txout); + fIsMine = (pwallet->IsMine(txout) & filter); } - else if (!(fIsMine = pwallet->IsMine(txout))) + else if (!(fIsMine = (pwallet->IsMine(txout) & filter))) continue; // In either case, we need to get the destination address @@ -1066,6 +1066,51 @@ int64_t CWallet::GetImmatureBalance() const return nTotal; } +int64_t CWallet::GetWatchOnlyBalance() const +{ + int64_t nTotal = 0; + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (pcoin->IsTrusted()) + nTotal += pcoin->GetAvailableWatchOnlyCredit(); + } + } + + return nTotal; +} + +int64_t CWallet::GetUnconfirmedWatchOnlyBalance() const +{ + int64_t nTotal = 0; + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0)) + nTotal += pcoin->GetAvailableWatchOnlyCredit(); + } + } + return nTotal; +} + +int64_t CWallet::GetImmatureWatchOnlyBalance() const +{ + int64_t nTotal = 0; + { + LOCK(cs_wallet); + for (map::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + { + const CWalletTx* pcoin = &(*it).second; + nTotal += pcoin->GetImmatureWatchOnlyCredit(); + } + } + return nTotal; +} + // populate vCoins with vector of available COutputs. void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const { diff --git a/src/wallet.h b/src/wallet.h index ff6af3a6a8..355aa36973 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -262,6 +262,9 @@ public: int64_t GetBalance() const; int64_t GetUnconfirmedBalance() const; int64_t GetImmatureBalance() const; + int64_t GetWatchOnlyBalance() const; + int64_t GetUnconfirmedWatchOnlyBalance() const; + int64_t GetImmatureWatchOnlyBalance() const; bool CreateTransaction(const std::vector >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); bool CreateTransaction(CScript scriptPubKey, int64_t nValue, @@ -290,11 +293,11 @@ public: { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout) const + int64_t GetCredit(const CTxOut& txout, const isminefilter& filter = (MINE_WATCH_ONLY | MINE_SPENDABLE)) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); - return (IsMine(txout) ? txout.nValue : 0); + return ((IsMine(txout) & filter) ? txout.nValue : 0); } bool IsChange(const CTxOut& txout) const; int64_t GetChange(const CTxOut& txout) const @@ -332,12 +335,12 @@ public: } return nDebit; } - int64_t GetCredit(const CTransaction& tx) const + int64_t GetCredit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { int64_t nCredit = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) { - nCredit += GetCredit(txout); + nCredit += GetCredit(txout, filter); if (!MoneyRange(nCredit)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); } @@ -483,11 +486,15 @@ public: mutable bool fCreditCached; mutable bool fImmatureCreditCached; mutable bool fAvailableCreditCached; + mutable bool fImmatureWatchCreditCached; + mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; mutable int64_t nDebitCached; mutable int64_t nCreditCached; mutable int64_t nImmatureCreditCached; mutable int64_t nAvailableCreditCached; + mutable int64_t nImmatureWatchCreditCached; + mutable int64_t nAvailableWatchCreditCached; mutable int64_t nChangeCached; CWalletTx() @@ -524,11 +531,15 @@ public: fCreditCached = false; fImmatureCreditCached = false; fAvailableCreditCached = false; + fImmatureWatchCreditCached = false; + fAvailableWatchCreditCached = false; fChangeCached = false; nDebitCached = 0; nCreditCached = 0; nImmatureCreditCached = 0; nAvailableCreditCached = 0; + nAvailableWatchCreditCached = 0; + nImmatureWatchCreditCached = 0; nChangeCached = 0; nOrderPos = -1; } @@ -581,6 +592,8 @@ public: { fCreditCached = false; fAvailableCreditCached = false; + fAvailableWatchCreditCached = false; + fImmatureWatchCreditCached = false; fDebitCached = false; fChangeCached = false; } @@ -622,7 +635,7 @@ public: { if (fUseCache && fImmatureCreditCached) return nImmatureCreditCached; - nImmatureCreditCached = pwallet->GetCredit(*this); + nImmatureCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE); fImmatureCreditCached = true; return nImmatureCreditCached; } @@ -649,7 +662,7 @@ public: if (!pwallet->IsSpent(hashTx, i)) { const CTxOut &txout = vout[i]; - nCredit += pwallet->GetCredit(txout); + nCredit += pwallet->GetCredit(txout, MINE_SPENDABLE); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } @@ -660,6 +673,48 @@ public: return nCredit; } + int64_t GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const + { + if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain()) + { + if (fUseCache && fImmatureWatchCreditCached) + return nImmatureWatchCreditCached; + nImmatureWatchCreditCached = pwallet->GetCredit(*this, MINE_WATCH_ONLY); + fImmatureWatchCreditCached = true; + return nImmatureWatchCreditCached; + } + + return 0; + } + + int64_t GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const + { + if (pwallet == 0) + return 0; + + // Must wait until coinbase is safely deep enough in the chain before valuing it + if (IsCoinBase() && GetBlocksToMaturity() > 0) + return 0; + + if (fUseCache && fAvailableWatchCreditCached) + return nAvailableWatchCreditCached; + + int64_t nCredit = 0; + for (unsigned int i = 0; i < vout.size(); i++) + { + if (!pwallet->IsSpent(GetHash(), i)) + { + const CTxOut &txout = vout[i]; + nCredit += pwallet->GetCredit(txout, MINE_WATCH_ONLY); + if (!MoneyRange(nCredit)) + throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); + } + } + + nAvailableWatchCreditCached = nCredit; + fAvailableWatchCreditCached = true; + return nCredit; + } int64_t GetChange() const { @@ -671,7 +726,7 @@ public: } void GetAmounts(std::list >& listReceived, - std::list >& listSent, int64_t& nFee, std::string& strSentAccount) const; + std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, int64_t& nSent, int64_t& nFee) const; @@ -702,7 +757,7 @@ public: if (parent == NULL) return false; const CTxOut& parentOut = parent->vout[txin.prevout.n]; - if (!pwallet->IsMine(parentOut)) + if (pwallet->IsMine(parentOut) != MINE_SPENDABLE) return false; } return true; -- cgit v1.2.3 From d2692f61164730322547871f2124de06ade0436b Mon Sep 17 00:00:00 2001 From: JaSK Date: Sat, 5 Apr 2014 21:36:48 +0200 Subject: Watchonly transactions are marked in transaction history --- src/qt/transactionrecord.cpp | 7 +++++++ src/qt/transactionrecord.h | 3 +++ src/qt/transactiontablemodel.cpp | 11 +++++++---- 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 3d77d39893..1011363f3e 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -70,16 +70,19 @@ QList TransactionRecord::decomposeTransaction(const CWallet * sub.type = TransactionRecord::Generated; } + sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; parts.append(sub); } } } else { + bool involvesWatchAddress = false; isminetype fAllFromMe = MINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { isminetype mine = wallet->IsMine(txin); + if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; } @@ -87,6 +90,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * BOOST_FOREACH(const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); + if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllToMe > mine) fAllToMe = mine; } @@ -97,6 +101,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); + parts.last().involvesWatchAddress = involvesWatchAddress; } else if (fAllFromMe) { @@ -141,6 +146,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * } sub.debit = -nValue; + sub.involvesWatchAddress = involvesWatchAddress; parts.append(sub); } } @@ -150,6 +156,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * // Mixed debit transaction, can't break down payees // parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); + parts.last().involvesWatchAddress = involvesWatchAddress; } } diff --git a/src/qt/transactionrecord.h b/src/qt/transactionrecord.h index 37679cebfa..d3cfa77d97 100644 --- a/src/qt/transactionrecord.h +++ b/src/qt/transactionrecord.h @@ -137,6 +137,9 @@ public: /** Status: can change with block chain update */ TransactionStatus status; + /** Whether the transaction was sent/received with a watch-only address */ + bool involvesWatchAddress; + /** Return the unique identifier for this transaction (part) */ QString getTxID() const; diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index a935752246..c357d26a9d 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -390,19 +390,22 @@ QVariant TransactionTableModel::txAddressDecoration(const TransactionRecord *wtx QString TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx, bool tooltip) const { + // mark transactions involving watch-only addresses: + QString watchAddress = wtx->involvesWatchAddress ? " (w) " : ""; + switch(wtx->type) { case TransactionRecord::RecvFromOther: - return QString::fromStdString(wtx->address); + return QString::fromStdString(wtx->address) + watchAddress; case TransactionRecord::RecvWithAddress: case TransactionRecord::SendToAddress: case TransactionRecord::Generated: - return lookupAddress(wtx->address, tooltip); + return lookupAddress(wtx->address, tooltip) + watchAddress; case TransactionRecord::SendToOther: - return QString::fromStdString(wtx->address); + return QString::fromStdString(wtx->address) + watchAddress; case TransactionRecord::SendToSelf: default: - return tr("(n/a)"); + return tr("(n/a)") + watchAddress; } } -- cgit v1.2.3 From d4640d7d8c3ba373195d33ab75db9c8cb43f8806 Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 8 Apr 2014 15:23:50 +0200 Subject: Added argument to getbalance to include watchonly addresses and fixed errors in balance calculation. --- src/rpcclient.cpp | 1 + src/rpcwallet.cpp | 23 +++++++++++++++-------- src/wallet.cpp | 10 +++++----- src/wallet.h | 52 +++++++++++++++++++++++++++++++++++++++++----------- 4 files changed, 62 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index 76c99e7c9f..ea5ca8e0f6 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -40,6 +40,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listreceivedbyaccount", 0 }, { "listreceivedbyaccount", 1 }, { "getbalance", 1 }, + { "getbalance", 2 }, { "getblockhash", 0 }, { "move", 2 }, { "move", 3 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 38e96133b4..79b438d417 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -557,7 +557,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth) +int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) { int64_t nBalance = 0; @@ -569,7 +569,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi continue; int64_t nReceived, nSent, nFee; - wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee); + wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter); if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth) nBalance += nReceived; @@ -582,18 +582,18 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi return nBalance; } -int64_t GetAccountBalance(const string& strAccount, int nMinDepth) +int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) { CWalletDB walletdb(pwalletMain->strWalletFile); - return GetAccountBalance(walletdb, strAccount, nMinDepth); + return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); } Value getbalance(const Array& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() > 3) throw runtime_error( - "getbalance ( \"account\" minconf )\n" + "getbalance ( \"account\" minconf includeWatchonly )\n" "\nIf account is not specified, returns the server's total available balance.\n" "If account is specified, returns the balance in the account.\n" "Note that the account \"\" is not the same as leaving the parameter out.\n" @@ -601,6 +601,7 @@ Value getbalance(const Array& params, bool fHelp) "\nArguments:\n" "1. \"account\" (string, optional) The selected account, or \"*\" for entire wallet. It may be the default account using \"\".\n" "2. minconf (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n" + "3. includeWatchonly (bool, optional, default=false) Also include balance in watchonly addresses (see 'importaddress')\n" "\nResult:\n" "amount (numeric) The total amount in btc received for this account.\n" "\nExamples:\n" @@ -620,8 +621,14 @@ Value getbalance(const Array& params, bool fHelp) return ValueFromAmount(pwalletMain->GetBalance()); int nMinDepth = 1; + isminefilter filter = MINE_SPENDABLE; if (params.size() > 1) + { nMinDepth = params[1].get_int(); + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + } if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -638,7 +645,7 @@ Value getbalance(const Array& params, bool fHelp) string strSentAccount; list > listReceived; list > listSent; - wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount); + wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); if (wtx.GetDepthInMainChain() >= nMinDepth) { BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64_t)& r, listReceived) @@ -653,7 +660,7 @@ Value getbalance(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, filter); return ValueFromAmount(nBalance); } diff --git a/src/wallet.cpp b/src/wallet.cpp index d4e9fe9d18..3c9aa3306f 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -711,7 +711,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return MINE_NO; } -int64_t CWallet::GetDebit(const CTxIn &txin) const +int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const { { LOCK(cs_wallet); @@ -720,7 +720,7 @@ int64_t CWallet::GetDebit(const CTxIn &txin) const { const CWalletTx& prev = (*mi).second; if (txin.prevout.n < prev.vout.size()) - if (IsMine(prev.vout[txin.prevout.n])) + if (IsMine(prev.vout[txin.prevout.n]) & filter) return prev.vout[txin.prevout.n].nValue; } } @@ -801,7 +801,7 @@ void CWalletTx::GetAmounts(list >& listReceived, strSentAccount = strFromAccount; // Compute fee: - int64_t nDebit = GetDebit(); + int64_t nDebit = GetDebit(filter); if (nDebit > 0) // debit>0 means we signed/sent this transaction { int64_t nValueOut = GetValueOut(); @@ -846,7 +846,7 @@ void CWalletTx::GetAmounts(list >& listReceived, } void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee) const + int64_t& nSent, int64_t& nFee, const isminefilter& filter) const { nReceived = nSent = nFee = 0; @@ -854,7 +854,7 @@ void CWalletTx::GetAccountAmounts(const string& strAccount, int64_t& nReceived, string strSentAccount; list > listReceived; list > listSent; - GetAmounts(listReceived, listSent, allFee, strSentAccount); + GetAmounts(listReceived, listSent, allFee, strSentAccount, filter); if (strAccount == strSentAccount) { diff --git a/src/wallet.h b/src/wallet.h index 355aa36973..b11e6c662e 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -288,12 +288,12 @@ public: std::set GetAccountAddresses(std::string strAccount) const; isminetype IsMine(const CTxIn& txin) const; - int64_t GetDebit(const CTxIn& txin) const; + int64_t GetDebit(const CTxIn& txin, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout, const isminefilter& filter = (MINE_WATCH_ONLY | MINE_SPENDABLE)) const + int64_t GetCredit(const CTxOut& txout, const isminefilter& filter=(MINE_WATCH_ONLY|MINE_SPENDABLE)) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); @@ -324,12 +324,12 @@ public: return true; return false; } - int64_t GetDebit(const CTransaction& tx) const + int64_t GetDebit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { int64_t nDebit = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) { - nDebit += GetDebit(txin); + nDebit += GetDebit(txin, filter); if (!MoneyRange(nDebit)) throw std::runtime_error("CWallet::GetDebit() : value out of range"); } @@ -486,6 +486,8 @@ public: mutable bool fCreditCached; mutable bool fImmatureCreditCached; mutable bool fAvailableCreditCached; + mutable bool fWatchDebitCached; + mutable bool fWatchCreditCached; mutable bool fImmatureWatchCreditCached; mutable bool fAvailableWatchCreditCached; mutable bool fChangeCached; @@ -493,6 +495,8 @@ public: mutable int64_t nCreditCached; mutable int64_t nImmatureCreditCached; mutable int64_t nAvailableCreditCached; + mutable int64_t nWatchDebitCached; + mutable int64_t nWatchCreditCached; mutable int64_t nImmatureWatchCreditCached; mutable int64_t nAvailableWatchCreditCached; mutable int64_t nChangeCached; @@ -531,6 +535,8 @@ public: fCreditCached = false; fImmatureCreditCached = false; fAvailableCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; fImmatureWatchCreditCached = false; fAvailableWatchCreditCached = false; fChangeCached = false; @@ -538,6 +544,8 @@ public: nCreditCached = 0; nImmatureCreditCached = 0; nAvailableCreditCached = 0; + nWatchDebitCached = 0; + nWatchCreditCached = 0; nAvailableWatchCreditCached = 0; nImmatureWatchCreditCached = 0; nChangeCached = 0; @@ -592,6 +600,8 @@ public: { fCreditCached = false; fAvailableCreditCached = false; + fWatchDebitCached = false; + fWatchCreditCached = false; fAvailableWatchCreditCached = false; fImmatureWatchCreditCached = false; fDebitCached = false; @@ -604,15 +614,35 @@ public: MarkDirty(); } - int64_t GetDebit() const + int64_t GetDebit(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { if (vin.empty()) return 0; - if (fDebitCached) - return nDebitCached; - nDebitCached = pwallet->GetDebit(*this); - fDebitCached = true; - return nDebitCached; + + int64_t debit = 0; + if(filter & MINE_SPENDABLE) + { + if (fDebitCached) + debit += nDebitCached; + else + { + nDebitCached = pwallet->GetDebit(*this, MINE_SPENDABLE); + fDebitCached = true; + debit += nDebitCached; + } + } + if(filter & MINE_WATCH_ONLY) + { + if(fWatchDebitCached) + debit += nWatchDebitCached; + else + { + nWatchDebitCached = pwallet->GetDebit(*this, MINE_WATCH_ONLY); + fWatchDebitCached = true; + debit += nWatchDebitCached; + } + } + return debit; } int64_t GetCredit(bool fUseCache=true) const @@ -729,7 +759,7 @@ public: std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee) const; + int64_t& nSent, int64_t& nFee, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; bool IsFromMe() const { -- cgit v1.2.3 From 83f3543f20348aa718620314e7deb37bd0f71b90 Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 8 Apr 2014 16:13:15 +0200 Subject: Added argument to listaccounts to include watchonly addresses --- src/rpcclient.cpp | 1 + src/rpcwallet.cpp | 17 ++++++++++++----- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index ea5ca8e0f6..d96b47833f 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -49,6 +49,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listtransactions", 1 }, { "listtransactions", 2 }, { "listaccounts", 0 }, + { "listaccounts", 1 }, { "walletpassphrase", 1 }, { "getblocktemplate", 0 }, { "listsinceblock", 1 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 79b438d417..d52a4bc5bb 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1302,12 +1302,13 @@ Value listtransactions(const Array& params, bool fHelp) Value listaccounts(const Array& params, bool fHelp) { - if (fHelp || params.size() > 1) + if (fHelp || params.size() > 2) throw runtime_error( - "listaccounts ( minconf )\n" + "listaccounts ( minconf includeWatchonly)\n" "\nReturns Object that has account names as keys, account balances as values.\n" "\nArguments:\n" - "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n" + "1. minconf (numeric, optional, default=1) Only onclude transactions with at least this many confirmations\n" + "2. includeWatchonly (bool, optional, default=false) Include balances in watchonly addresses (see 'importaddress')\n" "\nResult:\n" "{ (json object where keys are account names, and values are numeric balances\n" " \"account\": x.xxx, (numeric) The property name is the account name, and the value is the total balance for the account.\n" @@ -1325,12 +1326,18 @@ Value listaccounts(const Array& params, bool fHelp) ); int nMinDepth = 1; + isminefilter includeWatchonly = MINE_SPENDABLE; if (params.size() > 0) + { nMinDepth = params[0].get_int(); + if(params.size() > 1) + if(params[1].get_bool()) + includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; + } map mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { - if (IsMine(*pwalletMain, entry.first)) // This address belongs to me + if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me mapAccountBalances[entry.second.name] = 0; } @@ -1344,7 +1351,7 @@ Value listaccounts(const Array& params, bool fHelp) int nDepth = wtx.GetDepthInMainChain(); if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0) continue; - wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly); mapAccountBalances[strSentAccount] -= nFee; BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) mapAccountBalances[strSentAccount] -= s.second; -- cgit v1.2.3 From 952877e01c1045298fd51d1152d96c304d4cf2a4 Mon Sep 17 00:00:00 2001 From: JaSK Date: Wed, 9 Apr 2014 17:20:07 +0200 Subject: Showing 'involvesWatchonly' property for transactions returned by 'listtransactions' and 'listsinceblock'. It is only appended when the transaction involves a watchonly address. --- src/rpcwallet.cpp | 5 +++++ src/wallet.h | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index d52a4bc5bb..8de10c52f8 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1117,6 +1117,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); bool fAllAccounts = (strAccount == string("*")); + bool involvesWatchonly = wtx.IsFromMe(MINE_WATCH_ONLY); // Sent if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) @@ -1124,6 +1125,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) { Object entry; + if(involvesWatchonly || (::IsMine(*pwalletMain, s.first) & MINE_WATCH_ONLY)) + entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", strSentAccount)); MaybePushAddress(entry, s.first); entry.push_back(Pair("category", "send")); @@ -1146,6 +1149,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe if (fAllAccounts || (account == strAccount)) { Object entry; + if(involvesWatchonly || (::IsMine(*pwalletMain, r.first) & MINE_WATCH_ONLY)) + entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", account)); MaybePushAddress(entry, r.first); if (wtx.IsCoinBase()) diff --git a/src/wallet.h b/src/wallet.h index b11e6c662e..3453d23d97 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -761,9 +761,9 @@ public: void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, int64_t& nSent, int64_t& nFee, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; - bool IsFromMe() const + bool IsFromMe(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const { - return (GetDebit() > 0); + return (GetDebit(filter) > 0); } bool IsTrusted() const -- cgit v1.2.3 From d7d5d23b77e204eccd4bf8a5608c1a499d5fc42f Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 8 Apr 2014 17:51:04 +0200 Subject: Added argument to listtransactions and listsinceblock to include watchonly addresses --- src/rpcclient.cpp | 3 ++- src/rpcwallet.cpp | 62 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index d96b47833f..f329d517b3 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -48,11 +48,13 @@ static const CRPCConvertParam vRPCConvertParams[] = { "sendfrom", 3 }, { "listtransactions", 1 }, { "listtransactions", 2 }, + { "listtransactions", 3 }, { "listaccounts", 0 }, { "listaccounts", 1 }, { "walletpassphrase", 1 }, { "getblocktemplate", 0 }, { "listsinceblock", 1 }, + { "listsinceblock", 2 }, { "sendmany", 1 }, { "sendmany", 2 }, { "addmultisigaddress", 0 }, @@ -129,7 +131,6 @@ Array RPCConvertValues(const std::string &strMethod, const std::vector > listReceived; list > listSent; - wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount); + wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter); bool fAllAccounts = (strAccount == string("*")); bool involvesWatchonly = wtx.IsFromMe(MINE_WATCH_ONLY); @@ -1194,16 +1194,16 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar Value listtransactions(const Array& params, bool fHelp) { - if (fHelp || params.size() > 3) + if (fHelp || params.size() > 4) throw runtime_error( - "listtransactions ( \"account\" count from )\n" + "listtransactions ( \"account\" count from includeWatchonly)\n" "\nReturns up to 'count' most recent transactions skipping the first 'from' transactions for account 'account'.\n" "\nArguments:\n" "1. \"account\" (string, optional) The account name. If not included, it will list all transactions for all accounts.\n" " If \"\" is set, it will list transactions for the default account.\n" "2. count (numeric, optional, default=10) The number of transactions to return\n" "3. from (numeric, optional, default=0) The number of transactions to skip\n" - + "4. includeWatchonly (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')\n" "\nResult:\n" "[\n" " {\n" @@ -1255,15 +1255,26 @@ Value listtransactions(const Array& params, bool fHelp) ); string strAccount = "*"; - if (params.size() > 0) - strAccount = params[0].get_str(); int nCount = 10; - if (params.size() > 1) - nCount = params[1].get_int(); int nFrom = 0; - if (params.size() > 2) - nFrom = params[2].get_int(); - + isminefilter filter = MINE_SPENDABLE; + if (params.size() > 0) + { + strAccount = params[0].get_str(); + if (params.size() > 1) + { + nCount = params[1].get_int(); + if (params.size() > 2) + { + nFrom = params[2].get_int(); + if(params.size() > 3) + { + if(params[3].get_bool()) + filter = filter | MINE_WATCH_ONLY; + } + } + } + } if (nCount < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); if (nFrom < 0) @@ -1279,7 +1290,7 @@ Value listtransactions(const Array& params, bool fHelp) { CWalletTx *const pwtx = (*it).second.first; if (pwtx != 0) - ListTransactions(*pwtx, strAccount, 0, true, ret); + ListTransactions(*pwtx, strAccount, 0, true, ret, filter); CAccountingEntry *const pacentry = (*it).second.second; if (pacentry != 0) AcentryToJSON(*pacentry, strAccount, ret); @@ -1386,11 +1397,12 @@ Value listsinceblock(const Array& params, bool fHelp) { if (fHelp) throw runtime_error( - "listsinceblock ( \"blockhash\" target-confirmations )\n" + "listsinceblock ( \"blockhash\" target-confirmations includeWatchonly)\n" "\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n" "\nArguments:\n" "1. \"blockhash\" (string, optional) The block hash to list transactions since\n" "2. target-confirmations: (numeric, optional) The confirmations required, must be 1 or more\n" + "3. includeWatchonly: (bool, optional, default=false) Include transactions to watchonly addresses (see 'importaddress')" "\nResult:\n" "{\n" " \"transactions\": [\n" @@ -1426,7 +1438,7 @@ Value listsinceblock(const Array& params, bool fHelp) CBlockIndex *pindex = NULL; int target_confirms = 1; - + isminefilter filter = MINE_SPENDABLE; if (params.size() > 0) { uint256 blockId = 0; @@ -1435,14 +1447,20 @@ Value listsinceblock(const Array& params, bool fHelp) std::map::iterator it = mapBlockIndex.find(blockId); if (it != mapBlockIndex.end()) pindex = it->second; - } - if (params.size() > 1) - { - target_confirms = params[1].get_int(); + if (params.size() > 1) + { + target_confirms = params[1].get_int(); + + if (target_confirms < 1) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); - if (target_confirms < 1) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + if(params.size() > 2) + { + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + } + } } int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; @@ -1454,7 +1472,7 @@ Value listsinceblock(const Array& params, bool fHelp) CWalletTx tx = (*it).second; if (depth == -1 || tx.GetDepthInMainChain() < depth) - ListTransactions(tx, "*", 0, true, transactions); + ListTransactions(tx, "*", 0, true, transactions, filter); } CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms]; -- cgit v1.2.3 From a5c6c5d6df887764ac07664aae842234c19bbf8d Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 29 Apr 2014 19:39:01 +0200 Subject: fixed tiny glitch and improved readability like laanwj suggested --- src/qt/transactiondesc.cpp | 6 ++-- src/rpcmisc.cpp | 4 +-- src/rpcwallet.cpp | 70 +++++++++++++++++++--------------------------- src/wallet.cpp | 6 ++-- 4 files changed, 37 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 76dc47318d..d94f066ed9 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -101,11 +101,11 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; strHTML += "" + tr("To") + ": "; strHTML += GUIUtil::HtmlEscape(rec->address); - std::string addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? "own address" : "watch-only"; + QString addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? tr("own address") : tr("watch-only"); if (!wallet->mapAddressBook[address].name.empty()) - strHTML += " (" + tr(addressOwned.c_str()) + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; + strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; else - strHTML += " (" + tr(addressOwned.c_str()) + ")"; + strHTML += " (" + addressOwned + ")"; strHTML += "
"; } } diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 3245f7d713..f0b4619b26 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -171,9 +171,9 @@ Value validateaddress(const Array& params, bool fHelp) ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; - ret.push_back(Pair("ismine", mine == MINE_SPENDABLE)); + ret.push_back(Pair("ismine", (mine & MINE_SPENDABLE) ? true : false)); if (mine != MINE_NO) { - ret.push_back(Pair("watchonly", mine == MINE_WATCH_ONLY)); + ret.push_back(Pair("iswatchonly", (mine & MINE_WATCH_ONLY) ? true: false)); Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); ret.insert(ret.end(), detail.begin(), detail.end()); } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index a9db442d4c..e9a111f523 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -621,14 +621,12 @@ Value getbalance(const Array& params, bool fHelp) return ValueFromAmount(pwalletMain->GetBalance()); int nMinDepth = 1; - isminefilter filter = MINE_SPENDABLE; if (params.size() > 1) - { nMinDepth = params[1].get_int(); - if(params.size() > 2) - if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; - } + isminefilter filter = MINE_SPENDABLE; + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -1255,26 +1253,19 @@ Value listtransactions(const Array& params, bool fHelp) ); string strAccount = "*"; + if (params.size() > 0) + strAccount = params[0].get_str(); int nCount = 10; + if (params.size() > 1) + nCount = params[1].get_int(); int nFrom = 0; + if (params.size() > 2) + nFrom = params[2].get_int(); isminefilter filter = MINE_SPENDABLE; - if (params.size() > 0) - { - strAccount = params[0].get_str(); - if (params.size() > 1) - { - nCount = params[1].get_int(); - if (params.size() > 2) - { - nFrom = params[2].get_int(); - if(params.size() > 3) - { - if(params[3].get_bool()) - filter = filter | MINE_WATCH_ONLY; - } - } - } - } + if(params.size() > 3) + if(params[3].get_bool()) + filter = filter | MINE_WATCH_ONLY; + if (nCount < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); if (nFrom < 0) @@ -1342,14 +1333,12 @@ Value listaccounts(const Array& params, bool fHelp) ); int nMinDepth = 1; - isminefilter includeWatchonly = MINE_SPENDABLE; if (params.size() > 0) - { nMinDepth = params[0].get_int(); - if(params.size() > 1) - if(params[1].get_bool()) - includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; - } + isminefilter includeWatchonly = MINE_SPENDABLE; + if(params.size() > 1) + if(params[1].get_bool()) + includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; map mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { @@ -1439,6 +1428,7 @@ Value listsinceblock(const Array& params, bool fHelp) CBlockIndex *pindex = NULL; int target_confirms = 1; isminefilter filter = MINE_SPENDABLE; + if (params.size() > 0) { uint256 blockId = 0; @@ -1447,22 +1437,20 @@ Value listsinceblock(const Array& params, bool fHelp) std::map::iterator it = mapBlockIndex.find(blockId); if (it != mapBlockIndex.end()) pindex = it->second; + } - if (params.size() > 1) - { - target_confirms = params[1].get_int(); - - if (target_confirms < 1) - throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); + if (params.size() > 1) + { + target_confirms = params[1].get_int(); - if(params.size() > 2) - { - if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; - } - } + if (target_confirms < 1) + throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); } + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; Array transactions; diff --git a/src/wallet.cpp b/src/wallet.cpp index 3c9aa3306f..4b480321ac 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -811,7 +811,8 @@ void CWalletTx::GetAmounts(list >& listReceived, // Sent/received. BOOST_FOREACH(const CTxOut& txout, vout) { - bool fIsMine; + isminetype fIsMine = pwallet->IsMine(txout); + // Only need to handle txouts if AT LEAST one of these is true: // 1) they debit from us (sent) // 2) the output is to us (received) @@ -820,9 +821,8 @@ void CWalletTx::GetAmounts(list >& listReceived, // Don't report 'change' txouts if (pwallet->IsChange(txout)) continue; - fIsMine = (pwallet->IsMine(txout) & filter); } - else if (!(fIsMine = (pwallet->IsMine(txout) & filter))) + else if (!(fIsMine & filter)) continue; // In either case, we need to get the destination address -- cgit v1.2.3 From f87ba3df64bb5825f7e2f6a33c93cf5738682019 Mon Sep 17 00:00:00 2001 From: JaSK Date: Fri, 23 May 2014 00:58:15 +0200 Subject: added includeWatchonly argument to 'gettransaction' because it affects balance calculation --- src/rpcclient.cpp | 1 + src/rpcwallet.cpp | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index f329d517b3..b2387cb062 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -65,6 +65,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 1 }, { "listunspent", 2 }, { "getblock", 1 }, + { "gettransaction", 1}, { "getrawtransaction", 1 }, { "createrawtransaction", 0 }, { "createrawtransaction", 1 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index e9a111f523..61bc0b22f4 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -1475,12 +1475,13 @@ Value listsinceblock(const Array& params, bool fHelp) Value gettransaction(const Array& params, bool fHelp) { - if (fHelp || params.size() != 1) + if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( "gettransaction \"txid\"\n" "\nGet detailed information about in-wallet transaction \n" "\nArguments:\n" "1. \"txid\" (string, required) The transaction id\n" + "2. \"includeWatchonly\" (bool, optional, default=false) Whether to include watchonly addresses in balance calculation and details[]\n" "\nResult:\n" "{\n" " \"amount\" : x.xxx, (numeric) The transaction amount in btc\n" @@ -1517,6 +1518,11 @@ Value gettransaction(const Array& params, bool fHelp) uint256 hash; hash.SetHex(params[0].get_str()); + isminefilter filter = MINE_SPENDABLE; + if(params.size() > 1) + if(params[1].get_bool()) + filter = filter | MINE_WATCH_ONLY; + Object entry; if (!pwalletMain->mapWallet.count(hash)) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); @@ -1534,7 +1540,7 @@ Value gettransaction(const Array& params, bool fHelp) WalletTxToJSON(wtx, entry); Array details; - ListTransactions(wtx, "*", 0, false, details); + ListTransactions(wtx, "*", 0, false, details, filter); entry.push_back(Pair("details", details)); CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); -- cgit v1.2.3 From 0fa2f8899adf8f9f0ead29ba5d708ead6c5d4eaf Mon Sep 17 00:00:00 2001 From: JaSK Date: Sat, 31 May 2014 16:57:26 +0200 Subject: added includedWatchonly argument to listreceivedbyaddress/...account --- src/rpcclient.cpp | 3 ++- src/rpcwallet.cpp | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/rpcclient.cpp b/src/rpcclient.cpp index b2387cb062..5edeecf933 100644 --- a/src/rpcclient.cpp +++ b/src/rpcclient.cpp @@ -37,8 +37,10 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getreceivedbyaccount", 1 }, { "listreceivedbyaddress", 0 }, { "listreceivedbyaddress", 1 }, + { "listreceivedbyaddress", 2 }, { "listreceivedbyaccount", 0 }, { "listreceivedbyaccount", 1 }, + { "listreceivedbyaccount", 2 }, { "getbalance", 1 }, { "getbalance", 2 }, { "getblockhash", 0 }, @@ -65,7 +67,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "listunspent", 1 }, { "listunspent", 2 }, { "getblock", 1 }, - { "gettransaction", 1}, { "getrawtransaction", 1 }, { "createrawtransaction", 0 }, { "createrawtransaction", 1 }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 61bc0b22f4..1cbaadd45c 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -932,10 +932,12 @@ struct tallyitem int64_t nAmount; int nConf; vector txids; + bool fIsWatchonly; tallyitem() { nAmount = 0; nConf = std::numeric_limits::max(); + fIsWatchonly = false; } }; @@ -951,6 +953,11 @@ Value ListReceived(const Array& params, bool fByAccounts) if (params.size() > 1) fIncludeEmpty = params[1].get_bool(); + isminefilter filter = MINE_SPENDABLE; + if(params.size() > 2) + if(params[2].get_bool()) + filter = filter | MINE_WATCH_ONLY; + // Tally map mapTally; for (map::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it) @@ -967,13 +974,19 @@ Value ListReceived(const Array& params, bool fByAccounts) BOOST_FOREACH(const CTxOut& txout, wtx.vout) { CTxDestination address; - if (!ExtractDestination(txout.scriptPubKey, address) || !IsMine(*pwalletMain, address)) + if (!ExtractDestination(txout.scriptPubKey, address)) + continue; + + isminefilter mine = IsMine(*pwalletMain, address); + if(!mine & filter) continue; tallyitem& item = mapTally[address]; item.nAmount += txout.nValue; item.nConf = min(item.nConf, nDepth); item.txids.push_back(wtx.GetHash()); + if (mine & MINE_WATCH_ONLY) + item.fIsWatchonly = true; } } @@ -990,10 +1003,12 @@ Value ListReceived(const Array& params, bool fByAccounts) int64_t nAmount = 0; int nConf = std::numeric_limits::max(); + bool fIsWatchonly = false; if (it != mapTally.end()) { nAmount = (*it).second.nAmount; nConf = (*it).second.nConf; + fIsWatchonly = (*it).second.fIsWatchonly; } if (fByAccounts) @@ -1001,10 +1016,13 @@ Value ListReceived(const Array& params, bool fByAccounts) tallyitem& item = mapAccountTally[strAccount]; item.nAmount += nAmount; item.nConf = min(item.nConf, nConf); + item.fIsWatchonly = fIsWatchonly; } else { Object obj; + if(fIsWatchonly) + obj.push_back(Pair("involvesWatchonly", true)); obj.push_back(Pair("address", address.ToString())); obj.push_back(Pair("account", strAccount)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); @@ -1029,6 +1047,8 @@ Value ListReceived(const Array& params, bool fByAccounts) int64_t nAmount = (*it).second.nAmount; int nConf = (*it).second.nConf; Object obj; + if((*it).second.fIsWatchonly) + obj.push_back(Pair("involvesWatchonly", true)); obj.push_back(Pair("account", (*it).first)); obj.push_back(Pair("amount", ValueFromAmount(nAmount))); obj.push_back(Pair("confirmations", (nConf == std::numeric_limits::max() ? 0 : nConf))); @@ -1041,17 +1061,19 @@ Value ListReceived(const Array& params, bool fByAccounts) Value listreceivedbyaddress(const Array& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() > 3) throw runtime_error( - "listreceivedbyaddress ( minconf includeempty )\n" + "listreceivedbyaddress ( minconf includeempty includeWatchonly)\n" "\nList balances by receiving address.\n" "\nArguments:\n" "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n" "2. includeempty (numeric, optional, dafault=false) Whether to include addresses that haven't received any payments.\n" + "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n" "\nResult:\n" "[\n" " {\n" + " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n" " \"address\" : \"receivingaddress\", (string) The receiving address\n" " \"account\" : \"accountname\", (string) The account of the receiving address. The default account is \"\".\n" " \"amount\" : x.xxx, (numeric) The total amount in btc received by the address\n" @@ -1063,7 +1085,7 @@ Value listreceivedbyaddress(const Array& params, bool fHelp) "\nExamples:\n" + HelpExampleCli("listreceivedbyaddress", "") + HelpExampleCli("listreceivedbyaddress", "6 true") - + HelpExampleRpc("listreceivedbyaddress", "6, true") + + HelpExampleRpc("listreceivedbyaddress", "6, true, true") ); return ListReceived(params, false); @@ -1071,17 +1093,19 @@ Value listreceivedbyaddress(const Array& params, bool fHelp) Value listreceivedbyaccount(const Array& params, bool fHelp) { - if (fHelp || params.size() > 2) + if (fHelp || params.size() > 3) throw runtime_error( - "listreceivedbyaccount ( minconf includeempty )\n" + "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n" "\nList balances by account.\n" "\nArguments:\n" "1. minconf (numeric, optional, default=1) The minimum number of confirmations before payments are included.\n" "2. includeempty (boolean, optional, default=false) Whether to include accounts that haven't received any payments.\n" + "3. includeWatchonly (bool, optional, default=false) Whether to include watchonly addresses (see 'importaddress').\n" "\nResult:\n" "[\n" " {\n" + " \"involvesWatchonly\" : \"true\", (bool) Only returned if imported addresses were involved in transaction\n" " \"account\" : \"accountname\", (string) The account name of the receiving account\n" " \"amount\" : x.xxx, (numeric) The total amount received by addresses with this account\n" " \"confirmations\" : n (numeric) The number of confirmations of the most recent transaction included\n" @@ -1092,7 +1116,7 @@ Value listreceivedbyaccount(const Array& params, bool fHelp) "\nExamples:\n" + HelpExampleCli("listreceivedbyaccount", "") + HelpExampleCli("listreceivedbyaccount", "6 true") - + HelpExampleRpc("listreceivedbyaccount", "6, true") + + HelpExampleRpc("listreceivedbyaccount", "6, true, true") ); return ListReceived(params, true); -- cgit v1.2.3 From d5087d1ba08142bdf135333a0da08ef0f5fc7ef0 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Mon, 9 Jun 2014 21:11:59 +0200 Subject: Use script matching rather than destination matching for watch-only. This changes the keystore data format, wallet format and IsMine logic to detect watch-only outputs based on direct script matching rather than first trying to convert outputs to destinations (addresses). The reason is that we don't know how the software that has the spending keys works. It may support the same types of scripts as us, but that is not guaranteed. Furthermore, it removes the ambiguity between addresses used as identifiers for output scripts or identifiers for public keys. One practical implication is that adding a normal pay-to-pubkey-hash address via importaddress will not cause payments to the corresponding full public key to be detected as IsMine. If that is wanted, add those scripts directly (importaddress now also accepts any hex-encoded script). Conflicts: src/wallet.cpp --- src/keystore.cpp | 4 ++-- src/keystore.h | 10 +++++----- src/rpcdump.cpp | 23 +++++++++++++++-------- src/script.cpp | 22 +++++++--------------- src/script.h | 2 +- src/wallet.cpp | 15 ++++++++------- src/wallet.h | 4 ++-- src/walletdb.cpp | 12 ++++++------ src/walletdb.h | 2 +- 9 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/keystore.cpp b/src/keystore.cpp index c2ea1ce5a9..2a4c88d565 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -59,14 +59,14 @@ bool CBasicKeyStore::GetCScript(const CScriptID &hash, CScript& redeemScriptOut) return false; } -bool CBasicKeyStore::AddWatchOnly(const CTxDestination &dest) +bool CBasicKeyStore::AddWatchOnly(const CScript &dest) { LOCK(cs_KeyStore); setWatchOnly.insert(dest); return true; } -bool CBasicKeyStore::HaveWatchOnly(const CTxDestination &dest) const +bool CBasicKeyStore::HaveWatchOnly(const CScript &dest) const { LOCK(cs_KeyStore); return setWatchOnly.count(dest) > 0; diff --git a/src/keystore.h b/src/keystore.h index 90fc3a4c7b..72411a1387 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -48,13 +48,13 @@ public: virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; // Support for Watch-only addresses - virtual bool AddWatchOnly(const CTxDestination &dest) =0; - virtual bool HaveWatchOnly(const CTxDestination &dest) const =0; + virtual bool AddWatchOnly(const CScript &dest) =0; + virtual bool HaveWatchOnly(const CScript &dest) const =0; }; typedef std::map KeyMap; typedef std::map ScriptMap; -typedef std::set WatchOnlySet; +typedef std::set WatchOnlySet; /** Basic key store, that keeps keys in an address->secret map */ class CBasicKeyStore : public CKeyStore @@ -105,8 +105,8 @@ public: virtual bool HaveCScript(const CScriptID &hash) const; virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const; - virtual bool AddWatchOnly(const CTxDestination &dest); - virtual bool HaveWatchOnly(const CTxDestination &dest) const; + virtual bool AddWatchOnly(const CScript &dest); + virtual bool HaveWatchOnly(const CScript &dest) const; }; typedef std::vector > CKeyingMaterial; diff --git a/src/rpcdump.cpp b/src/rpcdump.cpp index 98af4695d6..e505d84b40 100644 --- a/src/rpcdump.cpp +++ b/src/rpcdump.cpp @@ -138,13 +138,19 @@ Value importaddress(const Array& params, bool fHelp) if (fHelp || params.size() < 1 || params.size() > 3) throw runtime_error( "importaddress
[label] [rescan=true]\n" - "Adds an address that can be watched as if it were in your wallet but cannot be used to spend."); + "Adds an address or script (in hex) that can be watched as if it were in your wallet but cannot be used to spend."); + + CScript script; CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address"); - CTxDestination dest; - dest = address.Get(); + if (address.IsValid()) { + script.SetDestination(address.Get()); + } else if (IsHex(params[0].get_str())) { + std::vector data(ParseHex(params[0].get_str())); + script = CScript(data.begin(), data.end()); + } else { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address or script"); + } string strLabel = ""; if (params.size() > 1) @@ -159,15 +165,16 @@ Value importaddress(const Array& params, bool fHelp) LOCK2(cs_main, pwalletMain->cs_wallet); // add to address book or update label - pwalletMain->SetAddressBook(dest, strLabel, "receive"); + if (address.IsValid()) + pwalletMain->SetAddressBook(address.Get(), strLabel, "receive"); // Don't throw error in case an address is already there - if (pwalletMain->HaveWatchOnly(dest)) + if (pwalletMain->HaveWatchOnly(script)) return Value::null; pwalletMain->MarkDirty(); - if (!pwalletMain->AddWatchOnly(dest)) + if (!pwalletMain->AddWatchOnly(script)) throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet"); if (fRescan) diff --git a/src/script.cpp b/src/script.cpp index 0ef0126255..89f752bd1f 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1456,13 +1456,11 @@ public: bool operator()(const CScriptID &scriptID) const { return keystore->HaveCScript(scriptID); } }; -isminetype IsMine(const CKeyStore &keystore, const CTxDestination &dest) +isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest) { - if (boost::apply_visitor(CKeyStoreIsMineVisitor(&keystore), dest)) - return MINE_SPENDABLE; - if (keystore.HaveWatchOnly(dest)) - return MINE_WATCH_ONLY; - return MINE_NO; + CScript script; + script.SetDestination(dest); + return IsMine(keystore, script); } isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) @@ -1470,7 +1468,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) vector vSolutions; txnouttype whichType; if (!Solver(scriptPubKey, whichType, vSolutions)) { - if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + if (keystore.HaveWatchOnly(scriptPubKey)) return MINE_WATCH_ONLY; return MINE_NO; } @@ -1485,15 +1483,11 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) keyID = CPubKey(vSolutions[0]).GetID(); if (keystore.HaveKey(keyID)) return MINE_SPENDABLE; - if (keystore.HaveWatchOnly(keyID)) - return MINE_WATCH_ONLY; break; case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); if (keystore.HaveKey(keyID)) return MINE_SPENDABLE; - if (keystore.HaveWatchOnly(keyID)) - return MINE_WATCH_ONLY; break; case TX_SCRIPTHASH: { @@ -1501,11 +1495,9 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { isminetype ret = IsMine(keystore, subscript); - if (ret) + if (ret == MINE_SPENDABLE) return ret; } - if (keystore.HaveWatchOnly(scriptID)) - return MINE_WATCH_ONLY; break; } case TX_MULTISIG: @@ -1522,7 +1514,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) } } - if (keystore.HaveWatchOnly(scriptPubKey.GetID())) + if (keystore.HaveWatchOnly(scriptPubKey)) return MINE_WATCH_ONLY; return MINE_NO; } diff --git a/src/script.h b/src/script.h index 56c7d01d4e..edba5757e4 100644 --- a/src/script.h +++ b/src/script.h @@ -812,7 +812,7 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector >& vSolutions); bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType); isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); -isminetype IsMine(const CKeyStore& keystore, const CTxDestination &dest); +isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest); void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector &vKeys); bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet); bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector& addressRet, int& nRequiredRet); diff --git a/src/wallet.cpp b/src/wallet.cpp index 4b480321ac..445d98b906 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -145,7 +145,7 @@ bool CWallet::LoadCScript(const CScript& redeemScript) return CCryptoKeyStore::AddCScript(redeemScript); } -bool CWallet::AddWatchOnly(const CTxDestination &dest) +bool CWallet::AddWatchOnly(const CScript &dest) { if (!CCryptoKeyStore::AddWatchOnly(dest)) return false; @@ -155,9 +155,8 @@ bool CWallet::AddWatchOnly(const CTxDestination &dest) return CWalletDB(strWalletFile).WriteWatchOnly(dest); } -bool CWallet::LoadWatchOnly(const CTxDestination &dest) +bool CWallet::LoadWatchOnly(const CScript &dest) { - LogPrintf("Loaded %s!\n", CBitcoinAddress(dest).ToString().c_str()); return CCryptoKeyStore::AddWatchOnly(dest); } @@ -729,17 +728,19 @@ int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const bool CWallet::IsChange(const CTxOut& txout) const { - CTxDestination 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 + // payment to a script that is ours, but is not 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 (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address) == MINE_SPENDABLE) + if (::IsMine(*this, txout.scriptPubKey)) { + CTxDestination address; + if (!ExtractDestination(txout.scriptPubKey, address)) + return true; + LOCK(cs_wallet); if (!mapAddressBook.count(address)) return true; diff --git a/src/wallet.h b/src/wallet.h index 3453d23d97..b44b73568b 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -227,9 +227,9 @@ public: bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const; // Adds a watch-only address to the store, and saves it to disk. - bool AddWatchOnly(const CTxDestination &dest); + bool AddWatchOnly(const CScript &dest); // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet) - bool LoadWatchOnly(const CTxDestination &dest); + bool LoadWatchOnly(const CScript &dest); bool Unlock(const SecureString& strWalletPassphrase); bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase); diff --git a/src/walletdb.cpp b/src/walletdb.cpp index 9338d57097..a95baf83d0 100644 --- a/src/walletdb.cpp +++ b/src/walletdb.cpp @@ -112,10 +112,10 @@ bool CWalletDB::WriteCScript(const uint160& hash, const CScript& redeemScript) return Write(std::make_pair(std::string("cscript"), hash), redeemScript, false); } -bool CWalletDB::WriteWatchOnly(const CTxDestination &dest) +bool CWalletDB::WriteWatchOnly(const CScript &dest) { nWalletDBUpdated++; - return Write(std::make_pair(std::string("watch"), CBitcoinAddress(dest).ToString()), '1'); + return Write(std::make_pair(std::string("watchs"), dest), '1'); } bool CWalletDB::WriteBestBlock(const CBlockLocator& locator) @@ -410,14 +410,14 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, wss.fAnyUnordered = true; } } - else if (strType == "watch") + else if (strType == "watchs") { - std::string strAddress; - ssKey >> strAddress; + CScript script; + ssKey >> script; char fYes; ssValue >> fYes; if (fYes == '1') - pwallet->LoadWatchOnly(CBitcoinAddress(strAddress).Get()); + pwallet->LoadWatchOnly(script); // Watch-only addresses have no birthday information for now, // so set the wallet birthday to the beginning of time. diff --git a/src/walletdb.h b/src/walletdb.h index 3a6cb152a1..58b4571b16 100644 --- a/src/walletdb.h +++ b/src/walletdb.h @@ -94,7 +94,7 @@ public: bool WriteCScript(const uint160& hash, const CScript& redeemScript); - bool WriteWatchOnly(const CTxDestination &dest); + bool WriteWatchOnly(const CScript &script); bool WriteBestBlock(const CBlockLocator& locator); bool ReadBestBlock(CBlockLocator& locator); -- cgit v1.2.3 From 80dda36a07d09f99be861fa5271d0da5bd4f07dc Mon Sep 17 00:00:00 2001 From: JaSK Date: Thu, 19 Jun 2014 15:24:17 +0200 Subject: removed default argument values for ismine filter --- src/qt/transactiondesc.cpp | 14 +++++++------- src/qt/transactionrecord.cpp | 2 +- src/rpcwallet.cpp | 18 +++++++++--------- src/wallet.cpp | 4 ++-- src/wallet.h | 25 +++++++++++++------------ 5 files changed, 32 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index d94f066ed9..95c7fa7582 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -54,8 +54,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += ""; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(); - int64_t nDebit = wtx.GetDebit(); + int64_t nCredit = wtx.GetCredit(MINE_SPENDABLE|MINE_WATCH_ONLY); + int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); int64_t nNet = nCredit - nDebit; strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); @@ -139,7 +139,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // int64_t nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout); + nUnmatured += wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; @@ -228,10 +228,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // BOOST_FOREACH(const CTxIn& txin, wtx.vin) if (wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; } } @@ -281,10 +281,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "

" + tr("Debug information") + "

"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) if(wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 1011363f3e..49916fed55 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -33,7 +33,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * QList parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(); + int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map mapValue = wtx.mapValue; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 1cbaadd45c..f745d25ab6 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -557,7 +557,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } -int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) +int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter) { int64_t nBalance = 0; @@ -582,7 +582,7 @@ int64_t GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMi return nBalance; } -int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter = MINE_SPENDABLE) +int64_t GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter) { CWalletDB walletdb(pwalletMain->strWalletFile); return GetAccountBalance(walletdb, strAccount, nMinDepth, filter); @@ -786,7 +786,7 @@ Value sendfrom(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -863,7 +863,7 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -1129,7 +1129,7 @@ static void MaybePushAddress(Object & entry, const CTxDestination &dest) entry.push_back(Pair("address", addr.ToString())); } -void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter=MINE_SPENDABLE) +void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret, const isminefilter& filter) { int64_t nFee; string strSentAccount; @@ -1552,13 +1552,13 @@ Value gettransaction(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id"); const CWalletTx& wtx = pwalletMain->mapWallet[hash]; - int64_t nCredit = wtx.GetCredit(); - int64_t nDebit = wtx.GetDebit(); + int64_t nCredit = wtx.GetCredit(filter); + int64_t nDebit = wtx.GetDebit(filter); int64_t nNet = nCredit - nDebit; - int64_t nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); + int64_t nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0); entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); - if (wtx.IsFromMe()) + if (wtx.IsFromMe(filter)) entry.push_back(Pair("fee", ValueFromAmount(nFee))); WalletTxToJSON(wtx, entry); diff --git a/src/wallet.cpp b/src/wallet.cpp index 445d98b906..e996fca3d2 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1216,7 +1216,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT const CWalletTx *pcoin = output.tx; - if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs)) + if (output.nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? nConfMine : nConfTheirs)) continue; int i = output.i; @@ -1845,7 +1845,7 @@ std::map CWallet::GetAddressBalances() continue; int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < (pcoin->IsFromMe() ? 0 : 1)) + if (nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? 0 : 1)) continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) diff --git a/src/wallet.h b/src/wallet.h index b44b73568b..ac90de3c9c 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -288,12 +288,12 @@ public: std::set GetAccountAddresses(std::string strAccount) const; isminetype IsMine(const CTxIn& txin) const; - int64_t GetDebit(const CTxIn& txin, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; + int64_t GetDebit(const CTxIn& txin, const isminefilter& filter) const; isminetype IsMine(const CTxOut& txout) const { return ::IsMine(*this, txout.scriptPubKey); } - int64_t GetCredit(const CTxOut& txout, const isminefilter& filter=(MINE_WATCH_ONLY|MINE_SPENDABLE)) const + int64_t GetCredit(const CTxOut& txout, const isminefilter& filter) const { if (!MoneyRange(txout.nValue)) throw std::runtime_error("CWallet::GetCredit() : value out of range"); @@ -313,9 +313,9 @@ public: return true; return false; } - bool IsFromMe(const CTransaction& tx) const + bool IsFromMe(const CTransaction& tx) const // should probably be renamed to IsRelevantToMe { - return (GetDebit(tx) > 0); + return (GetDebit(tx, MINE_SPENDABLE|MINE_WATCH_ONLY) > 0); } bool IsConflicting(const CTransaction& tx) const { @@ -324,7 +324,7 @@ public: return true; return false; } - int64_t GetDebit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const { int64_t nDebit = 0; BOOST_FOREACH(const CTxIn& txin, tx.vin) @@ -335,7 +335,7 @@ public: } return nDebit; } - int64_t GetCredit(const CTransaction& tx, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + int64_t GetCredit(const CTransaction& tx, const isminefilter& filter) const { int64_t nCredit = 0; BOOST_FOREACH(const CTxOut& txout, tx.vout) @@ -614,7 +614,8 @@ public: MarkDirty(); } - int64_t GetDebit(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + // filter decides which addresses will count towards the debit + int64_t GetDebit(const isminefilter& filter) const { if (vin.empty()) return 0; @@ -654,7 +655,7 @@ public: // GetBalance can assume transactions in mapWallet won't change if (fUseCache && fCreditCached) return nCreditCached; - nCreditCached = pwallet->GetCredit(*this); + nCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE|MINE_WATCH_ONLY); fCreditCached = true; return nCreditCached; } @@ -756,12 +757,12 @@ public: } void GetAmounts(std::list >& listReceived, - std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; + std::list >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const; void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived, - int64_t& nSent, int64_t& nFee, const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const; + int64_t& nSent, int64_t& nFee, const isminefilter& filter) const; - bool IsFromMe(const isminefilter& filter=(MINE_SPENDABLE|MINE_WATCH_ONLY)) const + bool IsFromMe(const isminefilter& filter) const { return (GetDebit(filter) > 0); } @@ -776,7 +777,7 @@ public: return true; if (nDepth < 0) return false; - if (!bSpendZeroConfChange || !IsFromMe()) // using wtx's cached debit + if (!bSpendZeroConfChange || !IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY)) // using wtx's cached debit return false; // Trusted if all inputs are from us and are in the mempool: -- cgit v1.2.3 From 23b0506c91020f69092389cf8b25576dcdf4e17e Mon Sep 17 00:00:00 2001 From: JaSK Date: Thu, 19 Jun 2014 01:42:39 +0200 Subject: Fixed some stuff in TransactionDesc --- src/qt/transactiondesc.cpp | 32 +++++++++++++------------------- src/qt/transactionrecord.cpp | 6 +++--- 2 files changed, 16 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 95c7fa7582..faa2077ff7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -15,6 +15,7 @@ #include "timedata.h" #include "ui_interface.h" #include "wallet.h" +#include "script.h" #include #include @@ -89,27 +90,20 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (nNet > 0) { // Credit - BOOST_FOREACH(const CTxOut& txout, wtx.vout) + if (CBitcoinAddress(rec->address).IsValid()) { - if (wallet->IsMine(txout)) + CTxDestination address = CBitcoinAddress(rec->address).Get(); + if (wallet->mapAddressBook.count(address)) { - if (CBitcoinAddress(rec->address).IsValid()) - { - CTxDestination address = CBitcoinAddress(rec->address).Get(); - if (wallet->mapAddressBook.count(address)) - { - strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; - strHTML += "" + tr("To") + ": "; - strHTML += GUIUtil::HtmlEscape(rec->address); - QString addressOwned = wallet->IsMine(txout) == MINE_SPENDABLE ? tr("own address") : tr("watch-only"); - if (!wallet->mapAddressBook[address].name.empty()) - strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; - else - strHTML += " (" + addressOwned + ")"; - strHTML += "
"; - } - } - break; + strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; + strHTML += "" + tr("To") + ": "; + strHTML += GUIUtil::HtmlEscape(rec->address); + QString addressOwned = (::IsMine(*wallet, address) == MINE_SPENDABLE) ? tr("own address") : tr("watch-only"); + if (!wallet->mapAddressBook[address].name.empty()) + strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; + else + strHTML += " (" + addressOwned + ")"; + strHTML += "
"; } } } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 49916fed55..cce2fa3f81 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -52,6 +52,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; + sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address @@ -70,7 +71,6 @@ QList TransactionRecord::decomposeTransaction(const CWallet * sub.type = TransactionRecord::Generated; } - sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; parts.append(sub); } } @@ -101,7 +101,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); - parts.last().involvesWatchAddress = involvesWatchAddress; + parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe) { @@ -115,6 +115,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * const CTxOut& txout = wtx.vout[nOut]; TransactionRecord sub(hash, nTime); sub.idx = parts.size(); + sub.involvesWatchAddress = involvesWatchAddress; if(wallet->IsMine(txout)) { @@ -146,7 +147,6 @@ QList TransactionRecord::decomposeTransaction(const CWallet * } sub.debit = -nValue; - sub.involvesWatchAddress = involvesWatchAddress; parts.append(sub); } } -- cgit v1.2.3 From 519dd1c89afa2b7d0f2720eb70cd11de23d61006 Mon Sep 17 00:00:00 2001 From: JaSK Date: Fri, 20 Jun 2014 05:02:14 +0200 Subject: Added MINE_ALL = (spendable|watchonly) --- src/qt/transactiondesc.cpp | 14 +++++++------- src/qt/transactionrecord.cpp | 2 +- src/script.h | 1 + src/wallet.cpp | 4 ++-- src/wallet.h | 6 +++--- 5 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index faa2077ff7..7cfa5424f7 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -55,8 +55,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += ""; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(MINE_SPENDABLE|MINE_WATCH_ONLY); - int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); + int64_t nCredit = wtx.GetCredit(MINE_ALL); + int64_t nDebit = wtx.GetDebit(MINE_ALL); int64_t nNet = nCredit - nDebit; strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); @@ -133,7 +133,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // int64_t nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY); + nUnmatured += wallet->GetCredit(txout, MINE_ALL); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; @@ -222,10 +222,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // BOOST_FOREACH(const CTxIn& txin, wtx.vin) if (wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; } } @@ -275,10 +275,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "

" + tr("Debug information") + "

"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) if(wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_SPENDABLE|MINE_WATCH_ONLY)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index cce2fa3f81..08092a5f1f 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -33,7 +33,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * QList parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(MINE_SPENDABLE|MINE_WATCH_ONLY); + int64_t nDebit = wtx.GetDebit(MINE_ALL); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map mapValue = wtx.mapValue; diff --git a/src/script.h b/src/script.h index edba5757e4..790822625a 100644 --- a/src/script.h +++ b/src/script.h @@ -200,6 +200,7 @@ enum isminetype MINE_NO = 0, MINE_WATCH_ONLY = 1, MINE_SPENDABLE = 2, + MINE_ALL = MINE_WATCH_ONLY | MINE_SPENDABLE }; /** used for bitflags of isminetype */ typedef uint8_t isminefilter; diff --git a/src/wallet.cpp b/src/wallet.cpp index e996fca3d2..2823e7fa34 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1216,7 +1216,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT const CWalletTx *pcoin = output.tx; - if (output.nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? nConfMine : nConfTheirs)) + if (output.nDepth < (pcoin->IsFromMe(MINE_ALL) ? nConfMine : nConfTheirs)) continue; int i = output.i; @@ -1845,7 +1845,7 @@ std::map CWallet::GetAddressBalances() continue; int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < (pcoin->IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY) ? 0 : 1)) + if (nDepth < (pcoin->IsFromMe(MINE_ALL) ? 0 : 1)) continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) diff --git a/src/wallet.h b/src/wallet.h index ac90de3c9c..639f51e3ca 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -315,7 +315,7 @@ public: } bool IsFromMe(const CTransaction& tx) const // should probably be renamed to IsRelevantToMe { - return (GetDebit(tx, MINE_SPENDABLE|MINE_WATCH_ONLY) > 0); + return (GetDebit(tx, MINE_ALL) > 0); } bool IsConflicting(const CTransaction& tx) const { @@ -655,7 +655,7 @@ public: // GetBalance can assume transactions in mapWallet won't change if (fUseCache && fCreditCached) return nCreditCached; - nCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE|MINE_WATCH_ONLY); + nCreditCached = pwallet->GetCredit(*this, MINE_ALL); fCreditCached = true; return nCreditCached; } @@ -777,7 +777,7 @@ public: return true; if (nDepth < 0) return false; - if (!bSpendZeroConfChange || !IsFromMe(MINE_SPENDABLE|MINE_WATCH_ONLY)) // using wtx's cached debit + if (!bSpendZeroConfChange || !IsFromMe(MINE_ALL)) // using wtx's cached debit return false; // Trusted if all inputs are from us and are in the mempool: -- cgit v1.2.3 From f28707a845d4098fed55a6948887d60043fcfde7 Mon Sep 17 00:00:00 2001 From: JaSK Date: Sun, 22 Jun 2014 23:29:33 +0200 Subject: fixed bug in ListReceived() --- src/rpcwallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index f745d25ab6..560be0570a 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -978,7 +978,7 @@ Value ListReceived(const Array& params, bool fByAccounts) continue; isminefilter mine = IsMine(*pwalletMain, address); - if(!mine & filter) + if(!(mine & filter)) continue; tallyitem& item = mapTally[address]; -- cgit v1.2.3 From 53a2148f0c182b83da255972acb3110a74e9957a Mon Sep 17 00:00:00 2001 From: JaSK Date: Mon, 23 Jun 2014 10:43:30 +0200 Subject: fixed bug where validateaddress doesn't display information --- src/rpcmisc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index f0b4619b26..56accc1b3a 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -115,7 +115,7 @@ public: Object operator()(const CScriptID &scriptID) const { Object obj; obj.push_back(Pair("isscript", true)); - if (mine == MINE_SPENDABLE) { + if (mine != MINE_NO) { CScript subscript; pwalletMain->GetCScript(scriptID, subscript); std::vector addresses; -- cgit v1.2.3 From a3e192a3274817517671f624d5744297905e20d2 Mon Sep 17 00:00:00 2001 From: JaSK Date: Tue, 1 Jul 2014 11:00:22 +0200 Subject: replaced MINE_ with ISMINE_ --- src/qt/transactiondesc.cpp | 32 ++++++++++++++++---------------- src/qt/transactionrecord.cpp | 12 ++++++------ src/rpcmisc.cpp | 12 ++++++------ src/rpcwallet.cpp | 36 ++++++++++++++++++------------------ src/script.cpp | 16 ++++++++-------- src/script.h | 8 ++++---- src/wallet.cpp | 10 +++++----- src/wallet.h | 24 ++++++++++++------------ 8 files changed, 75 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/qt/transactiondesc.cpp b/src/qt/transactiondesc.cpp index 7cfa5424f7..36e4d50e30 100644 --- a/src/qt/transactiondesc.cpp +++ b/src/qt/transactiondesc.cpp @@ -55,8 +55,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += ""; int64_t nTime = wtx.GetTxTime(); - int64_t nCredit = wtx.GetCredit(MINE_ALL); - int64_t nDebit = wtx.GetDebit(MINE_ALL); + int64_t nCredit = wtx.GetCredit(ISMINE_ALL); + int64_t nDebit = wtx.GetDebit(ISMINE_ALL); int64_t nNet = nCredit - nDebit; strHTML += "" + tr("Status") + ": " + FormatTxStatus(wtx); @@ -98,7 +98,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "" + tr("From") + ": " + tr("unknown") + "
"; strHTML += "" + tr("To") + ": "; strHTML += GUIUtil::HtmlEscape(rec->address); - QString addressOwned = (::IsMine(*wallet, address) == MINE_SPENDABLE) ? tr("own address") : tr("watch-only"); + QString addressOwned = (::IsMine(*wallet, address) == ISMINE_SPENDABLE) ? tr("own address") : tr("watch-only"); if (!wallet->mapAddressBook[address].name.empty()) strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + ")"; else @@ -133,7 +133,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // int64_t nUnmatured = 0; BOOST_FOREACH(const CTxOut& txout, wtx.vout) - nUnmatured += wallet->GetCredit(txout, MINE_ALL); + nUnmatured += wallet->GetCredit(txout, ISMINE_ALL); strHTML += "" + tr("Credit") + ": "; if (wtx.IsInMainChain()) strHTML += BitcoinUnits::formatWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", wtx.GetBlocksToMaturity()) + ")"; @@ -150,14 +150,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco } else { - isminetype fAllFromMe = MINE_SPENDABLE; + isminetype fAllFromMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { isminetype mine = wallet->IsMine(txin); if(fAllFromMe > mine) fAllFromMe = mine; } - isminetype fAllToMe = MINE_SPENDABLE; + isminetype fAllToMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); @@ -166,7 +166,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (fAllFromMe) { - if(fAllFromMe == MINE_WATCH_ONLY) + if(fAllFromMe == ISMINE_WATCH_ONLY) strHTML += "" + tr("From") + ": " + tr("watch-only") + "
"; // @@ -176,7 +176,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco { // Ignore change isminetype toSelf = wallet->IsMine(txout); - if ((toSelf == MINE_SPENDABLE) && (fAllFromMe == MINE_SPENDABLE)) + if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE)) continue; if (!wtx.mapValue.count("to") || wtx.mapValue["to"].empty()) @@ -189,9 +189,9 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco if (wallet->mapAddressBook.count(address) && !wallet->mapAddressBook[address].name.empty()) strHTML += GUIUtil::HtmlEscape(wallet->mapAddressBook[address].name) + " "; strHTML += GUIUtil::HtmlEscape(CBitcoinAddress(address).ToString()); - if(toSelf == MINE_SPENDABLE) + if(toSelf == ISMINE_SPENDABLE) strHTML += " (own address)"; - else if(toSelf == MINE_WATCH_ONLY) + else if(toSelf == ISMINE_WATCH_ONLY) strHTML += " (watch-only)"; strHTML += "
"; } @@ -222,10 +222,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco // BOOST_FOREACH(const CTxIn& txin, wtx.vin) if (wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
"; } } @@ -275,10 +275,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += "

" + tr("Debug information") + "

"; BOOST_FOREACH(const CTxIn& txin, wtx.vin) if(wallet->IsMine(txin)) - strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, MINE_ALL)) + "
"; + strHTML += "" + tr("Debit") + ": " + BitcoinUnits::formatWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "
"; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if(wallet->IsMine(txout)) - strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, MINE_ALL)) + "
"; + strHTML += "" + tr("Credit") + ": " + BitcoinUnits::formatWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "
"; strHTML += "
" + tr("Transaction") + ":
"; strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true); @@ -305,8 +305,8 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco strHTML += QString::fromStdString(CBitcoinAddress(address).ToString()); } strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatWithUnit(unit, vout.nValue); - strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & MINE_SPENDABLE ? tr("true") : tr("false")) + ""; - strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & MINE_WATCH_ONLY ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsMine=" + (wallet->IsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + ""; + strHTML = strHTML + " IsWatchOnly=" + (wallet->IsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + ""; } } } diff --git a/src/qt/transactionrecord.cpp b/src/qt/transactionrecord.cpp index 08092a5f1f..7d29c212b3 100644 --- a/src/qt/transactionrecord.cpp +++ b/src/qt/transactionrecord.cpp @@ -33,7 +33,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * QList parts; int64_t nTime = wtx.GetTxTime(); int64_t nCredit = wtx.GetCredit(true); - int64_t nDebit = wtx.GetDebit(MINE_ALL); + int64_t nDebit = wtx.GetDebit(ISMINE_ALL); int64_t nNet = nCredit - nDebit; uint256 hash = wtx.GetHash(); std::map mapValue = wtx.mapValue; @@ -52,7 +52,7 @@ QList TransactionRecord::decomposeTransaction(const CWallet * CTxDestination address; sub.idx = parts.size(); // sequence number sub.credit = txout.nValue; - sub.involvesWatchAddress = mine == MINE_WATCH_ONLY; + sub.involvesWatchAddress = mine == ISMINE_WATCH_ONLY; if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address)) { // Received by Bitcoin Address @@ -78,19 +78,19 @@ QList TransactionRecord::decomposeTransaction(const CWallet * else { bool involvesWatchAddress = false; - isminetype fAllFromMe = MINE_SPENDABLE; + isminetype fAllFromMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxIn& txin, wtx.vin) { isminetype mine = wallet->IsMine(txin); - if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; + if(mine == ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; } - isminetype fAllToMe = MINE_SPENDABLE; + isminetype fAllToMe = ISMINE_SPENDABLE; BOOST_FOREACH(const CTxOut& txout, wtx.vout) { isminetype mine = wallet->IsMine(txout); - if(mine == MINE_WATCH_ONLY) involvesWatchAddress = true; + if(mine == ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllToMe > mine) fAllToMe = mine; } diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp index 56accc1b3a..f51be2db2c 100644 --- a/src/rpcmisc.cpp +++ b/src/rpcmisc.cpp @@ -104,7 +104,7 @@ public: Object obj; CPubKey vchPubKey; obj.push_back(Pair("isscript", false)); - if (mine == MINE_SPENDABLE) { + if (mine == ISMINE_SPENDABLE) { pwalletMain->GetPubKey(keyID, vchPubKey); obj.push_back(Pair("pubkey", HexStr(vchPubKey))); obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); @@ -115,7 +115,7 @@ public: Object operator()(const CScriptID &scriptID) const { Object obj; obj.push_back(Pair("isscript", true)); - if (mine != MINE_NO) { + if (mine != ISMINE_NO) { CScript subscript; pwalletMain->GetCScript(scriptID, subscript); std::vector addresses; @@ -170,10 +170,10 @@ Value validateaddress(const Array& params, bool fHelp) string currentAddress = address.ToString(); ret.push_back(Pair("address", currentAddress)); #ifdef ENABLE_WALLET - isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : MINE_NO; - ret.push_back(Pair("ismine", (mine & MINE_SPENDABLE) ? true : false)); - if (mine != MINE_NO) { - ret.push_back(Pair("iswatchonly", (mine & MINE_WATCH_ONLY) ? true: false)); + isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO; + ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false)); + if (mine != ISMINE_NO) { + ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true: false)); Object detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest); ret.insert(ret.end(), detail.begin(), detail.end()); } diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 560be0570a..190c6b86b5 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -623,10 +623,10 @@ Value getbalance(const Array& params, bool fHelp) int nMinDepth = 1; if (params.size() > 1) nMinDepth = params[1].get_int(); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 2) if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -786,7 +786,7 @@ Value sendfrom(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (nAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -863,7 +863,7 @@ Value sendmany(const Array& params, bool fHelp) EnsureWalletIsUnlocked(); // Check funds - int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, MINE_SPENDABLE); + int64_t nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE); if (totalAmount > nBalance) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); @@ -953,10 +953,10 @@ Value ListReceived(const Array& params, bool fByAccounts) if (params.size() > 1) fIncludeEmpty = params[1].get_bool(); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 2) if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; // Tally map mapTally; @@ -985,7 +985,7 @@ Value ListReceived(const Array& params, bool fByAccounts) item.nAmount += txout.nValue; item.nConf = min(item.nConf, nDepth); item.txids.push_back(wtx.GetHash()); - if (mine & MINE_WATCH_ONLY) + if (mine & ISMINE_WATCH_ONLY) item.fIsWatchonly = true; } } @@ -1139,7 +1139,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter); bool fAllAccounts = (strAccount == string("*")); - bool involvesWatchonly = wtx.IsFromMe(MINE_WATCH_ONLY); + bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY); // Sent if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount)) @@ -1147,7 +1147,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe BOOST_FOREACH(const PAIRTYPE(CTxDestination, int64_t)& s, listSent) { Object entry; - if(involvesWatchonly || (::IsMine(*pwalletMain, s.first) & MINE_WATCH_ONLY)) + if(involvesWatchonly || (::IsMine(*pwalletMain, s.first) & ISMINE_WATCH_ONLY)) entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", strSentAccount)); MaybePushAddress(entry, s.first); @@ -1171,7 +1171,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe if (fAllAccounts || (account == strAccount)) { Object entry; - if(involvesWatchonly || (::IsMine(*pwalletMain, r.first) & MINE_WATCH_ONLY)) + if(involvesWatchonly || (::IsMine(*pwalletMain, r.first) & ISMINE_WATCH_ONLY)) entry.push_back(Pair("involvesWatchonly", true)); entry.push_back(Pair("account", account)); MaybePushAddress(entry, r.first); @@ -1285,10 +1285,10 @@ Value listtransactions(const Array& params, bool fHelp) int nFrom = 0; if (params.size() > 2) nFrom = params[2].get_int(); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 3) if(params[3].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; if (nCount < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count"); @@ -1359,10 +1359,10 @@ Value listaccounts(const Array& params, bool fHelp) int nMinDepth = 1; if (params.size() > 0) nMinDepth = params[0].get_int(); - isminefilter includeWatchonly = MINE_SPENDABLE; + isminefilter includeWatchonly = ISMINE_SPENDABLE; if(params.size() > 1) if(params[1].get_bool()) - includeWatchonly = includeWatchonly | MINE_WATCH_ONLY; + includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY; map mapAccountBalances; BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) { @@ -1451,7 +1451,7 @@ Value listsinceblock(const Array& params, bool fHelp) CBlockIndex *pindex = NULL; int target_confirms = 1; - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if (params.size() > 0) { @@ -1473,7 +1473,7 @@ Value listsinceblock(const Array& params, bool fHelp) if(params.size() > 2) if(params[2].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1; @@ -1542,10 +1542,10 @@ Value gettransaction(const Array& params, bool fHelp) uint256 hash; hash.SetHex(params[0].get_str()); - isminefilter filter = MINE_SPENDABLE; + isminefilter filter = ISMINE_SPENDABLE; if(params.size() > 1) if(params[1].get_bool()) - filter = filter | MINE_WATCH_ONLY; + filter = filter | ISMINE_WATCH_ONLY; Object entry; if (!pwalletMain->mapWallet.count(hash)) diff --git a/src/script.cpp b/src/script.cpp index 89f752bd1f..238a25e72d 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -1469,8 +1469,8 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) txnouttype whichType; if (!Solver(scriptPubKey, whichType, vSolutions)) { if (keystore.HaveWatchOnly(scriptPubKey)) - return MINE_WATCH_ONLY; - return MINE_NO; + return ISMINE_WATCH_ONLY; + return ISMINE_NO; } CKeyID keyID; @@ -1482,12 +1482,12 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) case TX_PUBKEY: keyID = CPubKey(vSolutions[0]).GetID(); if (keystore.HaveKey(keyID)) - return MINE_SPENDABLE; + return ISMINE_SPENDABLE; break; case TX_PUBKEYHASH: keyID = CKeyID(uint160(vSolutions[0])); if (keystore.HaveKey(keyID)) - return MINE_SPENDABLE; + return ISMINE_SPENDABLE; break; case TX_SCRIPTHASH: { @@ -1495,7 +1495,7 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) CScript subscript; if (keystore.GetCScript(scriptID, subscript)) { isminetype ret = IsMine(keystore, subscript); - if (ret == MINE_SPENDABLE) + if (ret == ISMINE_SPENDABLE) return ret; } break; @@ -1509,14 +1509,14 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey) // in shared-wallet situations. vector keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1); if (HaveKeys(keys, keystore) == keys.size()) - return MINE_SPENDABLE; + return ISMINE_SPENDABLE; break; } } if (keystore.HaveWatchOnly(scriptPubKey)) - return MINE_WATCH_ONLY; - return MINE_NO; + return ISMINE_WATCH_ONLY; + return ISMINE_NO; } bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet) diff --git a/src/script.h b/src/script.h index 790822625a..e36be2db9e 100644 --- a/src/script.h +++ b/src/script.h @@ -197,10 +197,10 @@ enum /** IsMine() return codes */ enum isminetype { - MINE_NO = 0, - MINE_WATCH_ONLY = 1, - MINE_SPENDABLE = 2, - MINE_ALL = MINE_WATCH_ONLY | MINE_SPENDABLE + ISMINE_NO = 0, + ISMINE_WATCH_ONLY = 1, + ISMINE_SPENDABLE = 2, + ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE }; /** used for bitflags of isminetype */ typedef uint8_t isminefilter; diff --git a/src/wallet.cpp b/src/wallet.cpp index 2823e7fa34..84b50c0f8c 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -707,7 +707,7 @@ isminetype CWallet::IsMine(const CTxIn &txin) const return IsMine(prev.vout[txin.prevout.n]); } } - return MINE_NO; + return ISMINE_NO; } int64_t CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const @@ -1139,10 +1139,10 @@ void CWallet::AvailableCoins(vector& vCoins, bool fOnlyConfirmed, const for (unsigned int i = 0; i < pcoin->vout.size(); i++) { isminetype mine = IsMine(pcoin->vout[i]); - if (!(IsSpent(wtxid, i)) && mine != MINE_NO && + if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO && !IsLockedCoin((*it).first, i) && pcoin->vout[i].nValue > 0 && (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i))) - vCoins.push_back(COutput(pcoin, i, nDepth, mine & MINE_SPENDABLE)); + vCoins.push_back(COutput(pcoin, i, nDepth, mine & ISMINE_SPENDABLE)); } } } @@ -1216,7 +1216,7 @@ bool CWallet::SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfT const CWalletTx *pcoin = output.tx; - if (output.nDepth < (pcoin->IsFromMe(MINE_ALL) ? nConfMine : nConfTheirs)) + if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs)) continue; int i = output.i; @@ -1845,7 +1845,7 @@ std::map CWallet::GetAddressBalances() continue; int nDepth = pcoin->GetDepthInMainChain(); - if (nDepth < (pcoin->IsFromMe(MINE_ALL) ? 0 : 1)) + if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1)) continue; for (unsigned int i = 0; i < pcoin->vout.size(); i++) diff --git a/src/wallet.h b/src/wallet.h index 639f51e3ca..8a51bf9821 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -315,7 +315,7 @@ public: } bool IsFromMe(const CTransaction& tx) const // should probably be renamed to IsRelevantToMe { - return (GetDebit(tx, MINE_ALL) > 0); + return (GetDebit(tx, ISMINE_ALL) > 0); } bool IsConflicting(const CTransaction& tx) const { @@ -621,24 +621,24 @@ public: return 0; int64_t debit = 0; - if(filter & MINE_SPENDABLE) + if(filter & ISMINE_SPENDABLE) { if (fDebitCached) debit += nDebitCached; else { - nDebitCached = pwallet->GetDebit(*this, MINE_SPENDABLE); + nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE); fDebitCached = true; debit += nDebitCached; } } - if(filter & MINE_WATCH_ONLY) + if(filter & ISMINE_WATCH_ONLY) { if(fWatchDebitCached) debit += nWatchDebitCached; else { - nWatchDebitCached = pwallet->GetDebit(*this, MINE_WATCH_ONLY); + nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY); fWatchDebitCached = true; debit += nWatchDebitCached; } @@ -655,7 +655,7 @@ public: // GetBalance can assume transactions in mapWallet won't change if (fUseCache && fCreditCached) return nCreditCached; - nCreditCached = pwallet->GetCredit(*this, MINE_ALL); + nCreditCached = pwallet->GetCredit(*this, ISMINE_ALL); fCreditCached = true; return nCreditCached; } @@ -666,7 +666,7 @@ public: { if (fUseCache && fImmatureCreditCached) return nImmatureCreditCached; - nImmatureCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE); + nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE); fImmatureCreditCached = true; return nImmatureCreditCached; } @@ -693,7 +693,7 @@ public: if (!pwallet->IsSpent(hashTx, i)) { const CTxOut &txout = vout[i]; - nCredit += pwallet->GetCredit(txout, MINE_SPENDABLE); + nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } @@ -710,7 +710,7 @@ public: { if (fUseCache && fImmatureWatchCreditCached) return nImmatureWatchCreditCached; - nImmatureWatchCreditCached = pwallet->GetCredit(*this, MINE_WATCH_ONLY); + nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY); fImmatureWatchCreditCached = true; return nImmatureWatchCreditCached; } @@ -736,7 +736,7 @@ public: if (!pwallet->IsSpent(GetHash(), i)) { const CTxOut &txout = vout[i]; - nCredit += pwallet->GetCredit(txout, MINE_WATCH_ONLY); + nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY); if (!MoneyRange(nCredit)) throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range"); } @@ -777,7 +777,7 @@ public: return true; if (nDepth < 0) return false; - if (!bSpendZeroConfChange || !IsFromMe(MINE_ALL)) // using wtx's cached debit + if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit return false; // Trusted if all inputs are from us and are in the mempool: @@ -788,7 +788,7 @@ public: if (parent == NULL) return false; const CTxOut& parentOut = parent->vout[txin.prevout.n]; - if (pwallet->IsMine(parentOut) != MINE_SPENDABLE) + if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE) return false; } return true; -- cgit v1.2.3