diff --git a/CMakeLists.txt b/CMakeLists.txt index a0318e9d08bc0..80f8fd29548b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,6 +213,7 @@ set(SERVER_SOURCES ./src/rpc/rawtransaction.cpp ./src/rpc/server.cpp ./src/script/sigcache.cpp + ./src/script/ismine.cpp ./src/sporkdb.cpp ./src/timedata.cpp ./src/torcontrol.cpp @@ -270,7 +271,6 @@ set(WALLET_SOURCES ./src/legacy/stakemodifier.cpp ./src/wallet/wallet.cpp ./src/wallet/wallet_zerocoin.cpp - ./src/wallet/wallet_ismine.cpp ./src/wallet/walletdb.cpp ./src/zpiv/zpivwallet.cpp ./src/zpiv/zpivtracker.cpp diff --git a/src/Makefile.am b/src/Makefile.am index fc2b94772a42c..04c8f0dce28ba 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -235,6 +235,7 @@ BITCOIN_CORE_H = \ sporkdb.h \ sporkid.h \ stakeinput.h \ + script/ismine.h \ streams.h \ support/cleanse.h \ sync.h \ @@ -264,7 +265,6 @@ BITCOIN_CORE_H = \ wallet/rpcwallet.h \ wallet/scriptpubkeyman.h \ wallet/wallet.h \ - wallet/wallet_ismine.h \ wallet/walletdb.h \ zpivchain.h \ zpiv/deterministicmint.h \ @@ -320,6 +320,7 @@ libbitcoin_server_a_SOURCES = \ rpc/rawtransaction.cpp \ rpc/server.cpp \ script/sigcache.cpp \ + script/ismine.cpp \ sporkdb.cpp \ timedata.cpp \ torcontrol.cpp \ @@ -367,7 +368,6 @@ libbitcoin_wallet_a_SOURCES = \ wallet/hdchain.cpp \ wallet/scriptpubkeyman.cpp \ wallet/wallet.cpp \ - wallet/wallet_ismine.cpp \ wallet/wallet_zerocoin.cpp \ wallet/walletdb.cpp \ zpiv/deterministicmint.cpp \ diff --git a/src/qt/walletmodel.cpp b/src/qt/walletmodel.cpp index 35a2ead21dd9e..4a5b272bc9607 100644 --- a/src/qt/walletmodel.cpp +++ b/src/qt/walletmodel.cpp @@ -842,7 +842,7 @@ void WalletModel::getOutputs(const std::vector& vOutpoints, std::vect bool fConflicted; const int nDepth = wallet->mapWallet[outpoint.hash].GetDepthAndMempool(fConflicted); if (nDepth < 0 || fConflicted) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true); vOutputs.push_back(out); } } @@ -884,7 +884,7 @@ void WalletModel::listCoins(std::map >& mapCoins) bool fConflicted; int nDepth = wallet->mapWallet[outpoint.hash].GetDepthAndMempool(fConflicted); if (nDepth < 0 || fConflicted) continue; - COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true); + COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true); if (outpoint.n < out.tx->vout.size() && (wallet->IsMine(out.tx->vout[outpoint.n]) & ISMINE_SPENDABLE_ALL) != ISMINE_NO) vCoins.push_back(out); @@ -895,7 +895,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, true); + cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true, true); } CTxDestination address; diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index 54df5d8c68a73..cbffc2ed64e43 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -436,6 +436,7 @@ UniValue fundrawtransaction(const JSONRPCRequest& request) "Note that all existing inputs must have their previous output transaction be in the wallet.\n" "Note that all inputs selected must be of standard form and P2SH scripts must be " "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n" + "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n" "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n" "\nArguments:\n" diff --git a/src/wallet/wallet_ismine.cpp b/src/script/ismine.cpp similarity index 99% rename from src/wallet/wallet_ismine.cpp rename to src/script/ismine.cpp index 2d96b95aea18f..8c94053882496 100644 --- a/src/wallet/wallet_ismine.cpp +++ b/src/script/ismine.cpp @@ -4,7 +4,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#include "wallet_ismine.h" +#include "ismine.h" #include "key.h" #include "keystore.h" diff --git a/src/wallet/wallet_ismine.h b/src/script/ismine.h similarity index 93% rename from src/wallet/wallet_ismine.h rename to src/script/ismine.h index 1b549b5fd576c..866d90496fcc4 100644 --- a/src/wallet/wallet_ismine.h +++ b/src/script/ismine.h @@ -4,8 +4,8 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. -#ifndef BITCOIN_WALLET_ISMINE_H -#define BITCOIN_WALLET_ISMINE_H +#ifndef BITCOIN_SCRIPT_ISMINE_H +#define BITCOIN_SCRIPT_ISMINE_H #include "key.h" #include "script/standard.h" @@ -36,4 +36,4 @@ typedef uint8_t isminefilter; isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey); isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest); -#endif // BITCOIN_WALLET_ISMINE_H +#endif // BITCOIN_SCRIPT_ISMINE_H diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index c241240748bcb..93b852210a1af 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -10,12 +10,10 @@ #include "script/script_error.h" #include "script/interpreter.h" #include "script/sign.h" +#include "script/ismine.h" #include "uint256.h" #include "test_pivx.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet_ismine.h" -#endif #include @@ -215,10 +213,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) CTxDestination addr; BOOST_CHECK(ExtractDestination(s, addr)); BOOST_CHECK(addr == keyaddr[0]); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); -#endif } { std::vector solutions; @@ -230,10 +226,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) CTxDestination addr; BOOST_CHECK(ExtractDestination(s, addr)); BOOST_CHECK(addr == keyaddr[0]); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); -#endif } { std::vector solutions; @@ -244,11 +238,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) BOOST_CHECK_EQUAL(solutions.size(), 4U); CTxDestination addr; BOOST_CHECK(!ExtractDestination(s, addr)); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); BOOST_CHECK(!IsMine(partialkeystore, s)); -#endif } { std::vector solutions; @@ -263,11 +255,9 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1) BOOST_CHECK(addrs[0] == keyaddr[0]); BOOST_CHECK(addrs[1] == keyaddr[1]); BOOST_CHECK(nRequired == 1); -#ifdef ENABLE_WALLET BOOST_CHECK(IsMine(keystore, s)); BOOST_CHECK(!IsMine(emptykeystore, s)); BOOST_CHECK(!IsMine(partialkeystore, s)); -#endif } { std::vector solutions; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index 382ebeea60b44..a5032805c97b8 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -11,12 +11,9 @@ #include "script/script.h" #include "script/script_error.h" #include "script/sign.h" +#include "script/ismine.h" #include "test_pivx.h" -#ifdef ENABLE_WALLET -#include "wallet/wallet_ismine.h" -#endif - #include #include @@ -101,9 +98,7 @@ BOOST_AUTO_TEST_CASE(sign) txTo[i].vin[0].prevout.n = i; txTo[i].vin[0].prevout.hash = txFrom.GetHash(); txTo[i].vout[0].nValue = 1; -#ifdef ENABLE_WALLET BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); -#endif } for (int i = 0; i < 8; i++) { @@ -200,9 +195,7 @@ BOOST_AUTO_TEST_CASE(set) txTo[i].vin[0].prevout.hash = txFrom.GetHash(); txTo[i].vout[0].nValue = 1*CENT; txTo[i].vout[0].scriptPubKey = inner[i]; -#ifdef ENABLE_WALLET BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); -#endif } for (int i = 0; i < 4; i++) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 07e3b64642765..45897b1f20d45 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3140,6 +3140,7 @@ UniValue listunspent(const JSONRPCRequest& request) " \"amount\" : x.xxx, (numeric) the transaction amount in PIV\n" " \"confirmations\" : n, (numeric) The number of confirmations\n" " \"spendable\" : true|false (boolean) Whether we have the private keys to spend this output\n" + " \"solvable\" : xxx (bool) Whether we know how to spend this output, ignoring the lack of keys\n" " }\n" " ,...\n" "]\n" @@ -3232,6 +3233,7 @@ UniValue listunspent(const JSONRPCRequest& request) entry.push_back(Pair("amount", ValueFromAmount(nValue))); entry.push_back(Pair("confirmations", out.nDepth)); entry.push_back(Pair("spendable", out.fSpendable)); + entry.push_back(Pair("solvable", out.fSolvable)); results.push_back(entry); } diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 86c72c4a25ee6..745b608ee9271 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -45,7 +45,7 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa wtx->fDebitCached = true; wtx->nDebitCached = 1; } - COutput output(wtx, nInput, nAge, true); + COutput output(wtx, nInput, nAge, true, true); vCoins.push_back(output); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index f44395cc1b78d..237a35dd45af9 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2013,9 +2013,10 @@ void CWallet::GetAvailableP2CSCoins(std::vector& vCoins) const { if (utxo.scriptPubKey.IsPayToColdStaking()) { isminetype mine = IsMine(utxo); bool isMineSpendable = mine & ISMINE_SPENDABLE_DELEGATED; + bool fIsSolvable = (mine & (ISMINE_SPENDABLE_ALL | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO; if (mine & ISMINE_COLD || isMineSpendable) // Depth is not used, no need waste resources and set it for now. - vCoins.emplace_back(COutput(pcoin, i, 0, isMineSpendable)); + vCoins.emplace_back(COutput(pcoin, i, 0, isMineSpendable, fIsSolvable)); } } } @@ -2112,7 +2113,7 @@ bool CWallet::GetMasternodeVinAndKeys(CTxIn& txinRet, CPubKey& pubKeyRet, CKey& } return GetVinAndKeysFromOutput( - COutput(&wtx, nOutputIndex, nDepth, true), + COutput(&wtx, nOutputIndex, nDepth, true, true), txinRet, pubKeyRet, keyRet); @@ -2181,15 +2182,16 @@ bool CWallet::AvailableCoins(std::vector* pCoins, // --> populates // skip auto-delegated coins if (mine == ISMINE_SPENDABLE_STAKEABLE && !fIncludeColdStaking && !fIncludeDelegated) continue; - bool fIsValid = ( - ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || - (coinControl && coinControl->fAllowWatchOnly && (mine & ISMINE_WATCH_SOLVABLE) != ISMINE_NO) || + bool solvable = (mine & (ISMINE_SPENDABLE_ALL | ISMINE_WATCH_SOLVABLE)) != ISMINE_NO; + + bool spendable = ((mine & ISMINE_SPENDABLE) != ISMINE_NO) || + (((mine & ISMINE_WATCH_ONLY) != ISMINE_NO) && (coinControl && coinControl->fAllowWatchOnly && solvable)) || ((mine & ((fIncludeColdStaking ? ISMINE_COLD : ISMINE_NO) | - (fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO) )) != ISMINE_NO)); + (fIncludeDelegated ? ISMINE_SPENDABLE_DELEGATED : ISMINE_NO) )) != ISMINE_NO); // found valid coin if (!pCoins) return true; - pCoins->emplace_back(COutput(pcoin, i, nDepth, fIsValid)); + pCoins->emplace_back(COutput(pcoin, i, nDepth, spendable, solvable)); } } return (pCoins && pCoins->size() > 0); diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index bcf156ab25e45..d911726ed3465 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -26,7 +26,7 @@ #include "util.h" #include "util/memory.h" #include "validationinterface.h" -#include "wallet/wallet_ismine.h" +#include "script/ismine.h" #include "wallet/scriptpubkeyman.h" #include "sapling/saplingscriptpubkeyman.h" #include "wallet/walletdb.h" @@ -992,20 +992,12 @@ class COutput int i; int nDepth; bool fSpendable; + bool fSolvable; - COutput(const CWalletTx* txIn, int iIn, int nDepthIn, bool fSpendableIn) - { - tx = txIn; - i = iIn; - nDepth = nDepthIn; - fSpendable = fSpendableIn; - } - - CAmount Value() const - { - return tx->vout[i].nValue; - } + COutput(const CWalletTx* txIn, int iIn, int nDepthIn, bool fSpendableIn, bool fSolvableIn) : + tx(txIn), i(iIn), nDepth(nDepthIn), fSpendable(fSpendableIn), fSolvable(fSolvableIn) {} + CAmount Value() const { return tx->vout[i].nValue; } std::string ToString() const; };