X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Frpcwallet.cpp;h=ff627c11adfdb21b1ed611a87dca8b9a2d7567c1;hb=0a18ce8f4cd1a723f50333945d94c84b45c8d56b;hp=70bb52a987265f87fd77e1d1d11f72c3a96919ba;hpb=126e51d5d96f8bc2c900df18af5827c279967dcc;p=novacoin.git diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index 70bb52a..ff627c1 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -7,6 +7,8 @@ #include "walletdb.h" #include "bitcoinrpc.h" #include "init.h" +#include "util.h" +#include "ntp.h" #include "base58.h" using namespace json_spirit; @@ -16,7 +18,7 @@ int64_t nWalletUnlockTime; static CCriticalSection cs_nWalletUnlockTime; extern int64_t nReserveBalance; -extern void TxToJSON(const CTransaction& tx, const uint256 hashBlock, json_spirit::Object& entry); +extern void TxToJSON(const CTransaction& tx, const uint256& hashBlock, json_spirit::Object& entry); std::string HelpRequiringPassphrase() { @@ -43,11 +45,11 @@ void WalletTxToJSON(const CWalletTx& wtx, Object& entry) { entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex())); entry.push_back(Pair("blockindex", wtx.nIndex)); - entry.push_back(Pair("blocktime", (boost::int64_t)(mapBlockIndex[wtx.hashBlock]->nTime))); + entry.push_back(Pair("blocktime", (int64_t)(mapBlockIndex[wtx.hashBlock]->nTime))); } entry.push_back(Pair("txid", wtx.GetHash().GetHex())); - entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime())); - entry.push_back(Pair("timereceived", (boost::int64_t)wtx.nTimeReceived)); + entry.push_back(Pair("time", (int64_t)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)); } @@ -70,7 +72,7 @@ Value getinfo(const Array& params, bool fHelp) proxyType proxy; GetProxy(NET_IPV4, proxy); - Object obj, diff; + Object obj, diff, timestamping; obj.push_back(Pair("version", FormatFullVersion())); obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); obj.push_back(Pair("walletversion", pwalletMain->GetVersion())); @@ -79,7 +81,18 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint()))); obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake()))); obj.push_back(Pair("blocks", (int)nBestHeight)); - obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset())); + + timestamping.push_back(Pair("systemclock", GetTime())); + timestamping.push_back(Pair("adjustedtime", GetAdjustedTime())); + + int64_t nNtpOffset = GetNtpOffset(), + nP2POffset = GetNodesOffset(); + + timestamping.push_back(Pair("ntpoffset", nNtpOffset != INT64_MAX ? nNtpOffset : Value::null)); + timestamping.push_back(Pair("p2poffset", nP2POffset != INT64_MAX ? nP2POffset : Value::null)); + + obj.push_back(Pair("timestamping", timestamping)); + obj.push_back(Pair("moneysupply", ValueFromAmount(pindexBest->nMoneySupply))); obj.push_back(Pair("connections", (int)vNodes.size())); obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); @@ -90,12 +103,12 @@ Value getinfo(const Array& params, bool fHelp) obj.push_back(Pair("difficulty", diff)); obj.push_back(Pair("testnet", fTestNet)); - obj.push_back(Pair("keypoololdest", (boost::int64_t)pwalletMain->GetOldestKeyPoolTime())); + obj.push_back(Pair("keypoololdest", (int64_t)pwalletMain->GetOldestKeyPoolTime())); obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize())); obj.push_back(Pair("paytxfee", ValueFromAmount(nTransactionFee))); obj.push_back(Pair("mininput", ValueFromAmount(nMinimumInputValue))); if (pwalletMain->IsCrypted()) - obj.push_back(Pair("unlocked_until", (boost::int64_t)nWalletUnlockTime / 1000)); + obj.push_back(Pair("unlocked_until", (int64_t)nWalletUnlockTime / 1000)); obj.push_back(Pair("errors", GetWarnings("statusbar"))); return obj; } @@ -264,7 +277,7 @@ Value mergecoins(const Array& params, bool fHelp) " is resulting inputs sum\n" " is minimum value of inputs which are used in join process\n" " is resulting value of inputs which will be created\n" - "All values are real and and rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT) + "All values are real and and rounded to the nearest " + FormatMoney(nMinimumInputValue) + HelpRequiringPassphrase()); if (pwalletMain->IsLocked()) @@ -279,13 +292,13 @@ Value mergecoins(const Array& params, bool fHelp) // Output amount int64_t nOutputValue = AmountFromValue(params[2]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); - if (nMinValue < MIN_TXOUT_AMOUNT) + if (nMinValue < nMinimumInputValue) throw JSONRPCError(-101, "Max value too small"); - if (nOutputValue < MIN_TXOUT_AMOUNT) + if (nOutputValue < nMinimumInputValue) throw JSONRPCError(-101, "Output value too small"); if (nOutputValue < nMinValue) @@ -307,17 +320,31 @@ Value sendtoaddress(const Array& params, bool fHelp) if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( "sendtoaddress [comment] [comment-to]\n" - " is a real and is rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT) + " is a real and is rounded to the nearest " + FormatMoney(nMinimumInputValue) + HelpRequiringPassphrase()); - CBitcoinAddress address(params[0].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address"); + // Parse address + CScript scriptPubKey; + string strAddress = params[0].get_str(); + + CBitcoinAddress address(strAddress); + if (address.IsValid()) + scriptPubKey.SetDestination(address.Get()); + else + { + CMalleablePubKey mpk(strAddress); + if (!mpk.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address"); + + CPubKey R, pubKeyVariant; + mpk.GetVariant(R, pubKeyVariant); + scriptPubKey.SetDestination(R, pubKeyVariant); + } // Amount int64_t nAmount = AmountFromValue(params[1]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); // Wallet comments @@ -330,7 +357,7 @@ Value sendtoaddress(const Array& params, bool fHelp) if (pwalletMain->IsLocked()) throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); - string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + string strError = pwalletMain->SendMoney(scriptPubKey, nAmount, wtx); if (strError != "") throw JSONRPCError(RPC_WALLET_ERROR, strError); @@ -454,7 +481,7 @@ Value getreceivedbyaddress(const Array& params, bool fHelp) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address"); scriptPubKey.SetDestination(address.Get()); if (!IsMine(*pwalletMain,scriptPubKey)) - return (double)0.0; + return 0.0; // Minimum confirmations int nMinDepth = 1; @@ -630,7 +657,7 @@ Value movecmd(const Array& params, bool fHelp) string strTo = AccountFromValue(params[1]); int64_t nAmount = AmountFromValue(params[2]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); if (params.size() > 3) @@ -678,16 +705,32 @@ Value sendfrom(const Array& params, bool fHelp) if (fHelp || params.size() < 3 || params.size() > 6) throw runtime_error( "sendfrom [minconf=1] [comment] [comment-to]\n" - " is a real and is rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT) + " is a real and is rounded to the nearest " + FormatMoney(nMinimumInputValue) + HelpRequiringPassphrase()); string strAccount = AccountFromValue(params[0]); - CBitcoinAddress address(params[1].get_str()); - if (!address.IsValid()) - throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address"); + + // Parse address + CScript scriptPubKey; + string strAddress = params[0].get_str(); + + CBitcoinAddress address(strAddress); + if (address.IsValid()) + scriptPubKey.SetDestination(address.Get()); + else + { + CMalleablePubKey mpk(strAddress); + if (!mpk.IsValid()) + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid NovaCoin address"); + + CPubKey R, pubKeyVariant; + mpk.GetVariant(R, pubKeyVariant); + scriptPubKey.SetDestination(R, pubKeyVariant); + } + int64_t nAmount = AmountFromValue(params[2]); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); int nMinDepth = 1; @@ -709,7 +752,7 @@ Value sendfrom(const Array& params, bool fHelp) throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, "Account has insufficient funds"); // Send - string strError = pwalletMain->SendMoneyToDestination(address.Get(), nAmount, wtx); + string strError = pwalletMain->SendMoney(scriptPubKey, nAmount, wtx); if (strError != "") throw JSONRPCError(RPC_WALLET_ERROR, strError); @@ -721,7 +764,7 @@ Value sendmany(const Array& params, bool fHelp) { if (fHelp || params.size() < 2 || params.size() > 4) throw runtime_error( - "sendmany {address:amount,...} [minconf=1] [comment]\n" + "sendmany '{address:amount,...}' [minconf=1] [comment]\n" "amounts are double-precision floating point numbers" + HelpRequiringPassphrase()); @@ -754,7 +797,7 @@ Value sendmany(const Array& params, bool fHelp) scriptPubKey.SetDestination(address.Get()); int64_t nAmount = AmountFromValue(s.value_); - if (nAmount < MIN_TXOUT_AMOUNT) + if (nAmount < nMinimumInputValue) throw JSONRPCError(-101, "Send amount too small"); totalAmount += nAmount; @@ -1126,7 +1169,7 @@ void AcentryToJSON(const CAccountingEntry& acentry, const string& strAccount, Ar Object entry; 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("time", (int64_t)acentry.nTime)); entry.push_back(Pair("amount", ValueFromAmount(acentry.nCreditDebit))); entry.push_back(Pair("otheraccount", acentry.strOtherAccount)); entry.push_back(Pair("comment", acentry.strComment)); @@ -1416,7 +1459,7 @@ Value keypoolrefill(const Array& params, bool fHelp) "should be replaced with the newly generated one." + HelpRequiringPassphrase()); - unsigned int nSize = max(GetArg("-keypool", 100), 0); + unsigned int nSize = max(GetArgUInt("-keypool", 100), 0); if (params.size() > 0) { if (params[0].get_int() < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size"); @@ -1443,7 +1486,7 @@ Value keypoolreset(const Array& params, bool fHelp) "should be replaced with the newly generated one." + HelpRequiringPassphrase()); - unsigned int nSize = max(GetArg("-keypool", 100), 0); + unsigned int nSize = max(GetArgUInt("-keypool", 100), 0); if (params.size() > 0) { if (params[0].get_int() < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected valid size"); @@ -1742,7 +1785,7 @@ Value reservebalance(const Array& params, bool fHelp) nAmount = (nAmount / CENT) * CENT; // round to cent if (nAmount < 0) throw runtime_error("amount cannot be negative.\n"); - mapArgs["-reservebalance"] = FormatMoney(nAmount).c_str(); + mapArgs["-reservebalance"] = FormatMoney(nAmount); } else { @@ -1820,25 +1863,152 @@ Value resendtx(const Array& params, bool fHelp) return Value::null; } -// ppcoin: make a public-private key pair +// Make a public-private key pair Value makekeypair(const Array& params, bool fHelp) { - if (fHelp || params.size() > 1) + if (fHelp || params.size() > 0) throw runtime_error( - "makekeypair [prefix]\n" - "Make a public/private key pair.\n" - "[prefix] is optional preferred prefix for the public key.\n"); + "makekeypair\n" + "Make a public/private key pair.\n"); string strPrefix = ""; if (params.size() > 0) strPrefix = params[0].get_str(); - + CKey key; - key.MakeNewKey(false); + key.MakeNewKey(true); CPrivKey vchPrivKey = key.GetPrivKey(); Object result; result.push_back(Pair("PrivateKey", HexStr(vchPrivKey.begin(), vchPrivKey.end()))); + + bool fCompressed; + CSecret vchSecret = key.GetSecret(fCompressed); + result.push_back(Pair("Secret", HexStr(vchSecret.begin(), vchSecret.end()))); result.push_back(Pair("PublicKey", HexStr(key.GetPubKey().Raw()))); return result; } + +Value newmalleablekey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 0) + throw runtime_error( + "newmalleablekey\n" + "Make a malleable public/private key pair.\n"); + + if (!fTestNet && GetTime() < SMALLDATA_SWITCH_TIME) + throw runtime_error("This feature has been disabled for mainNet clients"); + + CMalleableKeyView keyView = pwalletMain->GenerateNewMalleableKey(); + + CMalleableKey mKey; + if (!pwalletMain->GetMalleableKey(keyView, mKey)) + throw runtime_error("Unable to generate new malleable key"); + + Object result; + result.push_back(Pair("PublicPair", mKey.GetMalleablePubKey().ToString())); + result.push_back(Pair("KeyView", keyView.ToString())); + + return result; +} + +Value validatemalleablepubkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 1) + throw runtime_error( + "validatemalleablekey \n" + "Check the validity and ownership for priovided malleable public key.\n"); + + CMalleablePubKey mpk; + bool isValid = mpk.SetString(params[0].get_str()); + + Object result; + result.push_back(Pair("isvalid", isValid)); + + if (isValid) + { + CMalleableKeyView view; + bool isMine = pwalletMain->GetMalleableView(mpk, view); + result.push_back(Pair("ismine", isMine)); + + if (isMine) + result.push_back(Pair("KeyView", view.ToString())); + } + + return result; +} + +Value adjustmalleablekey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 3) + throw runtime_error( + "adjustmalleablekey \n" + "Calculate new private key using provided malleable key, public key and R data.\n"); + + CMalleableKey malleableKey; + malleableKey.SetString(params[0].get_str()); + + CKey privKeyVariant; + CPubKey vchPubKeyVariant = CPubKey(ParseHex(params[1].get_str())); + + CPubKey R(ParseHex(params[2].get_str())); + + if (!malleableKey.CheckKeyVariant(R,vchPubKeyVariant, privKeyVariant)) { + throw runtime_error("Unable to calculate the private key"); + } + + Object result; + bool fCompressed; + CSecret vchPrivKeyVariant = privKeyVariant.GetSecret(fCompressed); + + result.push_back(Pair("PrivateKey", CBitcoinSecret(vchPrivKeyVariant, fCompressed).ToString())); + + return result; +} + +Value adjustmalleablepubkey(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 2 || params.size() == 0) + throw runtime_error( + "adjustmalleablepubkey \n" + "Calculate new public key using provided malleable public key data.\n"); + + string pubKeyPair = params[0].get_str(); + CMalleablePubKey malleablePubKey; + + if (pubKeyPair.size() == 138) { + CDataStream ssPublicBytes(ParseHex(pubKeyPair), SER_NETWORK, PROTOCOL_VERSION); + ssPublicBytes >> malleablePubKey; + } else + malleablePubKey.SetString(pubKeyPair); + + CPubKey R, vchPubKeyVariant; + malleablePubKey.GetVariant(R, vchPubKeyVariant); + + Object result; + result.push_back(Pair("R", HexStr(R.Raw()))); + result.push_back(Pair("PubkeyVariant", HexStr(vchPubKeyVariant.Raw()))); + result.push_back(Pair("KeyVariantID", CBitcoinAddress(vchPubKeyVariant.GetID()).ToString())); + + return result; +} + +Value listmalleableviews(const Array& params, bool fHelp) +{ + if (fHelp || params.size() != 0) + throw runtime_error( + "listmalleableviews\n" + "Get list of views for generated malleable keys.\n"); + + std::list keyViewList; + pwalletMain->ListMalleableViews(keyViewList); + + Array result; + BOOST_FOREACH(const CMalleableKeyView &keyView, keyViewList) + { + result.push_back(keyView.ToString()); + } + + return result; +} +