aboutsummaryrefslogtreecommitdiff
path: root/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet')
-rw-r--r--src/wallet/rpcwallet.cpp77
-rw-r--r--src/wallet/test/accounting_tests.cpp141
-rw-r--r--src/wallet/test/rpc_wallet_tests.cpp229
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp28
-rw-r--r--src/wallet/test/wallet_test_fixture.h18
-rw-r--r--src/wallet/test/wallet_tests.cpp4
-rw-r--r--src/wallet/wallet.cpp103
-rw-r--r--src/wallet/wallet.h19
-rw-r--r--src/wallet/wallet_ismine.cpp95
-rw-r--r--src/wallet/wallet_ismine.h34
10 files changed, 540 insertions, 208 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
index 61c9846e11..d1e201ec11 100644
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -82,15 +82,11 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry)
std::string rbfStatus = "no";
if (confirms <= 0) {
LOCK(mempool.cs);
- if (!mempool.exists(hash)) {
- if (SignalsOptInRBF(wtx)) {
- rbfStatus = "yes";
- } else {
- rbfStatus = "unknown";
- }
- } else if (IsRBFOptIn(*mempool.mapTx.find(hash), mempool)) {
+ RBFTransactionState rbfState = IsRBFOptIn(wtx, mempool);
+ if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN)
+ rbfStatus = "unknown";
+ else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125)
rbfStatus = "yes";
- }
}
entry.push_back(Pair("bip125-replaceable", rbfStatus));
@@ -2441,18 +2437,25 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (fHelp || params.size() < 1 || params.size() > 2)
throw runtime_error(
- "fundrawtransaction \"hexstring\" includeWatching\n"
+ "fundrawtransaction \"hexstring\" ( options )\n"
"\nAdd inputs to a transaction until it has enough in value to meet its out value.\n"
"This will not modify existing inputs, and will add one change output to the outputs.\n"
"Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n"
"The inputs added will not be signed, use signrawtransaction for that.\n"
"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"
+ "Note that all inputs selected must be of standard form and P2SH scripts must be\n"
"in the wallet using importaddress or addmultisigaddress (to calculate fees).\n"
"Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n"
"\nArguments:\n"
- "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
- "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n"
+ "1. \"hexstring\" (string, required) The hex string of the raw transaction\n"
+ "2. options (object, optional)\n"
+ " {\n"
+ " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n"
+ " \"changePosition\" (numeric, optional, default random) The index of the change output\n"
+ " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n"
+ " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n"
+ " }\n"
+ " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n"
"\nResult:\n"
"{\n"
" \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n"
@@ -2471,7 +2474,44 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
+ HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"")
);
- RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL));
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR));
+
+ CTxDestination changeAddress = CNoDestination();
+ int changePosition = -1;
+ bool includeWatching = false;
+ bool lockUnspents = false;
+
+ if (params.size() > 1) {
+ if (params[1].type() == UniValue::VBOOL) {
+ // backward compatibility bool only fallback
+ includeWatching = params[1].get_bool();
+ }
+ else {
+ RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ));
+
+ UniValue options = params[1];
+
+ RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL), true, true);
+
+ if (options.exists("changeAddress")) {
+ CBitcoinAddress address(options["changeAddress"].get_str());
+
+ if (!address.IsValid())
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address");
+
+ changeAddress = address.Get();
+ }
+
+ if (options.exists("changePosition"))
+ changePosition = options["changePosition"].get_int();
+
+ if (options.exists("includeWatching"))
+ includeWatching = options["includeWatching"].get_bool();
+
+ if (options.exists("lockUnspents"))
+ lockUnspents = options["lockUnspents"].get_bool();
+ }
+ }
// parse hex string from parameter
CTransaction origTx;
@@ -2481,20 +2521,19 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp)
if (origTx.vout.size() == 0)
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
- bool includeWatching = false;
- if (params.size() > 1)
- includeWatching = params[1].get_bool();
+ if (changePosition != -1 && (changePosition < 0 || changePosition > origTx.vout.size()))
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
CMutableTransaction tx(origTx);
CAmount nFee;
string strFailReason;
- int nChangePos = -1;
- if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason, includeWatching))
+
+ if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress))
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
UniValue result(UniValue::VOBJ);
result.push_back(Pair("hex", EncodeHexTx(tx)));
- result.push_back(Pair("changepos", nChangePos));
+ result.push_back(Pair("changepos", changePosition));
result.push_back(Pair("fee", ValueFromAmount(nFee)));
return result;
diff --git a/src/wallet/test/accounting_tests.cpp b/src/wallet/test/accounting_tests.cpp
new file mode 100644
index 0000000000..d075b2b641
--- /dev/null
+++ b/src/wallet/test/accounting_tests.cpp
@@ -0,0 +1,141 @@
+// Copyright (c) 2012-2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "wallet/wallet.h"
+#include "wallet/walletdb.h"
+
+#include "wallet/test/wallet_test_fixture.h"
+
+#include <stdint.h>
+
+#include <boost/foreach.hpp>
+#include <boost/test/unit_test.hpp>
+
+extern CWallet* pwalletMain;
+
+BOOST_FIXTURE_TEST_SUITE(accounting_tests, WalletTestingSetup)
+
+static void
+GetResults(CWalletDB& walletdb, std::map<CAmount, CAccountingEntry>& results)
+{
+ std::list<CAccountingEntry> aes;
+
+ results.clear();
+ BOOST_CHECK(walletdb.ReorderTransactions(pwalletMain) == DB_LOAD_OK);
+ walletdb.ListAccountCreditDebit("", aes);
+ BOOST_FOREACH(CAccountingEntry& ae, aes)
+ {
+ results[ae.nOrderPos] = ae;
+ }
+}
+
+BOOST_AUTO_TEST_CASE(acc_orderupgrade)
+{
+ CWalletDB walletdb(pwalletMain->strWalletFile);
+ std::vector<CWalletTx*> vpwtx;
+ CWalletTx wtx;
+ CAccountingEntry ae;
+ std::map<CAmount, CAccountingEntry> results;
+
+ LOCK(pwalletMain->cs_wallet);
+
+ ae.strAccount = "";
+ ae.nCreditDebit = 1;
+ ae.nTime = 1333333333;
+ ae.strOtherAccount = "b";
+ ae.strComment = "";
+ pwalletMain->AddAccountingEntry(ae, walletdb);
+
+ wtx.mapValue["comment"] = "z";
+ pwalletMain->AddToWallet(wtx, false, &walletdb);
+ vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
+ vpwtx[0]->nTimeReceived = (unsigned int)1333333335;
+ vpwtx[0]->nOrderPos = -1;
+
+ ae.nTime = 1333333336;
+ ae.strOtherAccount = "c";
+ pwalletMain->AddAccountingEntry(ae, walletdb);
+
+ GetResults(walletdb, results);
+
+ BOOST_CHECK(pwalletMain->nOrderPosNext == 3);
+ BOOST_CHECK(2 == results.size());
+ BOOST_CHECK(results[0].nTime == 1333333333);
+ BOOST_CHECK(results[0].strComment.empty());
+ BOOST_CHECK(1 == vpwtx[0]->nOrderPos);
+ BOOST_CHECK(results[2].nTime == 1333333336);
+ BOOST_CHECK(results[2].strOtherAccount == "c");
+
+
+ ae.nTime = 1333333330;
+ ae.strOtherAccount = "d";
+ ae.nOrderPos = pwalletMain->IncOrderPosNext();
+ pwalletMain->AddAccountingEntry(ae, walletdb);
+
+ GetResults(walletdb, results);
+
+ BOOST_CHECK(results.size() == 3);
+ BOOST_CHECK(pwalletMain->nOrderPosNext == 4);
+ BOOST_CHECK(results[0].nTime == 1333333333);
+ BOOST_CHECK(1 == vpwtx[0]->nOrderPos);
+ BOOST_CHECK(results[2].nTime == 1333333336);
+ BOOST_CHECK(results[3].nTime == 1333333330);
+ BOOST_CHECK(results[3].strComment.empty());
+
+
+ wtx.mapValue["comment"] = "y";
+ {
+ CMutableTransaction tx(wtx);
+ --tx.nLockTime; // Just to change the hash :)
+ *static_cast<CTransaction*>(&wtx) = CTransaction(tx);
+ }
+ pwalletMain->AddToWallet(wtx, false, &walletdb);
+ vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
+ vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
+
+ wtx.mapValue["comment"] = "x";
+ {
+ CMutableTransaction tx(wtx);
+ --tx.nLockTime; // Just to change the hash :)
+ *static_cast<CTransaction*>(&wtx) = CTransaction(tx);
+ }
+ pwalletMain->AddToWallet(wtx, false, &walletdb);
+ vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
+ vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
+ vpwtx[2]->nOrderPos = -1;
+
+ GetResults(walletdb, results);
+
+ BOOST_CHECK(results.size() == 3);
+ BOOST_CHECK(pwalletMain->nOrderPosNext == 6);
+ BOOST_CHECK(0 == vpwtx[2]->nOrderPos);
+ BOOST_CHECK(results[1].nTime == 1333333333);
+ BOOST_CHECK(2 == vpwtx[0]->nOrderPos);
+ BOOST_CHECK(results[3].nTime == 1333333336);
+ BOOST_CHECK(results[4].nTime == 1333333330);
+ BOOST_CHECK(results[4].strComment.empty());
+ BOOST_CHECK(5 == vpwtx[1]->nOrderPos);
+
+
+ ae.nTime = 1333333334;
+ ae.strOtherAccount = "e";
+ ae.nOrderPos = -1;
+ pwalletMain->AddAccountingEntry(ae, walletdb);
+
+ GetResults(walletdb, results);
+
+ BOOST_CHECK(results.size() == 4);
+ BOOST_CHECK(pwalletMain->nOrderPosNext == 7);
+ BOOST_CHECK(0 == vpwtx[2]->nOrderPos);
+ BOOST_CHECK(results[1].nTime == 1333333333);
+ BOOST_CHECK(2 == vpwtx[0]->nOrderPos);
+ BOOST_CHECK(results[3].nTime == 1333333336);
+ BOOST_CHECK(results[3].strComment.empty());
+ BOOST_CHECK(results[4].nTime == 1333333330);
+ BOOST_CHECK(results[4].strComment.empty());
+ BOOST_CHECK(results[5].nTime == 1333333334);
+ BOOST_CHECK(6 == vpwtx[1]->nOrderPos);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/test/rpc_wallet_tests.cpp b/src/wallet/test/rpc_wallet_tests.cpp
new file mode 100644
index 0000000000..4e7d177f51
--- /dev/null
+++ b/src/wallet/test/rpc_wallet_tests.cpp
@@ -0,0 +1,229 @@
+// Copyright (c) 2013-2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "rpc/server.h"
+#include "rpc/client.h"
+
+#include "base58.h"
+#include "main.h"
+#include "wallet/wallet.h"
+
+#include "wallet/test/wallet_test_fixture.h"
+
+#include <boost/algorithm/string.hpp>
+#include <boost/test/unit_test.hpp>
+
+#include <univalue.h>
+
+using namespace std;
+
+extern UniValue createArgs(int nRequired, const char* address1 = NULL, const char* address2 = NULL);
+extern UniValue CallRPC(string args);
+
+extern CWallet* pwalletMain;
+
+BOOST_FIXTURE_TEST_SUITE(rpc_wallet_tests, WalletTestingSetup)
+
+BOOST_AUTO_TEST_CASE(rpc_addmultisig)
+{
+ rpcfn_type addmultisig = tableRPC["addmultisigaddress"]->actor;
+
+ // old, 65-byte-long:
+ const char address1Hex[] = "0434e3e09f49ea168c5bbf53f877ff4206923858aab7c7e1df25bc263978107c95e35065a27ef6f1b27222db0ec97e0e895eaca603d3ee0d4c060ce3d8a00286c8";
+ // new, compressed:
+ const char address2Hex[] = "0388c2037017c62240b6b72ac1a2a5f94da790596ebd06177c8572752922165cb4";
+
+ UniValue v;
+ CBitcoinAddress address;
+ BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex), false));
+ address.SetString(v.get_str());
+ BOOST_CHECK(address.IsValid() && address.IsScript());
+
+ BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(1, address1Hex, address2Hex), false));
+ address.SetString(v.get_str());
+ BOOST_CHECK(address.IsValid() && address.IsScript());
+
+ BOOST_CHECK_NO_THROW(v = addmultisig(createArgs(2, address1Hex, address2Hex), false));
+ address.SetString(v.get_str());
+ BOOST_CHECK(address.IsValid() && address.IsScript());
+
+ BOOST_CHECK_THROW(addmultisig(createArgs(0), false), runtime_error);
+ BOOST_CHECK_THROW(addmultisig(createArgs(1), false), runtime_error);
+ BOOST_CHECK_THROW(addmultisig(createArgs(2, address1Hex), false), runtime_error);
+
+ BOOST_CHECK_THROW(addmultisig(createArgs(1, ""), false), runtime_error);
+ BOOST_CHECK_THROW(addmultisig(createArgs(1, "NotAValidPubkey"), false), runtime_error);
+
+ string short1(address1Hex, address1Hex + sizeof(address1Hex) - 2); // last byte missing
+ BOOST_CHECK_THROW(addmultisig(createArgs(2, short1.c_str()), false), runtime_error);
+
+ string short2(address1Hex + 1, address1Hex + sizeof(address1Hex)); // first byte missing
+ BOOST_CHECK_THROW(addmultisig(createArgs(2, short2.c_str()), false), runtime_error);
+}
+
+BOOST_AUTO_TEST_CASE(rpc_wallet)
+{
+ // Test RPC calls for various wallet statistics
+ UniValue r;
+ CPubKey demoPubkey;
+ CBitcoinAddress demoAddress;
+ UniValue retValue;
+ string strAccount = "walletDemoAccount";
+ CBitcoinAddress setaccountDemoAddress;
+ {
+ LOCK(pwalletMain->cs_wallet);
+
+ demoPubkey = pwalletMain->GenerateNewKey();
+ demoAddress = CBitcoinAddress(CTxDestination(demoPubkey.GetID()));
+ string strPurpose = "receive";
+ BOOST_CHECK_NO_THROW({ /*Initialize Wallet with an account */
+ CWalletDB walletdb(pwalletMain->strWalletFile);
+ CAccount account;
+ account.vchPubKey = demoPubkey;
+ pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, strPurpose);
+ walletdb.WriteAccount(strAccount, account);
+ });
+
+ CPubKey setaccountDemoPubkey = pwalletMain->GenerateNewKey();
+ setaccountDemoAddress = CBitcoinAddress(CTxDestination(setaccountDemoPubkey.GetID()));
+ }
+ /*********************************
+ * setaccount
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("setaccount " + setaccountDemoAddress.ToString() + " nullaccount"));
+ /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ is not owned by the test wallet. */
+ BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ nullaccount"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("setaccount"), runtime_error);
+ /* 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X (33 chars) is an illegal address (should be 34 chars) */
+ BOOST_CHECK_THROW(CallRPC("setaccount 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X nullaccount"), runtime_error);
+
+
+ /*********************************
+ * getbalance
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("getbalance"));
+ BOOST_CHECK_NO_THROW(CallRPC("getbalance " + demoAddress.ToString()));
+
+ /*********************************
+ * listunspent
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listunspent"));
+ BOOST_CHECK_THROW(CallRPC("listunspent string"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 string"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 1 not_array"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listunspent 0 1 [] extra"), runtime_error);
+ BOOST_CHECK_NO_THROW(r = CallRPC("listunspent 0 1 []"));
+ BOOST_CHECK(r.get_array().empty());
+
+ /*********************************
+ * listreceivedbyaddress
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress"));
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress not_int"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 not_bool"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaddress 0 true"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaddress 0 true extra"), runtime_error);
+
+ /*********************************
+ * listreceivedbyaccount
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount"));
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount not_int"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 not_bool"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("listreceivedbyaccount 0 true"));
+ BOOST_CHECK_THROW(CallRPC("listreceivedbyaccount 0 true extra"), runtime_error);
+
+ /*********************************
+ * listsinceblock
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listsinceblock"));
+
+ /*********************************
+ * listtransactions
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listtransactions"));
+ BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString()));
+ BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20"));
+ BOOST_CHECK_NO_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " 20 0"));
+ BOOST_CHECK_THROW(CallRPC("listtransactions " + demoAddress.ToString() + " not_int"), runtime_error);
+
+ /*********************************
+ * listlockunspent
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listlockunspent"));
+
+ /*********************************
+ * listaccounts
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listaccounts"));
+
+ /*********************************
+ * listaddressgroupings
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("listaddressgroupings"));
+
+ /*********************************
+ * getrawchangeaddress
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("getrawchangeaddress"));
+
+ /*********************************
+ * getnewaddress
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("getnewaddress"));
+ BOOST_CHECK_NO_THROW(CallRPC("getnewaddress getnewaddress_demoaccount"));
+
+ /*********************************
+ * getaccountaddress
+ *********************************/
+ BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress \"\""));
+ BOOST_CHECK_NO_THROW(CallRPC("getaccountaddress accountThatDoesntExists")); // Should generate a new account
+ BOOST_CHECK_NO_THROW(retValue = CallRPC("getaccountaddress " + strAccount));
+ BOOST_CHECK(CBitcoinAddress(retValue.get_str()).Get() == demoAddress.Get());
+
+ /*********************************
+ * getaccount
+ *********************************/
+ BOOST_CHECK_THROW(CallRPC("getaccount"), runtime_error);
+ BOOST_CHECK_NO_THROW(CallRPC("getaccount " + demoAddress.ToString()));
+
+ /*********************************
+ * signmessage + verifymessage
+ *********************************/
+ BOOST_CHECK_NO_THROW(retValue = CallRPC("signmessage " + demoAddress.ToString() + " mymessage"));
+ BOOST_CHECK_THROW(CallRPC("signmessage"), runtime_error);
+ /* Should throw error because this address is not loaded in the wallet */
+ BOOST_CHECK_THROW(CallRPC("signmessage 1QFqqMUD55ZV3PJEJZtaKCsQmjLT6JkjvJ mymessage"), runtime_error);
+
+ /* missing arguments */
+ BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString()), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str()), runtime_error);
+ /* Illegal address */
+ BOOST_CHECK_THROW(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4X " + retValue.get_str() + " mymessage"), runtime_error);
+ /* wrong address */
+ BOOST_CHECK(CallRPC("verifymessage 1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ " + retValue.get_str() + " mymessage").get_bool() == false);
+ /* Correct address and signature but wrong message */
+ BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " wrongmessage").get_bool() == false);
+ /* Correct address, message and signature*/
+ BOOST_CHECK(CallRPC("verifymessage " + demoAddress.ToString() + " " + retValue.get_str() + " mymessage").get_bool() == true);
+
+ /*********************************
+ * getaddressesbyaccount
+ *********************************/
+ BOOST_CHECK_THROW(CallRPC("getaddressesbyaccount"), runtime_error);
+ BOOST_CHECK_NO_THROW(retValue = CallRPC("getaddressesbyaccount " + strAccount));
+ UniValue arr = retValue.get_array();
+ BOOST_CHECK(arr.size() > 0);
+ BOOST_CHECK(CBitcoinAddress(arr[0].get_str()).Get() == demoAddress.Get());
+
+ /*********************************
+ * fundrawtransaction
+ *********************************/
+ BOOST_CHECK_THROW(CallRPC("fundrawtransaction 28z"), runtime_error);
+ BOOST_CHECK_THROW(CallRPC("fundrawtransaction 01000000000180969800000000001976a91450ce0a4b0ee0ddeb633da85199728b940ac3fe9488ac00000000"), runtime_error);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
new file mode 100644
index 0000000000..9036ee26d8
--- /dev/null
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -0,0 +1,28 @@
+#include "wallet/test/wallet_test_fixture.h"
+
+#include "rpc/server.h"
+#include "wallet/db.h"
+#include "wallet/wallet.h"
+
+WalletTestingSetup::WalletTestingSetup(const std::string& chainName):
+ TestingSetup(chainName)
+{
+ bitdb.MakeMock();
+
+ bool fFirstRun;
+ pwalletMain = new CWallet("wallet_test.dat");
+ pwalletMain->LoadWallet(fFirstRun);
+ RegisterValidationInterface(pwalletMain);
+
+ RegisterWalletRPCCommands(tableRPC);
+}
+
+WalletTestingSetup::~WalletTestingSetup()
+{
+ UnregisterValidationInterface(pwalletMain);
+ delete pwalletMain;
+ pwalletMain = NULL;
+
+ bitdb.Flush(true);
+ bitdb.Reset();
+}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
new file mode 100644
index 0000000000..97a6d98397
--- /dev/null
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -0,0 +1,18 @@
+// Copyright (c) 2016 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_WALLET_TEST_FIXTURE_H
+#define BITCOIN_WALLET_TEST_FIXTURE_H
+
+#include "test/test_bitcoin.h"
+
+/** Testing setup and teardown for wallet.
+ */
+struct WalletTestingSetup: public TestingSetup {
+ WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
+ ~WalletTestingSetup();
+};
+
+#endif
+
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index e84d588026..b759a6b2e8 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -9,7 +9,7 @@
#include <utility>
#include <vector>
-#include "test/test_bitcoin.h"
+#include "wallet/test/wallet_test_fixture.h"
#include <boost/foreach.hpp>
#include <boost/test/unit_test.hpp>
@@ -25,7 +25,7 @@ using namespace std;
typedef set<pair<const CWalletTx*,unsigned int> > CoinSet;
-BOOST_FIXTURE_TEST_SUITE(wallet_tests, TestingSetup)
+BOOST_FIXTURE_TEST_SUITE(wallet_tests, WalletTestingSetup)
static CWallet wallet;
static vector<COutput> vCoins;
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 15b9af852b..8f2425fb6b 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -23,6 +23,7 @@
#include "timedata.h"
#include "txmempool.h"
#include "util.h"
+#include "ui_interface.h"
#include "utilmoneystr.h"
#include <assert.h>
@@ -365,22 +366,6 @@ void CWallet::Flush(bool shutdown)
bitdb.Flush(shutdown);
}
-bool static UIError(const std::string &str)
-{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
- return false;
-}
-
-void static UIWarning(const std::string &str)
-{
- uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
-}
-
-static std::string AmountErrMsg(const char * const optname, const std::string& strValue)
-{
- return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
-}
-
bool CWallet::Verify()
{
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
@@ -390,7 +375,7 @@ bool CWallet::Verify()
// Wallet file must be a plain filename without a directory
if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile))
- return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string()));
+ return InitError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string()));
if (!bitdb.Open(GetDataDir()))
{
@@ -407,7 +392,7 @@ bool CWallet::Verify()
// try again
if (!bitdb.Open(GetDataDir())) {
// if it still fails, it probably means we can't even create the database env
- return UIError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()));
+ return InitError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()));
}
}
@@ -423,14 +408,14 @@ bool CWallet::Verify()
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
if (r == CDBEnv::RECOVER_OK)
{
- UIWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!"
+ InitWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!"
" Original %s saved as %s in %s; if"
" your balance or transactions are incorrect you should"
" restore from a backup."),
walletFile, "wallet.{timestamp}.bak", GetDataDir()));
}
if (r == CDBEnv::RECOVER_FAIL)
- return UIError(strprintf(_("%s corrupt, salvage failed"), walletFile));
+ return InitError(strprintf(_("%s corrupt, salvage failed"), walletFile));
}
return true;
@@ -1932,7 +1917,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
return res;
}
-bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching)
+bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange)
{
vector<CRecipient> vecSend;
@@ -1944,6 +1929,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
}
CCoinControl coinControl;
+ coinControl.destChange = destChange;
coinControl.fAllowOtherInputs = true;
coinControl.fAllowWatchOnly = includeWatching;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
@@ -1951,26 +1937,35 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount &nFeeRet, int& nC
CReserveKey reservekey(this);
CWalletTx wtx;
- if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosRet, strFailReason, &coinControl, false))
+ if (!CreateTransaction(vecSend, wtx, reservekey, nFeeRet, nChangePosInOut, strFailReason, &coinControl, false))
return false;
- if (nChangePosRet != -1)
- tx.vout.insert(tx.vout.begin() + nChangePosRet, wtx.vout[nChangePosRet]);
+ if (nChangePosInOut != -1)
+ tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.vout[nChangePosInOut]);
// Add new txins (keeping original txin scriptSig/order)
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
{
if (!coinControl.IsSelected(txin.prevout))
+ {
tx.vin.push_back(txin);
+
+ if (lockUnspents)
+ {
+ LOCK2(cs_main, cs_wallet);
+ LockCoin(txin.prevout);
+ }
+ }
}
return true;
}
bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
- int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
+ int& nChangePosInOut, std::string& strFailReason, const CCoinControl* coinControl, bool sign)
{
CAmount nValue = 0;
+ int nChangePosRequest = nChangePosInOut;
unsigned int nSubtractFeeFromAmount = 0;
BOOST_FOREACH (const CRecipient& recipient, vecSend)
{
@@ -2036,10 +2031,10 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
// Start with no fee and loop until there is enough fee
while (true)
{
+ nChangePosInOut = nChangePosRequest;
txNew.vin.clear();
txNew.vout.clear();
wtxNew.fFromMe = true;
- nChangePosRet = -1;
bool fFirst = true;
CAmount nValueToSelect = nValue;
@@ -2159,14 +2154,24 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
// add the dust to the fee.
if (newTxOut.IsDust(::minRelayTxFee))
{
+ nChangePosInOut = -1;
nFeeRet += nChange;
reservekey.ReturnKey();
}
else
{
- // Insert change txn at random position:
- nChangePosRet = GetRandInt(txNew.vout.size()+1);
- vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
+ if (nChangePosInOut == -1)
+ {
+ // Insert change txn at random position:
+ nChangePosInOut = GetRandInt(txNew.vout.size()+1);
+ }
+ else if (nChangePosInOut > txNew.vout.size())
+ {
+ strFailReason = _("Change index out of range");
+ return false;
+ }
+
+ vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosInOut;
txNew.vout.insert(position, newTxOut);
}
}
@@ -2849,13 +2854,13 @@ void CWallet::GetScriptForMining(boost::shared_ptr<CReserveScript> &script)
script->reserveScript = CScript() << ToByteVector(pubkey) << OP_CHECKSIG;
}
-void CWallet::LockCoin(COutPoint& output)
+void CWallet::LockCoin(const COutPoint& output)
{
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.insert(output);
}
-void CWallet::UnlockCoin(COutPoint& output)
+void CWallet::UnlockCoin(const COutPoint& output)
{
AssertLockHeld(cs_wallet); // setLockedCoins
setLockedCoins.erase(output);
@@ -3062,7 +3067,7 @@ bool CWallet::InitLoadWallet()
CWallet *tempWallet = new CWallet(walletFile);
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DB_LOAD_OK) {
- return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
+ return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
}
delete tempWallet;
@@ -3078,22 +3083,22 @@ bool CWallet::InitLoadWallet()
if (nLoadWalletRet != DB_LOAD_OK)
{
if (nLoadWalletRet == DB_CORRUPT)
- return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
+ return InitError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
{
- UIWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
+ InitWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."),
walletFile));
}
else if (nLoadWalletRet == DB_TOO_NEW)
- return UIError(strprintf(_("Error loading %s: Wallet requires newer version of %s"),
+ return InitError(strprintf(_("Error loading %s: Wallet requires newer version of %s"),
walletFile, _(PACKAGE_NAME)));
else if (nLoadWalletRet == DB_NEED_REWRITE)
{
- return UIError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
+ return InitError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
}
else
- return UIError(strprintf(_("Error loading %s"), walletFile));
+ return InitError(strprintf(_("Error loading %s"), walletFile));
}
if (GetBoolArg("-upgradewallet", fFirstRun))
@@ -3109,7 +3114,7 @@ bool CWallet::InitLoadWallet()
LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion())
{
- return UIError(_("Cannot downgrade wallet"));
+ return InitError(_("Cannot downgrade wallet"));
}
walletInstance->SetMaxVersion(nMaxVersion);
}
@@ -3123,7 +3128,7 @@ bool CWallet::InitLoadWallet()
if (walletInstance->GetKeyFromPool(newDefaultKey)) {
walletInstance->SetDefaultKey(newDefaultKey);
if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive"))
- return UIError(_("Cannot write default address") += "\n");
+ return InitError(_("Cannot write default address") += "\n");
}
walletInstance->SetBestChain(chainActive.GetLocator());
@@ -3157,7 +3162,7 @@ bool CWallet::InitLoadWallet()
block = block->pprev;
if (pindexRescan != block)
- return UIError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
+ return InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
}
uiInterface.InitMessage(_("Rescanning..."));
@@ -3207,28 +3212,28 @@ bool CWallet::ParameterInteraction()
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
CWallet::minTxFee = CFeeRate(n);
else
- return UIError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
+ return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
}
if (mapArgs.count("-fallbackfee"))
{
CAmount nFeePerK = 0;
if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK))
- return UIError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"]));
+ return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"]));
if (nFeePerK > HIGH_TX_FEE_PER_KB)
- UIWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available."));
+ InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available."));
CWallet::fallbackFee = CFeeRate(nFeePerK);
}
if (mapArgs.count("-paytxfee"))
{
CAmount nFeePerK = 0;
if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
- return UIError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"]));
+ return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"]));
if (nFeePerK > HIGH_TX_FEE_PER_KB)
- UIWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
+ InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
payTxFee = CFeeRate(nFeePerK, 1000);
if (payTxFee < ::minRelayTxFee)
{
- return UIError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
+ return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
}
}
@@ -3236,13 +3241,13 @@ bool CWallet::ParameterInteraction()
{
CAmount nMaxFee = 0;
if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
- return UIError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
+ return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
if (nMaxFee > HIGH_MAX_TX_FEE)
- UIWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
+ InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
maxTxFee = nMaxFee;
if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
{
- return UIError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
+ return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
mapArgs["-maxtxfee"], ::minRelayTxFee.ToString()));
}
}
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index 867f33a7b5..fa8740eb7f 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -12,8 +12,8 @@
#include "ui_interface.h"
#include "utilstrencodings.h"
#include "validationinterface.h"
+#include "script/ismine.h"
#include "wallet/crypter.h"
-#include "wallet/wallet_ismine.h"
#include "wallet/walletdb.h"
#include "wallet/rpcwallet.h"
@@ -228,11 +228,11 @@ public:
mapValue_t mapValue;
std::vector<std::pair<std::string, std::string> > vOrderForm;
unsigned int fTimeReceivedIsTxTime;
- unsigned int nTimeReceived; //! time received by this node
+ unsigned int nTimeReceived; //!< time received by this node
unsigned int nTimeSmart;
char fFromMe;
std::string strFromAccount;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
// memory only
mutable bool fDebitCached;
@@ -324,7 +324,7 @@ public:
}
READWRITE(*(CMerkleTx*)this);
- std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
+ std::vector<CMerkleTx> vUnused; //!< Used to be vtxPrev
READWRITE(vUnused);
READWRITE(mapValue);
READWRITE(vOrderForm);
@@ -465,7 +465,7 @@ public:
std::string strOtherAccount;
std::string strComment;
mapValue_t mapValue;
- int64_t nOrderPos; //! position in ordered transaction list
+ int64_t nOrderPos; //!< position in ordered transaction list
uint64_t nEntryNo;
CAccountingEntry()
@@ -667,8 +667,8 @@ public:
bool IsSpent(const uint256& hash, unsigned int n) const;
bool IsLockedCoin(uint256 hash, unsigned int n) const;
- void LockCoin(COutPoint& output);
- void UnlockCoin(COutPoint& output);
+ void LockCoin(const COutPoint& output);
+ void UnlockCoin(const COutPoint& output);
void UnlockAllCoins();
void ListLockedCoins(std::vector<COutPoint>& vOutpts);
@@ -739,13 +739,14 @@ public:
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
- bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, bool includeWatching);
+ bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool includeWatching, bool lockUnspents, const CTxDestination& destChange = CNoDestination());
/**
* Create a new transaction paying the recipients with a set of coins
* selected by SelectCoins(); Also create the change output, when needed
+ * @note passing nChangePosInOut as -1 will result in setting a random position
*/
- bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet,
+ bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
diff --git a/src/wallet/wallet_ismine.cpp b/src/wallet/wallet_ismine.cpp
deleted file mode 100644
index ebda5cc53d..0000000000
--- a/src/wallet/wallet_ismine.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
-// 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 "key.h"
-#include "keystore.h"
-#include "script/script.h"
-#include "script/standard.h"
-#include "script/sign.h"
-
-#include <boost/foreach.hpp>
-
-using namespace std;
-
-typedef vector<unsigned char> valtype;
-
-unsigned int HaveKeys(const vector<valtype>& pubkeys, const CKeyStore& keystore)
-{
- unsigned int nResult = 0;
- BOOST_FOREACH(const valtype& pubkey, pubkeys)
- {
- CKeyID keyID = CPubKey(pubkey).GetID();
- if (keystore.HaveKey(keyID))
- ++nResult;
- }
- return nResult;
-}
-
-isminetype IsMine(const CKeyStore &keystore, const CTxDestination& dest)
-{
- CScript script = GetScriptForDestination(dest);
- return IsMine(keystore, script);
-}
-
-isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
-{
- vector<valtype> vSolutions;
- txnouttype whichType;
- if (!Solver(scriptPubKey, whichType, vSolutions)) {
- if (keystore.HaveWatchOnly(scriptPubKey))
- return ISMINE_WATCH_UNSOLVABLE;
- return ISMINE_NO;
- }
-
- CKeyID keyID;
- switch (whichType)
- {
- case TX_NONSTANDARD:
- case TX_NULL_DATA:
- break;
- case TX_PUBKEY:
- keyID = CPubKey(vSolutions[0]).GetID();
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
- break;
- case TX_PUBKEYHASH:
- keyID = CKeyID(uint160(vSolutions[0]));
- if (keystore.HaveKey(keyID))
- return ISMINE_SPENDABLE;
- break;
- case TX_SCRIPTHASH:
- {
- CScriptID scriptID = CScriptID(uint160(vSolutions[0]));
- CScript subscript;
- if (keystore.GetCScript(scriptID, subscript)) {
- isminetype ret = IsMine(keystore, subscript);
- if (ret == ISMINE_SPENDABLE)
- return ret;
- }
- break;
- }
- case TX_MULTISIG:
- {
- // Only consider transactions "mine" if we own ALL the
- // keys involved. Multi-signature transactions that are
- // partially owned (somebody else has a key that can spend
- // them) enable spend-out-from-under-you attacks, especially
- // in shared-wallet situations.
- vector<valtype> keys(vSolutions.begin()+1, vSolutions.begin()+vSolutions.size()-1);
- if (HaveKeys(keys, keystore) == keys.size())
- return ISMINE_SPENDABLE;
- break;
- }
- }
-
- if (keystore.HaveWatchOnly(scriptPubKey)) {
- // TODO: This could be optimized some by doing some work after the above solver
- CScript scriptSig;
- return ProduceSignature(DummySignatureCreator(&keystore), scriptPubKey, scriptSig) ? ISMINE_WATCH_SOLVABLE : ISMINE_WATCH_UNSOLVABLE;
- }
- return ISMINE_NO;
-}
diff --git a/src/wallet/wallet_ismine.h b/src/wallet/wallet_ismine.h
deleted file mode 100644
index 51afd1b140..0000000000
--- a/src/wallet/wallet_ismine.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2009-2010 Satoshi Nakamoto
-// Copyright (c) 2009-2015 The Bitcoin Core developers
-// Distributed under the MIT software license, see the accompanying
-// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-
-#ifndef BITCOIN_WALLET_WALLET_ISMINE_H
-#define BITCOIN_WALLET_WALLET_ISMINE_H
-
-#include "script/standard.h"
-
-#include <stdint.h>
-
-class CKeyStore;
-class CScript;
-
-/** IsMine() return codes */
-enum isminetype
-{
- ISMINE_NO = 0,
- //! Indicates that we don't know how to create a scriptSig that would solve this if we were given the appropriate private keys
- ISMINE_WATCH_UNSOLVABLE = 1,
- //! Indicates that we know how to create a scriptSig that would solve this if we were given the appropriate private keys
- ISMINE_WATCH_SOLVABLE = 2,
- ISMINE_WATCH_ONLY = ISMINE_WATCH_SOLVABLE | ISMINE_WATCH_UNSOLVABLE,
- ISMINE_SPENDABLE = 4,
- ISMINE_ALL = ISMINE_WATCH_ONLY | ISMINE_SPENDABLE
-};
-/** used for bitflags of isminetype */
-typedef uint8_t isminefilter;
-
-isminetype IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
-isminetype IsMine(const CKeyStore& keystore, const CTxDestination& dest);
-
-#endif // BITCOIN_WALLET_WALLET_ISMINE_H