diff --git a/init.cpp b/init.cpp index 04bdd68..ec843d8 100644 --- a/init.cpp +++ b/init.cpp @@ -185,6 +185,7 @@ bool AppInit2(int argc, char* argv[]) " -rpcport= \t\t " + _("Listen for JSON-RPC connections on (default: 8332)\n") + " -rpcallowip= \t\t " + _("Allow JSON-RPC connections from specified IP address\n") + " -rpcconnect= \t " + _("Send commands to node running on (default: 127.0.0.1)\n") + + " -rpcversion= \t " + _("Send commands in RPC version , default 0 (for now)\n") + " -keypool= \t " + _("Set key pool size to (default: 100)\n") + " -rescan \t " + _("Rescan the block chain for missing wallet transactions\n"); diff --git a/json/json_spirit_value.h b/json/json_spirit_value.h index 7e83a2a..89be790 100644 --- a/json/json_spirit_value.h +++ b/json/json_spirit_value.h @@ -59,6 +59,8 @@ namespace json_spirit bool is_uint64() const; bool is_null() const; + bool is_amount() const; + void set_amount(bool); const String_type& get_str() const; const Object& get_obj() const; @@ -88,6 +90,7 @@ namespace json_spirit Value_type type_; Variant v_; bool is_uint64_; + bool is_amount_; }; // vector objects @@ -211,6 +214,7 @@ namespace json_spirit template< class Config > Value_impl< Config >::Value_impl() : type_( null_type ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -219,6 +223,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( const Const_str_ptr value ) : type_( str_type ) , v_( String_type( value ) ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -227,6 +232,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( const String_type& value ) : type_( str_type ) , v_( value ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -235,6 +241,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( const Object& value ) : type_( obj_type ) , v_( value ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -243,6 +250,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( const Array& value ) : type_( array_type ) , v_( value ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -251,6 +259,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( bool value ) : type_( bool_type ) , v_( value ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -259,6 +268,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( int value ) : type_( int_type ) , v_( static_cast< boost::int64_t >( value ) ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -267,6 +277,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( boost::int64_t value ) : type_( int_type ) , v_( value ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -275,6 +286,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( boost::uint64_t value ) : type_( int_type ) , v_( static_cast< boost::int64_t >( value ) ) + , is_amount_( false ) , is_uint64_( true ) { } @@ -283,6 +295,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( double value ) : type_( real_type ) , v_( value ) + , is_amount_( false ) , is_uint64_( false ) { } @@ -291,6 +304,7 @@ namespace json_spirit Value_impl< Config >::Value_impl( const Value_impl< Config >& other ) : type_( other.type() ) , v_( other.v_ ) + , is_amount_( other.is_amount_ ) , is_uint64_( other.is_uint64_ ) { } @@ -303,6 +317,7 @@ namespace json_spirit std::swap( type_, tmp.type_ ); std::swap( v_, tmp.v_ ); std::swap( is_uint64_, tmp.is_uint64_ ); + std::swap( is_amount_, tmp.is_amount_ ); return *this; } @@ -330,6 +345,18 @@ namespace json_spirit } template< class Config > + bool Value_impl< Config >::is_amount() const + { + return is_amount_; + } + + template< class Config > + void Value_impl< Config >::set_amount(bool nv) + { + is_amount_ = nv; + } + + template< class Config > bool Value_impl< Config >::is_null() const { return type() == null_type; @@ -392,6 +419,11 @@ namespace json_spirit template< class Config > boost::int64_t Value_impl< Config >::get_int64() const { + if( type() == real_type ) + { + return static_cast< boost::int64_t >( get_real() ); + } + check_type( int_type ); return boost::get< boost::int64_t >( v_ ); diff --git a/json/json_spirit_writer_template.h b/json/json_spirit_writer_template.h index 28c49dd..98910a6 100644 --- a/json/json_spirit_writer_template.h +++ b/json/json_spirit_writer_template.h @@ -161,6 +161,8 @@ namespace json_spirit { os_ << value.get_int64(); } + if (value.is_amount()) + os_ << ".0"; } void output( const String_type& s ) diff --git a/main.cpp b/main.cpp index a47f3a9..cbbe795 100644 --- a/main.cpp +++ b/main.cpp @@ -3750,16 +3750,16 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< int64 n = pcoin->GetCredit(); if (n <= 0) continue; - if (n < nTargetValue) - { - vValue.push_back(make_pair(n, pcoin)); - nTotalLower += n; - } - else if (n == nTargetValue) + if (n == nTargetValue) { setCoinsRet.insert(pcoin); return true; } + else if (n < nTargetValue + CENT) + { + vValue.push_back(make_pair(n, pcoin)); + nTotalLower += n; + } else if (n < nLowestLarger) { nLowestLarger = n; @@ -3768,7 +3768,14 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< } } - if (nTotalLower < nTargetValue) + if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT) + { + for (int i = 0; i < vValue.size(); ++i) + setCoinsRet.insert(vValue[i].second); + return true; + } + + if (nTotalLower < nTargetValue + (pcoinLowestLarger ? CENT : 0)) { if (pcoinLowestLarger == NULL) return false; @@ -3776,6 +3783,9 @@ bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set< return true; } + if (nTotalLower >= nTargetValue + CENT) + nTargetValue += CENT; + // Solve subset sum by stochastic approximation sort(vValue.rbegin(), vValue.rend()); vector vfIncluded; diff --git a/rpc.cpp b/rpc.cpp index 69b09bc..21a098e 100644 --- a/rpc.cpp +++ b/rpc.cpp @@ -2,6 +2,8 @@ // Distributed under the MIT/X11 software license, see the accompanying // file license.txt or http://www.opensource.org/licenses/mit-license.php. +#include + #include "headers.h" #include "cryptopp/sha.h" #undef printf @@ -12,6 +14,7 @@ #include typedef boost::asio::ssl::stream SSLStream; #endif +#include #include "json/json_spirit_reader_template.h" #include "json/json_spirit_writer_template.h" #include "json/json_spirit_utils.h" @@ -25,7 +28,7 @@ using namespace boost::asio; using namespace json_spirit; void ThreadRPCServer2(void* parg); -typedef Value(*rpcfn_type)(const Array& params, bool fHelp); +typedef Value(*rpcfn_type)(int, const Array& params, bool fHelp); extern map mapCallTable; @@ -60,20 +63,41 @@ void PrintConsole(const char* format, ...) } -int64 AmountFromValue(const Value& value) +int64 AmountFromValue(int ver, const Value& value) { + int64 nAmount; + if (!ver) { double dAmount = value.get_real(); if (dAmount <= 0.0 || dAmount > 21000000.0) throw JSONRPCError(-3, "Invalid amount"); - int64 nAmount = roundint64(dAmount * 100.00) * CENT; + nAmount = roundint64(dAmount * 100.00) * CENT; + } + else + nAmount = value.get_int64(); if (!MoneyRange(nAmount)) throw JSONRPCError(-3, "Invalid amount"); return nAmount; } +Value ValueFromAmount(int ver, int64 amount) +{ + if (!ver) + return (double)amount / (double)COIN; + Value rv((boost::int64_t)amount); + rv.set_amount(true); + return rv; +} + +__deprecated__ +int64 AmountFromValue(const Value& value) +{ + return AmountFromValue(0, value); +} + +__deprecated__ Value ValueFromAmount(int64 amount) { - return (double)amount / (double)COIN; + return ValueFromAmount(0, amount); } void WalletTxToJSON(const CWalletTx& wtx, Object& entry) @@ -100,7 +124,7 @@ string AccountFromValue(const Value& value) /// -Value help(const Array& params, bool fHelp) +Value help(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( @@ -128,7 +152,7 @@ Value help(const Array& params, bool fHelp) Array params; rpcfn_type pfn = (*mi).second; if (setDone.insert(pfn).second) - (*pfn)(params, true); + (*pfn)(ver, params, true); } catch (std::exception& e) { @@ -147,7 +171,7 @@ Value help(const Array& params, bool fHelp) } -Value stop(const Array& params, bool fHelp) +Value stop(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -160,7 +184,7 @@ Value stop(const Array& params, bool fHelp) } -Value getblockcount(const Array& params, bool fHelp) +Value getblockcount(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -171,7 +195,7 @@ Value getblockcount(const Array& params, bool fHelp) } -Value getblocknumber(const Array& params, bool fHelp) +Value getblocknumber(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -182,7 +206,7 @@ Value getblocknumber(const Array& params, bool fHelp) } -Value getconnectioncount(const Array& params, bool fHelp) +Value getconnectioncount(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -205,7 +229,7 @@ double GetDifficulty() return dMinimum / dCurrently; } -Value getdifficulty(const Array& params, bool fHelp) +Value getdifficulty(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -216,7 +240,7 @@ Value getdifficulty(const Array& params, bool fHelp) } -Value getgenerate(const Array& params, bool fHelp) +Value getgenerate(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -227,7 +251,7 @@ Value getgenerate(const Array& params, bool fHelp) } -Value setgenerate(const Array& params, bool fHelp) +Value setgenerate(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( @@ -255,7 +279,7 @@ Value setgenerate(const Array& params, bool fHelp) } -Value gethashespersec(const Array& params, bool fHelp) +Value gethashespersec(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -268,7 +292,7 @@ Value gethashespersec(const Array& params, bool fHelp) } -Value getinfo(const Array& params, bool fHelp) +Value getinfo(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 0) throw runtime_error( @@ -277,23 +301,24 @@ Value getinfo(const Array& params, bool fHelp) Object obj; obj.push_back(Pair("version", (int)VERSION)); - obj.push_back(Pair("balance", (double)GetBalance() / (double)COIN)); + obj.push_back(Pair("rpcversion", (int)ver)); + obj.push_back(Pair("balance", ValueFromAmount(ver, GetBalance()))); + obj.push_back(Pair("paytxfee", ValueFromAmount(ver, nTransactionFee))); obj.push_back(Pair("blocks", (int)nBestHeight)); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (fUseProxy ? addrProxy.ToStringIPPort() : string()))); obj.push_back(Pair("generate", (bool)fGenerateBitcoins)); obj.push_back(Pair("genproclimit", (int)(fLimitProcessors ? nLimitProcessors : -1))); obj.push_back(Pair("difficulty", (double)GetDifficulty())); - obj.push_back(Pair("hashespersec", gethashespersec(params, false))); + obj.push_back(Pair("hashespersec", gethashespersec(ver, params, false))); obj.push_back(Pair("testnet", fTestNet)); obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime())); - obj.push_back(Pair("paytxfee", (double)nTransactionFee / (double)COIN)); obj.push_back(Pair("errors", GetWarnings("statusbar"))); return obj; } -Value getnewaddress(const Array& params, bool fHelp) +Value getnewaddress(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( @@ -358,7 +383,7 @@ string GetAccountAddress(string strAccount, bool bForceNew=false) return strAddress; } -Value getaccountaddress(const Array& params, bool fHelp) +Value getaccountaddress(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( @@ -373,7 +398,7 @@ Value getaccountaddress(const Array& params, bool fHelp) -Value setaccount(const Array& params, bool fHelp) +Value setaccount(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( @@ -401,7 +426,7 @@ Value setaccount(const Array& params, bool fHelp) } -Value getaccount(const Array& params, bool fHelp) +Value getaccount(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( @@ -421,7 +446,7 @@ Value getaccount(const Array& params, bool fHelp) } -Value getaddressesbyaccount(const Array& params, bool fHelp) +Value getaddressesbyaccount(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( @@ -450,7 +475,7 @@ Value getaddressesbyaccount(const Array& params, bool fHelp) return ret; } -Value sendtoaddress(const Array& params, bool fHelp) +Value sendtoaddress(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( @@ -460,7 +485,7 @@ Value sendtoaddress(const Array& params, bool fHelp) string strAddress = params[0].get_str(); // Amount - int64 nAmount = AmountFromValue(params[1]); + int64 nAmount = AmountFromValue(ver, params[1]); // Wallet comments CWalletTx wtx; @@ -476,7 +501,7 @@ Value sendtoaddress(const Array& params, bool fHelp) } -Value getreceivedbyaddress(const Array& params, bool fHelp) +Value getreceivedbyaddress(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( @@ -513,7 +538,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) } } - return (double)nAmount / (double)COIN; + return ValueFromAmount(ver, nAmount); } @@ -538,7 +563,7 @@ void GetAccountPubKeys(string strAccount, set& setPubKey) } -Value getreceivedbyaccount(const Array& params, bool fHelp) +Value getreceivedbyaccount(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 1 || params.size() > 2) throw runtime_error( @@ -572,7 +597,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp) } } - return (double)nAmount / (double)COIN; + return ValueFromAmount(ver, nAmount); } @@ -610,7 +635,7 @@ int64 GetAccountBalance(const string& strAccount, int nMinDepth) } -Value getbalance(const Array& params, bool fHelp) +Value getbalance(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 0 || params.size() > 2) throw runtime_error( @@ -618,8 +643,9 @@ Value getbalance(const Array& params, bool fHelp) "If [account] is not specified, returns the server's total available balance.\n" "If [account] is specified, returns the balance in the account."); - if (params.size() == 0) - return ((double)GetBalance() / (double)COIN); + if (params.size() == 0) { + return ValueFromAmount(ver, GetBalance()); + } if (params[0].get_str() == "*") { // Calculate total balance a different way from GetBalance() @@ -648,7 +674,7 @@ Value getbalance(const Array& params, bool fHelp) nBalance += allGenerated; } printf("Found %d accounts\n", vAccounts.size()); - return (double)nBalance / (double)COIN; + return ValueFromAmount(ver, nBalance); } string strAccount = AccountFromValue(params[0]); @@ -658,11 +684,11 @@ Value getbalance(const Array& params, bool fHelp) int64 nBalance = GetAccountBalance(strAccount, nMinDepth); - return (double)nBalance / (double)COIN; + return ValueFromAmount(ver, nBalance); } -Value movecmd(const Array& params, bool fHelp) +Value movecmd(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 3 || params.size() > 5) throw runtime_error( @@ -671,7 +697,7 @@ Value movecmd(const Array& params, bool fHelp) string strFrom = AccountFromValue(params[0]); string strTo = AccountFromValue(params[1]); - int64 nAmount = AmountFromValue(params[2]); + int64 nAmount = AmountFromValue(ver, params[2]); int nMinDepth = 1; if (params.size() > 3) nMinDepth = params[3].get_int(); @@ -725,7 +751,7 @@ Value movecmd(const Array& params, bool fHelp) } -Value sendfrom(const Array& params, bool fHelp) +Value sendfrom(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() < 3 || params.size() > 6) throw runtime_error( @@ -734,7 +760,7 @@ Value sendfrom(const Array& params, bool fHelp) string strAccount = AccountFromValue(params[0]); string strAddress = params[1].get_str(); - int64 nAmount = AmountFromValue(params[2]); + int64 nAmount = AmountFromValue(ver, params[2]); int nMinDepth = 1; if (params.size() > 3) nMinDepth = params[3].get_int(); @@ -775,7 +801,7 @@ struct tallyitem } }; -Value ListReceived(const Array& params, bool fByAccounts) +Value ListReceived(int ver, const Array& params, bool fByAccounts) { // Minimum confirmations int nMinDepth = 1; @@ -851,7 +877,7 @@ Value ListReceived(const Array& params, bool fByAccounts) obj.push_back(Pair("address", strAddress)); obj.push_back(Pair("account", strAccount)); obj.push_back(Pair("label", strAccount)); // deprecated - obj.push_back(Pair("amount", (double)nAmount / (double)COIN)); + obj.push_back(Pair("amount", ValueFromAmount(ver, nAmount))); obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); ret.push_back(obj); } @@ -867,7 +893,7 @@ Value ListReceived(const Array& params, bool fByAccounts) Object obj; obj.push_back(Pair("account", (*it).first)); obj.push_back(Pair("label", (*it).first)); // deprecated - obj.push_back(Pair("amount", (double)nAmount / (double)COIN)); + obj.push_back(Pair("amount", ValueFromAmount(ver, nAmount))); obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf))); ret.push_back(obj); } @@ -876,7 +902,7 @@ Value ListReceived(const Array& params, bool fByAccounts) return ret; } -Value listreceivedbyaddress(const Array& params, bool fHelp) +Value listreceivedbyaddress(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( @@ -889,10 +915,10 @@ Value listreceivedbyaddress(const Array& params, bool fHelp) " \"amount\" : total amount received by the address\n" " \"confirmations\" : number of confirmations of the most recent transaction included"); - return ListReceived(params, false); + return ListReceived(ver, params, false); } -Value listreceivedbyaccount(const Array& params, bool fHelp) +Value listreceivedbyaccount(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( @@ -904,10 +930,10 @@ Value listreceivedbyaccount(const Array& params, bool fHelp) " \"amount\" : total amount received by addresses with this account\n" " \"confirmations\" : number of confirmations of the most recent transaction included"); - return ListReceived(params, true); + return ListReceived(ver, params, true); } -void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret) +void ListTransactions(int ver, const CWalletTx& wtx, const string& strAccount, int nMinDepth, bool fLong, Array& ret) { int64 nGenerated, nFee; string strSentAccount; @@ -923,7 +949,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe Object entry; entry.push_back(Pair("account", string(""))); entry.push_back(Pair("category", "generate")); - entry.push_back(Pair("amount", ValueFromAmount(nGenerated))); + entry.push_back(Pair("amount", ValueFromAmount(ver, nGenerated))); if (fLong) WalletTxToJSON(wtx, entry); ret.push_back(entry); @@ -938,8 +964,8 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe entry.push_back(Pair("account", strSentAccount)); entry.push_back(Pair("address", s.first)); entry.push_back(Pair("category", "send")); - entry.push_back(Pair("amount", ValueFromAmount(-s.second))); - entry.push_back(Pair("fee", ValueFromAmount(-nFee))); + entry.push_back(Pair("amount", ValueFromAmount(ver, -s.second))); + entry.push_back(Pair("fee", ValueFromAmount(ver, -nFee))); if (fLong) WalletTxToJSON(wtx, entry); ret.push_back(entry); @@ -961,7 +987,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe entry.push_back(Pair("account", account)); entry.push_back(Pair("address", r.first)); entry.push_back(Pair("category", "receive")); - entry.push_back(Pair("amount", ValueFromAmount(r.second))); + entry.push_back(Pair("amount", ValueFromAmount(ver, r.second))); if (fLong) WalletTxToJSON(wtx, entry); ret.push_back(entry); @@ -971,7 +997,7 @@ void ListTransactions(const CWalletTx& wtx, const string& strAccount, int nMinDe } -void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Array& ret) +void AcentryToJSON(int ver, const CAccountingEntry& acentry, const string& strAccount, Array& ret) { bool fAllAccounts = (strAccount == string("*")); @@ -981,14 +1007,14 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar entry.push_back(Pair("account", acentry.strAccount)); entry.push_back(Pair("category", "move")); entry.push_back(Pair("time", (boost::int64_t)acentry.nTime)); - entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit))); + entry.push_back(Pair("amount", ValueFromAmount(ver, 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) +Value listtransactions(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() > 2) throw runtime_error( @@ -1029,10 +1055,10 @@ Value listtransactions(const Array& params, bool fHelp) { CWalletTx *const pwtx = (*it).second.first; if (pwtx != 0) - ListTransactions(*pwtx, strAccount, 0, true, ret); + ListTransactions(ver, *pwtx, strAccount, 0, true, ret); CAccountingEntry *const pacentry = (*it).second.second; if (pacentry != 0) - AcentryToJSON(*pacentry, strAccount, ret); + AcentryToJSON(ver, *pacentry, strAccount, ret); if (ret.size() >= nCount) break; } @@ -1051,7 +1077,7 @@ Value listtransactions(const Array& params, bool fHelp) return ret; } -Value listaccounts(const Array& params, bool fHelp) +Value listaccounts(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( @@ -1099,12 +1125,12 @@ Value listaccounts(const Array& params, bool fHelp) Object ret; foreach(const PAIRTYPE(string, int64)& accountBalance, mapAccountBalances) { - ret.push_back(Pair(accountBalance.first, ValueFromAmount(accountBalance.second))); + ret.push_back(Pair(accountBalance.first, ValueFromAmount(ver, accountBalance.second))); } return ret; } -Value gettransaction(const Array& params, bool fHelp) +Value gettransaction(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( @@ -1126,14 +1152,14 @@ Value gettransaction(const Array& params, bool fHelp) int64 nNet = nCredit - nDebit; int64 nFee = (wtx.IsFromMe() ? wtx.GetValueOut() - nDebit : 0); - entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee))); + entry.push_back(Pair("amount", ValueFromAmount(ver, nNet - nFee))); if (wtx.IsFromMe()) - entry.push_back(Pair("fee", ValueFromAmount(nFee))); + entry.push_back(Pair("fee", ValueFromAmount(ver, nFee))); WalletTxToJSON(mapWallet[hash], entry); Array details; - ListTransactions(mapWallet[hash], "*", 0, false, details); + ListTransactions(ver, mapWallet[hash], "*", 0, false, details); entry.push_back(Pair("details", details)); } @@ -1141,7 +1167,7 @@ Value gettransaction(const Array& params, bool fHelp) } -Value backupwallet(const Array& params, bool fHelp) +Value backupwallet(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( @@ -1155,7 +1181,7 @@ Value backupwallet(const Array& params, bool fHelp) } -Value validateaddress(const Array& params, bool fHelp) +Value validateaddress(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() != 1) throw runtime_error( @@ -1185,7 +1211,7 @@ Value validateaddress(const Array& params, bool fHelp) } -Value getwork(const Array& params, bool fHelp) +Value getwork(int ver, const Array& params, bool fHelp) { if (fHelp || params.size() > 1) throw runtime_error( @@ -1806,6 +1832,21 @@ void ThreadRPCServer2(void* parg) if (valMethod.type() != str_type) throw JSONRPCError(-32600, "Method must be a string"); string strMethod = valMethod.get_str(); + int APIVersion = 0; + { + size_t nlen; + const char*data; + if (strMethod.size() > 10 + && 0 == strncmp(data = strMethod.data(), "bitcoin.", 8) + && (nlen = strMethod.find('.', 8)) != string::npos) { + nlen -= 8; + char ndata[nlen + 1]; + memcpy(ndata, data + 8, nlen); + ndata[nlen] = '\0'; + APIVersion = atoi(ndata); + strMethod.erase(0, 9 + nlen); + } + } if (strMethod != "getwork") printf("ThreadRPCServer method=%s\n", strMethod.c_str()); @@ -1832,7 +1873,7 @@ void ThreadRPCServer2(void* parg) try { // Execute - Value result = (*(*mi).second)(params, false); + Value result = (*(*mi).second)(APIVersion, params, false); // Send reply string strReply = JSONRPCReply(result, Value::null, id); @@ -1938,6 +1979,18 @@ void ConvertTo(Value& value) } } +void ConvertToAmount(int ver, Value& value) +{ + switch (ver) { + case 0: + ConvertTo(value); + break; + default: + ConvertTo(value); + value.set_amount(true); + } +} + int CommandLineRPC(int argc, char *argv[]) { string strPrint; @@ -1951,6 +2004,8 @@ int CommandLineRPC(int argc, char *argv[]) argv++; } + int64 APIVersion = GetArg("-rpcversion", 0); + // Method if (argc < 2) throw runtime_error("too few parameters"); @@ -1967,7 +2022,7 @@ int CommandLineRPC(int argc, char *argv[]) // if (strMethod == "setgenerate" && n > 0) ConvertTo(params[0]); if (strMethod == "setgenerate" && n > 1) ConvertTo(params[1]); - if (strMethod == "sendtoaddress" && n > 1) ConvertTo(params[1]); + if (strMethod == "sendtoaddress" && n > 1) ConvertToAmount(APIVersion, params[1]); if (strMethod == "getamountreceived" && n > 1) ConvertTo(params[1]); // deprecated if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo(params[1]); if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo(params[1]); @@ -1981,13 +2036,16 @@ int CommandLineRPC(int argc, char *argv[]) if (strMethod == "listreceivedbylabel" && n > 0) ConvertTo(params[0]); // deprecated if (strMethod == "listreceivedbylabel" && n > 1) ConvertTo(params[1]); // deprecated if (strMethod == "getbalance" && n > 1) ConvertTo(params[1]); - if (strMethod == "move" && n > 2) ConvertTo(params[2]); + if (strMethod == "move" && n > 2) ConvertToAmount(APIVersion, params[2]); if (strMethod == "move" && n > 3) ConvertTo(params[3]); - if (strMethod == "sendfrom" && n > 2) ConvertTo(params[2]); + if (strMethod == "sendfrom" && n > 2) ConvertToAmount(APIVersion, params[2]); if (strMethod == "sendfrom" && n > 3) ConvertTo(params[3]); if (strMethod == "listtransactions" && n > 1) ConvertTo(params[1]); if (strMethod == "listaccounts" && n > 0) ConvertTo(params[0]); + if (APIVersion) + strMethod.insert(0, "bitcoin." + boost::lexical_cast(APIVersion) + '.'); + // Execute Object reply = CallRPC(strMethod, params); diff --git a/util.h b/util.h index c69bf1c..69fd2ea 100644 --- a/util.h +++ b/util.h @@ -17,6 +17,14 @@ typedef unsigned long long uint64; #define __forceinline inline #endif +#ifndef __deprecated__ +# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +# define __deprecated__ __attribute ((__deprecated__)) +# else +# define __deprecated /* noop */ +# endif +#endif + #define foreach BOOST_FOREACH #define loop for (;;) #define BEGIN(a) ((char*)&(a))