]> Git Repo - VerusCoin.git/commitdiff
Merge pull request #5745
authorWladimir J. van der Laan <[email protected]>
Fri, 20 Mar 2015 15:05:37 +0000 (16:05 +0100)
committerWladimir J. van der Laan <[email protected]>
Fri, 20 Mar 2015 15:08:35 +0000 (16:08 +0100)
50c72f2 [Move Only] Move wallet related things to src/wallet/ (Jonas Schnelli)

1  2 
src/Makefile.am
src/qt/coincontroldialog.cpp
src/qt/sendcoinsdialog.cpp
src/qt/walletmodel.cpp
src/qt/walletmodeltransaction.cpp
src/test/multisig_tests.cpp
src/test/script_P2SH_tests.cpp
src/test/test_bitcoin.cpp
src/wallet/rpcwallet.cpp
src/wallet/wallet.cpp
src/wallet/wallet.h

diff --cc src/Makefile.am
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 054bc3b37bf4966282562ad58ee111d78fe9579d,431ad995ded36d2f34e284c65fb4a2c3a5cfb291..6b189a6b55faab6f4f106d245da0f88e6628cea4
  #include "script/interpreter.h"
  #include "script/sign.h"
  #include "uint256.h"
 +#include "test/test_bitcoin.h"
  
  #ifdef ENABLE_WALLET
- #include "wallet_ismine.h"
+ #include "wallet/wallet_ismine.h"
  #endif
  
  #include <boost/foreach.hpp>
index 52171b9e3c82f1b8e3218bff30bf2c85fcad84d7,357c8e93c91d84dd9c49c41490b0e32220d226f4..c8cfe28729c51ad0100ed23a470d5222e94ff3ca
@@@ -8,10 -8,9 +8,10 @@@
  #include "script/script.h"
  #include "script/script_error.h"
  #include "script/sign.h"
 +#include "test/test_bitcoin.h"
  
  #ifdef ENABLE_WALLET
- #include "wallet_ismine.h"
+ #include "wallet/wallet_ismine.h"
  #endif
  
  #include <vector>
Simple merge
index 0000000000000000000000000000000000000000,d097b6a0fafc2042efbcc220216e308742b72348..5502b0b261dfd5e115e04ff740c4898bb3a59420
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2066 +1,2097 @@@
 -static void SendMoney(const CTxDestination &address, CAmount nValue, CWalletTx& wtxNew)
+ // Copyright (c) 2010 Satoshi Nakamoto
+ // Copyright (c) 2009-2014 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 "amount.h"
+ #include "base58.h"
+ #include "core_io.h"
+ #include "rpcserver.h"
+ #include "init.h"
+ #include "net.h"
+ #include "netbase.h"
+ #include "timedata.h"
+ #include "util.h"
+ #include "utilmoneystr.h"
+ #include "wallet.h"
+ #include "walletdb.h"
+ #include <stdint.h>
+ #include <boost/assign/list_of.hpp>
+ #include "json/json_spirit_utils.h"
+ #include "json/json_spirit_value.h"
+ using namespace std;
+ using namespace json_spirit;
+ int64_t nWalletUnlockTime;
+ static CCriticalSection cs_nWalletUnlockTime;
+ std::string HelpRequiringPassphrase()
+ {
+     return pwalletMain && pwalletMain->IsCrypted()
+         ? "\nRequires wallet passphrase to be set with walletpassphrase call."
+         : "";
+ }
+ void EnsureWalletIsUnlocked()
+ {
+     if (pwalletMain->IsLocked())
+         throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+ }
+ void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
+ {
+     int confirms = wtx.GetDepthInMainChain();
+     entry.push_back(Pair("confirmations", confirms));
+     if (wtx.IsCoinBase())
+         entry.push_back(Pair("generated", true));
+     if (confirms > 0)
+     {
+         entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
+         entry.push_back(Pair("blockindex", wtx.nIndex));
+         entry.push_back(Pair("blocktime", mapBlockIndex[wtx.hashBlock]->GetBlockTime()));
+     }
+     uint256 hash = wtx.GetHash();
+     entry.push_back(Pair("txid", hash.GetHex()));
+     Array conflicts;
+     BOOST_FOREACH(const uint256& conflict, wtx.GetConflicts())
+         conflicts.push_back(conflict.GetHex());
+     entry.push_back(Pair("walletconflicts", conflicts));
+     entry.push_back(Pair("time", wtx.GetTxTime()));
+     entry.push_back(Pair("timereceived", (int64_t)wtx.nTimeReceived));
+     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
+         entry.push_back(Pair(item.first, item.second));
+ }
+ string AccountFromValue(const Value& value)
+ {
+     string strAccount = value.get_str();
+     if (strAccount == "*")
+         throw JSONRPCError(RPC_WALLET_INVALID_ACCOUNT_NAME, "Invalid account name");
+     return strAccount;
+ }
+ Value getnewaddress(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 1)
+         throw runtime_error(
+             "getnewaddress ( \"account\" )\n"
+             "\nReturns a new Bitcoin address for receiving payments.\n"
+             "If 'account' is specified (DEPRECATED), it is added to the address book \n"
+             "so payments received with the address will be credited to 'account'.\n"
+             "\nArguments:\n"
+             "1. \"account\"        (string, optional) DEPRECATED. The account name for the address to be linked to. If not provided, the default account \"\" is used. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created if there is no account by the given name.\n"
+             "\nResult:\n"
+             "\"bitcoinaddress\"    (string) The new bitcoin address\n"
+             "\nExamples:\n"
+             + HelpExampleCli("getnewaddress", "")
+             + HelpExampleRpc("getnewaddress", "")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     // Parse the account first so we don't generate a key if there's an error
+     string strAccount;
+     if (params.size() > 0)
+         strAccount = AccountFromValue(params[0]);
+     if (!pwalletMain->IsLocked())
+         pwalletMain->TopUpKeyPool();
+     // Generate a new key that is added to wallet
+     CPubKey newKey;
+     if (!pwalletMain->GetKeyFromPool(newKey))
+         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
+     CKeyID keyID = newKey.GetID();
+     pwalletMain->SetAddressBook(keyID, strAccount, "receive");
+     return CBitcoinAddress(keyID).ToString();
+ }
+ CBitcoinAddress GetAccountAddress(string strAccount, bool bForceNew=false)
+ {
+     CWalletDB walletdb(pwalletMain->strWalletFile);
+     CAccount account;
+     walletdb.ReadAccount(strAccount, account);
+     bool bKeyUsed = false;
+     // Check if the current key has been used
+     if (account.vchPubKey.IsValid())
+     {
+         CScript scriptPubKey = GetScriptForDestination(account.vchPubKey.GetID());
+         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin();
+              it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid();
+              ++it)
+         {
+             const CWalletTx& wtx = (*it).second;
+             BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+                 if (txout.scriptPubKey == scriptPubKey)
+                     bKeyUsed = true;
+         }
+     }
+     // Generate a new key
+     if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed)
+     {
+         if (!pwalletMain->GetKeyFromPool(account.vchPubKey))
+             throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
+         pwalletMain->SetAddressBook(account.vchPubKey.GetID(), strAccount, "receive");
+         walletdb.WriteAccount(strAccount, account);
+     }
+     return CBitcoinAddress(account.vchPubKey.GetID());
+ }
+ Value getaccountaddress(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() != 1)
+         throw runtime_error(
+             "getaccountaddress \"account\"\n"
+             "\nDEPRECATED. Returns the current Bitcoin address for receiving payments to this account.\n"
+             "\nArguments:\n"
+             "1. \"account\"       (string, required) The account name for the address. It can also be set to the empty string \"\" to represent the default account. The account does not need to exist, it will be created and a new address created  if there is no account by the given name.\n"
+             "\nResult:\n"
+             "\"bitcoinaddress\"   (string) The account bitcoin address\n"
+             "\nExamples:\n"
+             + HelpExampleCli("getaccountaddress", "")
+             + HelpExampleCli("getaccountaddress", "\"\"")
+             + HelpExampleCli("getaccountaddress", "\"myaccount\"")
+             + HelpExampleRpc("getaccountaddress", "\"myaccount\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     // Parse the account first so we don't generate a key if there's an error
+     string strAccount = AccountFromValue(params[0]);
+     Value ret;
+     ret = GetAccountAddress(strAccount).ToString();
+     return ret;
+ }
+ Value getrawchangeaddress(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 1)
+         throw runtime_error(
+             "getrawchangeaddress\n"
+             "\nReturns a new Bitcoin address, for receiving change.\n"
+             "This is for use with raw transactions, NOT normal use.\n"
+             "\nResult:\n"
+             "\"address\"    (string) The address\n"
+             "\nExamples:\n"
+             + HelpExampleCli("getrawchangeaddress", "")
+             + HelpExampleRpc("getrawchangeaddress", "")
+        );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     if (!pwalletMain->IsLocked())
+         pwalletMain->TopUpKeyPool();
+     CReserveKey reservekey(pwalletMain);
+     CPubKey vchPubKey;
+     if (!reservekey.GetReservedKey(vchPubKey))
+         throw JSONRPCError(RPC_WALLET_KEYPOOL_RAN_OUT, "Error: Keypool ran out, please call keypoolrefill first");
+     reservekey.KeepKey();
+     CKeyID keyID = vchPubKey.GetID();
+     return CBitcoinAddress(keyID).ToString();
+ }
+ Value setaccount(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 1 || params.size() > 2)
+         throw runtime_error(
+             "setaccount \"bitcoinaddress\" \"account\"\n"
+             "\nDEPRECATED. Sets the account associated with the given address.\n"
+             "\nArguments:\n"
+             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to be associated with an account.\n"
+             "2. \"account\"         (string, required) The account to assign the address to.\n"
+             "\nExamples:\n"
+             + HelpExampleCli("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"tabby\"")
+             + HelpExampleRpc("setaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"tabby\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     CBitcoinAddress address(params[0].get_str());
+     if (!address.IsValid())
+         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+     string strAccount;
+     if (params.size() > 1)
+         strAccount = AccountFromValue(params[1]);
+     // Only add the account if the address is yours.
+     if (IsMine(*pwalletMain, address.Get()))
+     {
+         // Detect when changing the account of an address that is the 'unused current key' of another account:
+         if (pwalletMain->mapAddressBook.count(address.Get()))
+         {
+             string strOldAccount = pwalletMain->mapAddressBook[address.Get()].name;
+             if (address == GetAccountAddress(strOldAccount))
+                 GetAccountAddress(strOldAccount, true);
+         }
+         pwalletMain->SetAddressBook(address.Get(), strAccount, "receive");
+     }
+     else
+         throw JSONRPCError(RPC_MISC_ERROR, "setaccount can only be used with own address");
+     return Value::null;
+ }
+ Value getaccount(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() != 1)
+         throw runtime_error(
+             "getaccount \"bitcoinaddress\"\n"
+             "\nDEPRECATED. Returns the account associated with the given address.\n"
+             "\nArguments:\n"
+             "1. \"bitcoinaddress\"  (string, required) The bitcoin address for account lookup.\n"
+             "\nResult:\n"
+             "\"accountname\"        (string) the account address\n"
+             "\nExamples:\n"
+             + HelpExampleCli("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
+             + HelpExampleRpc("getaccount", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     CBitcoinAddress address(params[0].get_str());
+     if (!address.IsValid())
+         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+     string strAccount;
+     map<CTxDestination, CAddressBookData>::iterator mi = pwalletMain->mapAddressBook.find(address.Get());
+     if (mi != pwalletMain->mapAddressBook.end() && !(*mi).second.name.empty())
+         strAccount = (*mi).second.name;
+     return strAccount;
+ }
+ Value getaddressesbyaccount(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() != 1)
+         throw runtime_error(
+             "getaddressesbyaccount \"account\"\n"
+             "\nDEPRECATED. Returns the list of addresses for the given account.\n"
+             "\nArguments:\n"
+             "1. \"account\"  (string, required) The account name.\n"
+             "\nResult:\n"
+             "[                     (json array of string)\n"
+             "  \"bitcoinaddress\"  (string) a bitcoin address associated with the given account\n"
+             "  ,...\n"
+             "]\n"
+             "\nExamples:\n"
+             + HelpExampleCli("getaddressesbyaccount", "\"tabby\"")
+             + HelpExampleRpc("getaddressesbyaccount", "\"tabby\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     string strAccount = AccountFromValue(params[0]);
+     // Find all addresses that have the given account
+     Array ret;
+     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
+     {
+         const CBitcoinAddress& address = item.first;
+         const string& strName = item.second.name;
+         if (strName == strAccount)
+             ret.push_back(address.ToString());
+     }
+     return ret;
+ }
 -    if (!pwalletMain->CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired, strError)) {
 -        if (nValue + nFeeRequired > curBalance)
 -            throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired)));
 -        else
 -            throw JSONRPCError(RPC_WALLET_ERROR, strError);
++static void SendMoney(const CTxDestination &address, CAmount nValue, bool fSubtractFeeFromAmount, CWalletTx& wtxNew)
+ {
+     CAmount curBalance = pwalletMain->GetBalance();
+     // Check amount
+     if (nValue <= 0)
+         throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid amount");
+     if (nValue > curBalance)
+         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Insufficient funds");
+     // Parse Bitcoin address
+     CScript scriptPubKey = GetScriptForDestination(address);
+     // Create and send the transaction
+     CReserveKey reservekey(pwalletMain);
+     CAmount nFeeRequired;
+     std::string strError;
 -    if (fHelp || params.size() < 2 || params.size() > 4)
++    vector<CRecipient> vecSend;
++    int nChangePosRet = -1;
++    CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
++    vecSend.push_back(recipient);
++    if (!pwalletMain->CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, nChangePosRet, strError)) {
++        if (!fSubtractFeeFromAmount && nValue + nFeeRequired > pwalletMain->GetBalance())
++            strError = strprintf("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!", FormatMoney(nFeeRequired));
++        throw JSONRPCError(RPC_WALLET_ERROR, strError);
+     }
+     if (!pwalletMain->CommitTransaction(wtxNew, reservekey))
+         throw JSONRPCError(RPC_WALLET_ERROR, "Error: The transaction was rejected! This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
+ }
+ Value sendtoaddress(const Array& params, bool fHelp)
+ {
 -            "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" )\n"
++    if (fHelp || params.size() < 2 || params.size() > 5)
+         throw runtime_error(
 -    SendMoney(address.Get(), nAmount, wtx);
++            "sendtoaddress \"bitcoinaddress\" amount ( \"comment\" \"comment-to\" subtractfeefromamount )\n"
+             "\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
+             + HelpRequiringPassphrase() +
+             "\nArguments:\n"
+             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to send to.\n"
+             "2. \"amount\"      (numeric, required) The amount in btc to send. eg 0.1\n"
+             "3. \"comment\"     (string, optional) A comment used to store what the transaction is for. \n"
+             "                             This is not part of the transaction, just kept in your wallet.\n"
+             "4. \"comment-to\"  (string, optional) A comment to store the name of the person or organization \n"
+             "                             to which you're sending the transaction. This is not part of the \n"
+             "                             transaction, just kept in your wallet.\n"
++            "5. subtractfeefromamount  (boolean, optional, default=false) The fee will be deducted from the amount being sent.\n"
++            "                             The recipient will receive less bitcoins than you enter in the amount field.\n"
+             "\nResult:\n"
+             "\"transactionid\"  (string) The transaction id.\n"
+             "\nExamples:\n"
+             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
+             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
++            + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"\" \"\" true")
+             + HelpExampleRpc("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     CBitcoinAddress address(params[0].get_str());
+     if (!address.IsValid())
+         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+     // Amount
+     CAmount nAmount = AmountFromValue(params[1]);
+     // Wallet comments
+     CWalletTx wtx;
+     if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty())
+         wtx.mapValue["comment"] = params[2].get_str();
+     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
+         wtx.mapValue["to"]      = params[3].get_str();
++    bool fSubtractFeeFromAmount = false;
++    if (params.size() > 4)
++        fSubtractFeeFromAmount = params[4].get_bool();
++
+     EnsureWalletIsUnlocked();
 -    SendMoney(address.Get(), nAmount, wtx);
++    SendMoney(address.Get(), nAmount, fSubtractFeeFromAmount, wtx);
+     return wtx.GetHash().GetHex();
+ }
+ Value listaddressgroupings(const Array& params, bool fHelp)
+ {
+     if (fHelp)
+         throw runtime_error(
+             "listaddressgroupings\n"
+             "\nLists groups of addresses which have had their common ownership\n"
+             "made public by common use as inputs or as the resulting change\n"
+             "in past transactions\n"
+             "\nResult:\n"
+             "[\n"
+             "  [\n"
+             "    [\n"
+             "      \"bitcoinaddress\",     (string) The bitcoin address\n"
+             "      amount,                 (numeric) The amount in btc\n"
+             "      \"account\"             (string, optional) The account (DEPRECATED)\n"
+             "    ]\n"
+             "    ,...\n"
+             "  ]\n"
+             "  ,...\n"
+             "]\n"
+             "\nExamples:\n"
+             + HelpExampleCli("listaddressgroupings", "")
+             + HelpExampleRpc("listaddressgroupings", "")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     Array jsonGroupings;
+     map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();
+     BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
+     {
+         Array jsonGrouping;
+         BOOST_FOREACH(CTxDestination address, grouping)
+         {
+             Array addressInfo;
+             addressInfo.push_back(CBitcoinAddress(address).ToString());
+             addressInfo.push_back(ValueFromAmount(balances[address]));
+             {
+                 LOCK(pwalletMain->cs_wallet);
+                 if (pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get()) != pwalletMain->mapAddressBook.end())
+                     addressInfo.push_back(pwalletMain->mapAddressBook.find(CBitcoinAddress(address).Get())->second.name);
+             }
+             jsonGrouping.push_back(addressInfo);
+         }
+         jsonGroupings.push_back(jsonGrouping);
+     }
+     return jsonGroupings;
+ }
+ Value signmessage(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() != 2)
+         throw runtime_error(
+             "signmessage \"bitcoinaddress\" \"message\"\n"
+             "\nSign a message with the private key of an address"
+             + HelpRequiringPassphrase() + "\n"
+             "\nArguments:\n"
+             "1. \"bitcoinaddress\"  (string, required) The bitcoin address to use for the private key.\n"
+             "2. \"message\"         (string, required) The message to create a signature of.\n"
+             "\nResult:\n"
+             "\"signature\"          (string) The signature of the message encoded in base 64\n"
+             "\nExamples:\n"
+             "\nUnlock the wallet for 30 seconds\n"
+             + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
+             "\nCreate the signature\n"
+             + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"my message\"") +
+             "\nVerify the signature\n"
+             + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" \"signature\" \"my message\"") +
+             "\nAs json rpc\n"
+             + HelpExampleRpc("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"my message\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     EnsureWalletIsUnlocked();
+     string strAddress = params[0].get_str();
+     string strMessage = params[1].get_str();
+     CBitcoinAddress addr(strAddress);
+     if (!addr.IsValid())
+         throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
+     CKeyID keyID;
+     if (!addr.GetKeyID(keyID))
+         throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
+     CKey key;
+     if (!pwalletMain->GetKey(keyID, key))
+         throw JSONRPCError(RPC_WALLET_ERROR, "Private key not available");
+     CHashWriter ss(SER_GETHASH, 0);
+     ss << strMessageMagic;
+     ss << strMessage;
+     vector<unsigned char> vchSig;
+     if (!key.SignCompact(ss.GetHash(), vchSig))
+         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
+     return EncodeBase64(&vchSig[0], vchSig.size());
+ }
+ Value getreceivedbyaddress(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 1 || params.size() > 2)
+         throw runtime_error(
+             "getreceivedbyaddress \"bitcoinaddress\" ( minconf )\n"
+             "\nReturns the total amount received by the given bitcoinaddress in transactions with at least minconf confirmations.\n"
+             "\nArguments:\n"
+             "1. \"bitcoinaddress\"  (string, required) The bitcoin address for transactions.\n"
+             "2. minconf             (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
+             "\nResult:\n"
+             "amount   (numeric) The total amount in btc received at this address.\n"
+             "\nExamples:\n"
+             "\nThe amount from transactions with at least 1 confirmation\n"
+             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\"") +
+             "\nThe amount including unconfirmed transactions, zero confirmations\n"
+             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 0") +
+             "\nThe amount with at least 6 confirmation, very safe\n"
+             + HelpExampleCli("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\" 6") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("getreceivedbyaddress", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", 6")
+        );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     // Bitcoin address
+     CBitcoinAddress address = CBitcoinAddress(params[0].get_str());
+     if (!address.IsValid())
+         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+     CScript scriptPubKey = GetScriptForDestination(address.Get());
+     if (!IsMine(*pwalletMain,scriptPubKey))
+         return (double)0.0;
+     // Minimum confirmations
+     int nMinDepth = 1;
+     if (params.size() > 1)
+         nMinDepth = params[1].get_int();
+     // Tally
+     CAmount nAmount = 0;
+     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+     {
+         const CWalletTx& wtx = (*it).second;
+         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+             continue;
+         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+             if (txout.scriptPubKey == scriptPubKey)
+                 if (wtx.GetDepthInMainChain() >= nMinDepth)
+                     nAmount += txout.nValue;
+     }
+     return  ValueFromAmount(nAmount);
+ }
+ Value getreceivedbyaccount(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 1 || params.size() > 2)
+         throw runtime_error(
+             "getreceivedbyaccount \"account\" ( minconf )\n"
+             "\nDEPRECATED. Returns the total amount received by addresses with <account> in transactions with at least [minconf] confirmations.\n"
+             "\nArguments:\n"
+             "1. \"account\"      (string, required) The selected account, may be the default account using \"\".\n"
+             "2. minconf          (numeric, optional, default=1) Only include transactions confirmed at least this many times.\n"
+             "\nResult:\n"
+             "amount              (numeric) The total amount in btc received for this account.\n"
+             "\nExamples:\n"
+             "\nAmount received by the default account with at least 1 confirmation\n"
+             + HelpExampleCli("getreceivedbyaccount", "\"\"") +
+             "\nAmount received at the tabby account including unconfirmed amounts with zero confirmations\n"
+             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 0") +
+             "\nThe amount with at least 6 confirmation, very safe\n"
+             + HelpExampleCli("getreceivedbyaccount", "\"tabby\" 6") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("getreceivedbyaccount", "\"tabby\", 6")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     // Minimum confirmations
+     int nMinDepth = 1;
+     if (params.size() > 1)
+         nMinDepth = params[1].get_int();
+     // Get the set of pub keys assigned to account
+     string strAccount = AccountFromValue(params[0]);
+     set<CTxDestination> setAddress = pwalletMain->GetAccountAddresses(strAccount);
+     // Tally
+     CAmount nAmount = 0;
+     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+     {
+         const CWalletTx& wtx = (*it).second;
+         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+             continue;
+         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+         {
+             CTxDestination address;
+             if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
+                 if (wtx.GetDepthInMainChain() >= nMinDepth)
+                     nAmount += txout.nValue;
+         }
+     }
+     return (double)nAmount / (double)COIN;
+ }
+ CAmount GetAccountBalance(CWalletDB& walletdb, const string& strAccount, int nMinDepth, const isminefilter& filter)
+ {
+     CAmount nBalance = 0;
+     // Tally wallet transactions
+     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+     {
+         const CWalletTx& wtx = (*it).second;
+         if (!IsFinalTx(wtx) || wtx.GetBlocksToMaturity() > 0 || wtx.GetDepthInMainChain() < 0)
+             continue;
+         CAmount nReceived, nSent, nFee;
+         wtx.GetAccountAmounts(strAccount, nReceived, nSent, nFee, filter);
+         if (nReceived != 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+             nBalance += nReceived;
+         nBalance -= nSent + nFee;
+     }
+     // Tally internal accounting entries
+     nBalance += walletdb.GetAccountCreditDebit(strAccount);
+     return nBalance;
+ }
+ CAmount GetAccountBalance(const string& strAccount, int nMinDepth, const isminefilter& filter)
+ {
+     CWalletDB walletdb(pwalletMain->strWalletFile);
+     return GetAccountBalance(walletdb, strAccount, nMinDepth, filter);
+ }
+ Value getbalance(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 3)
+         throw runtime_error(
+             "getbalance ( \"account\" minconf includeWatchonly )\n"
+             "\nIf account is not specified, returns the server's total available balance.\n"
+             "If account is specified (DEPRECATED), returns the balance in the account.\n"
+             "Note that the account \"\" is not the same as leaving the parameter out.\n"
+             "The server total may be different to the balance in the default \"\" account.\n"
+             "\nArguments:\n"
+             "1. \"account\"      (string, optional) DEPRECATED. 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"
+             "\nThe total amount in the wallet\n"
+             + HelpExampleCli("getbalance", "") +
+             "\nThe total amount in the wallet at least 5 blocks confirmed\n"
+             + HelpExampleCli("getbalance", "\"*\" 6") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("getbalance", "\"*\", 6")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     if (params.size() == 0)
+         return  ValueFromAmount(pwalletMain->GetBalance());
+     int nMinDepth = 1;
+     if (params.size() > 1)
+         nMinDepth = params[1].get_int();
+     isminefilter filter = ISMINE_SPENDABLE;
+     if(params.size() > 2)
+         if(params[2].get_bool())
+             filter = filter | ISMINE_WATCH_ONLY;
+     if (params[0].get_str() == "*") {
+         // Calculate total balance a different way from GetBalance()
+         // (GetBalance() sums up all unspent TxOuts)
+         // getbalance and getbalance '*' 0 should return the same number
+         CAmount nBalance = 0;
+         for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+         {
+             const CWalletTx& wtx = (*it).second;
+             if (!wtx.IsTrusted() || wtx.GetBlocksToMaturity() > 0)
+                 continue;
+             CAmount allFee;
+             string strSentAccount;
+             list<COutputEntry> listReceived;
+             list<COutputEntry> listSent;
+             wtx.GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
+             if (wtx.GetDepthInMainChain() >= nMinDepth)
+             {
+                 BOOST_FOREACH(const COutputEntry& r, listReceived)
+                     nBalance += r.amount;
+             }
+             BOOST_FOREACH(const COutputEntry& s, listSent)
+                 nBalance -= s.amount;
+             nBalance -= allFee;
+         }
+         return  ValueFromAmount(nBalance);
+     }
+     string strAccount = AccountFromValue(params[0]);
+     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, filter);
+     return ValueFromAmount(nBalance);
+ }
+ Value getunconfirmedbalance(const Array &params, bool fHelp)
+ {
+     if (fHelp || params.size() > 0)
+         throw runtime_error(
+                 "getunconfirmedbalance\n"
+                 "Returns the server's total unconfirmed balance\n");
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     return ValueFromAmount(pwalletMain->GetUnconfirmedBalance());
+ }
+ Value movecmd(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 3 || params.size() > 5)
+         throw runtime_error(
+             "move \"fromaccount\" \"toaccount\" amount ( minconf \"comment\" )\n"
+             "\nDEPRECATED. Move a specified amount from one account in your wallet to another.\n"
+             "\nArguments:\n"
+             "1. \"fromaccount\"   (string, required) The name of the account to move funds from. May be the default account using \"\".\n"
+             "2. \"toaccount\"     (string, required) The name of the account to move funds to. May be the default account using \"\".\n"
+             "3. minconf           (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
+             "4. \"comment\"       (string, optional) An optional comment, stored in the wallet only.\n"
+             "\nResult:\n"
+             "true|false           (boolean) true if successfull.\n"
+             "\nExamples:\n"
+             "\nMove 0.01 btc from the default account to the account named tabby\n"
+             + HelpExampleCli("move", "\"\" \"tabby\" 0.01") +
+             "\nMove 0.01 btc timotei to akiko with a comment and funds have 6 confirmations\n"
+             + HelpExampleCli("move", "\"timotei\" \"akiko\" 0.01 6 \"happy birthday!\"") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("move", "\"timotei\", \"akiko\", 0.01, 6, \"happy birthday!\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     string strFrom = AccountFromValue(params[0]);
+     string strTo = AccountFromValue(params[1]);
+     CAmount nAmount = AmountFromValue(params[2]);
+     if (params.size() > 3)
+         // unused parameter, used to be nMinDepth, keep type-checking it though
+         (void)params[3].get_int();
+     string strComment;
+     if (params.size() > 4)
+         strComment = params[4].get_str();
+     CWalletDB walletdb(pwalletMain->strWalletFile);
+     if (!walletdb.TxnBegin())
+         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
+     int64_t nNow = GetAdjustedTime();
+     // Debit
+     CAccountingEntry debit;
+     debit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
+     debit.strAccount = strFrom;
+     debit.nCreditDebit = -nAmount;
+     debit.nTime = nNow;
+     debit.strOtherAccount = strTo;
+     debit.strComment = strComment;
+     walletdb.WriteAccountingEntry(debit);
+     // Credit
+     CAccountingEntry credit;
+     credit.nOrderPos = pwalletMain->IncOrderPosNext(&walletdb);
+     credit.strAccount = strTo;
+     credit.nCreditDebit = nAmount;
+     credit.nTime = nNow;
+     credit.strOtherAccount = strFrom;
+     credit.strComment = strComment;
+     walletdb.WriteAccountingEntry(credit);
+     if (!walletdb.TxnCommit())
+         throw JSONRPCError(RPC_DATABASE_ERROR, "database error");
+     return true;
+ }
+ Value sendfrom(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 3 || params.size() > 6)
+         throw runtime_error(
+             "sendfrom \"fromaccount\" \"tobitcoinaddress\" amount ( minconf \"comment\" \"comment-to\" )\n"
+             "\nDEPRECATED (use sendtoaddress). Sent an amount from an account to a bitcoin address.\n"
+             "The amount is a real and is rounded to the nearest 0.00000001."
+             + HelpRequiringPassphrase() + "\n"
+             "\nArguments:\n"
+             "1. \"fromaccount\"       (string, required) The name of the account to send funds from. May be the default account using \"\".\n"
+             "2. \"tobitcoinaddress\"  (string, required) The bitcoin address to send funds to.\n"
+             "3. amount                (numeric, required) The amount in btc. (transaction fee is added on top).\n"
+             "4. minconf               (numeric, optional, default=1) Only use funds with at least this many confirmations.\n"
+             "5. \"comment\"           (string, optional) A comment used to store what the transaction is for. \n"
+             "                                     This is not part of the transaction, just kept in your wallet.\n"
+             "6. \"comment-to\"        (string, optional) An optional comment to store the name of the person or organization \n"
+             "                                     to which you're sending the transaction. This is not part of the transaction, \n"
+             "                                     it is just kept in your wallet.\n"
+             "\nResult:\n"
+             "\"transactionid\"        (string) The transaction id.\n"
+             "\nExamples:\n"
+             "\nSend 0.01 btc from the default account to the address, must have at least 1 confirmation\n"
+             + HelpExampleCli("sendfrom", "\"\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01") +
+             "\nSend 0.01 from the tabby account to the given address, funds must have at least 6 confirmations\n"
+             + HelpExampleCli("sendfrom", "\"tabby\" \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.01 6 \"donation\" \"seans outpost\"") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("sendfrom", "\"tabby\", \"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.01, 6, \"donation\", \"seans outpost\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     string strAccount = AccountFromValue(params[0]);
+     CBitcoinAddress address(params[1].get_str());
+     if (!address.IsValid())
+         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Bitcoin address");
+     CAmount nAmount = AmountFromValue(params[2]);
+     int nMinDepth = 1;
+     if (params.size() > 3)
+         nMinDepth = params[3].get_int();
+     CWalletTx wtx;
+     wtx.strFromAccount = strAccount;
+     if (params.size() > 4 && params[4].type() != null_type && !params[4].get_str().empty())
+         wtx.mapValue["comment"] = params[4].get_str();
+     if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
+         wtx.mapValue["to"]      = params[5].get_str();
+     EnsureWalletIsUnlocked();
+     // Check funds
+     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
+     if (nAmount > nBalance)
+         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
 -    if (fHelp || params.size() < 2 || params.size() > 4)
++    SendMoney(address.Get(), nAmount, false, wtx);
+     return wtx.GetHash().GetHex();
+ }
+ Value sendmany(const Array& params, bool fHelp)
+ {
 -            "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" )\n"
++    if (fHelp || params.size() < 2 || params.size() > 5)
+         throw runtime_error(
 -    vector<pair<CScript, CAmount> > vecSend;
++            "sendmany \"fromaccount\" {\"address\":amount,...} ( minconf \"comment\" [\"address\",...] )\n"
+             "\nSend multiple times. Amounts are double-precision floating point numbers."
+             + HelpRequiringPassphrase() + "\n"
+             "\nArguments:\n"
+             "1. \"fromaccount\"         (string, required) DEPRECATED. The account to send the funds from. Should be \"\" for the default account\n"
+             "2. \"amounts\"             (string, required) A json object with addresses and amounts\n"
+             "    {\n"
+             "      \"address\":amount   (numeric) The bitcoin address is the key, the numeric amount in btc is the value\n"
+             "      ,...\n"
+             "    }\n"
+             "3. minconf                 (numeric, optional, default=1) Only use the balance confirmed at least this many times.\n"
+             "4. \"comment\"             (string, optional) A comment\n"
++            "5. subtractfeefromamount   (string, optional) A json array with addresses.\n"
++            "                           The fee will be equally deducted from the amount of each selected address.\n"
++            "                           Those recipients will receive less bitcoins than you enter in their corresponding amount field.\n"
++            "                           If no addresses are specified here, the sender pays the fee.\n"
++            "    [\n"
++            "      \"address\"            (string) Subtract fee from this address\n"
++            "      ,...\n"
++            "    ]\n"
+             "\nResult:\n"
+             "\"transactionid\"          (string) The transaction id for the send. Only 1 transaction is created regardless of \n"
+             "                                    the number of addresses.\n"
+             "\nExamples:\n"
+             "\nSend two amounts to two different addresses:\n"
+             + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\"") +
+             "\nSend two amounts to two different addresses setting the confirmation and comment:\n"
+             + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 6 \"testing\"") +
++            "\nSend two amounts to two different addresses, subtract fee from amount:\n"
++            + HelpExampleCli("sendmany", "\"\" \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\" 1 \"\" \"[\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\",\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\"]\"") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("sendmany", "\"\", \"{\\\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\\\":0.01,\\\"1353tsE8YMTA4EuV7dgUXGjNFf9KpVvKHz\\\":0.02}\", 6, \"testing\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     string strAccount = AccountFromValue(params[0]);
+     Object sendTo = params[1].get_obj();
+     int nMinDepth = 1;
+     if (params.size() > 2)
+         nMinDepth = params[2].get_int();
+     CWalletTx wtx;
+     wtx.strFromAccount = strAccount;
+     if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty())
+         wtx.mapValue["comment"] = params[3].get_str();
++    Array subtractFeeFromAmount;
++    if (params.size() > 4)
++        subtractFeeFromAmount = params[4].get_array();
++
+     set<CBitcoinAddress> setAddress;
 -        vecSend.push_back(make_pair(scriptPubKey, nAmount));
++    vector<CRecipient> vecSend;
+     CAmount totalAmount = 0;
+     BOOST_FOREACH(const Pair& s, sendTo)
+     {
+         CBitcoinAddress address(s.name_);
+         if (!address.IsValid())
+             throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid Bitcoin address: ")+s.name_);
+         if (setAddress.count(address))
+             throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+s.name_);
+         setAddress.insert(address);
+         CScript scriptPubKey = GetScriptForDestination(address.Get());
+         CAmount nAmount = AmountFromValue(s.value_);
+         totalAmount += nAmount;
 -    bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason);
++        bool fSubtractFeeFromAmount = false;
++        BOOST_FOREACH(const Value& addr, subtractFeeFromAmount)
++            if (addr.get_str() == s.name_)
++                fSubtractFeeFromAmount = true;
++
++        CRecipient recipient = {scriptPubKey, nAmount, fSubtractFeeFromAmount};
++        vecSend.push_back(recipient);
+     }
+     EnsureWalletIsUnlocked();
+     // Check funds
+     CAmount nBalance = GetAccountBalance(strAccount, nMinDepth, ISMINE_SPENDABLE);
+     if (totalAmount > nBalance)
+         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds");
+     // Send
+     CReserveKey keyChange(pwalletMain);
+     CAmount nFeeRequired = 0;
++    int nChangePosRet = -1;
+     string strFailReason;
++    bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, nChangePosRet, strFailReason);
+     if (!fCreated)
+         throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
+     if (!pwalletMain->CommitTransaction(wtx, keyChange))
+         throw JSONRPCError(RPC_WALLET_ERROR, "Transaction commit failed");
+     return wtx.GetHash().GetHex();
+ }
+ // Defined in rpcmisc.cpp
+ extern CScript _createmultisig_redeemScript(const Array& params);
+ Value addmultisigaddress(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 2 || params.size() > 3)
+     {
+         string msg = "addmultisigaddress nrequired [\"key\",...] ( \"account\" )\n"
+             "\nAdd a nrequired-to-sign multisignature address to the wallet.\n"
+             "Each key is a Bitcoin address or hex-encoded public key.\n"
+             "If 'account' is specified (DEPRECATED), assign address to that account.\n"
+             "\nArguments:\n"
+             "1. nrequired        (numeric, required) The number of required signatures out of the n keys or addresses.\n"
+             "2. \"keysobject\"   (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
+             "     [\n"
+             "       \"address\"  (string) bitcoin address or hex-encoded public key\n"
+             "       ...,\n"
+             "     ]\n"
+             "3. \"account\"      (string, optional) DEPRECATED. An account to assign the addresses to.\n"
+             "\nResult:\n"
+             "\"bitcoinaddress\"  (string) A bitcoin address associated with the keys.\n"
+             "\nExamples:\n"
+             "\nAdd a multisig address from 2 addresses\n"
+             + HelpExampleCli("addmultisigaddress", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") +
+             "\nAs json rpc call\n"
+             + HelpExampleRpc("addmultisigaddress", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"")
+         ;
+         throw runtime_error(msg);
+     }
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     string strAccount;
+     if (params.size() > 2)
+         strAccount = AccountFromValue(params[2]);
+     // Construct using pay-to-script-hash:
+     CScript inner = _createmultisig_redeemScript(params);
+     CScriptID innerID(inner);
+     pwalletMain->AddCScript(inner);
+     pwalletMain->SetAddressBook(innerID, strAccount, "send");
+     return CBitcoinAddress(innerID).ToString();
+ }
+ struct tallyitem
+ {
+     CAmount nAmount;
+     int nConf;
+     vector<uint256> txids;
+     bool fIsWatchonly;
+     tallyitem()
+     {
+         nAmount = 0;
+         nConf = std::numeric_limits<int>::max();
+         fIsWatchonly = false;
+     }
+ };
+ Value ListReceived(const Array& params, bool fByAccounts)
+ {
+     // Minimum confirmations
+     int nMinDepth = 1;
+     if (params.size() > 0)
+         nMinDepth = params[0].get_int();
+     // Whether to include empty accounts
+     bool fIncludeEmpty = false;
+     if (params.size() > 1)
+         fIncludeEmpty = params[1].get_bool();
+     isminefilter filter = ISMINE_SPENDABLE;
+     if(params.size() > 2)
+         if(params[2].get_bool())
+             filter = filter | ISMINE_WATCH_ONLY;
+     // Tally
+     map<CBitcoinAddress, tallyitem> mapTally;
+     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+     {
+         const CWalletTx& wtx = (*it).second;
+         if (wtx.IsCoinBase() || !IsFinalTx(wtx))
+             continue;
+         int nDepth = wtx.GetDepthInMainChain();
+         if (nDepth < nMinDepth)
+             continue;
+         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
+         {
+             CTxDestination 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 & ISMINE_WATCH_ONLY)
+                 item.fIsWatchonly = true;
+         }
+     }
+     // Reply
+     Array ret;
+     map<string, tallyitem> mapAccountTally;
+     BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress, CAddressBookData)& item, pwalletMain->mapAddressBook)
+     {
+         const CBitcoinAddress& address = item.first;
+         const string& strAccount = item.second.name;
+         map<CBitcoinAddress, tallyitem>::iterator it = mapTally.find(address);
+         if (it == mapTally.end() && !fIncludeEmpty)
+             continue;
+         CAmount nAmount = 0;
+         int nConf = std::numeric_limits<int>::max();
+         bool fIsWatchonly = false;
+         if (it != mapTally.end())
+         {
+             nAmount = (*it).second.nAmount;
+             nConf = (*it).second.nConf;
+             fIsWatchonly = (*it).second.fIsWatchonly;
+         }
+         if (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)));
+             obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
+             Array transactions;
+             if (it != mapTally.end())
+             {
+                 BOOST_FOREACH(const uint256& item, (*it).second.txids)
+                 {
+                     transactions.push_back(item.GetHex());
+                 }
+             }
+             obj.push_back(Pair("txids", transactions));
+             ret.push_back(obj);
+         }
+     }
+     if (fByAccounts)
+     {
+         for (map<string, tallyitem>::iterator it = mapAccountTally.begin(); it != mapAccountTally.end(); ++it)
+         {
+             CAmount 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<int>::max() ? 0 : nConf)));
+             ret.push_back(obj);
+         }
+     }
+     return ret;
+ }
+ Value listreceivedbyaddress(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 3)
+         throw runtime_error(
+             "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, default=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) DEPRECATED. 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"
+             "    \"confirmations\" : n                (numeric) The number of confirmations of the most recent transaction included\n"
+             "  }\n"
+             "  ,...\n"
+             "]\n"
+             "\nExamples:\n"
+             + HelpExampleCli("listreceivedbyaddress", "")
+             + HelpExampleCli("listreceivedbyaddress", "6 true")
+             + HelpExampleRpc("listreceivedbyaddress", "6, true, true")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     return ListReceived(params, false);
+ }
+ Value listreceivedbyaccount(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 3)
+         throw runtime_error(
+             "listreceivedbyaccount ( minconf includeempty includeWatchonly)\n"
+             "\nDEPRECATED. List 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"
+             "  }\n"
+             "  ,...\n"
+             "]\n"
+             "\nExamples:\n"
+             + HelpExampleCli("listreceivedbyaccount", "")
+             + HelpExampleCli("listreceivedbyaccount", "6 true")
+             + HelpExampleRpc("listreceivedbyaccount", "6, true, true")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     return ListReceived(params, true);
+ }
+ static void MaybePushAddress(Object & entry, const CTxDestination &dest)
+ {
+     CBitcoinAddress addr;
+     if (addr.Set(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)
+ {
+     CAmount nFee;
+     string strSentAccount;
+     list<COutputEntry> listReceived;
+     list<COutputEntry> listSent;
+     wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, filter);
+     bool fAllAccounts = (strAccount == string("*"));
+     bool involvesWatchonly = wtx.IsFromMe(ISMINE_WATCH_ONLY);
+     // Sent
+     if ((!listSent.empty() || nFee != 0) && (fAllAccounts || strAccount == strSentAccount))
+     {
+         BOOST_FOREACH(const COutputEntry& s, listSent)
+         {
+             Object entry;
+             if(involvesWatchonly || (::IsMine(*pwalletMain, s.destination) & ISMINE_WATCH_ONLY))
+                 entry.push_back(Pair("involvesWatchonly", true));
+             entry.push_back(Pair("account", strSentAccount));
+             MaybePushAddress(entry, s.destination);
+             entry.push_back(Pair("category", "send"));
+             entry.push_back(Pair("amount", ValueFromAmount(-s.amount)));
+             entry.push_back(Pair("vout", s.vout));
+             entry.push_back(Pair("fee", ValueFromAmount(-nFee)));
+             if (fLong)
+                 WalletTxToJSON(wtx, entry);
+             ret.push_back(entry);
+         }
+     }
+     // Received
+     if (listReceived.size() > 0 && wtx.GetDepthInMainChain() >= nMinDepth)
+     {
+         BOOST_FOREACH(const COutputEntry& r, listReceived)
+         {
+             string account;
+             if (pwalletMain->mapAddressBook.count(r.destination))
+                 account = pwalletMain->mapAddressBook[r.destination].name;
+             if (fAllAccounts || (account == strAccount))
+             {
+                 Object entry;
+                 if(involvesWatchonly || (::IsMine(*pwalletMain, r.destination) & ISMINE_WATCH_ONLY))
+                     entry.push_back(Pair("involvesWatchonly", true));
+                 entry.push_back(Pair("account", account));
+                 MaybePushAddress(entry, r.destination);
+                 if (wtx.IsCoinBase())
+                 {
+                     if (wtx.GetDepthInMainChain() < 1)
+                         entry.push_back(Pair("category", "orphan"));
+                     else if (wtx.GetBlocksToMaturity() > 0)
+                         entry.push_back(Pair("category", "immature"));
+                     else
+                         entry.push_back(Pair("category", "generate"));
+                 }
+                 else
+                 {
+                     entry.push_back(Pair("category", "receive"));
+                 }
+                 entry.push_back(Pair("amount", ValueFromAmount(r.amount)));
+                 entry.push_back(Pair("vout", r.vout));
+                 if (fLong)
+                     WalletTxToJSON(wtx, entry);
+                 ret.push_back(entry);
+             }
+         }
+     }
+ }
+ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret)
+ {
+     bool fAllAccounts = (strAccount == string("*"));
+     if (fAllAccounts || acentry.strAccount == strAccount)
+     {
+         Object entry;
+         entry.push_back(Pair("account", acentry.strAccount));
+         entry.push_back(Pair("category", "move"));
+         entry.push_back(Pair("time", acentry.nTime));
+         entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit)));
+         entry.push_back(Pair("otheraccount", acentry.strOtherAccount));
+         entry.push_back(Pair("comment", acentry.strComment));
+         ret.push_back(entry);
+     }
+ }
+ Value listtransactions(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 4)
+         throw runtime_error(
+             "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) DEPRECATED. The account name. Should be \"*\".\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"
+             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. \n"
+             "                                                It will be \"\" for the default account.\n"
+             "    \"address\":\"bitcoinaddress\",    (string) The bitcoin address of the transaction. Not present for \n"
+             "                                                move transactions (category = move).\n"
+             "    \"category\":\"send|receive|move\", (string) The transaction category. 'move' is a local (off blockchain)\n"
+             "                                                transaction between accounts, and not associated with an address,\n"
+             "                                                transaction id or block. 'send' and 'receive' transactions are \n"
+             "                                                associated with an address, transaction id and block details\n"
+             "    \"amount\": x.xxx,          (numeric) The amount in btc. This is negative for the 'send' category, and for the\n"
+             "                                         'move' category for moves outbound. It is positive for the 'receive' category,\n"
+             "                                         and for the 'move' category for inbound funds.\n"
+             "    \"vout\" : n,               (numeric) the vout value\n"
+             "    \"fee\": x.xxx,             (numeric) The amount of the fee in btc. This is negative and only available for the \n"
+             "                                         'send' category of transactions.\n"
+             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and \n"
+             "                                         'receive' category of transactions.\n"
+             "    \"blockhash\": \"hashvalue\", (string) The block hash containing the transaction. Available for 'send' and 'receive'\n"
+             "                                          category of transactions.\n"
+             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive'\n"
+             "                                          category of transactions.\n"
+             "    \"txid\": \"transactionid\", (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
+             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (midnight Jan 1 1970 GMT).\n"
+             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (midnight Jan 1 1970 GMT). Available \n"
+             "                                          for 'send' and 'receive' category of transactions.\n"
+             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
+             "    \"otheraccount\": \"accountname\",  (string) For the 'move' category of transactions, the account the funds came \n"
+             "                                          from (for receiving funds, positive amounts), or went to (for sending funds,\n"
+             "                                          negative amounts).\n"
+             "  }\n"
+             "]\n"
+             "\nExamples:\n"
+             "\nList the most recent 10 transactions in the systems\n"
+             + HelpExampleCli("listtransactions", "") +
+             "\nList transactions 100 to 120\n"
+             + HelpExampleCli("listtransactions", "\"*\" 20 100") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("listtransactions", "\"*\", 20, 100")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     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 = ISMINE_SPENDABLE;
+     if(params.size() > 3)
+         if(params[3].get_bool())
+             filter = filter | ISMINE_WATCH_ONLY;
+     if (nCount < 0)
+         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
+     if (nFrom < 0)
+         throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative from");
+     Array ret;
+     std::list<CAccountingEntry> acentries;
+     CWallet::TxItems txOrdered = pwalletMain->OrderedTxItems(acentries, strAccount);
+     // iterate backwards until we have nCount items to return:
+     for (CWallet::TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
+     {
+         CWalletTx *const pwtx = (*it).second.first;
+         if (pwtx != 0)
+             ListTransactions(*pwtx, strAccount, 0, true, ret, filter);
+         CAccountingEntry *const pacentry = (*it).second.second;
+         if (pacentry != 0)
+             AcentryToJSON(*pacentry, strAccount, ret);
+         if ((int)ret.size() >= (nCount+nFrom)) break;
+     }
+     // ret is newest to oldest
+     if (nFrom > (int)ret.size())
+         nFrom = ret.size();
+     if ((nFrom + nCount) > (int)ret.size())
+         nCount = ret.size() - nFrom;
+     Array::iterator first = ret.begin();
+     std::advance(first, nFrom);
+     Array::iterator last = ret.begin();
+     std::advance(last, nFrom+nCount);
+     if (last != ret.end()) ret.erase(last, ret.end());
+     if (first != ret.begin()) ret.erase(ret.begin(), first);
+     std::reverse(ret.begin(), ret.end()); // Return oldest to newest
+     return ret;
+ }
+ Value listaccounts(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 2)
+         throw runtime_error(
+             "listaccounts ( minconf includeWatchonly)\n"
+             "\nDEPRECATED. Returns Object that has account names as keys, account balances as values.\n"
+             "\nArguments:\n"
+             "1. minconf          (numeric, optional, default=1) Only include 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"
+             "  ...\n"
+             "}\n"
+             "\nExamples:\n"
+             "\nList account balances where there at least 1 confirmation\n"
+             + HelpExampleCli("listaccounts", "") +
+             "\nList account balances including zero confirmation transactions\n"
+             + HelpExampleCli("listaccounts", "0") +
+             "\nList account balances for 6 or more confirmations\n"
+             + HelpExampleCli("listaccounts", "6") +
+             "\nAs json rpc call\n"
+             + HelpExampleRpc("listaccounts", "6")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     int nMinDepth = 1;
+     if (params.size() > 0)
+         nMinDepth = params[0].get_int();
+     isminefilter includeWatchonly = ISMINE_SPENDABLE;
+     if(params.size() > 1)
+         if(params[1].get_bool())
+             includeWatchonly = includeWatchonly | ISMINE_WATCH_ONLY;
+     map<string, CAmount> mapAccountBalances;
+     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& entry, pwalletMain->mapAddressBook) {
+         if (IsMine(*pwalletMain, entry.first) & includeWatchonly) // This address belongs to me
+             mapAccountBalances[entry.second.name] = 0;
+     }
+     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
+     {
+         const CWalletTx& wtx = (*it).second;
+         CAmount nFee;
+         string strSentAccount;
+         list<COutputEntry> listReceived;
+         list<COutputEntry> listSent;
+         int nDepth = wtx.GetDepthInMainChain();
+         if (wtx.GetBlocksToMaturity() > 0 || nDepth < 0)
+             continue;
+         wtx.GetAmounts(listReceived, listSent, nFee, strSentAccount, includeWatchonly);
+         mapAccountBalances[strSentAccount] -= nFee;
+         BOOST_FOREACH(const COutputEntry& s, listSent)
+             mapAccountBalances[strSentAccount] -= s.amount;
+         if (nDepth >= nMinDepth)
+         {
+             BOOST_FOREACH(const COutputEntry& r, listReceived)
+                 if (pwalletMain->mapAddressBook.count(r.destination))
+                     mapAccountBalances[pwalletMain->mapAddressBook[r.destination].name] += r.amount;
+                 else
+                     mapAccountBalances[""] += r.amount;
+         }
+     }
+     list<CAccountingEntry> acentries;
+     CWalletDB(pwalletMain->strWalletFile).ListAccountCreditDebit("*", acentries);
+     BOOST_FOREACH(const CAccountingEntry& entry, acentries)
+         mapAccountBalances[entry.strAccount] += entry.nCreditDebit;
+     Object ret;
+     BOOST_FOREACH(const PAIRTYPE(string, CAmount)& accountBalance, mapAccountBalances) {
+         ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second)));
+     }
+     return ret;
+ }
+ Value listsinceblock(const Array& params, bool fHelp)
+ {
+     if (fHelp)
+         throw runtime_error(
+             "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"
+             "    \"account\":\"accountname\",       (string) DEPRECATED. The account name associated with the transaction. Will be \"\" for the default account.\n"
+             "    \"address\":\"bitcoinaddress\",    (string) The bitcoin address of the transaction. Not present for move transactions (category = move).\n"
+             "    \"category\":\"send|receive\",     (string) The transaction category. 'send' has negative amounts, 'receive' has positive amounts.\n"
+             "    \"amount\": x.xxx,          (numeric) The amount in btc. This is negative for the 'send' category, and for the 'move' category for moves \n"
+             "                                          outbound. It is positive for the 'receive' category, and for the 'move' category for inbound funds.\n"
+             "    \"vout\" : n,               (numeric) the vout value\n"
+             "    \"fee\": x.xxx,             (numeric) The amount of the fee in btc. This is negative and only available for the 'send' category of transactions.\n"
+             "    \"confirmations\": n,       (numeric) The number of confirmations for the transaction. Available for 'send' and 'receive' category of transactions.\n"
+             "    \"blockhash\": \"hashvalue\",     (string) The block hash containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
+             "    \"blockindex\": n,          (numeric) The block index containing the transaction. Available for 'send' and 'receive' category of transactions.\n"
+             "    \"blocktime\": xxx,         (numeric) The block time in seconds since epoch (1 Jan 1970 GMT).\n"
+             "    \"txid\": \"transactionid\",  (string) The transaction id. Available for 'send' and 'receive' category of transactions.\n"
+             "    \"time\": xxx,              (numeric) The transaction time in seconds since epoch (Jan 1 1970 GMT).\n"
+             "    \"timereceived\": xxx,      (numeric) The time received in seconds since epoch (Jan 1 1970 GMT). Available for 'send' and 'receive' category of transactions.\n"
+             "    \"comment\": \"...\",       (string) If a comment is associated with the transaction.\n"
+             "    \"to\": \"...\",            (string) If a comment to is associated with the transaction.\n"
+              "  ],\n"
+             "  \"lastblock\": \"lastblockhash\"     (string) The hash of the last block\n"
+             "}\n"
+             "\nExamples:\n"
+             + HelpExampleCli("listsinceblock", "")
+             + HelpExampleCli("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\" 6")
+             + HelpExampleRpc("listsinceblock", "\"000000000000000bacf66f7497b7dc45ef753ee9a7d38571037cdb1a57f663ad\", 6")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     CBlockIndex *pindex = NULL;
+     int target_confirms = 1;
+     isminefilter filter = ISMINE_SPENDABLE;
+     if (params.size() > 0)
+     {
+         uint256 blockId;
+         blockId.SetHex(params[0].get_str());
+         BlockMap::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() > 2)
+         if(params[2].get_bool())
+             filter = filter | ISMINE_WATCH_ONLY;
+     int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
+     Array transactions;
+     for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); it++)
+     {
+         CWalletTx tx = (*it).second;
+         if (depth == -1 || tx.GetDepthInMainChain() < depth)
+             ListTransactions(tx, "*", 0, true, transactions, filter);
+     }
+     CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
+     uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : uint256();
+     Object ret;
+     ret.push_back(Pair("transactions", transactions));
+     ret.push_back(Pair("lastblock", lastblock.GetHex()));
+     return ret;
+ }
+ Value gettransaction(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 1 || params.size() > 2)
+         throw runtime_error(
+             "gettransaction \"txid\" ( includeWatchonly )\n"
+             "\nGet detailed information about in-wallet transaction <txid>\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"
+             "  \"confirmations\" : n,     (numeric) The number of confirmations\n"
+             "  \"blockhash\" : \"hash\",  (string) The block hash\n"
+             "  \"blockindex\" : xx,       (numeric) The block index\n"
+             "  \"blocktime\" : ttt,       (numeric) The time in seconds since epoch (1 Jan 1970 GMT)\n"
+             "  \"txid\" : \"transactionid\",   (string) The transaction id.\n"
+             "  \"time\" : ttt,            (numeric) The transaction time in seconds since epoch (1 Jan 1970 GMT)\n"
+             "  \"timereceived\" : ttt,    (numeric) The time received in seconds since epoch (1 Jan 1970 GMT)\n"
+             "  \"details\" : [\n"
+             "    {\n"
+             "      \"account\" : \"accountname\",  (string) DEPRECATED. The account name involved in the transaction, can be \"\" for the default account.\n"
+             "      \"address\" : \"bitcoinaddress\",   (string) The bitcoin address involved in the transaction\n"
+             "      \"category\" : \"send|receive\",    (string) The category, either 'send' or 'receive'\n"
+             "      \"amount\" : x.xxx                  (numeric) The amount in btc\n"
+             "      \"vout\" : n,                       (numeric) the vout value\n"
+             "    }\n"
+             "    ,...\n"
+             "  ],\n"
+             "  \"hex\" : \"data\"         (string) Raw data for transaction\n"
+             "}\n"
+             "\nExamples:\n"
+             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+             + HelpExampleCli("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\" true")
+             + HelpExampleRpc("gettransaction", "\"1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     uint256 hash;
+     hash.SetHex(params[0].get_str());
+     isminefilter filter = ISMINE_SPENDABLE;
+     if(params.size() > 1)
+         if(params[1].get_bool())
+             filter = filter | ISMINE_WATCH_ONLY;
+     Object entry;
+     if (!pwalletMain->mapWallet.count(hash))
+         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid or non-wallet transaction id");
+     const CWalletTx& wtx = pwalletMain->mapWallet[hash];
+     CAmount nCredit = wtx.GetCredit(filter);
+     CAmount nDebit = wtx.GetDebit(filter);
+     CAmount nNet = nCredit - nDebit;
+     CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
+     entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
+     if (wtx.IsFromMe(filter))
+         entry.push_back(Pair("fee", ValueFromAmount(nFee)));
+     WalletTxToJSON(wtx, entry);
+     Array details;
+     ListTransactions(wtx, "*", 0, false, details, filter);
+     entry.push_back(Pair("details", details));
+     string strHex = EncodeHexTx(static_cast<CTransaction>(wtx));
+     entry.push_back(Pair("hex", strHex));
+     return entry;
+ }
+ Value backupwallet(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() != 1)
+         throw runtime_error(
+             "backupwallet \"destination\"\n"
+             "\nSafely copies wallet.dat to destination, which can be a directory or a path with filename.\n"
+             "\nArguments:\n"
+             "1. \"destination\"   (string) The destination directory or file\n"
+             "\nExamples:\n"
+             + HelpExampleCli("backupwallet", "\"backup.dat\"")
+             + HelpExampleRpc("backupwallet", "\"backup.dat\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     string strDest = params[0].get_str();
+     if (!BackupWallet(*pwalletMain, strDest))
+         throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!");
+     return Value::null;
+ }
+ Value keypoolrefill(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 1)
+         throw runtime_error(
+             "keypoolrefill ( newsize )\n"
+             "\nFills the keypool."
+             + HelpRequiringPassphrase() + "\n"
+             "\nArguments\n"
+             "1. newsize     (numeric, optional, default=100) The new keypool size\n"
+             "\nExamples:\n"
+             + HelpExampleCli("keypoolrefill", "")
+             + HelpExampleRpc("keypoolrefill", "")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     // 0 is interpreted by TopUpKeyPool() as the default keypool size given by -keypool
+     unsigned int kpSize = 0;
+     if (params.size() > 0) {
+         if (params[0].get_int() < 0)
+             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size.");
+         kpSize = (unsigned int)params[0].get_int();
+     }
+     EnsureWalletIsUnlocked();
+     pwalletMain->TopUpKeyPool(kpSize);
+     if (pwalletMain->GetKeyPoolSize() < kpSize)
+         throw JSONRPCError(RPC_WALLET_ERROR, "Error refreshing keypool.");
+     return Value::null;
+ }
+ static void LockWallet(CWallet* pWallet)
+ {
+     LOCK(cs_nWalletUnlockTime);
+     nWalletUnlockTime = 0;
+     pWallet->Lock();
+ }
+ Value walletpassphrase(const Array& params, bool fHelp)
+ {
+     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
+         throw runtime_error(
+             "walletpassphrase \"passphrase\" timeout\n"
+             "\nStores the wallet decryption key in memory for 'timeout' seconds.\n"
+             "This is needed prior to performing transactions related to private keys such as sending bitcoins\n"
+             "\nArguments:\n"
+             "1. \"passphrase\"     (string, required) The wallet passphrase\n"
+             "2. timeout            (numeric, required) The time to keep the decryption key in seconds.\n"
+             "\nNote:\n"
+             "Issuing the walletpassphrase command while the wallet is already unlocked will set a new unlock\n"
+             "time that overrides the old one.\n"
+             "\nExamples:\n"
+             "\nunlock the wallet for 60 seconds\n"
+             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 60") +
+             "\nLock the wallet again (before 60 seconds)\n"
+             + HelpExampleCli("walletlock", "") +
+             "\nAs json rpc call\n"
+             + HelpExampleRpc("walletpassphrase", "\"my pass phrase\", 60")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     if (fHelp)
+         return true;
+     if (!pwalletMain->IsCrypted())
+         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrase was called.");
+     // Note that the walletpassphrase is stored in params[0] which is not mlock()ed
+     SecureString strWalletPass;
+     strWalletPass.reserve(100);
+     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
+     // Alternately, find a way to make params[0] mlock()'d to begin with.
+     strWalletPass = params[0].get_str().c_str();
+     if (strWalletPass.length() > 0)
+     {
+         if (!pwalletMain->Unlock(strWalletPass))
+             throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
+     }
+     else
+         throw runtime_error(
+             "walletpassphrase <passphrase> <timeout>\n"
+             "Stores the wallet decryption key in memory for <timeout> seconds.");
+     pwalletMain->TopUpKeyPool();
+     int64_t nSleepTime = params[1].get_int64();
+     LOCK(cs_nWalletUnlockTime);
+     nWalletUnlockTime = GetTime() + nSleepTime;
+     RPCRunLater("lockwallet", boost::bind(LockWallet, pwalletMain), nSleepTime);
+     return Value::null;
+ }
+ Value walletpassphrasechange(const Array& params, bool fHelp)
+ {
+     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 2))
+         throw runtime_error(
+             "walletpassphrasechange \"oldpassphrase\" \"newpassphrase\"\n"
+             "\nChanges the wallet passphrase from 'oldpassphrase' to 'newpassphrase'.\n"
+             "\nArguments:\n"
+             "1. \"oldpassphrase\"      (string) The current passphrase\n"
+             "2. \"newpassphrase\"      (string) The new passphrase\n"
+             "\nExamples:\n"
+             + HelpExampleCli("walletpassphrasechange", "\"old one\" \"new one\"")
+             + HelpExampleRpc("walletpassphrasechange", "\"old one\", \"new one\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     if (fHelp)
+         return true;
+     if (!pwalletMain->IsCrypted())
+         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletpassphrasechange was called.");
+     // TODO: get rid of these .c_str() calls by implementing SecureString::operator=(std::string)
+     // Alternately, find a way to make params[0] mlock()'d to begin with.
+     SecureString strOldWalletPass;
+     strOldWalletPass.reserve(100);
+     strOldWalletPass = params[0].get_str().c_str();
+     SecureString strNewWalletPass;
+     strNewWalletPass.reserve(100);
+     strNewWalletPass = params[1].get_str().c_str();
+     if (strOldWalletPass.length() < 1 || strNewWalletPass.length() < 1)
+         throw runtime_error(
+             "walletpassphrasechange <oldpassphrase> <newpassphrase>\n"
+             "Changes the wallet passphrase from <oldpassphrase> to <newpassphrase>.");
+     if (!pwalletMain->ChangeWalletPassphrase(strOldWalletPass, strNewWalletPass))
+         throw JSONRPCError(RPC_WALLET_PASSPHRASE_INCORRECT, "Error: The wallet passphrase entered was incorrect.");
+     return Value::null;
+ }
+ Value walletlock(const Array& params, bool fHelp)
+ {
+     if (pwalletMain->IsCrypted() && (fHelp || params.size() != 0))
+         throw runtime_error(
+             "walletlock\n"
+             "\nRemoves the wallet encryption key from memory, locking the wallet.\n"
+             "After calling this method, you will need to call walletpassphrase again\n"
+             "before being able to call any methods which require the wallet to be unlocked.\n"
+             "\nExamples:\n"
+             "\nSet the passphrase for 2 minutes to perform a transaction\n"
+             + HelpExampleCli("walletpassphrase", "\"my pass phrase\" 120") +
+             "\nPerform a send (requires passphrase set)\n"
+             + HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 1.0") +
+             "\nClear the passphrase since we are done before 2 minutes is up\n"
+             + HelpExampleCli("walletlock", "") +
+             "\nAs json rpc call\n"
+             + HelpExampleRpc("walletlock", "")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     if (fHelp)
+         return true;
+     if (!pwalletMain->IsCrypted())
+         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an unencrypted wallet, but walletlock was called.");
+     {
+         LOCK(cs_nWalletUnlockTime);
+         pwalletMain->Lock();
+         nWalletUnlockTime = 0;
+     }
+     return Value::null;
+ }
+ Value encryptwallet(const Array& params, bool fHelp)
+ {
+     if (!pwalletMain->IsCrypted() && (fHelp || params.size() != 1))
+         throw runtime_error(
+             "encryptwallet \"passphrase\"\n"
+             "\nEncrypts the wallet with 'passphrase'. This is for first time encryption.\n"
+             "After this, any calls that interact with private keys such as sending or signing \n"
+             "will require the passphrase to be set prior the making these calls.\n"
+             "Use the walletpassphrase call for this, and then walletlock call.\n"
+             "If the wallet is already encrypted, use the walletpassphrasechange call.\n"
+             "Note that this will shutdown the server.\n"
+             "\nArguments:\n"
+             "1. \"passphrase\"    (string) The pass phrase to encrypt the wallet with. It must be at least 1 character, but should be long.\n"
+             "\nExamples:\n"
+             "\nEncrypt you wallet\n"
+             + HelpExampleCli("encryptwallet", "\"my pass phrase\"") +
+             "\nNow set the passphrase to use the wallet, such as for signing or sending bitcoin\n"
+             + HelpExampleCli("walletpassphrase", "\"my pass phrase\"") +
+             "\nNow we can so something like sign\n"
+             + HelpExampleCli("signmessage", "\"bitcoinaddress\" \"test message\"") +
+             "\nNow lock the wallet again by removing the passphrase\n"
+             + HelpExampleCli("walletlock", "") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("encryptwallet", "\"my pass phrase\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     if (fHelp)
+         return true;
+     if (pwalletMain->IsCrypted())
+         throw JSONRPCError(RPC_WALLET_WRONG_ENC_STATE, "Error: running with an encrypted wallet, but encryptwallet was called.");
+     // TODO: get rid of this .c_str() by implementing SecureString::operator=(std::string)
+     // Alternately, find a way to make params[0] mlock()'d to begin with.
+     SecureString strWalletPass;
+     strWalletPass.reserve(100);
+     strWalletPass = params[0].get_str().c_str();
+     if (strWalletPass.length() < 1)
+         throw runtime_error(
+             "encryptwallet <passphrase>\n"
+             "Encrypts the wallet with <passphrase>.");
+     if (!pwalletMain->EncryptWallet(strWalletPass))
+         throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Failed to encrypt the wallet.");
+     // BDB seems to have a bad habit of writing old data into
+     // slack space in .dat files; that is bad if the old data is
+     // unencrypted private keys. So:
+     StartShutdown();
+     return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
+ }
+ Value lockunspent(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 1 || params.size() > 2)
+         throw runtime_error(
+             "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n"
+             "\nUpdates list of temporarily unspendable outputs.\n"
+             "Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
+             "A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
+             "Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
+             "is always cleared (by virtue of process exit) when a node stops or fails.\n"
+             "Also see the listunspent call\n"
+             "\nArguments:\n"
+             "1. unlock            (boolean, required) Whether to unlock (true) or lock (false) the specified transactions\n"
+             "2. \"transactions\"  (string, required) A json array of objects. Each object the txid (string) vout (numeric)\n"
+             "     [           (json array of json objects)\n"
+             "       {\n"
+             "         \"txid\":\"id\",    (string) The transaction id\n"
+             "         \"vout\": n         (numeric) The output number\n"
+             "       }\n"
+             "       ,...\n"
+             "     ]\n"
+             "\nResult:\n"
+             "true|false    (boolean) Whether the command was successful or not\n"
+             "\nExamples:\n"
+             "\nList the unspent transactions\n"
+             + HelpExampleCli("listunspent", "") +
+             "\nLock an unspent transaction\n"
+             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
+             "\nList the locked transactions\n"
+             + HelpExampleCli("listlockunspent", "") +
+             "\nUnlock the transaction again\n"
+             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("lockunspent", "false, \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     if (params.size() == 1)
+         RPCTypeCheck(params, boost::assign::list_of(bool_type));
+     else
+         RPCTypeCheck(params, boost::assign::list_of(bool_type)(array_type));
+     bool fUnlock = params[0].get_bool();
+     if (params.size() == 1) {
+         if (fUnlock)
+             pwalletMain->UnlockAllCoins();
+         return true;
+     }
+     Array outputs = params[1].get_array();
+     BOOST_FOREACH(Value& output, outputs)
+     {
+         if (output.type() != obj_type)
+             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected object");
+         const Object& o = output.get_obj();
+         RPCTypeCheck(o, boost::assign::map_list_of("txid", str_type)("vout", int_type));
+         string txid = find_value(o, "txid").get_str();
+         if (!IsHex(txid))
+             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid");
+         int nOutput = find_value(o, "vout").get_int();
+         if (nOutput < 0)
+             throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive");
+         COutPoint outpt(uint256S(txid), nOutput);
+         if (fUnlock)
+             pwalletMain->UnlockCoin(outpt);
+         else
+             pwalletMain->LockCoin(outpt);
+     }
+     return true;
+ }
+ Value listlockunspent(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() > 0)
+         throw runtime_error(
+             "listlockunspent\n"
+             "\nReturns list of temporarily unspendable outputs.\n"
+             "See the lockunspent call to lock and unlock transactions for spending.\n"
+             "\nResult:\n"
+             "[\n"
+             "  {\n"
+             "    \"txid\" : \"transactionid\",     (string) The transaction id locked\n"
+             "    \"vout\" : n                      (numeric) The vout value\n"
+             "  }\n"
+             "  ,...\n"
+             "]\n"
+             "\nExamples:\n"
+             "\nList the unspent transactions\n"
+             + HelpExampleCli("listunspent", "") +
+             "\nLock an unspent transaction\n"
+             + HelpExampleCli("lockunspent", "false \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
+             "\nList the locked transactions\n"
+             + HelpExampleCli("listlockunspent", "") +
+             "\nUnlock the transaction again\n"
+             + HelpExampleCli("lockunspent", "true \"[{\\\"txid\\\":\\\"a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\",\\\"vout\\\":1}]\"") +
+             "\nAs a json rpc call\n"
+             + HelpExampleRpc("listlockunspent", "")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     vector<COutPoint> vOutpts;
+     pwalletMain->ListLockedCoins(vOutpts);
+     Array ret;
+     BOOST_FOREACH(COutPoint &outpt, vOutpts) {
+         Object o;
+         o.push_back(Pair("txid", outpt.hash.GetHex()));
+         o.push_back(Pair("vout", (int)outpt.n));
+         ret.push_back(o);
+     }
+     return ret;
+ }
+ Value settxfee(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() < 1 || params.size() > 1)
+         throw runtime_error(
+             "settxfee amount\n"
+             "\nSet the transaction fee per kB.\n"
+             "\nArguments:\n"
+             "1. amount         (numeric, required) The transaction fee in BTC/kB rounded to the nearest 0.00000001\n"
+             "\nResult\n"
+             "true|false        (boolean) Returns true if successful\n"
+             "\nExamples:\n"
+             + HelpExampleCli("settxfee", "0.00001")
+             + HelpExampleRpc("settxfee", "0.00001")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     // Amount
+     CAmount nAmount = 0;
+     if (params[0].get_real() != 0.0)
+         nAmount = AmountFromValue(params[0]);        // rejects 0.0 amounts
+     payTxFee = CFeeRate(nAmount, 1000);
+     return true;
+ }
+ Value getwalletinfo(const Array& params, bool fHelp)
+ {
+     if (fHelp || params.size() != 0)
+         throw runtime_error(
+             "getwalletinfo\n"
+             "Returns an object containing various wallet state info.\n"
+             "\nResult:\n"
+             "{\n"
+             "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
+             "  \"balance\": xxxxxxx,         (numeric) the total confirmed bitcoin balance of the wallet\n"
+             "  \"unconfirmed_balance\": xxx, (numeric) the total unconfirmed bitcoin balance of the wallet\n"
+             "  \"immature_balance\": xxxxxx, (numeric) the total immature balance of the wallet\n"
+             "  \"txcount\": xxxxxxx,         (numeric) the total number of transactions in the wallet\n"
+             "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
+             "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
+             "  \"unlocked_until\": ttt,      (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
+             "}\n"
+             "\nExamples:\n"
+             + HelpExampleCli("getwalletinfo", "")
+             + HelpExampleRpc("getwalletinfo", "")
+         );
+     LOCK2(cs_main, pwalletMain->cs_wallet);
+     Object obj;
+     obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
+     obj.push_back(Pair("balance",       ValueFromAmount(pwalletMain->GetBalance())));
+     obj.push_back(Pair("unconfirmed_balance", ValueFromAmount(pwalletMain->GetUnconfirmedBalance())));
+     obj.push_back(Pair("immature_balance",    ValueFromAmount(pwalletMain->GetImmatureBalance())));
+     obj.push_back(Pair("txcount",       (int)pwalletMain->mapWallet.size()));
+     obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
+     obj.push_back(Pair("keypoolsize",   (int)pwalletMain->GetKeyPoolSize()));
+     if (pwalletMain->IsCrypted())
+         obj.push_back(Pair("unlocked_until", nWalletUnlockTime));
+     return obj;
+ }
index 0000000000000000000000000000000000000000,5b4add8431844c1bd2763159ea83a5a354d23356..dd3310926704cfb3be97fdea3740a8670448da2a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,2564 +1,2607 @@@
 -
 -
 -
 -bool CWallet::CreateTransaction(const vector<pair<CScript, CAmount> >& vecSend,
 -                                CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
+ // Copyright (c) 2009-2010 Satoshi Nakamoto
+ // Copyright (c) 2009-2014 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 "base58.h"
+ #include "checkpoints.h"
+ #include "coincontrol.h"
+ #include "net.h"
+ #include "script/script.h"
+ #include "script/sign.h"
+ #include "timedata.h"
+ #include "util.h"
+ #include "utilmoneystr.h"
+ #include <assert.h>
+ #include <boost/algorithm/string/replace.hpp>
+ #include <boost/thread.hpp>
+ using namespace std;
+ /**
+  * Settings
+  */
+ CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
+ CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
+ unsigned int nTxConfirmTarget = 1;
+ bool bSpendZeroConfChange = true;
+ bool fSendFreeTransactions = false;
+ bool fPayAtLeastCustomFee = true;
+ /** 
+  * Fees smaller than this (in satoshi) are considered zero fee (for transaction creation) 
+  * Override with -mintxfee
+  */
+ CFeeRate CWallet::minTxFee = CFeeRate(1000);
+ /** @defgroup mapWallet
+  *
+  * @{
+  */
+ struct CompareValueOnly
+ {
+     bool operator()(const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t1,
+                     const pair<CAmount, pair<const CWalletTx*, unsigned int> >& t2) const
+     {
+         return t1.first < t2.first;
+     }
+ };
+ std::string COutput::ToString() const
+ {
+     return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue));
+ }
+ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
+ {
+     LOCK(cs_wallet);
+     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(hash);
+     if (it == mapWallet.end())
+         return NULL;
+     return &(it->second);
+ }
+ CPubKey CWallet::GenerateNewKey()
+ {
+     AssertLockHeld(cs_wallet); // mapKeyMetadata
+     bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
+     CKey secret;
+     secret.MakeNewKey(fCompressed);
+     // Compressed public keys were introduced in version 0.6.0
+     if (fCompressed)
+         SetMinVersion(FEATURE_COMPRPUBKEY);
+     CPubKey pubkey = secret.GetPubKey();
+     assert(secret.VerifyPubKey(pubkey));
+     // Create new metadata
+     int64_t nCreationTime = GetTime();
+     mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
+     if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
+         nTimeFirstKey = nCreationTime;
+     if (!AddKeyPubKey(secret, pubkey))
+         throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed");
+     return pubkey;
+ }
+ bool CWallet::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
+ {
+     AssertLockHeld(cs_wallet); // mapKeyMetadata
+     if (!CCryptoKeyStore::AddKeyPubKey(secret, pubkey))
+         return false;
+     // check if we need to remove from watch-only
+     CScript script;
+     script = GetScriptForDestination(pubkey.GetID());
+     if (HaveWatchOnly(script))
+         RemoveWatchOnly(script);
+     if (!fFileBacked)
+         return true;
+     if (!IsCrypted()) {
+         return CWalletDB(strWalletFile).WriteKey(pubkey,
+                                                  secret.GetPrivKey(),
+                                                  mapKeyMetadata[pubkey.GetID()]);
+     }
+     return true;
+ }
+ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey,
+                             const vector<unsigned char> &vchCryptedSecret)
+ {
+     if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
+         return false;
+     if (!fFileBacked)
+         return true;
+     {
+         LOCK(cs_wallet);
+         if (pwalletdbEncryption)
+             return pwalletdbEncryption->WriteCryptedKey(vchPubKey,
+                                                         vchCryptedSecret,
+                                                         mapKeyMetadata[vchPubKey.GetID()]);
+         else
+             return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey,
+                                                             vchCryptedSecret,
+                                                             mapKeyMetadata[vchPubKey.GetID()]);
+     }
+     return false;
+ }
+ bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
+ {
+     AssertLockHeld(cs_wallet); // mapKeyMetadata
+     if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
+         nTimeFirstKey = meta.nCreateTime;
+     mapKeyMetadata[pubkey.GetID()] = meta;
+     return true;
+ }
+ bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
+ {
+     return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
+ }
+ bool CWallet::AddCScript(const CScript& redeemScript)
+ {
+     if (!CCryptoKeyStore::AddCScript(redeemScript))
+         return false;
+     if (!fFileBacked)
+         return true;
+     return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
+ }
+ bool CWallet::LoadCScript(const CScript& redeemScript)
+ {
+     /* A sanity check was added in pull #3843 to avoid adding redeemScripts
+      * that never can be redeemed. However, old wallets may still contain
+      * these. Do not add them to the wallet and warn. */
+     if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE)
+     {
+         std::string strAddr = CBitcoinAddress(CScriptID(redeemScript)).ToString();
+         LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i which exceeds maximum size %i thus can never be redeemed. Do not use address %s.\n",
+             __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, strAddr);
+         return true;
+     }
+     return CCryptoKeyStore::AddCScript(redeemScript);
+ }
+ bool CWallet::AddWatchOnly(const CScript &dest)
+ {
+     if (!CCryptoKeyStore::AddWatchOnly(dest))
+         return false;
+     nTimeFirstKey = 1; // No birthday information for watch-only keys.
+     NotifyWatchonlyChanged(true);
+     if (!fFileBacked)
+         return true;
+     return CWalletDB(strWalletFile).WriteWatchOnly(dest);
+ }
+ bool CWallet::RemoveWatchOnly(const CScript &dest)
+ {
+     AssertLockHeld(cs_wallet);
+     if (!CCryptoKeyStore::RemoveWatchOnly(dest))
+         return false;
+     if (!HaveWatchOnly())
+         NotifyWatchonlyChanged(false);
+     if (fFileBacked)
+         if (!CWalletDB(strWalletFile).EraseWatchOnly(dest))
+             return false;
+     return true;
+ }
+ bool CWallet::LoadWatchOnly(const CScript &dest)
+ {
+     return CCryptoKeyStore::AddWatchOnly(dest);
+ }
+ bool CWallet::Unlock(const SecureString& strWalletPassphrase)
+ {
+     CCrypter crypter;
+     CKeyingMaterial vMasterKey;
+     {
+         LOCK(cs_wallet);
+         BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
+         {
+             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
+                 return false;
+             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
+                 continue; // try another master key
+             if (CCryptoKeyStore::Unlock(vMasterKey))
+                 return true;
+         }
+     }
+     return false;
+ }
+ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
+ {
+     bool fWasLocked = IsLocked();
+     {
+         LOCK(cs_wallet);
+         Lock();
+         CCrypter crypter;
+         CKeyingMaterial vMasterKey;
+         BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
+         {
+             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
+                 return false;
+             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
+                 return false;
+             if (CCryptoKeyStore::Unlock(vMasterKey))
+             {
+                 int64_t nStartTime = GetTimeMillis();
+                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
+                 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
+                 nStartTime = GetTimeMillis();
+                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
+                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
+                 if (pMasterKey.second.nDeriveIterations < 25000)
+                     pMasterKey.second.nDeriveIterations = 25000;
+                 LogPrintf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
+                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
+                     return false;
+                 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
+                     return false;
+                 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
+                 if (fWasLocked)
+                     Lock();
+                 return true;
+             }
+         }
+     }
+     return false;
+ }
+ void CWallet::SetBestChain(const CBlockLocator& loc)
+ {
+     CWalletDB walletdb(strWalletFile);
+     walletdb.WriteBestBlock(loc);
+ }
+ bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
+ {
+     LOCK(cs_wallet); // nWalletVersion
+     if (nWalletVersion >= nVersion)
+         return true;
+     // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
+     if (fExplicit && nVersion > nWalletMaxVersion)
+             nVersion = FEATURE_LATEST;
+     nWalletVersion = nVersion;
+     if (nVersion > nWalletMaxVersion)
+         nWalletMaxVersion = nVersion;
+     if (fFileBacked)
+     {
+         CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
+         if (nWalletVersion > 40000)
+             pwalletdb->WriteMinVersion(nWalletVersion);
+         if (!pwalletdbIn)
+             delete pwalletdb;
+     }
+     return true;
+ }
+ bool CWallet::SetMaxVersion(int nVersion)
+ {
+     LOCK(cs_wallet); // nWalletVersion, nWalletMaxVersion
+     // cannot downgrade below current version
+     if (nWalletVersion > nVersion)
+         return false;
+     nWalletMaxVersion = nVersion;
+     return true;
+ }
+ set<uint256> CWallet::GetConflicts(const uint256& txid) const
+ {
+     set<uint256> result;
+     AssertLockHeld(cs_wallet);
+     std::map<uint256, CWalletTx>::const_iterator it = mapWallet.find(txid);
+     if (it == mapWallet.end())
+         return result;
+     const CWalletTx& wtx = it->second;
+     std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
+     BOOST_FOREACH(const CTxIn& txin, wtx.vin)
+     {
+         if (mapTxSpends.count(txin.prevout) <= 1)
+             continue;  // No conflict if zero or one spends
+         range = mapTxSpends.equal_range(txin.prevout);
+         for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
+             result.insert(it->second);
+     }
+     return result;
+ }
+ void CWallet::SyncMetaData(pair<TxSpends::iterator, TxSpends::iterator> range)
+ {
+     // We want all the wallet transactions in range to have the same metadata as
+     // the oldest (smallest nOrderPos).
+     // So: find smallest nOrderPos:
+     int nMinOrderPos = std::numeric_limits<int>::max();
+     const CWalletTx* copyFrom = NULL;
+     for (TxSpends::iterator it = range.first; it != range.second; ++it)
+     {
+         const uint256& hash = it->second;
+         int n = mapWallet[hash].nOrderPos;
+         if (n < nMinOrderPos)
+         {
+             nMinOrderPos = n;
+             copyFrom = &mapWallet[hash];
+         }
+     }
+     // Now copy data from copyFrom to rest:
+     for (TxSpends::iterator it = range.first; it != range.second; ++it)
+     {
+         const uint256& hash = it->second;
+         CWalletTx* copyTo = &mapWallet[hash];
+         if (copyFrom == copyTo) continue;
+         copyTo->mapValue = copyFrom->mapValue;
+         copyTo->vOrderForm = copyFrom->vOrderForm;
+         // fTimeReceivedIsTxTime not copied on purpose
+         // nTimeReceived not copied on purpose
+         copyTo->nTimeSmart = copyFrom->nTimeSmart;
+         copyTo->fFromMe = copyFrom->fFromMe;
+         copyTo->strFromAccount = copyFrom->strFromAccount;
+         // nOrderPos not copied on purpose
+         // cached members not copied on purpose
+     }
+ }
+ /**
+  * Outpoint is spent if any non-conflicted transaction
+  * spends it:
+  */
+ bool CWallet::IsSpent(const uint256& hash, unsigned int n) const
+ {
+     const COutPoint outpoint(hash, n);
+     pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
+     range = mapTxSpends.equal_range(outpoint);
+     for (TxSpends::const_iterator it = range.first; it != range.second; ++it)
+     {
+         const uint256& wtxid = it->second;
+         std::map<uint256, CWalletTx>::const_iterator mit = mapWallet.find(wtxid);
+         if (mit != mapWallet.end() && mit->second.GetDepthInMainChain() >= 0)
+             return true; // Spent
+     }
+     return false;
+ }
+ void CWallet::AddToSpends(const COutPoint& outpoint, const uint256& wtxid)
+ {
+     mapTxSpends.insert(make_pair(outpoint, wtxid));
+     pair<TxSpends::iterator, TxSpends::iterator> range;
+     range = mapTxSpends.equal_range(outpoint);
+     SyncMetaData(range);
+ }
+ void CWallet::AddToSpends(const uint256& wtxid)
+ {
+     assert(mapWallet.count(wtxid));
+     CWalletTx& thisTx = mapWallet[wtxid];
+     if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
+         return;
+     BOOST_FOREACH(const CTxIn& txin, thisTx.vin)
+         AddToSpends(txin.prevout, wtxid);
+ }
+ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
+ {
+     if (IsCrypted())
+         return false;
+     CKeyingMaterial vMasterKey;
+     RandAddSeedPerfmon();
+     vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
+     GetRandBytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
+     CMasterKey kMasterKey;
+     RandAddSeedPerfmon();
+     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
+     GetRandBytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
+     CCrypter crypter;
+     int64_t nStartTime = GetTimeMillis();
+     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
+     kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
+     nStartTime = GetTimeMillis();
+     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
+     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
+     if (kMasterKey.nDeriveIterations < 25000)
+         kMasterKey.nDeriveIterations = 25000;
+     LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
+     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
+         return false;
+     if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
+         return false;
+     {
+         LOCK(cs_wallet);
+         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
+         if (fFileBacked)
+         {
+             assert(!pwalletdbEncryption);
+             pwalletdbEncryption = new CWalletDB(strWalletFile);
+             if (!pwalletdbEncryption->TxnBegin()) {
+                 delete pwalletdbEncryption;
+                 pwalletdbEncryption = NULL;
+                 return false;
+             }
+             pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
+         }
+         if (!EncryptKeys(vMasterKey))
+         {
+             if (fFileBacked) {
+                 pwalletdbEncryption->TxnAbort();
+                 delete pwalletdbEncryption;
+             }
+             // We now probably have half of our keys encrypted in memory, and half not...
+             // die and let the user reload their unencrypted wallet.
+             assert(false);
+         }
+         // Encryption was introduced in version 0.4.0
+         SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
+         if (fFileBacked)
+         {
+             if (!pwalletdbEncryption->TxnCommit()) {
+                 delete pwalletdbEncryption;
+                 // We now have keys encrypted in memory, but not on disk...
+                 // die to avoid confusion and let the user reload their unencrypted wallet.
+                 assert(false);
+             }
+             delete pwalletdbEncryption;
+             pwalletdbEncryption = NULL;
+         }
+         Lock();
+         Unlock(strWalletPassphrase);
+         NewKeyPool();
+         Lock();
+         // Need to completely rewrite the wallet file; if we don't, bdb might keep
+         // bits of the unencrypted private key in slack space in the database file.
+         CDB::Rewrite(strWalletFile);
+     }
+     NotifyStatusChanged(this);
+     return true;
+ }
+ int64_t CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
+ {
+     AssertLockHeld(cs_wallet); // nOrderPosNext
+     int64_t nRet = nOrderPosNext++;
+     if (pwalletdb) {
+         pwalletdb->WriteOrderPosNext(nOrderPosNext);
+     } else {
+         CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
+     }
+     return nRet;
+ }
+ CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
+ {
+     AssertLockHeld(cs_wallet); // mapWallet
+     CWalletDB walletdb(strWalletFile);
+     // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
+     TxItems txOrdered;
+     // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
+     // would make this much faster for applications that do this a lot.
+     for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+     {
+         CWalletTx* wtx = &((*it).second);
+         txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
+     }
+     acentries.clear();
+     walletdb.ListAccountCreditDebit(strAccount, acentries);
+     BOOST_FOREACH(CAccountingEntry& entry, acentries)
+     {
+         txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
+     }
+     return txOrdered;
+ }
+ void CWallet::MarkDirty()
+ {
+     {
+         LOCK(cs_wallet);
+         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+             item.second.MarkDirty();
+     }
+ }
+ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb)
+ {
+     uint256 hash = wtxIn.GetHash();
+     if (fFromLoadWallet)
+     {
+         mapWallet[hash] = wtxIn;
+         mapWallet[hash].BindWallet(this);
+         AddToSpends(hash);
+     }
+     else
+     {
+         LOCK(cs_wallet);
+         // Inserts only if not already there, returns tx inserted or tx found
+         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
+         CWalletTx& wtx = (*ret.first).second;
+         wtx.BindWallet(this);
+         bool fInsertedNew = ret.second;
+         if (fInsertedNew)
+         {
+             wtx.nTimeReceived = GetAdjustedTime();
+             wtx.nOrderPos = IncOrderPosNext(pwalletdb);
+             wtx.nTimeSmart = wtx.nTimeReceived;
+             if (!wtxIn.hashBlock.IsNull())
+             {
+                 if (mapBlockIndex.count(wtxIn.hashBlock))
+                 {
+                     int64_t latestNow = wtx.nTimeReceived;
+                     int64_t latestEntry = 0;
+                     {
+                         // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
+                         int64_t latestTolerated = latestNow + 300;
+                         std::list<CAccountingEntry> acentries;
+                         TxItems txOrdered = OrderedTxItems(acentries);
+                         for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
+                         {
+                             CWalletTx *const pwtx = (*it).second.first;
+                             if (pwtx == &wtx)
+                                 continue;
+                             CAccountingEntry *const pacentry = (*it).second.second;
+                             int64_t nSmartTime;
+                             if (pwtx)
+                             {
+                                 nSmartTime = pwtx->nTimeSmart;
+                                 if (!nSmartTime)
+                                     nSmartTime = pwtx->nTimeReceived;
+                             }
+                             else
+                                 nSmartTime = pacentry->nTime;
+                             if (nSmartTime <= latestTolerated)
+                             {
+                                 latestEntry = nSmartTime;
+                                 if (nSmartTime > latestNow)
+                                     latestNow = nSmartTime;
+                                 break;
+                             }
+                         }
+                     }
+                     int64_t blocktime = mapBlockIndex[wtxIn.hashBlock]->GetBlockTime();
+                     wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
+                 }
+                 else
+                     LogPrintf("AddToWallet(): found %s in block %s not in index\n",
+                              wtxIn.GetHash().ToString(),
+                              wtxIn.hashBlock.ToString());
+             }
+             AddToSpends(hash);
+         }
+         bool fUpdated = false;
+         if (!fInsertedNew)
+         {
+             // Merge
+             if (!wtxIn.hashBlock.IsNull() && wtxIn.hashBlock != wtx.hashBlock)
+             {
+                 wtx.hashBlock = wtxIn.hashBlock;
+                 fUpdated = true;
+             }
+             if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
+             {
+                 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
+                 wtx.nIndex = wtxIn.nIndex;
+                 fUpdated = true;
+             }
+             if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
+             {
+                 wtx.fFromMe = wtxIn.fFromMe;
+                 fUpdated = true;
+             }
+         }
+         //// debug print
+         LogPrintf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+         // Write to disk
+         if (fInsertedNew || fUpdated)
+             if (!wtx.WriteToDisk(pwalletdb))
+                 return false;
+         // Break debit/credit balance caches:
+         wtx.MarkDirty();
+         // Notify UI of new or updated transaction
+         NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
+         // notify an external script when a wallet transaction comes in or is updated
+         std::string strCmd = GetArg("-walletnotify", "");
+         if ( !strCmd.empty())
+         {
+             boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
+             boost::thread t(runCommand, strCmd); // thread runs free
+         }
+     }
+     return true;
+ }
+ /**
+  * Add a transaction to the wallet, or update it.
+  * pblock is optional, but should be provided if the transaction is known to be in a block.
+  * If fUpdate is true, existing transactions will be updated.
+  */
+ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
+ {
+     {
+         AssertLockHeld(cs_wallet);
+         bool fExisted = mapWallet.count(tx.GetHash()) != 0;
+         if (fExisted && !fUpdate) return false;
+         if (fExisted || IsMine(tx) || IsFromMe(tx))
+         {
+             CWalletTx wtx(this,tx);
+             // Get merkle branch if transaction was found in a block
+             if (pblock)
+                 wtx.SetMerkleBranch(*pblock);
+             // Do not flush the wallet here for performance reasons
+             // this is safe, as in case of a crash, we rescan the necessary blocks on startup through our SetBestChain-mechanism
+             CWalletDB walletdb(strWalletFile, "r+", false);
+             return AddToWallet(wtx, false, &walletdb);
+         }
+     }
+     return false;
+ }
+ void CWallet::SyncTransaction(const CTransaction& tx, const CBlock* pblock)
+ {
+     LOCK2(cs_main, cs_wallet);
+     if (!AddToWalletIfInvolvingMe(tx, pblock, true))
+         return; // Not one of ours
+     // If a transaction changes 'conflicted' state, that changes the balance
+     // available of the outputs it spends. So force those to be
+     // recomputed, also:
+     BOOST_FOREACH(const CTxIn& txin, tx.vin)
+     {
+         if (mapWallet.count(txin.prevout.hash))
+             mapWallet[txin.prevout.hash].MarkDirty();
+     }
+ }
+ void CWallet::EraseFromWallet(const uint256 &hash)
+ {
+     if (!fFileBacked)
+         return;
+     {
+         LOCK(cs_wallet);
+         if (mapWallet.erase(hash))
+             CWalletDB(strWalletFile).EraseTx(hash);
+     }
+     return;
+ }
+ isminetype CWallet::IsMine(const CTxIn &txin) const
+ {
+     {
+         LOCK(cs_wallet);
+         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
+         if (mi != mapWallet.end())
+         {
+             const CWalletTx& prev = (*mi).second;
+             if (txin.prevout.n < prev.vout.size())
+                 return IsMine(prev.vout[txin.prevout.n]);
+         }
+     }
+     return ISMINE_NO;
+ }
+ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
+ {
+     {
+         LOCK(cs_wallet);
+         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
+         if (mi != mapWallet.end())
+         {
+             const CWalletTx& prev = (*mi).second;
+             if (txin.prevout.n < prev.vout.size())
+                 if (IsMine(prev.vout[txin.prevout.n]) & filter)
+                     return prev.vout[txin.prevout.n].nValue;
+         }
+     }
+     return 0;
+ }
+ bool CWallet::IsChange(const CTxOut& txout) const
+ {
+     // TODO: fix handling of 'change' outputs. The assumption is that any
+     // 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 (::IsMine(*this, txout.scriptPubKey))
+     {
+         CTxDestination address;
+         if (!ExtractDestination(txout.scriptPubKey, address))
+             return true;
+         LOCK(cs_wallet);
+         if (!mapAddressBook.count(address))
+             return true;
+     }
+     return false;
+ }
+ int64_t CWalletTx::GetTxTime() const
+ {
+     int64_t n = nTimeSmart;
+     return n ? n : nTimeReceived;
+ }
+ int CWalletTx::GetRequestCount() const
+ {
+     // Returns -1 if it wasn't being tracked
+     int nRequests = -1;
+     {
+         LOCK(pwallet->cs_wallet);
+         if (IsCoinBase())
+         {
+             // Generated block
+             if (!hashBlock.IsNull())
+             {
+                 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
+                 if (mi != pwallet->mapRequestCount.end())
+                     nRequests = (*mi).second;
+             }
+         }
+         else
+         {
+             // Did anyone request this transaction?
+             map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
+             if (mi != pwallet->mapRequestCount.end())
+             {
+                 nRequests = (*mi).second;
+                 // How about the block it's in?
+                 if (nRequests == 0 && !hashBlock.IsNull())
+                 {
+                     map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
+                     if (mi != pwallet->mapRequestCount.end())
+                         nRequests = (*mi).second;
+                     else
+                         nRequests = 1; // If it's in someone else's block it must have got out
+                 }
+             }
+         }
+     }
+     return nRequests;
+ }
+ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
+                            list<COutputEntry>& listSent, CAmount& nFee, string& strSentAccount, const isminefilter& filter) const
+ {
+     nFee = 0;
+     listReceived.clear();
+     listSent.clear();
+     strSentAccount = strFromAccount;
+     // Compute fee:
+     CAmount nDebit = GetDebit(filter);
+     if (nDebit > 0) // debit>0 means we signed/sent this transaction
+     {
+         CAmount nValueOut = GetValueOut();
+         nFee = nDebit - nValueOut;
+     }
+     // Sent/received.
+     for (unsigned int i = 0; i < vout.size(); ++i)
+     {
+         const CTxOut& txout = vout[i];
+         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)
+         if (nDebit > 0)
+         {
+             // Don't report 'change' txouts
+             if (pwallet->IsChange(txout))
+                 continue;
+         }
+         else if (!(fIsMine & filter))
+             continue;
+         // In either case, we need to get the destination address
+         CTxDestination address;
+         if (!ExtractDestination(txout.scriptPubKey, address))
+         {
+             LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
+                      this->GetHash().ToString());
+             address = CNoDestination();
+         }
+         COutputEntry output = {address, txout.nValue, (int)i};
+         // If we are debited by the transaction, add the output as a "sent" entry
+         if (nDebit > 0)
+             listSent.push_back(output);
+         // If we are receiving the output, add it as a "received" entry
+         if (fIsMine & filter)
+             listReceived.push_back(output);
+     }
+ }
+ void CWalletTx::GetAccountAmounts(const string& strAccount, CAmount& nReceived,
+                                   CAmount& nSent, CAmount& nFee, const isminefilter& filter) const
+ {
+     nReceived = nSent = nFee = 0;
+     CAmount allFee;
+     string strSentAccount;
+     list<COutputEntry> listReceived;
+     list<COutputEntry> listSent;
+     GetAmounts(listReceived, listSent, allFee, strSentAccount, filter);
+     if (strAccount == strSentAccount)
+     {
+         BOOST_FOREACH(const COutputEntry& s, listSent)
+             nSent += s.amount;
+         nFee = allFee;
+     }
+     {
+         LOCK(pwallet->cs_wallet);
+         BOOST_FOREACH(const COutputEntry& r, listReceived)
+         {
+             if (pwallet->mapAddressBook.count(r.destination))
+             {
+                 map<CTxDestination, CAddressBookData>::const_iterator mi = pwallet->mapAddressBook.find(r.destination);
+                 if (mi != pwallet->mapAddressBook.end() && (*mi).second.name == strAccount)
+                     nReceived += r.amount;
+             }
+             else if (strAccount.empty())
+             {
+                 nReceived += r.amount;
+             }
+         }
+     }
+ }
+ bool CWalletTx::WriteToDisk(CWalletDB *pwalletdb)
+ {
+     return pwalletdb->WriteTx(GetHash(), *this);
+ }
+ /**
+  * Scan the block chain (starting in pindexStart) for transactions
+  * from or to us. If fUpdate is true, found transactions that already
+  * exist in the wallet will be updated.
+  */
+ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
+ {
+     int ret = 0;
+     int64_t nNow = GetTime();
+     CBlockIndex* pindex = pindexStart;
+     {
+         LOCK2(cs_main, cs_wallet);
+         // no need to read and scan block, if block was created before
+         // our wallet birthday (as adjusted for block time variability)
+         while (pindex && nTimeFirstKey && (pindex->GetBlockTime() < (nTimeFirstKey - 7200)))
+             pindex = chainActive.Next(pindex);
+         ShowProgress(_("Rescanning..."), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
+         double dProgressStart = Checkpoints::GuessVerificationProgress(pindex, false);
+         double dProgressTip = Checkpoints::GuessVerificationProgress(chainActive.Tip(), false);
+         while (pindex)
+         {
+             if (pindex->nHeight % 100 == 0 && dProgressTip - dProgressStart > 0.0)
+                 ShowProgress(_("Rescanning..."), std::max(1, std::min(99, (int)((Checkpoints::GuessVerificationProgress(pindex, false) - dProgressStart) / (dProgressTip - dProgressStart) * 100))));
+             CBlock block;
+             ReadBlockFromDisk(block, pindex);
+             BOOST_FOREACH(CTransaction& tx, block.vtx)
+             {
+                 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
+                     ret++;
+             }
+             pindex = chainActive.Next(pindex);
+             if (GetTime() >= nNow + 60) {
+                 nNow = GetTime();
+                 LogPrintf("Still rescanning. At block %d. Progress=%f\n", pindex->nHeight, Checkpoints::GuessVerificationProgress(pindex));
+             }
+         }
+         ShowProgress(_("Rescanning..."), 100); // hide progress dialog in GUI
+     }
+     return ret;
+ }
+ void CWallet::ReacceptWalletTransactions()
+ {
+     LOCK2(cs_main, cs_wallet);
+     BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+     {
+         const uint256& wtxid = item.first;
+         CWalletTx& wtx = item.second;
+         assert(wtx.GetHash() == wtxid);
+         int nDepth = wtx.GetDepthInMainChain();
+         if (!wtx.IsCoinBase() && nDepth < 0)
+         {
+             // Try to add to memory pool
+             LOCK(mempool.cs);
+             wtx.AcceptToMemoryPool(false);
+         }
+     }
+ }
+ void CWalletTx::RelayWalletTransaction()
+ {
+     if (!IsCoinBase())
+     {
+         if (GetDepthInMainChain() == 0) {
+             LogPrintf("Relaying wtx %s\n", GetHash().ToString());
+             RelayTransaction((CTransaction)*this);
+         }
+     }
+ }
+ set<uint256> CWalletTx::GetConflicts() const
+ {
+     set<uint256> result;
+     if (pwallet != NULL)
+     {
+         uint256 myHash = GetHash();
+         result = pwallet->GetConflicts(myHash);
+         result.erase(myHash);
+     }
+     return result;
+ }
+ CAmount CWalletTx::GetDebit(const isminefilter& filter) const
+ {
+     if (vin.empty())
+         return 0;
+     CAmount debit = 0;
+     if(filter & ISMINE_SPENDABLE)
+     {
+         if (fDebitCached)
+             debit += nDebitCached;
+         else
+         {
+             nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
+             fDebitCached = true;
+             debit += nDebitCached;
+         }
+     }
+     if(filter & ISMINE_WATCH_ONLY)
+     {
+         if(fWatchDebitCached)
+             debit += nWatchDebitCached;
+         else
+         {
+             nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
+             fWatchDebitCached = true;
+             debit += nWatchDebitCached;
+         }
+     }
+     return debit;
+ }
+ CAmount CWalletTx::GetCredit(const isminefilter& filter) const
+ {
+     // Must wait until coinbase is safely deep enough in the chain before valuing it
+     if (IsCoinBase() && GetBlocksToMaturity() > 0)
+         return 0;
+     int64_t credit = 0;
+     if (filter & ISMINE_SPENDABLE)
+     {
+         // GetBalance can assume transactions in mapWallet won't change
+         if (fCreditCached)
+             credit += nCreditCached;
+         else
+         {
+             nCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
+             fCreditCached = true;
+             credit += nCreditCached;
+         }
+     }
+     if (filter & ISMINE_WATCH_ONLY)
+     {
+         if (fWatchCreditCached)
+             credit += nWatchCreditCached;
+         else
+         {
+             nWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
+             fWatchCreditCached = true;
+             credit += nWatchCreditCached;
+         }
+     }
+     return credit;
+ }
+ CAmount CWalletTx::GetImmatureCredit(bool fUseCache) const
+ {
+     if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
+     {
+         if (fUseCache && fImmatureCreditCached)
+             return nImmatureCreditCached;
+         nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
+         fImmatureCreditCached = true;
+         return nImmatureCreditCached;
+     }
+     return 0;
+ }
+ CAmount CWalletTx::GetAvailableCredit(bool fUseCache) 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 && fAvailableCreditCached)
+         return nAvailableCreditCached;
+     CAmount nCredit = 0;
+     uint256 hashTx = GetHash();
+     for (unsigned int i = 0; i < vout.size(); i++)
+     {
+         if (!pwallet->IsSpent(hashTx, i))
+         {
+             const CTxOut &txout = vout[i];
+             nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
+             if (!MoneyRange(nCredit))
+                 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
+         }
+     }
+     nAvailableCreditCached = nCredit;
+     fAvailableCreditCached = true;
+     return nCredit;
+ }
+ CAmount CWalletTx::GetImmatureWatchOnlyCredit(const bool& fUseCache) const
+ {
+     if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
+     {
+         if (fUseCache && fImmatureWatchCreditCached)
+             return nImmatureWatchCreditCached;
+         nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
+         fImmatureWatchCreditCached = true;
+         return nImmatureWatchCreditCached;
+     }
+     return 0;
+ }
+ CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) 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;
+     CAmount 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, ISMINE_WATCH_ONLY);
+             if (!MoneyRange(nCredit))
+                 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
+         }
+     }
+     nAvailableWatchCreditCached = nCredit;
+     fAvailableWatchCreditCached = true;
+     return nCredit;
+ }
+ CAmount CWalletTx::GetChange() const
+ {
+     if (fChangeCached)
+         return nChangeCached;
+     nChangeCached = pwallet->GetChange(*this);
+     fChangeCached = true;
+     return nChangeCached;
+ }
+ bool CWalletTx::IsTrusted() const
+ {
+     // Quick answer in most cases
+     if (!IsFinalTx(*this))
+         return false;
+     int nDepth = GetDepthInMainChain();
+     if (nDepth >= 1)
+         return true;
+     if (nDepth < 0)
+         return false;
+     if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
+         return false;
+     // Trusted if all inputs are from us and are in the mempool:
+     BOOST_FOREACH(const CTxIn& txin, vin)
+     {
+         // Transactions not sent by us: not trusted
+         const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
+         if (parent == NULL)
+             return false;
+         const CTxOut& parentOut = parent->vout[txin.prevout.n];
+         if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
+             return false;
+     }
+     return true;
+ }
+ void CWallet::ResendWalletTransactions()
+ {
+     // Do this infrequently and randomly to avoid giving away
+     // that these are our transactions.
+     if (GetTime() < nNextResend)
+         return;
+     bool fFirst = (nNextResend == 0);
+     nNextResend = GetTime() + GetRand(30 * 60);
+     if (fFirst)
+         return;
+     // Only do it if there's been a new block since last time
+     if (nTimeBestReceived < nLastResend)
+         return;
+     nLastResend = GetTime();
+     // Rebroadcast any of our txes that aren't in a block yet
+     LogPrintf("ResendWalletTransactions()\n");
+     {
+         LOCK(cs_wallet);
+         // Sort them in chronological order
+         multimap<unsigned int, CWalletTx*> mapSorted;
+         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
+         {
+             CWalletTx& wtx = item.second;
+             // Don't rebroadcast until it's had plenty of time that
+             // it should have gotten in already by now.
+             if (nTimeBestReceived - (int64_t)wtx.nTimeReceived > 5 * 60)
+                 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
+         }
+         BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
+         {
+             CWalletTx& wtx = *item.second;
+             wtx.RelayWalletTransaction();
+         }
+     }
+ }
+ /** @} */ // end of mapWallet
+ /** @defgroup Actions
+  *
+  * @{
+  */
+ CAmount CWallet::GetBalance() const
+ {
+     CAmount nTotal = 0;
+     {
+         LOCK2(cs_main, cs_wallet);
+         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+         {
+             const CWalletTx* pcoin = &(*it).second;
+             if (pcoin->IsTrusted())
+                 nTotal += pcoin->GetAvailableCredit();
+         }
+     }
+     return nTotal;
+ }
+ CAmount CWallet::GetUnconfirmedBalance() const
+ {
+     CAmount nTotal = 0;
+     {
+         LOCK2(cs_main, cs_wallet);
+         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+         {
+             const CWalletTx* pcoin = &(*it).second;
+             if (!IsFinalTx(*pcoin) || (!pcoin->IsTrusted() && pcoin->GetDepthInMainChain() == 0))
+                 nTotal += pcoin->GetAvailableCredit();
+         }
+     }
+     return nTotal;
+ }
+ CAmount CWallet::GetImmatureBalance() const
+ {
+     CAmount nTotal = 0;
+     {
+         LOCK2(cs_main, cs_wallet);
+         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+         {
+             const CWalletTx* pcoin = &(*it).second;
+             nTotal += pcoin->GetImmatureCredit();
+         }
+     }
+     return nTotal;
+ }
+ CAmount CWallet::GetWatchOnlyBalance() const
+ {
+     CAmount nTotal = 0;
+     {
+         LOCK2(cs_main, cs_wallet);
+         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+         {
+             const CWalletTx* pcoin = &(*it).second;
+             if (pcoin->IsTrusted())
+                 nTotal += pcoin->GetAvailableWatchOnlyCredit();
+         }
+     }
+     return nTotal;
+ }
+ CAmount CWallet::GetUnconfirmedWatchOnlyBalance() const
+ {
+     CAmount nTotal = 0;
+     {
+         LOCK2(cs_main, cs_wallet);
+         for (map<uint256, CWalletTx>::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;
+ }
+ CAmount CWallet::GetImmatureWatchOnlyBalance() const
+ {
+     CAmount nTotal = 0;
+     {
+         LOCK2(cs_main, cs_wallet);
+         for (map<uint256, CWalletTx>::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<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const
+ {
+     vCoins.clear();
+     {
+         LOCK2(cs_main, cs_wallet);
+         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
+         {
+             const uint256& wtxid = it->first;
+             const CWalletTx* pcoin = &(*it).second;
+             if (!IsFinalTx(*pcoin))
+                 continue;
+             if (fOnlyConfirmed && !pcoin->IsTrusted())
+                 continue;
+             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+                 continue;
+             int nDepth = pcoin->GetDepthInMainChain();
+             if (nDepth < 0)
+                 continue;
+             for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
+                 isminetype mine = IsMine(pcoin->vout[i]);
+                 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 & ISMINE_SPENDABLE) != ISMINE_NO));
+             }
+         }
+     }
+ }
+ static void ApproximateBestSubset(vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > >vValue, const CAmount& nTotalLower, const CAmount& nTargetValue,
+                                   vector<char>& vfBest, CAmount& nBest, int iterations = 1000)
+ {
+     vector<char> vfIncluded;
+     vfBest.assign(vValue.size(), true);
+     nBest = nTotalLower;
+     seed_insecure_rand();
+     for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
+     {
+         vfIncluded.assign(vValue.size(), false);
+         CAmount nTotal = 0;
+         bool fReachedTarget = false;
+         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
+         {
+             for (unsigned int i = 0; i < vValue.size(); i++)
+             {
+                 //The solver here uses a randomized algorithm,
+                 //the randomness serves no real security purpose but is just
+                 //needed to prevent degenerate behavior and it is important
+                 //that the rng is fast. We do not use a constant random sequence,
+                 //because there may be some privacy improvement by making
+                 //the selection random.
+                 if (nPass == 0 ? insecure_rand()&1 : !vfIncluded[i])
+                 {
+                     nTotal += vValue[i].first;
+                     vfIncluded[i] = true;
+                     if (nTotal >= nTargetValue)
+                     {
+                         fReachedTarget = true;
+                         if (nTotal < nBest)
+                         {
+                             nBest = nTotal;
+                             vfBest = vfIncluded;
+                         }
+                         nTotal -= vValue[i].first;
+                         vfIncluded[i] = false;
+                     }
+                 }
+             }
+         }
+     }
+ }
+ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
+                                  set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const
+ {
+     setCoinsRet.clear();
+     nValueRet = 0;
+     // List of values less than target
+     pair<CAmount, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
+     coinLowestLarger.first = std::numeric_limits<CAmount>::max();
+     coinLowestLarger.second.first = NULL;
+     vector<pair<CAmount, pair<const CWalletTx*,unsigned int> > > vValue;
+     CAmount nTotalLower = 0;
+     random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
+     BOOST_FOREACH(const COutput &output, vCoins)
+     {
+         if (!output.fSpendable)
+             continue;
+         const CWalletTx *pcoin = output.tx;
+         if (output.nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? nConfMine : nConfTheirs))
+             continue;
+         int i = output.i;
+         CAmount n = pcoin->vout[i].nValue;
+         pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
+         if (n == nTargetValue)
+         {
+             setCoinsRet.insert(coin.second);
+             nValueRet += coin.first;
+             return true;
+         }
+         else if (n < nTargetValue + CENT)
+         {
+             vValue.push_back(coin);
+             nTotalLower += n;
+         }
+         else if (n < coinLowestLarger.first)
+         {
+             coinLowestLarger = coin;
+         }
+     }
+     if (nTotalLower == nTargetValue)
+     {
+         for (unsigned int i = 0; i < vValue.size(); ++i)
+         {
+             setCoinsRet.insert(vValue[i].second);
+             nValueRet += vValue[i].first;
+         }
+         return true;
+     }
+     if (nTotalLower < nTargetValue)
+     {
+         if (coinLowestLarger.second.first == NULL)
+             return false;
+         setCoinsRet.insert(coinLowestLarger.second);
+         nValueRet += coinLowestLarger.first;
+         return true;
+     }
+     // Solve subset sum by stochastic approximation
+     sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
+     vector<char> vfBest;
+     CAmount nBest;
+     ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
+     if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
+         ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
+     // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
+     //                                   or the next bigger coin is closer), return the bigger coin
+     if (coinLowestLarger.second.first &&
+         ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
+     {
+         setCoinsRet.insert(coinLowestLarger.second);
+         nValueRet += coinLowestLarger.first;
+     }
+     else {
+         for (unsigned int i = 0; i < vValue.size(); i++)
+             if (vfBest[i])
+             {
+                 setCoinsRet.insert(vValue[i].second);
+                 nValueRet += vValue[i].first;
+             }
+         LogPrint("selectcoins", "SelectCoins() best subset: ");
+         for (unsigned int i = 0; i < vValue.size(); i++)
+             if (vfBest[i])
+                 LogPrint("selectcoins", "%s ", FormatMoney(vValue[i].first));
+         LogPrint("selectcoins", "total %s\n", FormatMoney(nBest));
+     }
+     return true;
+ }
+ bool CWallet::SelectCoins(const CAmount& nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl* coinControl) const
+ {
+     vector<COutput> vCoins;
+     AvailableCoins(vCoins, true, coinControl);
+     // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
+     if (coinControl && coinControl->HasSelected())
+     {
+         BOOST_FOREACH(const COutput& out, vCoins)
+         {
+             if(!out.fSpendable)
+                 continue;
+             nValueRet += out.tx->vout[out.i].nValue;
+             setCoinsRet.insert(make_pair(out.tx, out.i));
+         }
+         return (nValueRet >= nTargetValue);
+     }
+     return (SelectCoinsMinConf(nTargetValue, 1, 6, vCoins, setCoinsRet, nValueRet) ||
+             SelectCoinsMinConf(nTargetValue, 1, 1, vCoins, setCoinsRet, nValueRet) ||
+             (bSpendZeroConfChange && SelectCoinsMinConf(nTargetValue, 0, 1, vCoins, setCoinsRet, nValueRet)));
+ }
 -    BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
++bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend,
++                                CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl* coinControl)
+ {
+     CAmount nValue = 0;
 -        if (nValue < 0)
++    unsigned int nSubtractFeeFromAmount = 0;
++    BOOST_FOREACH (const CRecipient& recipient, vecSend)
+     {
 -        nValue += s.second;
++        if (nValue < 0 || recipient.nAmount < 0)
+         {
+             strFailReason = _("Transaction amounts must be positive");
+             return false;
+         }
 -                CAmount nTotalValue = nValue + nFeeRet;
++        nValue += recipient.nAmount;
++
++        if (recipient.fSubtractFeeFromAmount)
++            nSubtractFeeFromAmount++;
+     }
+     if (vecSend.empty() || nValue < 0)
+     {
+         strFailReason = _("Transaction amounts must be positive");
+         return false;
+     }
+     wtxNew.fTimeReceivedIsTxTime = true;
+     wtxNew.BindWallet(this);
+     CMutableTransaction txNew;
+     // Discourage fee sniping.
+     //
+     // However because of a off-by-one-error in previous versions we need to
+     // neuter it by setting nLockTime to at least one less than nBestHeight.
+     // Secondly currently propagation of transactions created for block heights
+     // corresponding to blocks that were just mined may be iffy - transactions
+     // aren't re-accepted into the mempool - we additionally neuter the code by
+     // going ten blocks back. Doesn't yet do anything for sniping, but does act
+     // to shake out wallet bugs like not showing nLockTime'd transactions at
+     // all.
+     txNew.nLockTime = std::max(0, chainActive.Height() - 10);
+     // Secondly occasionally randomly pick a nLockTime even further back, so
+     // that transactions that are delayed after signing for whatever reason,
+     // e.g. high-latency mix networks and some CoinJoin implementations, have
+     // better privacy.
+     if (GetRandInt(10) == 0)
+         txNew.nLockTime = std::max(0, (int)txNew.nLockTime - GetRandInt(100));
+     assert(txNew.nLockTime <= (unsigned int)chainActive.Height());
+     assert(txNew.nLockTime < LOCKTIME_THRESHOLD);
+     {
+         LOCK2(cs_main, cs_wallet);
+         {
+             nFeeRet = 0;
+             while (true)
+             {
+                 txNew.vin.clear();
+                 txNew.vout.clear();
+                 wtxNew.fFromMe = true;
++                nChangePosRet = -1;
++                bool fFirst = true;
 -                BOOST_FOREACH (const PAIRTYPE(CScript, CAmount)& s, vecSend)
++                CAmount nTotalValue = nValue;
++                if (nSubtractFeeFromAmount == 0)
++                    nTotalValue += nFeeRet;
+                 double dPriority = 0;
+                 // vouts to the payees
 -                    CTxOut txout(s.second, s.first);
++                BOOST_FOREACH (const CRecipient& recipient, vecSend)
+                 {
 -                        strFailReason = _("Transaction amount too small");
++                    CTxOut txout(recipient.nAmount, recipient.scriptPubKey);
++
++                    if (recipient.fSubtractFeeFromAmount)
++                    {
++                        txout.nValue -= nFeeRet / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
++
++                        if (fFirst) // first receiver pays the remainder not divisible by output count
++                        {
++                            fFirst = false;
++                            txout.nValue -= nFeeRet % nSubtractFeeFromAmount;
++                        }
++                    }
++
+                     if (txout.IsDust(::minRelayTxFee))
+                     {
 -                CAmount nChange = nValueIn - nValue - nFeeRet;
++                        if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
++                        {
++                            if (txout.nValue < 0)
++                                strFailReason = _("The transaction amount is too small to pay the fee");
++                            else
++                                strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
++                        }
++                        else
++                            strFailReason = _("Transaction amount too small");
+                         return false;
+                     }
+                     txNew.vout.push_back(txout);
+                 }
+                 // Choose coins to use
+                 set<pair<const CWalletTx*,unsigned int> > setCoins;
+                 CAmount nValueIn = 0;
+                 if (!SelectCoins(nTotalValue, setCoins, nValueIn, coinControl))
+                 {
+                     strFailReason = _("Insufficient funds");
+                     return false;
+                 }
+                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
+                 {
+                     CAmount nCredit = pcoin.first->vout[pcoin.second].nValue;
+                     //The coin age after the next block (depth+1) is used instead of the current,
+                     //reflecting an assumption the user would accept a bit more delay for
+                     //a chance at a free transaction.
+                     //But mempool inputs might still be in the mempool, so their age stays 0
+                     int age = pcoin.first->GetDepthInMainChain();
+                     if (age != 0)
+                         age += 1;
+                     dPriority += (double)nCredit * age;
+                 }
 -                        vector<CTxOut>::iterator position = txNew.vout.begin()+GetRandInt(txNew.vout.size()+1);
++                CAmount nChange = nValueIn - nValue;
++                if (nSubtractFeeFromAmount == 0)
++                    nChange -= nFeeRet;
+                 if (nChange > 0)
+                 {
+                     // Fill a vout to ourself
+                     // TODO: pass in scriptChange instead of reservekey so
+                     // change transaction isn't always pay-to-bitcoin-address
+                     CScript scriptChange;
+                     // coin control: send change to custom address
+                     if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
+                         scriptChange = GetScriptForDestination(coinControl->destChange);
+                     // no coin control: send change to newly generated address
+                     else
+                     {
+                         // Note: We use a new key here to keep it from being obvious which side is the change.
+                         //  The drawback is that by not reusing a previous key, the change may be lost if a
+                         //  backup is restored, if the backup doesn't have the new private key for the change.
+                         //  If we reused the old key, it would be possible to add code to look for and
+                         //  rediscover unknown transactions that were written with keys of ours to recover
+                         //  post-backup change.
+                         // Reserve a new key pair from key pool
+                         CPubKey vchPubKey;
+                         bool ret;
+                         ret = reservekey.GetReservedKey(vchPubKey);
+                         assert(ret); // should never fail, as we just unlocked
+                         scriptChange = GetScriptForDestination(vchPubKey.GetID());
+                     }
+                     CTxOut newTxOut(nChange, scriptChange);
++                    // We do not move dust-change to fees, because the sender would end up paying more than requested.
++                    // This would be against the purpose of the all-inclusive feature.
++                    // So instead we raise the change and deduct from the recipient.
++                    if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(::minRelayTxFee))
++                    {
++                        CAmount nDust = newTxOut.GetDustThreshold(::minRelayTxFee) - newTxOut.nValue;
++                        newTxOut.nValue += nDust; // raise change until no more dust
++                        for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
++                        {
++                            if (vecSend[i].fSubtractFeeFromAmount)
++                            {
++                                txNew.vout[i].nValue -= nDust;
++                                if (txNew.vout[i].IsDust(::minRelayTxFee))
++                                {
++                                    strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
++                                    return false;
++                                }
++                                break;
++                            }
++                        }
++                    }
++
+                     // Never create dust outputs; if we would, just
+                     // add the dust to the fee.
+                     if (newTxOut.IsDust(::minRelayTxFee))
+                     {
+                         nFeeRet += nChange;
+                         reservekey.ReturnKey();
+                     }
+                     else
+                     {
+                         // Insert change txn at random position:
 -    return true;
 -}
++                        nChangePosRet = GetRandInt(txNew.vout.size()+1);
++                        vector<CTxOut>::iterator position = txNew.vout.begin()+nChangePosRet;
+                         txNew.vout.insert(position, newTxOut);
+                     }
+                 }
+                 else
+                     reservekey.ReturnKey();
+                 // Fill vin
+                 //
+                 // Note how the sequence number is set to max()-1 so that the
+                 // nLockTime set above actually works.
+                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
+                     txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second,CScript(),
+                                               std::numeric_limits<unsigned int>::max()-1));
+                 // Sign
+                 int nIn = 0;
+                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
+                     if (!SignSignature(*this, *coin.first, txNew, nIn++))
+                     {
+                         strFailReason = _("Signing transaction failed");
+                         return false;
+                     }
+                 // Embed the constructed transaction data in wtxNew.
+                 *static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
+                 // Limit size
+                 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
+                 if (nBytes >= MAX_STANDARD_TX_SIZE)
+                 {
+                     strFailReason = _("Transaction too large");
+                     return false;
+                 }
+                 dPriority = wtxNew.ComputePriority(dPriority, nBytes);
+                 // Can we complete this as a free transaction?
+                 if (fSendFreeTransactions && nBytes <= MAX_FREE_TRANSACTION_CREATE_SIZE)
+                 {
+                     // Not enough fee: enough priority?
+                     double dPriorityNeeded = mempool.estimatePriority(nTxConfirmTarget);
+                     // Not enough mempool history to estimate: use hard-coded AllowFree.
+                     if (dPriorityNeeded <= 0 && AllowFree(dPriority))
+                         break;
+                     // Small enough, and priority high enough, to send for free
+                     if (dPriorityNeeded > 0 && dPriority >= dPriorityNeeded)
+                         break;
+                 }
+                 CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
+                 // If we made it here and we aren't even able to meet the relay fee on the next pass, give up
+                 // because we must be at the maximum allowed fee.
+                 if (nFeeNeeded < ::minRelayTxFee.GetFee(nBytes))
+                 {
+                     strFailReason = _("Transaction too large for fee policy");
+                     return false;
+                 }
+                 if (nFeeRet >= nFeeNeeded)
+                     break; // Done, enough fee included.
+                 // Include more fee and try again.
+                 nFeeRet = nFeeNeeded;
+                 continue;
+             }
+         }
+     }
 -bool CWallet::CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
 -                                CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
 -{
 -    vector< pair<CScript, CAmount> > vecSend;
 -    vecSend.push_back(make_pair(scriptPubKey, nValue));
 -    return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl);
++    return true;
+ }
+ /**
+  * Call after CreateTransaction unless you want to abort
+  */
+ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
+ {
+     {
+         LOCK2(cs_main, cs_wallet);
+         LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
+         {
+             // This is only to keep the database open to defeat the auto-flush for the
+             // duration of this scope.  This is the only place where this optimization
+             // maybe makes sense; please don't do it anywhere else.
+             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r+") : NULL;
+             // Take key pair from key pool so it won't be used again
+             reservekey.KeepKey();
+             // Add tx to wallet, because if it has change it's also ours,
+             // otherwise just for transaction history.
+             AddToWallet(wtxNew, false, pwalletdb);
+             // Notify that old coins are spent
+             set<CWalletTx*> setCoins;
+             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
+             {
+                 CWalletTx &coin = mapWallet[txin.prevout.hash];
+                 coin.BindWallet(this);
+                 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
+             }
+             if (fFileBacked)
+                 delete pwalletdb;
+         }
+         // Track how many getdata requests our transaction gets
+         mapRequestCount[wtxNew.GetHash()] = 0;
+         // Broadcast
+         if (!wtxNew.AcceptToMemoryPool(false))
+         {
+             // This must not fail. The transaction has already been signed and recorded.
+             LogPrintf("CommitTransaction(): Error: Transaction not valid");
+             return false;
+         }
+         wtxNew.RelayWalletTransaction();
+     }
+     return true;
+ }
+ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool)
+ {
+     // payTxFee is user-set "I want to pay this much"
+     CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
+     // user selected total at least (default=true)
+     if (fPayAtLeastCustomFee && nFeeNeeded > 0 && nFeeNeeded < payTxFee.GetFeePerK())
+         nFeeNeeded = payTxFee.GetFeePerK();
+     // User didn't set: use -txconfirmtarget to estimate...
+     if (nFeeNeeded == 0)
+         nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
+     // ... unless we don't have enough mempool data, in which case fall
+     // back to a hard-coded fee
+     if (nFeeNeeded == 0)
+         nFeeNeeded = minTxFee.GetFee(nTxBytes);
+     // prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
+     if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
+         nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
+     // But always obey the maximum
+     if (nFeeNeeded > maxTxFee)
+         nFeeNeeded = maxTxFee;
+     return nFeeNeeded;
+ }
+ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
+ {
+     if (!fFileBacked)
+         return DB_LOAD_OK;
+     fFirstRunRet = false;
+     DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
+     if (nLoadWalletRet == DB_NEED_REWRITE)
+     {
+         if (CDB::Rewrite(strWalletFile, "\x04pool"))
+         {
+             LOCK(cs_wallet);
+             setKeyPool.clear();
+             // Note: can't top-up keypool here, because wallet is locked.
+             // User will be prompted to unlock wallet the next operation
+             // the requires a new key.
+         }
+     }
+     if (nLoadWalletRet != DB_LOAD_OK)
+         return nLoadWalletRet;
+     fFirstRunRet = !vchDefaultKey.IsValid();
+     uiInterface.LoadWallet(this);
+     return DB_LOAD_OK;
+ }
+ DBErrors CWallet::ZapWalletTx(std::vector<CWalletTx>& vWtx)
+ {
+     if (!fFileBacked)
+         return DB_LOAD_OK;
+     DBErrors nZapWalletTxRet = CWalletDB(strWalletFile,"cr+").ZapWalletTx(this, vWtx);
+     if (nZapWalletTxRet == DB_NEED_REWRITE)
+     {
+         if (CDB::Rewrite(strWalletFile, "\x04pool"))
+         {
+             LOCK(cs_wallet);
+             setKeyPool.clear();
+             // Note: can't top-up keypool here, because wallet is locked.
+             // User will be prompted to unlock wallet the next operation
+             // that requires a new key.
+         }
+     }
+     if (nZapWalletTxRet != DB_LOAD_OK)
+         return nZapWalletTxRet;
+     return DB_LOAD_OK;
+ }
+ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strName, const string& strPurpose)
+ {
+     bool fUpdated = false;
+     {
+         LOCK(cs_wallet); // mapAddressBook
+         std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
+         fUpdated = mi != mapAddressBook.end();
+         mapAddressBook[address].name = strName;
+         if (!strPurpose.empty()) /* update purpose only if requested */
+             mapAddressBook[address].purpose = strPurpose;
+     }
+     NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address) != ISMINE_NO,
+                              strPurpose, (fUpdated ? CT_UPDATED : CT_NEW) );
+     if (!fFileBacked)
+         return false;
+     if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
+         return false;
+     return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
+ }
+ bool CWallet::DelAddressBook(const CTxDestination& address)
+ {
+     {
+         LOCK(cs_wallet); // mapAddressBook
+         if(fFileBacked)
+         {
+             // Delete destdata tuples associated with address
+             std::string strAddress = CBitcoinAddress(address).ToString();
+             BOOST_FOREACH(const PAIRTYPE(string, string) &item, mapAddressBook[address].destdata)
+             {
+                 CWalletDB(strWalletFile).EraseDestData(strAddress, item.first);
+             }
+         }
+         mapAddressBook.erase(address);
+     }
+     NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address) != ISMINE_NO, "", CT_DELETED);
+     if (!fFileBacked)
+         return false;
+     CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
+     return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
+ }
+ bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
+ {
+     if (fFileBacked)
+     {
+         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
+             return false;
+     }
+     vchDefaultKey = vchPubKey;
+     return true;
+ }
+ /**
+  * Mark old keypool keys as used,
+  * and generate all new keys 
+  */
+ bool CWallet::NewKeyPool()
+ {
+     {
+         LOCK(cs_wallet);
+         CWalletDB walletdb(strWalletFile);
+         BOOST_FOREACH(int64_t nIndex, setKeyPool)
+             walletdb.ErasePool(nIndex);
+         setKeyPool.clear();
+         if (IsLocked())
+             return false;
+         int64_t nKeys = max(GetArg("-keypool", 100), (int64_t)0);
+         for (int i = 0; i < nKeys; i++)
+         {
+             int64_t nIndex = i+1;
+             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
+             setKeyPool.insert(nIndex);
+         }
+         LogPrintf("CWallet::NewKeyPool wrote %d new keys\n", nKeys);
+     }
+     return true;
+ }
+ bool CWallet::TopUpKeyPool(unsigned int kpSize)
+ {
+     {
+         LOCK(cs_wallet);
+         if (IsLocked())
+             return false;
+         CWalletDB walletdb(strWalletFile);
+         // Top up key pool
+         unsigned int nTargetSize;
+         if (kpSize > 0)
+             nTargetSize = kpSize;
+         else
+             nTargetSize = max(GetArg("-keypool", 100), (int64_t) 0);
+         while (setKeyPool.size() < (nTargetSize + 1))
+         {
+             int64_t nEnd = 1;
+             if (!setKeyPool.empty())
+                 nEnd = *(--setKeyPool.end()) + 1;
+             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
+                 throw runtime_error("TopUpKeyPool(): writing generated key failed");
+             setKeyPool.insert(nEnd);
+             LogPrintf("keypool added key %d, size=%u\n", nEnd, setKeyPool.size());
+         }
+     }
+     return true;
+ }
+ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool)
+ {
+     nIndex = -1;
+     keypool.vchPubKey = CPubKey();
+     {
+         LOCK(cs_wallet);
+         if (!IsLocked())
+             TopUpKeyPool();
+         // Get the oldest key
+         if(setKeyPool.empty())
+             return;
+         CWalletDB walletdb(strWalletFile);
+         nIndex = *(setKeyPool.begin());
+         setKeyPool.erase(setKeyPool.begin());
+         if (!walletdb.ReadPool(nIndex, keypool))
+             throw runtime_error("ReserveKeyFromKeyPool(): read failed");
+         if (!HaveKey(keypool.vchPubKey.GetID()))
+             throw runtime_error("ReserveKeyFromKeyPool(): unknown key in key pool");
+         assert(keypool.vchPubKey.IsValid());
+         LogPrintf("keypool reserve %d\n", nIndex);
+     }
+ }
+ void CWallet::KeepKey(int64_t nIndex)
+ {
+     // Remove from key pool
+     if (fFileBacked)
+     {
+         CWalletDB walletdb(strWalletFile);
+         walletdb.ErasePool(nIndex);
+     }
+     LogPrintf("keypool keep %d\n", nIndex);
+ }
+ void CWallet::ReturnKey(int64_t nIndex)
+ {
+     // Return to key pool
+     {
+         LOCK(cs_wallet);
+         setKeyPool.insert(nIndex);
+     }
+     LogPrintf("keypool return %d\n", nIndex);
+ }
+ bool CWallet::GetKeyFromPool(CPubKey& result)
+ {
+     int64_t nIndex = 0;
+     CKeyPool keypool;
+     {
+         LOCK(cs_wallet);
+         ReserveKeyFromKeyPool(nIndex, keypool);
+         if (nIndex == -1)
+         {
+             if (IsLocked()) return false;
+             result = GenerateNewKey();
+             return true;
+         }
+         KeepKey(nIndex);
+         result = keypool.vchPubKey;
+     }
+     return true;
+ }
+ int64_t CWallet::GetOldestKeyPoolTime()
+ {
+     int64_t nIndex = 0;
+     CKeyPool keypool;
+     ReserveKeyFromKeyPool(nIndex, keypool);
+     if (nIndex == -1)
+         return GetTime();
+     ReturnKey(nIndex);
+     return keypool.nTime;
+ }
+ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
+ {
+     map<CTxDestination, CAmount> balances;
+     {
+         LOCK(cs_wallet);
+         BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
+         {
+             CWalletTx *pcoin = &walletEntry.second;
+             if (!IsFinalTx(*pcoin) || !pcoin->IsTrusted())
+                 continue;
+             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
+                 continue;
+             int nDepth = pcoin->GetDepthInMainChain();
+             if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
+                 continue;
+             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
+             {
+                 CTxDestination addr;
+                 if (!IsMine(pcoin->vout[i]))
+                     continue;
+                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
+                     continue;
+                 CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
+                 if (!balances.count(addr))
+                     balances[addr] = 0;
+                 balances[addr] += n;
+             }
+         }
+     }
+     return balances;
+ }
+ set< set<CTxDestination> > CWallet::GetAddressGroupings()
+ {
+     AssertLockHeld(cs_wallet); // mapWallet
+     set< set<CTxDestination> > groupings;
+     set<CTxDestination> grouping;
+     BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
+     {
+         CWalletTx *pcoin = &walletEntry.second;
+         if (pcoin->vin.size() > 0)
+         {
+             bool any_mine = false;
+             // group all input addresses with each other
+             BOOST_FOREACH(CTxIn txin, pcoin->vin)
+             {
+                 CTxDestination address;
+                 if(!IsMine(txin)) /* If this input isn't mine, ignore it */
+                     continue;
+                 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
+                     continue;
+                 grouping.insert(address);
+                 any_mine = true;
+             }
+             // group change with input addresses
+             if (any_mine)
+             {
+                BOOST_FOREACH(CTxOut txout, pcoin->vout)
+                    if (IsChange(txout))
+                    {
+                        CTxDestination txoutAddr;
+                        if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
+                            continue;
+                        grouping.insert(txoutAddr);
+                    }
+             }
+             if (grouping.size() > 0)
+             {
+                 groupings.insert(grouping);
+                 grouping.clear();
+             }
+         }
+         // group lone addrs by themselves
+         for (unsigned int i = 0; i < pcoin->vout.size(); i++)
+             if (IsMine(pcoin->vout[i]))
+             {
+                 CTxDestination address;
+                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
+                     continue;
+                 grouping.insert(address);
+                 groupings.insert(grouping);
+                 grouping.clear();
+             }
+     }
+     set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
+     map< CTxDestination, set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
+     BOOST_FOREACH(set<CTxDestination> grouping, groupings)
+     {
+         // make a set of all the groups hit by this new group
+         set< set<CTxDestination>* > hits;
+         map< CTxDestination, set<CTxDestination>* >::iterator it;
+         BOOST_FOREACH(CTxDestination address, grouping)
+             if ((it = setmap.find(address)) != setmap.end())
+                 hits.insert((*it).second);
+         // merge all hit groups into a new single group and delete old groups
+         set<CTxDestination>* merged = new set<CTxDestination>(grouping);
+         BOOST_FOREACH(set<CTxDestination>* hit, hits)
+         {
+             merged->insert(hit->begin(), hit->end());
+             uniqueGroupings.erase(hit);
+             delete hit;
+         }
+         uniqueGroupings.insert(merged);
+         // update setmap
+         BOOST_FOREACH(CTxDestination element, *merged)
+             setmap[element] = merged;
+     }
+     set< set<CTxDestination> > ret;
+     BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
+     {
+         ret.insert(*uniqueGrouping);
+         delete uniqueGrouping;
+     }
+     return ret;
+ }
+ set<CTxDestination> CWallet::GetAccountAddresses(string strAccount) const
+ {
+     LOCK(cs_wallet);
+     set<CTxDestination> result;
+     BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, mapAddressBook)
+     {
+         const CTxDestination& address = item.first;
+         const string& strName = item.second.name;
+         if (strName == strAccount)
+             result.insert(address);
+     }
+     return result;
+ }
+ bool CReserveKey::GetReservedKey(CPubKey& pubkey)
+ {
+     if (nIndex == -1)
+     {
+         CKeyPool keypool;
+         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
+         if (nIndex != -1)
+             vchPubKey = keypool.vchPubKey;
+         else {
+             return false;
+         }
+     }
+     assert(vchPubKey.IsValid());
+     pubkey = vchPubKey;
+     return true;
+ }
+ void CReserveKey::KeepKey()
+ {
+     if (nIndex != -1)
+         pwallet->KeepKey(nIndex);
+     nIndex = -1;
+     vchPubKey = CPubKey();
+ }
+ void CReserveKey::ReturnKey()
+ {
+     if (nIndex != -1)
+         pwallet->ReturnKey(nIndex);
+     nIndex = -1;
+     vchPubKey = CPubKey();
+ }
+ void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
+ {
+     setAddress.clear();
+     CWalletDB walletdb(strWalletFile);
+     LOCK2(cs_main, cs_wallet);
+     BOOST_FOREACH(const int64_t& id, setKeyPool)
+     {
+         CKeyPool keypool;
+         if (!walletdb.ReadPool(id, keypool))
+             throw runtime_error("GetAllReserveKeyHashes(): read failed");
+         assert(keypool.vchPubKey.IsValid());
+         CKeyID keyID = keypool.vchPubKey.GetID();
+         if (!HaveKey(keyID))
+             throw runtime_error("GetAllReserveKeyHashes(): unknown key in key pool");
+         setAddress.insert(keyID);
+     }
+ }
+ void CWallet::UpdatedTransaction(const uint256 &hashTx)
+ {
+     {
+         LOCK(cs_wallet);
+         // Only notify UI if this transaction is in this wallet
+         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
+         if (mi != mapWallet.end())
+             NotifyTransactionChanged(this, hashTx, CT_UPDATED);
+     }
+ }
+ void CWallet::LockCoin(COutPoint& output)
+ {
+     AssertLockHeld(cs_wallet); // setLockedCoins
+     setLockedCoins.insert(output);
+ }
+ void CWallet::UnlockCoin(COutPoint& output)
+ {
+     AssertLockHeld(cs_wallet); // setLockedCoins
+     setLockedCoins.erase(output);
+ }
+ void CWallet::UnlockAllCoins()
+ {
+     AssertLockHeld(cs_wallet); // setLockedCoins
+     setLockedCoins.clear();
+ }
+ bool CWallet::IsLockedCoin(uint256 hash, unsigned int n) const
+ {
+     AssertLockHeld(cs_wallet); // setLockedCoins
+     COutPoint outpt(hash, n);
+     return (setLockedCoins.count(outpt) > 0);
+ }
+ void CWallet::ListLockedCoins(std::vector<COutPoint>& vOutpts)
+ {
+     AssertLockHeld(cs_wallet); // setLockedCoins
+     for (std::set<COutPoint>::iterator it = setLockedCoins.begin();
+          it != setLockedCoins.end(); it++) {
+         COutPoint outpt = (*it);
+         vOutpts.push_back(outpt);
+     }
+ }
+ /** @} */ // end of Actions
+ class CAffectedKeysVisitor : public boost::static_visitor<void> {
+ private:
+     const CKeyStore &keystore;
+     std::vector<CKeyID> &vKeys;
+ public:
+     CAffectedKeysVisitor(const CKeyStore &keystoreIn, std::vector<CKeyID> &vKeysIn) : keystore(keystoreIn), vKeys(vKeysIn) {}
+     void Process(const CScript &script) {
+         txnouttype type;
+         std::vector<CTxDestination> vDest;
+         int nRequired;
+         if (ExtractDestinations(script, type, vDest, nRequired)) {
+             BOOST_FOREACH(const CTxDestination &dest, vDest)
+                 boost::apply_visitor(*this, dest);
+         }
+     }
+     void operator()(const CKeyID &keyId) {
+         if (keystore.HaveKey(keyId))
+             vKeys.push_back(keyId);
+     }
+     void operator()(const CScriptID &scriptId) {
+         CScript script;
+         if (keystore.GetCScript(scriptId, script))
+             Process(script);
+     }
+     void operator()(const CNoDestination &none) {}
+ };
+ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
+     AssertLockHeld(cs_wallet); // mapKeyMetadata
+     mapKeyBirth.clear();
+     // get birth times for keys with metadata
+     for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
+         if (it->second.nCreateTime)
+             mapKeyBirth[it->first] = it->second.nCreateTime;
+     // map in which we'll infer heights of other keys
+     CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
+     std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
+     std::set<CKeyID> setKeys;
+     GetKeys(setKeys);
+     BOOST_FOREACH(const CKeyID &keyid, setKeys) {
+         if (mapKeyBirth.count(keyid) == 0)
+             mapKeyFirstBlock[keyid] = pindexMax;
+     }
+     setKeys.clear();
+     // if there are no such keys, we're done
+     if (mapKeyFirstBlock.empty())
+         return;
+     // find first block that affects those keys, if there are any left
+     std::vector<CKeyID> vAffected;
+     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
+         // iterate over all wallet transactions...
+         const CWalletTx &wtx = (*it).second;
+         BlockMap::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
+         if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
+             // ... which are already in a block
+             int nHeight = blit->second->nHeight;
+             BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
+                 // iterate over all their outputs
+                 CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
+                 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
+                     // ... and all their affected keys
+                     std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
+                     if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
+                         rit->second = blit->second;
+                 }
+                 vAffected.clear();
+             }
+         }
+     }
+     // Extract block timestamps for those keys
+     for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
+         mapKeyBirth[it->first] = it->second->GetBlockTime() - 7200; // block times can be 2h off
+ }
+ bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
+ {
+     if (boost::get<CNoDestination>(&dest))
+         return false;
+     mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
+     if (!fFileBacked)
+         return true;
+     return CWalletDB(strWalletFile).WriteDestData(CBitcoinAddress(dest).ToString(), key, value);
+ }
+ bool CWallet::EraseDestData(const CTxDestination &dest, const std::string &key)
+ {
+     if (!mapAddressBook[dest].destdata.erase(key))
+         return false;
+     if (!fFileBacked)
+         return true;
+     return CWalletDB(strWalletFile).EraseDestData(CBitcoinAddress(dest).ToString(), key);
+ }
+ bool CWallet::LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value)
+ {
+     mapAddressBook[dest].destdata.insert(std::make_pair(key, value));
+     return true;
+ }
+ bool CWallet::GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const
+ {
+     std::map<CTxDestination, CAddressBookData>::const_iterator i = mapAddressBook.find(dest);
+     if(i != mapAddressBook.end())
+     {
+         CAddressBookData::StringMap::const_iterator j = i->second.destdata.find(key);
+         if(j != i->second.destdata.end())
+         {
+             if(value)
+                 *value = j->second;
+             return true;
+         }
+     }
+     return false;
+ }
+ CKeyPool::CKeyPool()
+ {
+     nTime = GetTime();
+ }
+ CKeyPool::CKeyPool(const CPubKey& vchPubKeyIn)
+ {
+     nTime = GetTime();
+     vchPubKey = vchPubKeyIn;
+ }
+ CWalletKey::CWalletKey(int64_t nExpires)
+ {
+     nTimeCreated = (nExpires ? GetTime() : 0);
+     nTimeExpires = nExpires;
+ }
+ int CMerkleTx::SetMerkleBranch(const CBlock& block)
+ {
+     AssertLockHeld(cs_main);
+     CBlock blockTmp;
+     // Update the tx's hashBlock
+     hashBlock = block.GetHash();
+     // Locate the transaction
+     for (nIndex = 0; nIndex < (int)block.vtx.size(); nIndex++)
+         if (block.vtx[nIndex] == *(CTransaction*)this)
+             break;
+     if (nIndex == (int)block.vtx.size())
+     {
+         vMerkleBranch.clear();
+         nIndex = -1;
+         LogPrintf("ERROR: SetMerkleBranch(): couldn't find tx in block\n");
+         return 0;
+     }
+     // Fill in merkle branch
+     vMerkleBranch = block.GetMerkleBranch(nIndex);
+     // Is the tx in a block that's in the main chain
+     BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
+     if (mi == mapBlockIndex.end())
+         return 0;
+     const CBlockIndex* pindex = (*mi).second;
+     if (!pindex || !chainActive.Contains(pindex))
+         return 0;
+     return chainActive.Height() - pindex->nHeight + 1;
+ }
+ int CMerkleTx::GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const
+ {
+     if (hashBlock.IsNull() || nIndex == -1)
+         return 0;
+     AssertLockHeld(cs_main);
+     // Find the block it claims to be in
+     BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
+     if (mi == mapBlockIndex.end())
+         return 0;
+     CBlockIndex* pindex = (*mi).second;
+     if (!pindex || !chainActive.Contains(pindex))
+         return 0;
+     // Make sure the merkle branch connects to this block
+     if (!fMerkleVerified)
+     {
+         if (CBlock::CheckMerkleBranch(GetHash(), vMerkleBranch, nIndex) != pindex->hashMerkleRoot)
+             return 0;
+         fMerkleVerified = true;
+     }
+     pindexRet = pindex;
+     return chainActive.Height() - pindex->nHeight + 1;
+ }
+ int CMerkleTx::GetDepthInMainChain(const CBlockIndex* &pindexRet) const
+ {
+     AssertLockHeld(cs_main);
+     int nResult = GetDepthInMainChainINTERNAL(pindexRet);
+     if (nResult == 0 && !mempool.exists(GetHash()))
+         return -1; // Not in chain, not in mempool
+     return nResult;
+ }
+ int CMerkleTx::GetBlocksToMaturity() const
+ {
+     if (!IsCoinBase())
+         return 0;
+     return max(0, (COINBASE_MATURITY+1) - GetDepthInMainChain());
+ }
+ bool CMerkleTx::AcceptToMemoryPool(bool fLimitFree, bool fRejectAbsurdFee)
+ {
+     CValidationState state;
+     return ::AcceptToMemoryPool(mempool, state, *this, fLimitFree, NULL, fRejectAbsurdFee);
+ }
index 0000000000000000000000000000000000000000,093336080e842f02da33d5daee64493c2024c3b7..b2973250a440c5e408194ac0e3031257bdf4b8a0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,902 +1,906 @@@
 -    bool CreateTransaction(const std::vector<std::pair<CScript, CAmount> >& vecSend,
 -                           CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
 -    bool CreateTransaction(CScript scriptPubKey, const CAmount& nValue,
 -                           CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
+ // Copyright (c) 2009-2010 Satoshi Nakamoto
+ // Copyright (c) 2009-2014 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_H
+ #define BITCOIN_WALLET_H
+ #include "amount.h"
+ #include "primitives/block.h"
+ #include "primitives/transaction.h"
+ #include "crypter.h"
+ #include "key.h"
+ #include "keystore.h"
+ #include "main.h"
+ #include "ui_interface.h"
+ #include "wallet/wallet_ismine.h"
+ #include "wallet/walletdb.h"
+ #include <algorithm>
+ #include <map>
+ #include <set>
+ #include <stdexcept>
+ #include <stdint.h>
+ #include <string>
+ #include <utility>
+ #include <vector>
+ /**
+  * Settings
+  */
+ extern CFeeRate payTxFee;
+ extern CAmount maxTxFee;
+ extern unsigned int nTxConfirmTarget;
+ extern bool bSpendZeroConfChange;
+ extern bool fSendFreeTransactions;
+ extern bool fPayAtLeastCustomFee;
+ //! -paytxfee default
+ static const CAmount DEFAULT_TRANSACTION_FEE = 0;
+ //! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
+ static const CAmount nHighTransactionFeeWarning = 0.01 * COIN;
+ //! -maxtxfee default
+ static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN;
+ //! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
+ static const CAmount nHighTransactionMaxFeeWarning = 100 * nHighTransactionFeeWarning;
+ //! Largest (in bytes) free transaction we're willing to create
+ static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
+ class CAccountingEntry;
+ class CCoinControl;
+ class COutput;
+ class CReserveKey;
+ class CScript;
+ class CWalletTx;
+ /** (client) version numbers for particular wallet features */
+ enum WalletFeature
+ {
+     FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
+     FEATURE_WALLETCRYPT = 40000, // wallet encryption
+     FEATURE_COMPRPUBKEY = 60000, // compressed public keys
+     FEATURE_LATEST = 60000
+ };
+ /** A key pool entry */
+ class CKeyPool
+ {
+ public:
+     int64_t nTime;
+     CPubKey vchPubKey;
+     CKeyPool();
+     CKeyPool(const CPubKey& vchPubKeyIn);
+     ADD_SERIALIZE_METHODS;
+     template <typename Stream, typename Operation>
+     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+         if (!(nType & SER_GETHASH))
+             READWRITE(nVersion);
+         READWRITE(nTime);
+         READWRITE(vchPubKey);
+     }
+ };
+ /** Address book data */
+ class CAddressBookData
+ {
+ public:
+     std::string name;
+     std::string purpose;
+     CAddressBookData()
+     {
+         purpose = "unknown";
+     }
+     typedef std::map<std::string, std::string> StringMap;
+     StringMap destdata;
+ };
++struct CRecipient
++{
++    CScript scriptPubKey;
++    CAmount nAmount;
++    bool fSubtractFeeFromAmount;
++};
+ typedef std::map<std::string, std::string> mapValue_t;
+ static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
+ {
+     if (!mapValue.count("n"))
+     {
+         nOrderPos = -1; // TODO: calculate elsewhere
+         return;
+     }
+     nOrderPos = atoi64(mapValue["n"].c_str());
+ }
+ static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
+ {
+     if (nOrderPos == -1)
+         return;
+     mapValue["n"] = i64tostr(nOrderPos);
+ }
+ struct COutputEntry
+ {
+     CTxDestination destination;
+     CAmount amount;
+     int vout;
+ };
+ /** A transaction with a merkle branch linking it to the block chain. */
+ class CMerkleTx : public CTransaction
+ {
+ private:
+     int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const;
+ public:
+     uint256 hashBlock;
+     std::vector<uint256> vMerkleBranch;
+     int nIndex;
+     // memory only
+     mutable bool fMerkleVerified;
+     CMerkleTx()
+     {
+         Init();
+     }
+     CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
+     {
+         Init();
+     }
+     void Init()
+     {
+         hashBlock = uint256();
+         nIndex = -1;
+         fMerkleVerified = false;
+     }
+     ADD_SERIALIZE_METHODS;
+     template <typename Stream, typename Operation>
+     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+         READWRITE(*(CTransaction*)this);
+         nVersion = this->nVersion;
+         READWRITE(hashBlock);
+         READWRITE(vMerkleBranch);
+         READWRITE(nIndex);
+     }
+     int SetMerkleBranch(const CBlock& block);
+     /**
+      * Return depth of transaction in blockchain:
+      * -1  : not in blockchain, and not in memory pool (conflicted transaction)
+      *  0  : in memory pool, waiting to be included in a block
+      * >=1 : this many blocks deep in the main chain
+      */
+     int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
+     int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
+     bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
+     int GetBlocksToMaturity() const;
+     bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
+ };
+ /** 
+  * A transaction with a bunch of additional info that only the owner cares about.
+  * It includes any unrecorded transactions needed to link it back to the block chain.
+  */
+ class CWalletTx : public CMerkleTx
+ {
+ private:
+     const CWallet* pwallet;
+ 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 nTimeSmart;
+     char fFromMe;
+     std::string strFromAccount;
+     int64_t nOrderPos; //! position in ordered transaction list
+     // memory only
+     mutable bool fDebitCached;
+     mutable bool fCreditCached;
+     mutable bool fImmatureCreditCached;
+     mutable bool fAvailableCreditCached;
+     mutable bool fWatchDebitCached;
+     mutable bool fWatchCreditCached;
+     mutable bool fImmatureWatchCreditCached;
+     mutable bool fAvailableWatchCreditCached;
+     mutable bool fChangeCached;
+     mutable CAmount nDebitCached;
+     mutable CAmount nCreditCached;
+     mutable CAmount nImmatureCreditCached;
+     mutable CAmount nAvailableCreditCached;
+     mutable CAmount nWatchDebitCached;
+     mutable CAmount nWatchCreditCached;
+     mutable CAmount nImmatureWatchCreditCached;
+     mutable CAmount nAvailableWatchCreditCached;
+     mutable CAmount nChangeCached;
+     CWalletTx()
+     {
+         Init(NULL);
+     }
+     CWalletTx(const CWallet* pwalletIn)
+     {
+         Init(pwalletIn);
+     }
+     CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
+     {
+         Init(pwalletIn);
+     }
+     CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
+     {
+         Init(pwalletIn);
+     }
+     void Init(const CWallet* pwalletIn)
+     {
+         pwallet = pwalletIn;
+         mapValue.clear();
+         vOrderForm.clear();
+         fTimeReceivedIsTxTime = false;
+         nTimeReceived = 0;
+         nTimeSmart = 0;
+         fFromMe = false;
+         strFromAccount.clear();
+         fDebitCached = false;
+         fCreditCached = false;
+         fImmatureCreditCached = false;
+         fAvailableCreditCached = false;
+         fWatchDebitCached = false;
+         fWatchCreditCached = false;
+         fImmatureWatchCreditCached = false;
+         fAvailableWatchCreditCached = false;
+         fChangeCached = false;
+         nDebitCached = 0;
+         nCreditCached = 0;
+         nImmatureCreditCached = 0;
+         nAvailableCreditCached = 0;
+         nWatchDebitCached = 0;
+         nWatchCreditCached = 0;
+         nAvailableWatchCreditCached = 0;
+         nImmatureWatchCreditCached = 0;
+         nChangeCached = 0;
+         nOrderPos = -1;
+     }
+     ADD_SERIALIZE_METHODS;
+     template <typename Stream, typename Operation>
+     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+         if (ser_action.ForRead())
+             Init(NULL);
+         char fSpent = false;
+         if (!ser_action.ForRead())
+         {
+             mapValue["fromaccount"] = strFromAccount;
+             WriteOrderPos(nOrderPos, mapValue);
+             if (nTimeSmart)
+                 mapValue["timesmart"] = strprintf("%u", nTimeSmart);
+         }
+         READWRITE(*(CMerkleTx*)this);
+         std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
+         READWRITE(vUnused);
+         READWRITE(mapValue);
+         READWRITE(vOrderForm);
+         READWRITE(fTimeReceivedIsTxTime);
+         READWRITE(nTimeReceived);
+         READWRITE(fFromMe);
+         READWRITE(fSpent);
+         if (ser_action.ForRead())
+         {
+             strFromAccount = mapValue["fromaccount"];
+             ReadOrderPos(nOrderPos, mapValue);
+             nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
+         }
+         mapValue.erase("fromaccount");
+         mapValue.erase("version");
+         mapValue.erase("spent");
+         mapValue.erase("n");
+         mapValue.erase("timesmart");
+     }
+     //! make sure balances are recalculated
+     void MarkDirty()
+     {
+         fCreditCached = false;
+         fAvailableCreditCached = false;
+         fWatchDebitCached = false;
+         fWatchCreditCached = false;
+         fAvailableWatchCreditCached = false;
+         fImmatureWatchCreditCached = false;
+         fDebitCached = false;
+         fChangeCached = false;
+     }
+     void BindWallet(CWallet *pwalletIn)
+     {
+         pwallet = pwalletIn;
+         MarkDirty();
+     }
+     //! filter decides which addresses will count towards the debit
+     CAmount GetDebit(const isminefilter& filter) const;
+     CAmount GetCredit(const isminefilter& filter) const;
+     CAmount GetImmatureCredit(bool fUseCache=true) const;
+     CAmount GetAvailableCredit(bool fUseCache=true) const;
+     CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const;
+     CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const;
+     CAmount GetChange() const;
+     void GetAmounts(std::list<COutputEntry>& listReceived,
+                     std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
+     void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
+                            CAmount& nSent, CAmount& nFee, const isminefilter& filter) const;
+     bool IsFromMe(const isminefilter& filter) const
+     {
+         return (GetDebit(filter) > 0);
+     }
+     bool IsTrusted() const;
+     bool WriteToDisk(CWalletDB *pwalletdb);
+     int64_t GetTxTime() const;
+     int GetRequestCount() const;
+     void RelayWalletTransaction();
+     std::set<uint256> GetConflicts() const;
+ };
+ class COutput
+ {
+ public:
+     const CWalletTx *tx;
+     int i;
+     int nDepth;
+     bool fSpendable;
+     COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
+     {
+         tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
+     }
+     std::string ToString() const;
+ };
+ /** Private key that includes an expiration date in case it never gets used. */
+ class CWalletKey
+ {
+ public:
+     CPrivKey vchPrivKey;
+     int64_t nTimeCreated;
+     int64_t nTimeExpires;
+     std::string strComment;
+     //! todo: add something to note what created it (user, getnewaddress, change)
+     //!   maybe should have a map<string, string> property map
+     CWalletKey(int64_t nExpires=0);
+     ADD_SERIALIZE_METHODS;
+     template <typename Stream, typename Operation>
+     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+         if (!(nType & SER_GETHASH))
+             READWRITE(nVersion);
+         READWRITE(vchPrivKey);
+         READWRITE(nTimeCreated);
+         READWRITE(nTimeExpires);
+         READWRITE(LIMITED_STRING(strComment, 65536));
+     }
+ };
+ /** 
+  * A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
+  * and provides the ability to create new transactions.
+  */
+ class CWallet : public CCryptoKeyStore, public CValidationInterface
+ {
+ private:
+     bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, const CCoinControl *coinControl = NULL) const;
+     CWalletDB *pwalletdbEncryption;
+     //! the current wallet version: clients below this version are not able to load the wallet
+     int nWalletVersion;
+     //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
+     int nWalletMaxVersion;
+     int64_t nNextResend;
+     int64_t nLastResend;
+     /**
+      * Used to keep track of spent outpoints, and
+      * detect and report conflicts (double-spends or
+      * mutated transactions where the mutant gets mined).
+      */
+     typedef std::multimap<COutPoint, uint256> TxSpends;
+     TxSpends mapTxSpends;
+     void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
+     void AddToSpends(const uint256& wtxid);
+     void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
+ public:
+     /*
+      * Main wallet lock.
+      * This lock protects all the fields added by CWallet
+      *   except for:
+      *      fFileBacked (immutable after instantiation)
+      *      strWalletFile (immutable after instantiation)
+      */
+     mutable CCriticalSection cs_wallet;
+     bool fFileBacked;
+     std::string strWalletFile;
+     std::set<int64_t> setKeyPool;
+     std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
+     typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
+     MasterKeyMap mapMasterKeys;
+     unsigned int nMasterKeyMaxID;
+     CWallet()
+     {
+         SetNull();
+     }
+     CWallet(std::string strWalletFileIn)
+     {
+         SetNull();
+         strWalletFile = strWalletFileIn;
+         fFileBacked = true;
+     }
+     ~CWallet()
+     {
+         delete pwalletdbEncryption;
+         pwalletdbEncryption = NULL;
+     }
+     void SetNull()
+     {
+         nWalletVersion = FEATURE_BASE;
+         nWalletMaxVersion = FEATURE_BASE;
+         fFileBacked = false;
+         nMasterKeyMaxID = 0;
+         pwalletdbEncryption = NULL;
+         nOrderPosNext = 0;
+         nNextResend = 0;
+         nLastResend = 0;
+         nTimeFirstKey = 0;
+     }
+     std::map<uint256, CWalletTx> mapWallet;
+     int64_t nOrderPosNext;
+     std::map<uint256, int> mapRequestCount;
+     std::map<CTxDestination, CAddressBookData> mapAddressBook;
+     CPubKey vchDefaultKey;
+     std::set<COutPoint> setLockedCoins;
+     int64_t nTimeFirstKey;
+     const CWalletTx* GetWalletTx(const uint256& hash) const;
+     //! check whether we are allowed to upgrade (or already support) to the named feature
+     bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
+     void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const;
+     bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
+     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 UnlockAllCoins();
+     void ListLockedCoins(std::vector<COutPoint>& vOutpts);
+     /**
+      * keystore implementation
+      * Generate a new key
+      */
+     CPubKey GenerateNewKey();
+     //! Adds a key to the store, and saves it to disk.
+     bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
+     //! Adds a key to the store, without saving it to disk (used by LoadWallet)
+     bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
+     //! Load metadata (used by LoadWallet)
+     bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
+     bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
+     //! Adds an encrypted key to the store, and saves it to disk.
+     bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+     //! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
+     bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+     bool AddCScript(const CScript& redeemScript);
+     bool LoadCScript(const CScript& redeemScript);
+     //! Adds a destination data tuple to the store, and saves it to disk
+     bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
+     //! Erases a destination data tuple in the store and on disk
+     bool EraseDestData(const CTxDestination &dest, const std::string &key);
+     //! Adds a destination data tuple to the store, without saving it to disk
+     bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
+     //! 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 CScript &dest);
+     bool RemoveWatchOnly(const CScript &dest);
+     //! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
+     bool LoadWatchOnly(const CScript &dest);
+     bool Unlock(const SecureString& strWalletPassphrase);
+     bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
+     bool EncryptWallet(const SecureString& strWalletPassphrase);
+     void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const;
+     /** 
+      * Increment the next transaction order id
+      * @return next transaction order id
+      */
+     int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);
+     typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
+     typedef std::multimap<int64_t, TxPair > TxItems;
+     /**
+      * Get the wallet's activity log
+      * @return multimap of ordered transactions and accounting entries
+      * @warning Returned pointers are *only* valid within the scope of passed acentries
+      */
+     TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
+     void MarkDirty();
+     bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
+     void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
+     bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
+     void EraseFromWallet(const uint256 &hash);
+     int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
+     void ReacceptWalletTransactions();
+     void ResendWalletTransactions();
+     CAmount GetBalance() const;
+     CAmount GetUnconfirmedBalance() const;
+     CAmount GetImmatureBalance() const;
+     CAmount GetWatchOnlyBalance() const;
+     CAmount GetUnconfirmedWatchOnlyBalance() const;
+     CAmount GetImmatureWatchOnlyBalance() const;
++    bool CreateTransaction(const std::vector<CRecipient>& vecSend,
++                           CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
+     bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
+     static CFeeRate minTxFee;
+     static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
+     bool NewKeyPool();
+     bool TopUpKeyPool(unsigned int kpSize = 0);
+     void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool);
+     void KeepKey(int64_t nIndex);
+     void ReturnKey(int64_t nIndex);
+     bool GetKeyFromPool(CPubKey &key);
+     int64_t GetOldestKeyPoolTime();
+     void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
+     std::set< std::set<CTxDestination> > GetAddressGroupings();
+     std::map<CTxDestination, CAmount> GetAddressBalances();
+     std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const;
+     isminetype IsMine(const CTxIn& txin) const;
+     CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
+     isminetype IsMine(const CTxOut& txout) const
+     {
+         return ::IsMine(*this, txout.scriptPubKey);
+     }
+     CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const
+     {
+         if (!MoneyRange(txout.nValue))
+             throw std::runtime_error("CWallet::GetCredit(): value out of range");
+         return ((IsMine(txout) & filter) ? txout.nValue : 0);
+     }
+     bool IsChange(const CTxOut& txout) const;
+     CAmount GetChange(const CTxOut& txout) const
+     {
+         if (!MoneyRange(txout.nValue))
+             throw std::runtime_error("CWallet::GetChange(): value out of range");
+         return (IsChange(txout) ? txout.nValue : 0);
+     }
+     bool IsMine(const CTransaction& tx) const
+     {
+         BOOST_FOREACH(const CTxOut& txout, tx.vout)
+             if (IsMine(txout))
+                 return true;
+         return false;
+     }
+     /** should probably be renamed to IsRelevantToMe */
+     bool IsFromMe(const CTransaction& tx) const
+     {
+         return (GetDebit(tx, ISMINE_ALL) > 0);
+     }
+     CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const
+     {
+         CAmount nDebit = 0;
+         BOOST_FOREACH(const CTxIn& txin, tx.vin)
+         {
+             nDebit += GetDebit(txin, filter);
+             if (!MoneyRange(nDebit))
+                 throw std::runtime_error("CWallet::GetDebit(): value out of range");
+         }
+         return nDebit;
+     }
+     CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const
+     {
+         CAmount nCredit = 0;
+         BOOST_FOREACH(const CTxOut& txout, tx.vout)
+         {
+             nCredit += GetCredit(txout, filter);
+             if (!MoneyRange(nCredit))
+                 throw std::runtime_error("CWallet::GetCredit(): value out of range");
+         }
+         return nCredit;
+     }
+     CAmount GetChange(const CTransaction& tx) const
+     {
+         CAmount nChange = 0;
+         BOOST_FOREACH(const CTxOut& txout, tx.vout)
+         {
+             nChange += GetChange(txout);
+             if (!MoneyRange(nChange))
+                 throw std::runtime_error("CWallet::GetChange(): value out of range");
+         }
+         return nChange;
+     }
+     void SetBestChain(const CBlockLocator& loc);
+     DBErrors LoadWallet(bool& fFirstRunRet);
+     DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
+     bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
+     bool DelAddressBook(const CTxDestination& address);
+     void UpdatedTransaction(const uint256 &hashTx);
+     void Inventory(const uint256 &hash)
+     {
+         {
+             LOCK(cs_wallet);
+             std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
+             if (mi != mapRequestCount.end())
+                 (*mi).second++;
+         }
+     }
+     unsigned int GetKeyPoolSize()
+     {
+         AssertLockHeld(cs_wallet); // setKeyPool
+         return setKeyPool.size();
+     }
+     bool SetDefaultKey(const CPubKey &vchPubKey);
+     //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
+     bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
+     //! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
+     bool SetMaxVersion(int nVersion);
+     //! get the current wallet format (the oldest client version guaranteed to understand this wallet)
+     int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
+     //! Get wallet transactions that conflict with given transaction (spend same outputs)
+     std::set<uint256> GetConflicts(const uint256& txid) const;
+     /** 
+      * Address book entry changed.
+      * @note called with lock cs_wallet held.
+      */
+     boost::signals2::signal<void (CWallet *wallet, const CTxDestination
+             &address, const std::string &label, bool isMine,
+             const std::string &purpose,
+             ChangeType status)> NotifyAddressBookChanged;
+     /** 
+      * Wallet transaction added, removed or updated.
+      * @note called with lock cs_wallet held.
+      */
+     boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
+             ChangeType status)> NotifyTransactionChanged;
+     /** Show progress e.g. for rescan */
+     boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
+     /** Watch-only address added */
+     boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
+ };
+ /** A key allocated from the key pool. */
+ class CReserveKey
+ {
+ protected:
+     CWallet* pwallet;
+     int64_t nIndex;
+     CPubKey vchPubKey;
+ public:
+     CReserveKey(CWallet* pwalletIn)
+     {
+         nIndex = -1;
+         pwallet = pwalletIn;
+     }
+     ~CReserveKey()
+     {
+         ReturnKey();
+     }
+     void ReturnKey();
+     bool GetReservedKey(CPubKey &pubkey);
+     void KeepKey();
+ };
+ /** 
+  * Account information.
+  * Stored in wallet with key "acc"+string account name.
+  */
+ class CAccount
+ {
+ public:
+     CPubKey vchPubKey;
+     CAccount()
+     {
+         SetNull();
+     }
+     void SetNull()
+     {
+         vchPubKey = CPubKey();
+     }
+     ADD_SERIALIZE_METHODS;
+     template <typename Stream, typename Operation>
+     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+         if (!(nType & SER_GETHASH))
+             READWRITE(nVersion);
+         READWRITE(vchPubKey);
+     }
+ };
+ /** 
+  * Internal transfers.
+  * Database key is acentry<account><counter>.
+  */
+ class CAccountingEntry
+ {
+ public:
+     std::string strAccount;
+     CAmount nCreditDebit;
+     int64_t nTime;
+     std::string strOtherAccount;
+     std::string strComment;
+     mapValue_t mapValue;
+     int64_t nOrderPos;  //! position in ordered transaction list
+     uint64_t nEntryNo;
+     CAccountingEntry()
+     {
+         SetNull();
+     }
+     void SetNull()
+     {
+         nCreditDebit = 0;
+         nTime = 0;
+         strAccount.clear();
+         strOtherAccount.clear();
+         strComment.clear();
+         nOrderPos = -1;
+         nEntryNo = 0;
+     }
+     ADD_SERIALIZE_METHODS;
+     template <typename Stream, typename Operation>
+     inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
+         if (!(nType & SER_GETHASH))
+             READWRITE(nVersion);
+         //! Note: strAccount is serialized as part of the key, not here.
+         READWRITE(nCreditDebit);
+         READWRITE(nTime);
+         READWRITE(LIMITED_STRING(strOtherAccount, 65536));
+         if (!ser_action.ForRead())
+         {
+             WriteOrderPos(nOrderPos, mapValue);
+             if (!(mapValue.empty() && _ssExtra.empty()))
+             {
+                 CDataStream ss(nType, nVersion);
+                 ss.insert(ss.begin(), '\0');
+                 ss << mapValue;
+                 ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
+                 strComment.append(ss.str());
+             }
+         }
+         READWRITE(LIMITED_STRING(strComment, 65536));
+         size_t nSepPos = strComment.find("\0", 0, 1);
+         if (ser_action.ForRead())
+         {
+             mapValue.clear();
+             if (std::string::npos != nSepPos)
+             {
+                 CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
+                 ss >> mapValue;
+                 _ssExtra = std::vector<char>(ss.begin(), ss.end());
+             }
+             ReadOrderPos(nOrderPos, mapValue);
+         }
+         if (std::string::npos != nSepPos)
+             strComment.erase(nSepPos);
+         mapValue.erase("n");
+     }
+ private:
+     std::vector<char> _ssExtra;
+ };
+ #endif // BITCOIN_WALLET_H
This page took 0.171475 seconds and 4 git commands to generate.