Malleable keys: Crypted R parameter support.
[novacoin.git] / src / rpcwallet.cpp
index 260cc57..c1be536 100644 (file)
@@ -467,7 +467,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;
@@ -1833,25 +1833,126 @@ 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<CPrivKey::iterator>(vchPrivKey.begin(), vchPrivKey.end())));
+
+    bool fCompressed;
+    CSecret vchSecret = key.GetSecret(fCompressed);
+    result.push_back(Pair("Secret", HexStr<CSecret::iterator>(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");
+
+    CMalleableKey malleableKey;
+    malleableKey.MakeNewKeys();
+    CMalleablePubKey malleablePubKey = malleableKey.GetMalleablePubKey();
+
+    CDataStream ssPublicBytes(SER_NETWORK, PROTOCOL_VERSION);
+    ssPublicBytes << malleablePubKey;
+
+    Object result;
+    result.push_back(Pair("PrivatePair", malleableKey.ToString()));
+    result.push_back(Pair("PublicPair", malleablePubKey.ToString()));
+    result.push_back(Pair("PublicBytes", HexStr(ssPublicBytes.begin(), ssPublicBytes.end())));
+
+    return result;
+}
+
+Value adjustmalleablekey(const Array& params, bool fHelp)
+{
+    if (fHelp || params.size() != 3)
+        throw runtime_error(
+            "adjustmalleablekey <Malleable key data> <Public key variant data> <R data>\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()));
+
+    std::vector<unsigned char> vchR = ParseHex(params[2].get_str());
+
+    CPubKey R;
+    if (vchR.size() == 33)
+        R = CPubKey(vchR);
+    else {
+        // R is encrypted
+        CSecret pvchSecretL, pvchSecretH;
+
+        malleableKey.GetSecrets(pvchSecretL, pvchSecretH);
+        CKey key;
+        key.SetSecret(pvchSecretL);
+
+        std::vector<unsigned char> vchDecryptedR;
+        key.DecryptData(vchR, vchDecryptedR);
+        R = CPubKey(vchDecryptedR);
+    }
+
+    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 <Malleable public key data>\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);
+
+    std::vector<unsigned char> encryptedR;
+    malleablePubKey.GetL().EncryptData(R.Raw(), encryptedR);
+
+    Object result;
+    result.push_back(Pair("R", HexStr(R.Raw())));
+    result.push_back(Pair("Rcrypted", HexStr(encryptedR)));
+    result.push_back(Pair("PubkeyVariant", HexStr(vchPubKeyVariant.Raw())));
+    result.push_back(Pair("KeyVariantID", CBitcoinAddress(vchPubKeyVariant.GetID()).ToString()));
+
+
+    return result;
+}