diff options
Diffstat (limited to 'src/wallet/rpcwallet.cpp')
-rw-r--r-- | src/wallet/rpcwallet.cpp | 102 |
1 files changed, 71 insertions, 31 deletions
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 077b352547..623037e766 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -82,15 +82,11 @@ void WalletTxToJSON(const CWalletTx& wtx, UniValue& entry) std::string rbfStatus = "no"; if (confirms <= 0) { LOCK(mempool.cs); - if (!mempool.exists(hash)) { - if (SignalsOptInRBF(wtx)) { - rbfStatus = "yes"; - } else { - rbfStatus = "unknown"; - } - } else if (IsRBFOptIn(*mempool.mapTx.find(hash), mempool)) { + RBFTransactionState rbfState = IsRBFOptIn(wtx, mempool); + if (rbfState == RBF_TRANSACTIONSTATE_UNKNOWN) + rbfStatus = "unknown"; + else if (rbfState == RBF_TRANSACTIONSTATE_REPLACEABLE_BIP125) rbfStatus = "yes"; - } } entry.push_back(Pair("bip125-replaceable", rbfStatus)); @@ -1346,6 +1342,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe entry.push_back(Pair("fee", ValueFromAmount(-nFee))); if (fLong) WalletTxToJSON(wtx, entry); + entry.push_back(Pair("abandoned", wtx.isAbandoned())); ret.push_back(entry); } } @@ -1438,6 +1435,7 @@ UniValue listtransactions(const UniValue& params, bool fHelp) " \"vout\": n, (numeric) the vout value\n" " \"fee\": x.xxx, (numeric) The amount of the fee in " + CURRENCY_UNIT + ". This is negative and only available for the \n" " 'send' category of transactions.\n" + " \"abandoned\": xxx (bool) 'true' if the transaction has been abandoned (inputs are respendable).\n" " \"confirmations\": n, (numeric) The number of confirmations for the transaction. Available for 'send' and \n" " 'receive' category of transactions. Negative confirmations indicate the\n" " transaction conflicts with the block chain\n" @@ -2098,16 +2096,17 @@ UniValue lockunspent(const UniValue& params, bool fHelp) if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "lockunspent unlock [{\"txid\":\"txid\",\"vout\":n},...]\n" + "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" + "If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\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" + "2. \"transactions\" (string, optional) 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" @@ -2441,19 +2440,26 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( - "fundrawtransaction \"hexstring\" includeWatching\n" + "fundrawtransaction \"hexstring\" ( options )\n" "\nAdd inputs to a transaction until it has enough in value to meet its out value.\n" "This will not modify existing inputs, and will add one change output to the outputs.\n" "Note that inputs which were signed may need to be resigned after completion since in/outputs have been added.\n" "The inputs added will not be signed, use signrawtransaction for that.\n" "Note that all existing inputs must have their previous output transaction be in the wallet.\n" - "Note that all inputs selected must be of standard form and P2SH scripts must be" + "Note that all inputs selected must be of standard form and P2SH scripts must be\n" "in the wallet using importaddress or addmultisigaddress (to calculate fees).\n" "You can see whether this is the case by checking the \"solvable\" field in the listunspent output.\n" "Only pay-to-pubkey, multisig, and P2SH versions thereof are currently supported for watch-only\n" "\nArguments:\n" - "1. \"hexstring\" (string, required) The hex string of the raw transaction\n" - "2. includeWatching (boolean, optional, default false) Also select inputs which are watch only\n" + "1. \"hexstring\" (string, required) The hex string of the raw transaction\n" + "2. options (object, optional)\n" + " {\n" + " \"changeAddress\" (string, optional, default pool address) The bitcoin address to receive the change\n" + " \"changePosition\" (numeric, optional, default random) The index of the change output\n" + " \"includeWatching\" (boolean, optional, default false) Also select inputs which are watch only\n" + " \"lockUnspents\" (boolean, optional, default false) Lock selected unspent outputs\n" + " }\n" + " for backward compatibility: passing in a true instead of an object will result in {\"includeWatching\":true}\n" "\nResult:\n" "{\n" " \"hex\": \"value\", (string) The resulting raw transaction (hex-encoded string)\n" @@ -2472,7 +2478,44 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) + HelpExampleCli("sendrawtransaction", "\"signedtransactionhex\"") ); - RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)); + RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)); + + CTxDestination changeAddress = CNoDestination(); + int changePosition = -1; + bool includeWatching = false; + bool lockUnspents = false; + + if (params.size() > 1) { + if (params[1].type() == UniValue::VBOOL) { + // backward compatibility bool only fallback + includeWatching = params[1].get_bool(); + } + else { + RPCTypeCheck(params, boost::assign::list_of(UniValue::VSTR)(UniValue::VOBJ)); + + UniValue options = params[1]; + + RPCTypeCheckObj(options, boost::assign::map_list_of("changeAddress", UniValue::VSTR)("changePosition", UniValue::VNUM)("includeWatching", UniValue::VBOOL)("lockUnspents", UniValue::VBOOL), true, true); + + if (options.exists("changeAddress")) { + CBitcoinAddress address(options["changeAddress"].get_str()); + + if (!address.IsValid()) + throw JSONRPCError(RPC_INVALID_PARAMETER, "changeAddress must be a valid bitcoin address"); + + changeAddress = address.Get(); + } + + if (options.exists("changePosition")) + changePosition = options["changePosition"].get_int(); + + if (options.exists("includeWatching")) + includeWatching = options["includeWatching"].get_bool(); + + if (options.exists("lockUnspents")) + lockUnspents = options["lockUnspents"].get_bool(); + } + } // parse hex string from parameter CTransaction origTx; @@ -2482,20 +2525,19 @@ UniValue fundrawtransaction(const UniValue& params, bool fHelp) if (origTx.vout.size() == 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output"); - bool includeWatching = false; - if (params.size() > 1) - includeWatching = params[1].get_bool(); + if (changePosition != -1 && (changePosition < 0 || changePosition > origTx.vout.size())) + throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds"); CMutableTransaction tx(origTx); CAmount nFee; string strFailReason; - int nChangePos = -1; - if(!pwalletMain->FundTransaction(tx, nFee, nChangePos, strFailReason, includeWatching)) + + if(!pwalletMain->FundTransaction(tx, nFee, changePosition, strFailReason, includeWatching, lockUnspents, changeAddress)) throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason); UniValue result(UniValue::VOBJ); result.push_back(Pair("hex", EncodeHexTx(tx))); - result.push_back(Pair("changepos", nChangePos)); + result.push_back(Pair("changepos", changePosition)); result.push_back(Pair("fee", ValueFromAmount(nFee))); return result; @@ -2507,8 +2549,10 @@ extern UniValue importaddress(const UniValue& params, bool fHelp); extern UniValue importpubkey(const UniValue& params, bool fHelp); extern UniValue dumpwallet(const UniValue& params, bool fHelp); extern UniValue importwallet(const UniValue& params, bool fHelp); +extern UniValue importprunedfunds(const UniValue& params, bool fHelp); +extern UniValue removeprunedfunds(const UniValue& params, bool fHelp); -const CRPCCommand vWalletRPCCommands[] = +static const CRPCCommand commands[] = { // category name actor (function) okSafeMode // --------------------- ------------------------ ----------------------- ---------- { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false }, @@ -2533,6 +2577,7 @@ const CRPCCommand vWalletRPCCommands[] = { "wallet", "importprivkey", &importprivkey, true }, { "wallet", "importwallet", &importwallet, true }, { "wallet", "importaddress", &importaddress, true }, + { "wallet", "importprunedfunds", &importprunedfunds, true }, { "wallet", "importpubkey", &importpubkey, true }, { "wallet", "keypoolrefill", &keypoolrefill, true }, { "wallet", "listaccounts", &listaccounts, false }, @@ -2554,16 +2599,11 @@ const CRPCCommand vWalletRPCCommands[] = { "wallet", "walletlock", &walletlock, true }, { "wallet", "walletpassphrasechange", &walletpassphrasechange, true }, { "wallet", "walletpassphrase", &walletpassphrase, true }, + { "wallet", "removeprunedfunds", &removeprunedfunds, true }, }; -void walletRegisterRPCCommands() +void RegisterWalletRPCCommands(CRPCTable &tableRPC) { - unsigned int vcidx; - for (vcidx = 0; vcidx < ARRAYLEN(vWalletRPCCommands); vcidx++) - { - const CRPCCommand *pcmd; - - pcmd = &vWalletRPCCommands[vcidx]; - tableRPC.appendCommand(pcmd->name, pcmd); - } + for (unsigned int vcidx = 0; vcidx < ARRAYLEN(commands); vcidx++) + tableRPC.appendCommand(commands[vcidx].name, &commands[vcidx]); } |