Revert "Use standard C99 (and Qt) types for 64-bit integers"
[novacoin.git] / src / bitcoinrpc.cpp
index 122bf61..bed90d4 100644 (file)
@@ -91,7 +91,13 @@ Value ValueFromAmount(int64 amount)
 
 void WalletTxToJSON(const CWalletTx& wtx, Object& entry)
 {
-    entry.push_back(Pair("confirmations", wtx.GetDepthInMainChain()));
+    int confirms = wtx.GetDepthInMainChain();
+    entry.push_back(Pair("confirmations", confirms));
+    if (confirms)
+    {
+        entry.push_back(Pair("blockhash", wtx.hashBlock.GetHex()));
+        entry.push_back(Pair("blockindex", wtx.nIndex));
+    }
     entry.push_back(Pair("txid", wtx.GetHash().GetHex()));
     entry.push_back(Pair("time", (boost::int64_t)wtx.GetTxTime()));
     BOOST_FOREACH(const PAIRTYPE(string,string)& item, wtx.mapValue)
@@ -667,7 +673,7 @@ Value getreceivedbyaccount(const Array& params, bool fHelp)
     if (params.size() > 1)
         nMinDepth = params[1].get_int();
 
-    // Get the set of pub keys that have the label
+    // Get the set of pub keys assigned to account
     string strAccount = AccountFromValue(params[0]);
     set<CBitcoinAddress> setAddress;
     GetAccountAddresses(strAccount, setAddress);
@@ -936,56 +942,32 @@ Value sendmany(const Array& params, bool fHelp)
     return wtx.GetHash().GetHex();
 }
 
-Value sendmultisig(const Array& params, bool fHelp)
+Value addmultisigaddress(const Array& params, bool fHelp)
 {
-    if (fHelp || params.size() < 4 || params.size() > 7)
+    if (fHelp || params.size() < 2 || params.size() > 3)
     {
-        string msg = "sendmultisig <fromaccount> <type> <[\"key\",\"key\"]> <amount> [minconf=1] [comment] [comment-to]\n"
-            "<type> is one of: \"and\", \"or\", \"escrow\"\n"
-            "<keys> is an array of strings (in JSON array format); each key is a bitcoin address, hex or base58 public key\n"
-            "<amount> is a real and is rounded to the nearest 0.00000001";
-        if (pwalletMain->IsCrypted())
-            msg += "\nrequires wallet passphrase to be set with walletpassphrase first";
+        string msg = "addmultisigaddress <nrequired> <'[\"key\",\"key\"]'> [account]\n"
+            "Add a nrequired-to-sign multisignature address to the wallet\"\n"
+            "each key is a bitcoin address, hex or base58 public key\n"
+            "If [account] is specified, assign address to [account].";
         throw runtime_error(msg);
     }
+    if (!fTestNet)
+        throw runtime_error("addmultisigaddress available only when running -testnet\n");
 
-    string strAccount = AccountFromValue(params[0]);
-    string strType = params[1].get_str();
-    const Array& keys = params[2].get_array();
-    int64 nAmount = AmountFromValue(params[3]);
-    int nMinDepth = 1;
-    if (params.size() > 4)
-        nMinDepth = params[4].get_int();
-
-    CWalletTx wtx;
-    wtx.strFromAccount = strAccount;
-    if (params.size() > 5 && params[5].type() != null_type && !params[5].get_str().empty())
-        wtx.mapValue["comment"] = params[5].get_str();
-    if (params.size() > 6 && params[6].type() != null_type && !params[6].get_str().empty())
-        wtx.mapValue["to"]      = params[6].get_str();
-
-    if (pwalletMain->IsLocked())
-        throw JSONRPCError(-13, "Error: Please enter the wallet passphrase with walletpassphrase first.");
-
-    // Check funds
-    int64 nBalance = GetAccountBalance(strAccount, nMinDepth);
-    if (nAmount > nBalance)
-        throw JSONRPCError(-6, "Account has insufficient funds");
+    int nRequired = params[0].get_int();
+    const Array& keys = params[1].get_array();
+    string strAccount;
+    if (params.size() > 2)
+        strAccount = AccountFromValue(params[2]);
 
     // Gather public keys
-    int nKeysNeeded = 0;
-    if (strType == "and" || strType == "or")
-        nKeysNeeded = 2;
-    else if (strType == "escrow")
-        nKeysNeeded = 3;
-    else
-        throw runtime_error("sendmultisig: <type> must be one of: and or and_or");
-    if (keys.size() != nKeysNeeded)
+    if (keys.size() < nRequired)
         throw runtime_error(
-            strprintf("sendmultisig: wrong number of keys (got %d, need %d)", keys.size(), nKeysNeeded));
+            strprintf("addmultisigaddress: wrong number of keys (got %d, need at least %d)", keys.size(), nRequired));
     std::vector<CKey> pubkeys;
-    pubkeys.resize(nKeysNeeded);
-    for (int i = 0; i < nKeysNeeded; i++)
+    pubkeys.resize(keys.size());
+    for (int i = 0; i < keys.size(); i++)
     {
         const std::string& ks = keys[i].get_str();
         if (ks.size() == 130) // hex public key
@@ -1003,32 +985,23 @@ Value sendmultisig(const Array& params, bool fHelp)
             CBitcoinAddress address(ks);
             if (!pwalletMain->GetKey(address, pubkeys[i]))
                 throw runtime_error(
-                    strprintf("sendmultisig: unknown address: %s",ks.c_str()));
+                    strprintf("addmultisigaddress: unknown address: %s",ks.c_str()));
         }
     }
 
-    // Send
-    CScript scriptPubKey;
-    if (strType == "and")
-        scriptPubKey.SetMultisigAnd(pubkeys);
-    else if (strType == "or")
-        scriptPubKey.SetMultisigOr(pubkeys);
-    else
-        scriptPubKey.SetMultisigEscrow(pubkeys);
+    // Construct using OP_EVAL
+    CScript inner;
+    inner.SetMultisig(nRequired, pubkeys);
 
-    CReserveKey keyChange(pwalletMain);
-    int64 nFeeRequired = 0;
-    bool fCreated = pwalletMain->CreateTransaction(scriptPubKey, nAmount, wtx, keyChange, nFeeRequired);
-    if (!fCreated)
-    {
-        if (nAmount + nFeeRequired > pwalletMain->GetBalance())
-            throw JSONRPCError(-6, "Insufficient funds");
-        throw JSONRPCError(-4, "Transaction creation failed");
-    }
-    if (!pwalletMain->CommitTransaction(wtx, keyChange))
-        throw JSONRPCError(-4, "Transaction commit failed");
+    uint160 scriptHash = Hash160(inner);
+    CScript scriptPubKey;
+    scriptPubKey.SetEval(inner);
+    pwalletMain->AddCScript(scriptHash, inner);
+    CBitcoinAddress address;
+    address.SetScriptHash160(scriptHash);
 
-    return wtx.GetHash().GetHex();
+    pwalletMain->SetAddressBookName(address, strAccount);
+    return address.ToString();
 }
 
 
@@ -1039,7 +1012,7 @@ struct tallyitem
     tallyitem()
     {
         nAmount = 0;
-        nConf = INT_MAX;
+        nConf = std::numeric_limits<int>::max();
     }
 };
 
@@ -1091,7 +1064,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
             continue;
 
         int64 nAmount = 0;
-        int nConf = INT_MAX;
+        int nConf = std::numeric_limits<int>::max();
         if (it != mapTally.end())
         {
             nAmount = (*it).second.nAmount;
@@ -1110,7 +1083,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
             obj.push_back(Pair("address",       address.ToString()));
             obj.push_back(Pair("account",       strAccount));
             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
-            obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
+            obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
             ret.push_back(obj);
         }
     }
@@ -1124,7 +1097,7 @@ Value ListReceived(const Array& params, bool fByAccounts)
             Object obj;
             obj.push_back(Pair("account",       (*it).first));
             obj.push_back(Pair("amount",        ValueFromAmount(nAmount)));
-            obj.push_back(Pair("confirmations", (nConf == INT_MAX ? 0 : nConf)));
+            obj.push_back(Pair("confirmations", (nConf == std::numeric_limits<int>::max() ? 0 : nConf)));
             ret.push_back(obj);
         }
     }
@@ -1700,6 +1673,24 @@ Value validateaddress(const Array& params, bool fHelp)
             std::string strPubKey(vchPubKey.begin(), vchPubKey.end());
             ret.push_back(Pair("pubkey58", EncodeBase58(vchPubKey)));
         }
+        else if (pwalletMain->HaveCScript(address.GetHash160()))
+        {
+            ret.push_back(Pair("isscript", true));
+            CScript subscript;
+            pwalletMain->GetCScript(address.GetHash160(), subscript);
+            ret.push_back(Pair("ismine", ::IsMine(*pwalletMain, subscript)));
+            std::vector<CBitcoinAddress> addresses;
+            txnouttype whichType;
+            int nRequired;
+            ExtractAddresses(subscript, pwalletMain, whichType, addresses, nRequired);
+            ret.push_back(Pair("script", GetTxnOutputType(whichType)));
+            Array a;
+            BOOST_FOREACH(const CBitcoinAddress& addr, addresses)
+                a.push_back(addr.ToString());
+            ret.push_back(Pair("addresses", a));
+            if (whichType == TX_MULTISIG)
+                ret.push_back(Pair("sigsrequired", nRequired));
+        }
         else
             ret.push_back(Pair("ismine", false));
         if (pwalletMain->mapAddressBook.count(address))
@@ -1946,7 +1937,7 @@ pair<string, rpcfn_type> pCallTable[] =
     make_pair("move",                   &movecmd),
     make_pair("sendfrom",               &sendfrom),
     make_pair("sendmany",               &sendmany),
-    make_pair("sendmultisig",           &sendmultisig),
+    make_pair("addmultisigaddress",     &addmultisigaddress),
     make_pair("gettransaction",         &gettransaction),
     make_pair("listtransactions",       &listtransactions),
     make_pair("signmessage",            &signmessage),
@@ -2590,16 +2581,15 @@ int CommandLineRPC(int argc, char *argv[])
             params[1] = v.get_obj();
         }
         if (strMethod == "sendmany"                && n > 2) ConvertTo<boost::int64_t>(params[2]);
-        if (strMethod == "sendmultisig"            && n > 2)
+        if (strMethod == "addmultisigaddress"      && n > 0) ConvertTo<boost::int64_t>(params[0]);
+        if (strMethod == "addmultisigaddress"      && n > 1)
         {
-            string s = params[2].get_str();
+            string s = params[1].get_str();
             Value v;
             if (!read_string(s, v) || v.type() != array_type)
-                throw runtime_error("sendmultisig: type mismatch "+s);
-            params[2] = v.get_array();
+                throw runtime_error("addmultisigaddress: type mismatch "+s);
+            params[1] = v.get_array();
         }
-        if (strMethod == "sendmultisig"            && n > 3) ConvertTo<double>(params[3]);
-        if (strMethod == "sendmultisig"            && n > 4) ConvertTo<boost::int64_t>(params[4]);
 
         // Execute
         Object reply = CallRPC(strMethod, params);