diff --git a/src/Makefile.am b/src/Makefile.am index 62dd63abe..5ce1c8e1b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,6 +53,7 @@ libbitcoin_server_a_SOURCES = \ noui.cpp \ rpcblockchain.cpp \ rpcmining.cpp \ + rpcmisc.cpp \ rpcnet.cpp \ rpcrawtransaction.cpp \ txdb.cpp \ diff --git a/src/init.cpp b/src/init.cpp index 22ee0cfc0..a0b9f89f2 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -535,6 +535,7 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer) return InitError(strprintf(_("Invalid amount for -minrelaytxfee=: '%s'"), mapArgs["-minrelaytxfee"].c_str())); } +#ifdef ENABLE_WALLET if (mapArgs.count("-paytxfee")) { if (!ParseMoney(mapArgs["-paytxfee"], nTransactionFee)) @@ -543,7 +544,6 @@ bool AppInit2(boost::thread_group& threadGroup, bool fForceServer) InitWarning(_("Warning: -paytxfee is set very high! This is the transaction fee you will pay if you send a transaction.")); } -#ifdef ENABLE_WALLET strWalletFile = GetArg("-wallet", "wallet.dat"); #endif // ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log diff --git a/src/main.cpp b/src/main.cpp index d130e9705..e3f9fdd84 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -67,9 +67,6 @@ CScript COINBASE_FLAGS; const string strMessageMagic = "Bitcoin Signed Message:\n"; -// Settings -int64_t nTransactionFee = 0; - // Internal stuff namespace { struct CBlockIndexWorkComparator diff --git a/src/main.h b/src/main.h index fd5e352cb..f3f9acb63 100644 --- a/src/main.h +++ b/src/main.h @@ -96,9 +96,6 @@ extern bool fTxIndex; extern unsigned int nCoinCacheSize; extern bool fHaveGUI; -// Settings -extern int64_t nTransactionFee; - // Minimum disk space required - used in CheckDiskSpace() static const uint64_t nMinDiskSpace = 52428800; diff --git a/src/qt/bitcoin.cpp b/src/qt/bitcoin.cpp index b74452d4c..2f04a71ec 100644 --- a/src/qt/bitcoin.cpp +++ b/src/qt/bitcoin.cpp @@ -17,6 +17,7 @@ #include "main.h" #include "ui_interface.h" #include "util.h" +#include "wallet.h" #include diff --git a/src/qt/optionsmodel.cpp b/src/qt/optionsmodel.cpp index 15a873d2b..363f432d6 100644 --- a/src/qt/optionsmodel.cpp +++ b/src/qt/optionsmodel.cpp @@ -14,6 +14,7 @@ #include "init.h" #include "main.h" #include "net.h" +#include "wallet.h" #include "walletdb.h" #include diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 34ae6e054..661deffb1 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -127,30 +127,6 @@ Value getdifficulty(const Array& params, bool fHelp) } -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. 'amount' is a real and is rounded to the nearest 0.00000001\n" - "\nArguments:\n" - "1. amount (numeric, required) The transaction fee in btc 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") - ); - - // Amount - int64_t nAmount = 0; - if (params[0].get_real() != 0.0) - nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts - - nTransactionFee = nAmount; - return true; -} - Value getrawmempool(const Array& params, bool fHelp) { if (fHelp || params.size() > 1) diff --git a/src/rpcmisc.cpp b/src/rpcmisc.cpp new file mode 100644 index 000000000..c61cc4192 --- /dev/null +++ b/src/rpcmisc.cpp @@ -0,0 +1,326 @@ +// Copyright (c) 2010 Satoshi Nakamoto +// Copyright (c) 2009-2013 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "base58.h" +#include "rpcserver.h" +#include "init.h" +#include "main.h" +#include "net.h" +#include "netbase.h" +#include "util.h" +#ifdef ENABLE_WALLET +#include "wallet.h" +#include "walletdb.h" +#endif + +#include + +#include +#include "json/json_spirit_utils.h" +#include "json/json_spirit_value.h" + +using namespace std; +using namespace boost; +using namespace boost::assign; +using namespace json_spirit; + +Value getinfo(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "getinfo\n" + "Returns an object containing various state info.\n" + "\nResult:\n" + "{\n" + " \"version\": xxxxx, (numeric) the server version\n" + " \"protocolversion\": xxxxx, (numeric) the protocol version\n" + " \"walletversion\": xxxxx, (numeric) the wallet version\n" + " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n" + " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" + " \"timeoffset\": xxxxx, (numeric) the time offset\n" + " \"connections\": xxxxx, (numeric) the number of connections\n" + " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n" + " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" + " \"testnet\": true|false, (boolean) if the server is using testnet or not\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" + " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc\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" + " \"errors\": \"...\" (string) any error messages\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getinfo", "") + + HelpExampleRpc("getinfo", "") + ); + + proxyType proxy; + GetProxy(NET_IPV4, proxy); + + Object obj; + obj.push_back(Pair("version", (int)CLIENT_VERSION)); + obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); +#ifdef ENABLE_WALLET + if (pwalletMain) { + obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); + obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); + } +#endif + obj.push_back(Pair("blocks", (int)chainActive.Height())); + obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset())); + obj.push_back(Pair("connections", (int)vNodes.size())); + obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); + obj.push_back(Pair("difficulty", (double)GetDifficulty())); + obj.push_back(Pair("testnet", TestNet())); +#ifdef ENABLE_WALLET + if (pwalletMain) { + obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); + } + obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); + if (pwalletMain && pwalletMain->IsCrypted()) + obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); +#endif + obj.push_back(Pair("errors", GetWarnings("statusbar"))); + return obj; +} + +#ifdef ENABLE_WALLET +class DescribeAddressVisitor : public boost::static_visitor +{ +public: + Object operator()(const CNoDestination &dest) const { return Object(); } + + Object operator()(const CKeyID &keyID) const { + Object obj; + CPubKey vchPubKey; + pwalletMain->GetPubKey(keyID, vchPubKey); + obj.push_back(Pair("isscript", false)); + obj.push_back(Pair("pubkey", HexStr(vchPubKey))); + obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); + return obj; + } + + Object operator()(const CScriptID &scriptID) const { + Object obj; + obj.push_back(Pair("isscript", true)); + CScript subscript; + pwalletMain->GetCScript(scriptID, subscript); + std::vector addresses; + txnouttype whichType; + int nRequired; + ExtractDestinations(subscript, whichType, addresses, nRequired); + obj.push_back(Pair("script", GetTxnOutputType(whichType))); + obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); + Array a; + BOOST_FOREACH(const CTxDestination& addr, addresses) + a.push_back(CBitcoinAddress(addr).ToString()); + obj.push_back(Pair("addresses", a)); + if (whichType == TX_MULTISIG) + obj.push_back(Pair("sigsrequired", nRequired)); + return obj; + } +}; +#endif + +Value validateaddress(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "validateaddress \"bitcoinaddress\"\n" + "\nReturn information about the given bitcoin address.\n" + "\nArguments:\n" + "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n" + "\nResult:\n" + "{\n" + " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" + " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n" + " \"ismine\" : true|false, (boolean) If the address is yours or not\n" + " \"isscript\" : true|false, (boolean) If the key is a script\n" + " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" + " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" + " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + ); + + CBitcoinAddress address(params[0].get_str()); + bool isValid = address.IsValid(); + + Object ret; + ret.push_back(Pair("isvalid", isValid)); + if (isValid) + { + CTxDestination dest = address.Get(); + string currentAddress = address.ToString(); + ret.push_back(Pair("address", currentAddress)); +#ifdef ENABLE_WALLET + bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false; + ret.push_back(Pair("ismine", fMine)); + if (fMine) { + Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest); + ret.insert(ret.end(), detail.begin(), detail.end()); + } + if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) + ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name)); +#endif + } + return ret; +} + +// +// Used by addmultisigaddress / createmultisig: +// +CScript _createmultisig(const Array& params) +{ + int nRequired = params[0].get_int(); + const Array& keys = params[1].get_array(); + + // Gather public keys + if (nRequired < 1) + throw runtime_error("a multisignature address must require at least one key to redeem"); + if ((int)keys.size() < nRequired) + throw runtime_error( + strprintf("not enough keys supplied " + "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired)); + std::vector pubkeys; + pubkeys.resize(keys.size()); + for (unsigned int i = 0; i < keys.size(); i++) + { + const std::string& ks = keys[i].get_str(); +#ifdef ENABLE_WALLET + // Case 1: Bitcoin address and we have full public key: + CBitcoinAddress address(ks); + if (pwalletMain && address.IsValid()) + { + CKeyID keyID; + if (!address.GetKeyID(keyID)) + throw runtime_error( + strprintf("%s does not refer to a key",ks.c_str())); + CPubKey vchPubKey; + if (!pwalletMain->GetPubKey(keyID, vchPubKey)) + throw runtime_error( + strprintf("no full public key for address %s",ks.c_str())); + if (!vchPubKey.IsFullyValid()) + throw runtime_error(" Invalid public key: "+ks); + pubkeys[i] = vchPubKey; + } + + // Case 2: hex public key + else +#endif + if (IsHex(ks)) + { + CPubKey vchPubKey(ParseHex(ks)); + if (!vchPubKey.IsFullyValid()) + throw runtime_error(" Invalid public key: "+ks); + pubkeys[i] = vchPubKey; + } + else + { + throw runtime_error(" Invalid public key: "+ks); + } + } + CScript result; + result.SetMultisig(nRequired, pubkeys); + return result; +} + +Value createmultisig(const Array& params, bool fHelp) +{ + if (fHelp || params.size() < 2 || params.size() > 2) + { + string msg = "createmultisig nrequired [\"key\",...]\n" + "\nCreates a multi-signature address with n signature of m keys required.\n" + "It returns a json object with the address and redeemScript.\n" + + "\nArguments:\n" + "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" + "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n" + " [\n" + " \"key\" (string) bitcoin address or hex-encoded public key\n" + " ,...\n" + " ]\n" + + "\nResult:\n" + "{\n" + " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n" + " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n" + "}\n" + + "\nExamples:\n" + "\nCreate a multisig address from 2 addresses\n" + + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + + "\nAs a json rpc call\n" + + HelpExampleRpc("icreatemultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + ; + throw runtime_error(msg); + } + + // Construct using pay-to-script-hash: + CScript inner = _createmultisig(params); + CScriptID innerID = inner.GetID(); + CBitcoinAddress address(innerID); + + Object result; + result.push_back(Pair("address", address.ToString())); + result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end()))); + + return result; +} + +Value verifymessage(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n" + "\nVerify a signed message\n" + "\nArguments:\n" + "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n" + "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n" + "3. \"message\" (string, required) The message that was signed.\n" + "\nResult:\n" + "true|false (boolean) If the signature is verified or not.\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("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"") + ); + + string strAddress = params[0].get_str(); + string strSign = params[1].get_str(); + string strMessage = params[2].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"); + + bool fInvalid = false; + vector vchSig = DecodeBase64(strSign.c_str(), &fInvalid); + + if (fInvalid) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); + + CHashWriter ss(SER_GETHASH, 0); + ss << strMessageMagic; + ss << strMessage; + + CPubKey pubkey; + if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) + return false; + + return (pubkey.GetID() == keyID); +} + diff --git a/src/rpcnet.cpp b/src/rpcnet.cpp index fd72fe638..06ae7070c 100644 --- a/src/rpcnet.cpp +++ b/src/rpcnet.cpp @@ -338,65 +338,3 @@ Value getnettotals(const Array& params, bool fHelp) obj.push_back(Pair("timemillis", static_cast(GetTimeMillis()))); return obj; } - -Value getinfo(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 0) - throw runtime_error( - "getinfo\n" - "Returns an object containing various state info.\n" - "\nResult:\n" - "{\n" - " \"version\": xxxxx, (numeric) the server version\n" - " \"protocolversion\": xxxxx, (numeric) the protocol version\n" - " \"walletversion\": xxxxx, (numeric) the wallet version\n" - " \"balance\": xxxxxxx, (numeric) the total bitcoin balance of the wallet\n" - " \"blocks\": xxxxxx, (numeric) the current number of blocks processed in the server\n" - " \"timeoffset\": xxxxx, (numeric) the time offset\n" - " \"connections\": xxxxx, (numeric) the number of connections\n" - " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n" - " \"difficulty\": xxxxxx, (numeric) the current difficulty\n" - " \"testnet\": true|false, (boolean) if the server is using testnet or not\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" - " \"paytxfee\": x.xxxx, (numeric) the transaction fee set in btc\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" - " \"errors\": \"...\" (string) any error messages\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("getinfo", "") - + HelpExampleRpc("getinfo", "") - ); - - proxyType proxy; - GetProxy(NET_IPV4, proxy); - - Object obj; - obj.push_back(Pair("version", (int)CLIENT_VERSION)); - obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); -#ifdef ENABLE_WALLET - if (pwalletMain) { - obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); - obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance()))); - } -#endif - obj.push_back(Pair("blocks", (int)chainActive.Height())); - obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset())); - obj.push_back(Pair("connections", (int)vNodes.size())); - obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); - obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("testnet", TestNet())); -#ifdef ENABLE_WALLET - if (pwalletMain) { - obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); - obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); - } -#endif - obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); -#ifdef ENABLE_WALLET - if (pwalletMain && pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime)); -#endif - obj.push_back(Pair("errors", GetWarnings("statusbar"))); - return obj; -} diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp index c95f450c8..d1fa81628 100644 --- a/src/rpcserver.cpp +++ b/src/rpcserver.cpp @@ -237,7 +237,6 @@ static const CRPCCommand vRPCCommands[] = { "getrawmempool", &getrawmempool, true, false, false }, { "getblock", &getblock, false, false, false }, { "getblockhash", &getblockhash, false, false, false }, - { "settxfee", &settxfee, false, false, true }, { "getrawtransaction", &getrawtransaction, false, false, false }, { "createrawtransaction", &createrawtransaction, false, false, false }, { "decoderawtransaction", &decoderawtransaction, false, false, false }, @@ -253,6 +252,9 @@ static const CRPCCommand vRPCCommands[] = { "getmininginfo", &getmininginfo, true, false, false }, { "getblocktemplate", &getblocktemplate, true, false, false }, { "submitblock", &submitblock, false, false, false }, + { "validateaddress", &validateaddress, true, false, false }, + { "createmultisig", &createmultisig, true, true , false }, + { "verifymessage", &verifymessage, false, false, false }, #ifdef ENABLE_WALLET /* Wallet */ @@ -273,18 +275,15 @@ static const CRPCCommand vRPCCommands[] = { "walletpassphrasechange", &walletpassphrasechange, false, false, true }, { "walletlock", &walletlock, true, false, true }, { "encryptwallet", &encryptwallet, false, false, true }, - { "validateaddress", &validateaddress, true, false, false }, { "getbalance", &getbalance, false, false, true }, { "move", &movecmd, false, false, true }, { "sendfrom", &sendfrom, false, false, true }, { "sendmany", &sendmany, false, false, true }, { "addmultisigaddress", &addmultisigaddress, false, false, true }, - { "createmultisig", &createmultisig, true, true , false }, { "gettransaction", &gettransaction, false, false, true }, { "listtransactions", &listtransactions, false, false, true }, { "listaddressgroupings", &listaddressgroupings, false, false, true }, { "signmessage", &signmessage, false, false, true }, - { "verifymessage", &verifymessage, false, false, false }, { "listaccounts", &listaccounts, false, false, true }, { "listsinceblock", &listsinceblock, false, false, true }, { "dumpprivkey", &dumpprivkey, true, false, true }, @@ -294,6 +293,7 @@ static const CRPCCommand vRPCCommands[] = { "listunspent", &listunspent, false, false, true }, { "lockunspent", &lockunspent, false, false, true }, { "listlockunspent", &listlockunspent, false, false, true }, + { "settxfee", &settxfee, false, false, true }, /* Wallet-enabled mining */ { "getgenerate", &getgenerate, true, false, false }, diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 82fa9d88c..32db0b46a 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -441,59 +441,6 @@ Value signmessage(const Array& params, bool fHelp) return EncodeBase64(&vchSig[0], vchSig.size()); } -Value verifymessage(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 3) - throw runtime_error( - "verifymessage \"bitcoinaddress\" \"signature\" \"message\"\n" - "\nVerify a signed message\n" - "\nArguments:\n" - "1. \"bitcoinaddress\" (string, required) The bitcoin address to use for the signature.\n" - "2. \"signature\" (string, required) The signature provided by the signer in base 64 encoding (see signmessage).\n" - "3. \"message\" (string, required) The message that was signed.\n" - "\nResult:\n" - "true|false (boolean) If the signature is verified or not.\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("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XZ\", \"signature\", \"my message\"") - ); - - string strAddress = params[0].get_str(); - string strSign = params[1].get_str(); - string strMessage = params[2].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"); - - bool fInvalid = false; - vector vchSig = DecodeBase64(strSign.c_str(), &fInvalid); - - if (fInvalid) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding"); - - CHashWriter ss(SER_GETHASH, 0); - ss << strMessageMagic; - ss << strMessage; - - CPubKey pubkey; - if (!pubkey.RecoverCompact(ss.GetHash(), vchSig)) - return false; - - return (pubkey.GetID() == keyID); -} - - Value getreceivedbyaddress(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) @@ -907,61 +854,8 @@ Value sendmany(const Array& params, bool fHelp) return wtx.GetHash().GetHex(); } -// -// Used by addmultisigaddress / createmultisig: -// -static CScript _createmultisig(const Array& params) -{ - int nRequired = params[0].get_int(); - const Array& keys = params[1].get_array(); - - // Gather public keys - if (nRequired < 1) - throw runtime_error("a multisignature address must require at least one key to redeem"); - if ((int)keys.size() < nRequired) - throw runtime_error( - strprintf("not enough keys supplied " - "(got %"PRIszu" keys, but need at least %d to redeem)", keys.size(), nRequired)); - std::vector pubkeys; - pubkeys.resize(keys.size()); - for (unsigned int i = 0; i < keys.size(); i++) - { - const std::string& ks = keys[i].get_str(); - - // Case 1: Bitcoin address and we have full public key: - CBitcoinAddress address(ks); - if (pwalletMain && address.IsValid()) - { - CKeyID keyID; - if (!address.GetKeyID(keyID)) - throw runtime_error( - strprintf("%s does not refer to a key",ks.c_str())); - CPubKey vchPubKey; - if (!pwalletMain->GetPubKey(keyID, vchPubKey)) - throw runtime_error( - strprintf("no full public key for address %s",ks.c_str())); - if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); - pubkeys[i] = vchPubKey; - } - - // Case 2: hex public key - else if (IsHex(ks)) - { - CPubKey vchPubKey(ParseHex(ks)); - if (!vchPubKey.IsFullyValid()) - throw runtime_error(" Invalid public key: "+ks); - pubkeys[i] = vchPubKey; - } - else - { - throw runtime_error(" Invalid public key: "+ks); - } - } - CScript result; - result.SetMultisig(nRequired, pubkeys); - return result; -} +// Defined in rpcmisc.cpp +extern CScript _createmultisig(const Array& params); Value addmultisigaddress(const Array& params, bool fHelp) { @@ -1006,49 +900,6 @@ Value addmultisigaddress(const Array& params, bool fHelp) return CBitcoinAddress(innerID).ToString(); } -Value createmultisig(const Array& params, bool fHelp) -{ - if (fHelp || params.size() < 2 || params.size() > 2) - { - string msg = "createmultisig nrequired [\"key\",...]\n" - "\nCreates a multi-signature address with n signature of m keys required.\n" - "It returns a json object with the address and redeemScript.\n" - - "\nArguments:\n" - "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" - "2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n" - " [\n" - " \"key\" (string) bitcoin address or hex-encoded public key\n" - " ,...\n" - " ]\n" - - "\nResult:\n" - "{\n" - " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n" - " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n" - "}\n" - - "\nExamples:\n" - "\nCreate a multisig address from 2 addresses\n" - + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + - "\nAs a json rpc call\n" - + HelpExampleRpc("icreatemultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") - ; - throw runtime_error(msg); - } - - // Construct using pay-to-script-hash: - CScript inner = _createmultisig(params); - CScriptID innerID = inner.GetID(); - CBitcoinAddress address(innerID); - - Object result; - result.push_back(Pair("address", address.ToString())); - result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end()))); - - return result; -} - struct tallyitem { @@ -1862,87 +1713,6 @@ Value encryptwallet(const Array& params, bool fHelp) return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; } -class DescribeAddressVisitor : public boost::static_visitor -{ -public: - Object operator()(const CNoDestination &dest) const { return Object(); } - - Object operator()(const CKeyID &keyID) const { - Object obj; - CPubKey vchPubKey; - pwalletMain->GetPubKey(keyID, vchPubKey); - obj.push_back(Pair("isscript", false)); - obj.push_back(Pair("pubkey", HexStr(vchPubKey))); - obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed())); - return obj; - } - - Object operator()(const CScriptID &scriptID) const { - Object obj; - obj.push_back(Pair("isscript", true)); - CScript subscript; - pwalletMain->GetCScript(scriptID, subscript); - std::vector addresses; - txnouttype whichType; - int nRequired; - ExtractDestinations(subscript, whichType, addresses, nRequired); - obj.push_back(Pair("script", GetTxnOutputType(whichType))); - obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); - Array a; - BOOST_FOREACH(const CTxDestination& addr, addresses) - a.push_back(CBitcoinAddress(addr).ToString()); - obj.push_back(Pair("addresses", a)); - if (whichType == TX_MULTISIG) - obj.push_back(Pair("sigsrequired", nRequired)); - return obj; - } -}; - -Value validateaddress(const Array& params, bool fHelp) -{ - if (fHelp || params.size() != 1) - throw runtime_error( - "validateaddress \"bitcoinaddress\"\n" - "\nReturn information about the given bitcoin address.\n" - "\nArguments:\n" - "1. \"bitcoinaddress\" (string, required) The bitcoin address to validate\n" - "\nResult:\n" - "{\n" - " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" - " \"address\" : \"bitcoinaddress\", (string) The bitcoin address validated\n" - " \"ismine\" : true|false, (boolean) If the address is yours or not\n" - " \"isscript\" : true|false, (boolean) If the key is a script\n" - " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" - " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" - " \"account\" : \"account\" (string) The account associated with the address, \"\" is the default account\n" - "}\n" - "\nExamples:\n" - + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") - + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") - ); - - CBitcoinAddress address(params[0].get_str()); - bool isValid = address.IsValid(); - - Object ret; - ret.push_back(Pair("isvalid", isValid)); - if (isValid) - { - CTxDestination dest = address.Get(); - string currentAddress = address.ToString(); - ret.push_back(Pair("address", currentAddress)); - bool fMine = pwalletMain ? IsMine(*pwalletMain, dest) : false; - ret.push_back(Pair("ismine", fMine)); - if (fMine) { - Object detail = boost::apply_visitor(DescribeAddressVisitor(), dest); - ret.insert(ret.end(), detail.begin(), detail.end()); - } - if (pwalletMain && pwalletMain->mapAddressBook.count(dest)) - ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name)); - } - return ret; -} - Value lockunspent(const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) @@ -2066,3 +1836,28 @@ Value listlockunspent(const Array& params, bool fHelp) 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. 'amount' is a real and is rounded to the nearest 0.00000001\n" + "\nArguments:\n" + "1. amount (numeric, required) The transaction fee in btc 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") + ); + + // Amount + int64_t nAmount = 0; + if (params[0].get_real() != 0.0) + nAmount = AmountFromValue(params[0]); // rejects 0.0 amounts + + nTransactionFee = nAmount; + return true; +} + + diff --git a/src/wallet.cpp b/src/wallet.cpp index 3c3d890e2..76a83082a 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -16,6 +16,8 @@ using namespace std; +// Settings +int64_t nTransactionFee = 0; ////////////////////////////////////////////////////////////////////////////// // diff --git a/src/wallet.h b/src/wallet.h index 8e879c5e1..99f6293b1 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -23,6 +23,9 @@ #include #include +// Settings +extern int64_t nTransactionFee; + class CAccountingEntry; class CCoinControl; class COutput;