From 34aca1b03c85d8c88b2ac83d7c0aa4e83467dde9 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 7 Jan 2016 08:33:49 +0100 Subject: [PATCH] [RPC, Wallet] Move RPC dispatch table registration to wallet/ code Allow extending the rpc dispatch table by appending commands when server is not running. --- src/Makefile.am | 1 + src/init.cpp | 2 + src/rpcserver.cpp | 92 ++++++------------------------------ src/rpcserver.h | 61 ++++-------------------- src/test/test_bitcoin.cpp | 1 + src/wallet/rpcwallet.cpp | 99 +++++++++++++++++++++++++++++++++++++++ src/wallet/rpcwallet.h | 10 ++++ src/wallet/wallet.h | 1 + src/zcbenchmarks.cpp | 3 ++ 9 files changed, 141 insertions(+), 129 deletions(-) create mode 100644 src/wallet/rpcwallet.h diff --git a/src/Makefile.am b/src/Makefile.am index 2057fba26..cc206dab9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -215,6 +215,7 @@ BITCOIN_CORE_H = \ wallet/asyncrpcoperation_shieldcoinbase.h \ wallet/crypter.h \ wallet/db.h \ + wallet/rpcwallet.h \ wallet/wallet.h \ wallet/wallet_ismine.h \ wallet/walletdb.h \ diff --git a/src/init.cpp b/src/init.cpp index 33405a31f..7f38fb872 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -999,6 +999,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) #ifdef ENABLE_WALLET bool fDisableWallet = GetBoolArg("-disablewallet", false); + if (!fDisableWallet) + walletRegisterRPCCommands(); #endif nConnectTimeout = GetArg("-timeout", DEFAULT_CONNECT_TIMEOUT); diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index d15fc7a27..50794527f 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -318,9 +318,6 @@ static const CRPCCommand vRPCCommands[] = { "rawtransactions", "getrawtransaction", &getrawtransaction, true }, { "rawtransactions", "sendrawtransaction", &sendrawtransaction, false }, { "rawtransactions", "signrawtransaction", &signrawtransaction, false }, /* uses wallet if enabled */ -#ifdef ENABLE_WALLET - { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false }, -#endif /* Utility functions */ { "util", "createmultisig", &createmultisig, true }, @@ -334,79 +331,6 @@ static const CRPCCommand vRPCCommands[] = { "hidden", "invalidateblock", &invalidateblock, true }, { "hidden", "reconsiderblock", &reconsiderblock, true }, { "hidden", "setmocktime", &setmocktime, true }, -#ifdef ENABLE_WALLET - { "hidden", "resendwallettransactions", &resendwallettransactions, true}, -#endif - -#ifdef ENABLE_WALLET - /* Wallet */ - { "wallet", "addmultisigaddress", &addmultisigaddress, true }, - { "wallet", "backupwallet", &backupwallet, true }, - { "wallet", "dumpprivkey", &dumpprivkey, true }, - { "wallet", "dumpwallet", &dumpwallet, true }, - { "wallet", "encryptwallet", &encryptwallet, true }, - { "wallet", "getaccountaddress", &getaccountaddress, true }, - { "wallet", "getaccount", &getaccount, true }, - { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true }, - { "wallet", "getbalance", &getbalance, false }, - { "wallet", "getnewaddress", &getnewaddress, true }, - { "wallet", "getrawchangeaddress", &getrawchangeaddress, true }, - { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false }, - { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false }, - { "wallet", "gettransaction", &gettransaction, false }, - { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false }, - { "wallet", "getwalletinfo", &getwalletinfo, false }, - { "wallet", "importprivkey", &importprivkey, true }, - { "wallet", "importwallet", &importwallet, true }, - { "wallet", "importaddress", &importaddress, true }, - { "wallet", "keypoolrefill", &keypoolrefill, true }, - { "wallet", "listaccounts", &listaccounts, false }, - { "wallet", "listaddressgroupings", &listaddressgroupings, false }, - { "wallet", "listlockunspent", &listlockunspent, false }, - { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false }, - { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false }, - { "wallet", "listsinceblock", &listsinceblock, false }, - { "wallet", "listtransactions", &listtransactions, false }, - { "wallet", "listunspent", &listunspent, false }, - { "wallet", "lockunspent", &lockunspent, true }, - { "wallet", "move", &movecmd, false }, - { "wallet", "sendfrom", &sendfrom, false }, - { "wallet", "sendmany", &sendmany, false }, - { "wallet", "sendtoaddress", &sendtoaddress, false }, - { "wallet", "setaccount", &setaccount, true }, - { "wallet", "settxfee", &settxfee, true }, - { "wallet", "signmessage", &signmessage, true }, - { "wallet", "walletlock", &walletlock, true }, - { "wallet", "walletpassphrasechange", &walletpassphrasechange, true }, - { "wallet", "walletpassphrase", &walletpassphrase, true }, - { "wallet", "zcbenchmark", &zc_benchmark, true }, - { "wallet", "zcrawkeygen", &zc_raw_keygen, true }, - { "wallet", "zcrawjoinsplit", &zc_raw_joinsplit, true }, - { "wallet", "zcrawreceive", &zc_raw_receive, true }, - { "wallet", "zcsamplejoinsplit", &zc_sample_joinsplit, true }, - { "wallet", "z_listreceivedbyaddress",&z_listreceivedbyaddress,false }, - { "wallet", "z_listunspent", &z_listunspent, false }, - { "wallet", "z_getbalance", &z_getbalance, false }, - { "wallet", "z_gettotalbalance", &z_gettotalbalance, false }, - { "wallet", "z_mergetoaddress", &z_mergetoaddress, false }, - { "wallet", "z_sendmany", &z_sendmany, false }, - { "wallet", "z_shieldcoinbase", &z_shieldcoinbase, false }, - { "wallet", "z_getoperationstatus", &z_getoperationstatus, true }, - { "wallet", "z_getoperationresult", &z_getoperationresult, true }, - { "wallet", "z_listoperationids", &z_listoperationids, true }, - { "wallet", "z_getnewaddress", &z_getnewaddress, true }, - { "wallet", "z_listaddresses", &z_listaddresses, true }, - { "wallet", "z_exportkey", &z_exportkey, true }, - { "wallet", "z_importkey", &z_importkey, true }, - { "wallet", "z_exportviewingkey", &z_exportviewingkey, true }, - { "wallet", "z_importviewingkey", &z_importviewingkey, true }, - { "wallet", "z_exportwallet", &z_exportwallet, true }, - { "wallet", "z_importwallet", &z_importwallet, true }, - - // TODO: rearrange into another category - { "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true }, - { "disclosure", "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true } -#endif // ENABLE_WALLET }; CRPCTable::CRPCTable() @@ -429,6 +353,20 @@ const CRPCCommand *CRPCTable::operator[](const std::string &name) const return (*it).second; } +bool CRPCTable::appendCommand(const std::string& name, const CRPCCommand* pcmd) +{ + if (IsRPCRunning()) + return false; + + // don't allow overwriting for now + map::const_iterator it = mapCommands.find(name); + if (it != mapCommands.end()) + return false; + + mapCommands[name] = pcmd; + return true; +} + bool StartRPC() { LogPrint("rpc", "Starting RPC\n"); @@ -631,7 +569,7 @@ void RPCRunLater(const std::string& name, boost::function func, int6 deadlineTimers.insert(std::make_pair(name, boost::shared_ptr(timerInterface->NewTimer(func, nSeconds*1000)))); } -const CRPCTable tableRPC; +CRPCTable tableRPC; // Return async rpc queue std::shared_ptr getAsyncRPCQueue() diff --git a/src/rpcserver.h b/src/rpcserver.h index e10ca039f..dcf1399bb 100644 --- a/src/rpcserver.h +++ b/src/rpcserver.h @@ -148,9 +148,17 @@ public: * @throws an exception (UniValue) when an error happens. */ UniValue execute(const std::string &method, const UniValue ¶ms) const; + + + /** + * Appends a CRPCCommand to the dispatch table. + * Returns false if RPC server is already running (dump concurrency protection). + * Commands cannot be overwritten (returns false). + */ + bool appendCommand(const std::string& name, const CRPCCommand* pcmd); }; -extern const CRPCTable tableRPC; +extern CRPCTable tableRPC; /** * Utilities: convert hex-encoded Values @@ -183,12 +191,6 @@ extern UniValue setban(const UniValue& params, bool fHelp); extern UniValue listbanned(const UniValue& params, bool fHelp); extern UniValue clearbanned(const UniValue& params, bool fHelp); -extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp -extern UniValue importprivkey(const UniValue& params, bool fHelp); -extern UniValue importaddress(const UniValue& params, bool fHelp); -extern UniValue dumpwallet(const UniValue& params, bool fHelp); -extern UniValue importwallet(const UniValue& params, bool fHelp); - extern UniValue getgenerate(const UniValue& params, bool fHelp); // in rpcmining.cpp extern UniValue setgenerate(const UniValue& params, bool fHelp); extern UniValue generate(const UniValue& params, bool fHelp); @@ -202,50 +204,14 @@ extern UniValue submitblock(const UniValue& params, bool fHelp); extern UniValue estimatefee(const UniValue& params, bool fHelp); extern UniValue estimatepriority(const UniValue& params, bool fHelp); -extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp -extern UniValue getaccountaddress(const UniValue& params, bool fHelp); -extern UniValue getrawchangeaddress(const UniValue& params, bool fHelp); -extern UniValue setaccount(const UniValue& params, bool fHelp); -extern UniValue getaccount(const UniValue& params, bool fHelp); -extern UniValue getaddressesbyaccount(const UniValue& params, bool fHelp); -extern UniValue sendtoaddress(const UniValue& params, bool fHelp); -extern UniValue signmessage(const UniValue& params, bool fHelp); extern UniValue verifymessage(const UniValue& params, bool fHelp); -extern UniValue getreceivedbyaddress(const UniValue& params, bool fHelp); -extern UniValue getreceivedbyaccount(const UniValue& params, bool fHelp); -extern UniValue getbalance(const UniValue& params, bool fHelp); -extern UniValue getunconfirmedbalance(const UniValue& params, bool fHelp); -extern UniValue movecmd(const UniValue& params, bool fHelp); -extern UniValue sendfrom(const UniValue& params, bool fHelp); -extern UniValue sendmany(const UniValue& params, bool fHelp); -extern UniValue addmultisigaddress(const UniValue& params, bool fHelp); extern UniValue createmultisig(const UniValue& params, bool fHelp); -extern UniValue listreceivedbyaddress(const UniValue& params, bool fHelp); -extern UniValue listreceivedbyaccount(const UniValue& params, bool fHelp); -extern UniValue listtransactions(const UniValue& params, bool fHelp); -extern UniValue listaddressgroupings(const UniValue& params, bool fHelp); -extern UniValue listaccounts(const UniValue& params, bool fHelp); -extern UniValue listsinceblock(const UniValue& params, bool fHelp); -extern UniValue gettransaction(const UniValue& params, bool fHelp); -extern UniValue backupwallet(const UniValue& params, bool fHelp); -extern UniValue keypoolrefill(const UniValue& params, bool fHelp); -extern UniValue walletpassphrase(const UniValue& params, bool fHelp); -extern UniValue walletpassphrasechange(const UniValue& params, bool fHelp); -extern UniValue walletlock(const UniValue& params, bool fHelp); -extern UniValue encryptwallet(const UniValue& params, bool fHelp); extern UniValue validateaddress(const UniValue& params, bool fHelp); extern UniValue getinfo(const UniValue& params, bool fHelp); -extern UniValue getwalletinfo(const UniValue& params, bool fHelp); extern UniValue getblockchaininfo(const UniValue& params, bool fHelp); extern UniValue getnetworkinfo(const UniValue& params, bool fHelp); extern UniValue getdeprecationinfo(const UniValue& params, bool fHelp); extern UniValue setmocktime(const UniValue& params, bool fHelp); -extern UniValue resendwallettransactions(const UniValue& params, bool fHelp); -extern UniValue zc_benchmark(const UniValue& params, bool fHelp); -extern UniValue zc_raw_keygen(const UniValue& params, bool fHelp); -extern UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp); -extern UniValue zc_raw_receive(const UniValue& params, bool fHelp); -extern UniValue zc_sample_joinsplit(const UniValue& params, bool fHelp); extern UniValue getrawtransaction(const UniValue& params, bool fHelp); // in rcprawtransaction.cpp extern UniValue listunspent(const UniValue& params, bool fHelp); @@ -254,7 +220,6 @@ extern UniValue listlockunspent(const UniValue& params, bool fHelp); extern UniValue createrawtransaction(const UniValue& params, bool fHelp); extern UniValue decoderawtransaction(const UniValue& params, bool fHelp); extern UniValue decodescript(const UniValue& params, bool fHelp); -extern UniValue fundrawtransaction(const UniValue& params, bool fHelp); extern UniValue signrawtransaction(const UniValue& params, bool fHelp); extern UniValue sendrawtransaction(const UniValue& params, bool fHelp); extern UniValue gettxoutproof(const UniValue& params, bool fHelp); @@ -278,14 +243,8 @@ extern UniValue reconsiderblock(const UniValue& params, bool fHelp); extern UniValue getblocksubsidy(const UniValue& params, bool fHelp); -extern UniValue z_exportkey(const UniValue& params, bool fHelp); // in rpcdump.cpp -extern UniValue z_importkey(const UniValue& params, bool fHelp); // in rpcdump.cpp -extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp); // in rpcdump.cpp -extern UniValue z_importviewingkey(const UniValue& params, bool fHelp); // in rpcdump.cpp extern UniValue z_getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp extern UniValue z_listaddresses(const UniValue& params, bool fHelp); // in rpcwallet.cpp -extern UniValue z_exportwallet(const UniValue& params, bool fHelp); // in rpcdump.cpp -extern UniValue z_importwallet(const UniValue& params, bool fHelp); // in rpcdump.cpp extern UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp extern UniValue z_listunspent(const UniValue& params, bool fHelp); // in rpcwallet.cpp extern UniValue z_getbalance(const UniValue& params, bool fHelp); // in rpcwallet.cpp @@ -297,8 +256,6 @@ extern UniValue z_getoperationstatus(const UniValue& params, bool fHelp); // in extern UniValue z_getoperationresult(const UniValue& params, bool fHelp); // in rpcwallet.cpp extern UniValue z_listoperationids(const UniValue& params, bool fHelp); // in rpcwallet.cpp extern UniValue z_validateaddress(const UniValue& params, bool fHelp); // in rpcmisc.cpp -extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp -extern UniValue z_validatepaymentdisclosure(const UniValue ¶ms, bool fHelp); // in rpcdisclosure.cpp bool StartRPC(); void InterruptRPC(); diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index d862c2c7f..bca7a4d6e 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -77,6 +77,7 @@ TestingSetup::TestingSetup() { #ifdef ENABLE_WALLET bitdb.MakeMock(); + walletRegisterRPCCommands(); #endif ClearDatadirCache(); pathTemp = GetTempPath() / strprintf("test_bitcoin_%lu_%i", (unsigned long)GetTime(), (int)(GetRand(100000))); diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 038c4f25e..0e89a866f 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4347,3 +4347,102 @@ UniValue z_listoperationids(const UniValue& params, bool fHelp) return ret; } + +extern UniValue dumpprivkey(const UniValue& params, bool fHelp); // in rpcdump.cpp +extern UniValue importprivkey(const UniValue& params, bool fHelp); +extern UniValue importaddress(const UniValue& params, bool fHelp); +extern UniValue dumpwallet(const UniValue& params, bool fHelp); +extern UniValue importwallet(const UniValue& params, bool fHelp); +extern UniValue z_exportkey(const UniValue& params, bool fHelp); +extern UniValue z_importkey(const UniValue& params, bool fHelp); +extern UniValue z_exportviewingkey(const UniValue& params, bool fHelp); +extern UniValue z_importviewingkey(const UniValue& params, bool fHelp); +extern UniValue z_exportwallet(const UniValue& params, bool fHelp); +extern UniValue z_importwallet(const UniValue& params, bool fHelp); + +extern UniValue z_getpaymentdisclosure(const UniValue& params, bool fHelp); // in rpcdisclosure.cpp +extern UniValue z_validatepaymentdisclosure(const UniValue ¶ms, bool fHelp); + +const CRPCCommand vWalletRPCCommands[] = +{ // category name actor (function) okSafeMode + // --------------------- ------------------------ ----------------------- ---------- + { "rawtransactions", "fundrawtransaction", &fundrawtransaction, false }, + { "hidden", "resendwallettransactions", &resendwallettransactions, true }, + { "wallet", "addmultisigaddress", &addmultisigaddress, true }, + { "wallet", "backupwallet", &backupwallet, true }, + { "wallet", "dumpprivkey", &dumpprivkey, true }, + { "wallet", "dumpwallet", &dumpwallet, true }, + { "wallet", "encryptwallet", &encryptwallet, true }, + { "wallet", "getaccountaddress", &getaccountaddress, true }, + { "wallet", "getaccount", &getaccount, true }, + { "wallet", "getaddressesbyaccount", &getaddressesbyaccount, true }, + { "wallet", "getbalance", &getbalance, false }, + { "wallet", "getnewaddress", &getnewaddress, true }, + { "wallet", "getrawchangeaddress", &getrawchangeaddress, true }, + { "wallet", "getreceivedbyaccount", &getreceivedbyaccount, false }, + { "wallet", "getreceivedbyaddress", &getreceivedbyaddress, false }, + { "wallet", "gettransaction", &gettransaction, false }, + { "wallet", "getunconfirmedbalance", &getunconfirmedbalance, false }, + { "wallet", "getwalletinfo", &getwalletinfo, false }, + { "wallet", "importprivkey", &importprivkey, true }, + { "wallet", "importwallet", &importwallet, true }, + { "wallet", "importaddress", &importaddress, true }, + { "wallet", "keypoolrefill", &keypoolrefill, true }, + { "wallet", "listaccounts", &listaccounts, false }, + { "wallet", "listaddressgroupings", &listaddressgroupings, false }, + { "wallet", "listlockunspent", &listlockunspent, false }, + { "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false }, + { "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false }, + { "wallet", "listsinceblock", &listsinceblock, false }, + { "wallet", "listtransactions", &listtransactions, false }, + { "wallet", "listunspent", &listunspent, false }, + { "wallet", "lockunspent", &lockunspent, true }, + { "wallet", "move", &movecmd, false }, + { "wallet", "sendfrom", &sendfrom, false }, + { "wallet", "sendmany", &sendmany, false }, + { "wallet", "sendtoaddress", &sendtoaddress, false }, + { "wallet", "setaccount", &setaccount, true }, + { "wallet", "settxfee", &settxfee, true }, + { "wallet", "signmessage", &signmessage, true }, + { "wallet", "walletlock", &walletlock, true }, + { "wallet", "walletpassphrasechange", &walletpassphrasechange, true }, + { "wallet", "walletpassphrase", &walletpassphrase, true }, + { "wallet", "zcbenchmark", &zc_benchmark, true }, + { "wallet", "zcrawkeygen", &zc_raw_keygen, true }, + { "wallet", "zcrawjoinsplit", &zc_raw_joinsplit, true }, + { "wallet", "zcrawreceive", &zc_raw_receive, true }, + { "wallet", "zcsamplejoinsplit", &zc_sample_joinsplit, true }, + { "wallet", "z_listreceivedbyaddress", &z_listreceivedbyaddress, false }, + { "wallet", "z_listunspent", &z_listunspent, false }, + { "wallet", "z_getbalance", &z_getbalance, false }, + { "wallet", "z_gettotalbalance", &z_gettotalbalance, false }, + { "wallet", "z_mergetoaddress", &z_mergetoaddress, false }, + { "wallet", "z_sendmany", &z_sendmany, false }, + { "wallet", "z_shieldcoinbase", &z_shieldcoinbase, false }, + { "wallet", "z_getoperationstatus", &z_getoperationstatus, true }, + { "wallet", "z_getoperationresult", &z_getoperationresult, true }, + { "wallet", "z_listoperationids", &z_listoperationids, true }, + { "wallet", "z_getnewaddress", &z_getnewaddress, true }, + { "wallet", "z_listaddresses", &z_listaddresses, true }, + { "wallet", "z_exportkey", &z_exportkey, true }, + { "wallet", "z_importkey", &z_importkey, true }, + { "wallet", "z_exportviewingkey", &z_exportviewingkey, true }, + { "wallet", "z_importviewingkey", &z_importviewingkey, true }, + { "wallet", "z_exportwallet", &z_exportwallet, true }, + { "wallet", "z_importwallet", &z_importwallet, true }, + // TODO: rearrange into another category + { "disclosure", "z_getpaymentdisclosure", &z_getpaymentdisclosure, true }, + { "disclosure", "z_validatepaymentdisclosure", &z_validatepaymentdisclosure, true } +}; + +void walletRegisterRPCCommands() +{ + unsigned int vcidx; + for (vcidx = 0; vcidx < ARRAYLEN(vWalletRPCCommands); vcidx++) + { + const CRPCCommand *pcmd; + + pcmd = &vWalletRPCCommands[vcidx]; + tableRPC.appendCommand(pcmd->name, pcmd); + } +} diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h new file mode 100644 index 000000000..42e8021af --- /dev/null +++ b/src/wallet/rpcwallet.h @@ -0,0 +1,10 @@ +// Copyright (c) 2016 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_WALLET_RPCWALLET_H +#define BITCOIN_WALLET_RPCWALLET_H + +void walletRegisterRPCCommands(); + +#endif //BITCOIN_WALLET_RPCWALLET_H diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index a473cbd17..4aee8d01f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -21,6 +21,7 @@ #include "wallet/crypter.h" #include "wallet/wallet_ismine.h" #include "wallet/walletdb.h" +#include "wallet/rpcwallet.h" #include "zcash/Address.hpp" #include "base58.h" diff --git a/src/zcbenchmarks.cpp b/src/zcbenchmarks.cpp index 2547a7b06..4f2585466 100644 --- a/src/zcbenchmarks.cpp +++ b/src/zcbenchmarks.cpp @@ -431,6 +431,9 @@ double benchmark_connectblock_slow() return duration; } +extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp +extern UniValue sendtoaddress(const UniValue& params, bool fHelp); + double benchmark_sendtoaddress(CAmount amount) { UniValue params(UniValue::VARR);