ListMalleablePubKeys method
author0xDEADFACE <masmfan@gmail.com>
Sat, 13 Feb 2016 21:25:37 +0000 (13:25 -0800)
committer0xDEADFACE <masmfan@gmail.com>
Sat, 13 Feb 2016 21:25:37 +0000 (13:25 -0800)
src/bitcoinrpc.cpp
src/bitcoinrpc.h
src/key.cpp
src/key.h
src/keystore.cpp
src/keystore.h
src/rpcwallet.cpp

index 719aef0..92042d0 100644 (file)
@@ -319,6 +319,7 @@ static const CRPCCommand vRPCCommands[] =
     { "newmalleablekey",        &newmalleablekey,        false,  false},
     { "adjustmalleablekey",     &adjustmalleablekey,     false,  false},
     { "adjustmalleablepubkey",  &adjustmalleablepubkey,  false,  false},
+    { "listmalleablepubkeys",   &listmalleablepubkeys,   false,  false},
     { "sendalert",              &sendalert,              false,  false},
 };
 
index 3b0e199..226007b 100644 (file)
@@ -209,6 +209,7 @@ extern json_spirit::Value mergecoins(const json_spirit::Array& params, bool fHel
 extern json_spirit::Value newmalleablekey(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value adjustmalleablekey(const json_spirit::Array& params, bool fHelp);
 extern json_spirit::Value adjustmalleablepubkey(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value listmalleablepubkeys(const json_spirit::Array& params, bool fHelp);
 
 extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
 extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
index 89c0dcc..dafffcf 100644 (file)
@@ -592,6 +592,12 @@ bool CPoint::setBytes(const std::vector<unsigned char> &vchBytes)
     return true;
 }
 
+// Initialize from octets stream
+bool CPoint::setPubKey(const CPubKey &vchPubKey)
+{
+    return setBytes(vchPubKey.Raw());
+}
+
 // Serialize to octets stream
 bool CPoint::getBytes(std::vector<unsigned char> &vchBytes)
 {
@@ -666,7 +672,7 @@ void CMalleablePubKey::GetVariant(CPubKey &R, CPubKey &vchPubKeyVariant)
     EC_KEY_free(eckey);
 
     CPoint point;
-    if (!point.setBytes(pubKeyL.Raw())) {
+    if (!point.setPubKey(pubKeyL)) {
         throw key_error("CMalleablePubKey::GetVariant() : Unable to decode L value");
     }
 
@@ -683,7 +689,7 @@ void CMalleablePubKey::GetVariant(CPubKey &R, CPubKey &vchPubKeyVariant)
     bnHash.setuint160(Hash160(vchLr));
 
     CPoint pointH;
-    pointH.setBytes(pubKeyH.Raw());
+    pointH.setPubKey(pubKeyH);
 
     CPoint P;
     // Calculate P = Hash(L*r)*G + H
@@ -699,7 +705,7 @@ void CMalleablePubKey::GetVariant(CPubKey &R, CPubKey &vchPubKeyVariant)
     vchPubKeyVariant = CPubKey(vchResult);
 }
 
-std::string CMalleablePubKey::ToString()
+std::string CMalleablePubKey::ToString() const
 {
     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
     ssKey << *this;
@@ -789,7 +795,7 @@ bool CMalleableKey::SetSecrets(const CSecret &pvchSecretL, const CSecret &pvchSe
     Reset();
     CKey L, H;
 
-    if (!L.SetSecret(pvchSecretL, true) || !H.SetSecret(pvchSecretH, true))
+    if (pvchSecretL.size() != 32 || !pvchSecretH.size() != 32 || !L.SetSecret(pvchSecretL, true) || !H.SetSecret(pvchSecretH, true))
     {
         nVersion = 0;
         return false;
@@ -821,7 +827,7 @@ CMalleablePubKey CMalleableKey::GetMalleablePubKey() const
 }
 
 // Check ownership
-bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant)
+bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const
 {
     if (IsNull()) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Attempting to run on NULL key object.");
@@ -836,7 +842,7 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
     }
 
     CPoint point_R;
-    if (!point_R.setBytes(R.Raw())) {
+    if (!point_R.setPubKey(R)) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode R value");
     }
 
@@ -845,12 +851,12 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
     std::vector<unsigned char> vchPubKeyH = H.GetPubKey().Raw();
 
     CPoint point_H;
-    if (!point_H.setBytes(vchPubKeyH)) {
+    if (!point_H.setPubKey(vchPubKeyH)) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode H value");
     }
 
     CPoint point_P;
-    if (!point_P.setBytes(vchPubKeyVariant.Raw())) {
+    if (!point_P.setPubKey(vchPubKeyVariant)) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode P value");
     }
 
@@ -891,7 +897,7 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
 }
 
 // Check ownership and restore private key
-bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant)
+bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant) const
 {
     if (IsNull()) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Attempting to run on NULL key object.");
@@ -906,7 +912,7 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
     }
 
     CPoint point_R;
-    if (!point_R.setBytes(R.Raw())) {
+    if (!point_R.setPubKey(R)) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode R value");
     }
 
@@ -915,12 +921,12 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
     std::vector<unsigned char> vchPubKeyH = H.GetPubKey().Raw();
 
     CPoint point_H;
-    if (!point_H.setBytes(vchPubKeyH)) {
+    if (!point_H.setPubKey(vchPubKeyH)) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode H value");
     }
 
     CPoint point_P;
-    if (!point_P.setBytes(vchPubKeyVariant.Raw())) {
+    if (!point_P.setPubKey(vchPubKeyVariant)) {
         throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode P value");
     }
 
@@ -970,7 +976,7 @@ bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVa
     return true;
 }
 
-std::string CMalleableKey::ToString()
+std::string CMalleableKey::ToString() const
 {
     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
     ssKey << *this;
@@ -996,10 +1002,17 @@ bool CMalleableKey::SetString(const std::string& strMutableKey)
 
 CMalleableKeyView::CMalleableKeyView(const CMalleableKey &b)
 {
+    if (b.vchSecretL.size() != 32)
+        throw key_error("CMalleableKeyView::CMalleableKeyView() : L size must be 32 bytes");
+
+    if (b.vchSecretH.size() != 32)
+        throw key_error("CMalleableKeyView::CMalleableKeyView() : L size must be 32 bytes");
+
     vchSecretL = b.vchSecretL;
 
     CKey H;
     H.SetSecret(b.vchSecretH, true);
+
     vchPubKeyH = H.GetPubKey().Raw();
     nVersion = b.nVersion;
 }
@@ -1042,7 +1055,7 @@ CMalleablePubKey CMalleableKeyView::GetMalleablePubKey() const
 }
 
 // Check ownership
-bool CMalleableKeyView::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant)
+bool CMalleableKeyView::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const
 {
     if (!R.IsValid()) {
         throw key_error("CMalleableKeyView::CheckKeyVariant() : R is invalid");
@@ -1053,17 +1066,17 @@ bool CMalleableKeyView::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubK
     }
 
     CPoint point_R;
-    if (!point_R.setBytes(R.Raw())) {
+    if (!point_R.setPubKey(R)) {
         throw key_error("CMalleableKeyView::CheckKeyVariant() : Unable to decode R value");
     }
 
     CPoint point_H;
-    if (!point_H.setBytes(vchPubKeyH)) {
+    if (!point_H.setPubKey(vchPubKeyH)) {
         throw key_error("CMalleableKeyView::CheckKeyVariant() : Unable to decode H value");
     }
 
     CPoint point_P;
-    if (!point_P.setBytes(vchPubKeyVariant.Raw())) {
+    if (!point_P.setPubKey(vchPubKeyVariant)) {
         throw key_error("CMalleableKeyView::CheckKeyVariant() : Unable to decode P value");
     }
 
@@ -1103,7 +1116,7 @@ bool CMalleableKeyView::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubK
     return true;
 }
 
-std::string CMalleableKeyView::ToString()
+std::string CMalleableKeyView::ToString() const
 {
     CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
     ssKey << *this;
index ca78c72..a829834 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -191,6 +191,9 @@ public:
     // Initialize from octets stream
     bool setBytes(const std::vector<unsigned char> &vchBytes);
 
+    // Initialize from pubkey
+    bool setPubKey(const CPubKey &vchPubKey);
+
     // Serialize to octets stream
     bool getBytes(std::vector<unsigned char> &vchBytes);
 
@@ -233,7 +236,7 @@ public:
     bool operator==(const CMalleablePubKey &b);
     bool operator!=(const CMalleablePubKey &b) { return !(*this == b); }
 
-    std::string ToString();
+    std::string ToString() const;
     bool SetString(const std::string& strMalleablePubKey);
     uint256 GetID() const;
 
@@ -267,7 +270,7 @@ public:
         READWRITE(vchSecretH);
     )
 
-    std::string ToString();
+    std::string ToString() const;
     bool SetString(const std::string& strMalleablePubKey);
 
     void Reset();
@@ -277,8 +280,8 @@ public:
     void GetSecrets(CSecret &pvchSecretL, CSecret &pvchSecretH) const;
 
     CMalleablePubKey GetMalleablePubKey() const;
-    bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant);
-    bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant);
+    bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const;
+    bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant) const;
 };
 
 class CMalleableKeyView
@@ -286,7 +289,7 @@ class CMalleableKeyView
 private:
     unsigned char nVersion;
     CSecret vchSecretL;
-    std::vector<unsigned char> vchPubKeyH;
+    CPubKey vchPubKeyH;
 
     static const unsigned char CURRENT_VERSION = 1;
 
@@ -308,11 +311,13 @@ public:
     )
 
     bool IsNull() const;
-    std::string ToString();
+    std::string ToString() const;
     bool SetString(const std::string& strMalleablePubKey);
 
     CMalleablePubKey GetMalleablePubKey() const;
-    bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant);
+    bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant) const;
+
+    bool operator <(const CMalleableKeyView& kv) const { return vchPubKeyH.GetID() < kv.vchPubKeyH.GetID(); }
 };
 
 #endif
index 197b73e..fdba291 100644 (file)
@@ -111,9 +111,8 @@ CCryptoKeyStore::CCryptoKeyStore() : fUseCrypto(false)
     else
         malleableKey.MakeNewKeys();
 
-    CMalleableKeyView keyView(malleableKey);
-
-    malleableKeyPair = std::pair<CMalleableKeyView, CMalleableKey>(keyView, malleableKey);
+    const CMalleableKeyView& keyView(malleableKey);
+    mapMalleableKeys[keyView] = malleableKey;
 }
 
 bool CCryptoKeyStore::SetCrypted()
index 7dc3464..7d49735 100644 (file)
@@ -67,21 +67,23 @@ public:
 
     virtual bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const =0;
     virtual bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const =0;
+    virtual void ListMalleablePubKeys(std::list<CMalleablePubKey> &malleablePubKeyList) const =0;
 };
 
 typedef std::map<CKeyID, std::pair<CSecret, bool> > KeyMap;
 typedef std::map<CScriptID, CScript > ScriptMap;
 typedef std::set<CScript> WatchOnlySet;
-typedef std::pair<CMalleableKeyView, CMalleableKey> MalleableKeyPair;
+typedef std::map<CMalleableKeyView, CMalleableKey> MalleableKeyMap;
 
 /** Basic key store, that keeps keys in an address->secret map */
 class CBasicKeyStore : public CKeyStore
 {
 protected:
     KeyMap mapKeys;
+    MalleableKeyMap mapMalleableKeys;
+
     ScriptMap mapScripts;
     WatchOnlySet setWatchOnly;
-    MalleableKeyPair malleableKeyPair;
 
 public:
     bool AddKey(const CKey& key);
@@ -132,22 +134,39 @@ public:
 
     bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
     {
-        bool result;
         {
             LOCK(cs_KeyStore);
-            result = const_cast<CBasicKeyStore*>(this)->malleableKeyPair.first.CheckKeyVariant(R, pubKeyVariant);
+            for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
+            {
+                if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+                    return true;
+            }
         }
-        return result;
+        return false;
     }
 
     bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
     {
-        bool result;
         {
             LOCK(cs_KeyStore);
-            result = const_cast<CBasicKeyStore*>(this)->malleableKeyPair.second.CheckKeyVariant(R, pubKeyVariant, privKey);
+            for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
+            {
+                if (mi->second.CheckKeyVariant(R, pubKeyVariant, privKey))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    void ListMalleablePubKeys(std::list<CMalleablePubKey> &malleablePubKeyList) const
+    {
+        malleablePubKeyList.clear();
+
+        {
+            LOCK(cs_KeyStore);
+            for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
+                malleablePubKeyList.push_back(mi->first.GetMalleablePubKey());
         }
-        return result;
     }
 };
 
index c2b43c7..6a7a3b1 100644 (file)
@@ -1936,3 +1936,22 @@ Value adjustmalleablepubkey(const Array& params, bool fHelp)
 
     return result;
 }
+
+Value listmalleablepubkeys(const Array& params, bool fHelp)
+{
+    if (fHelp || params.size() != 0)
+        throw runtime_error(
+            "listmalleablepubkeys\n"
+            "Get list of malleable public keys.\n");
+
+    std::list<CMalleablePubKey> keyList;
+    pwalletMain->ListMalleablePubKeys(keyList);
+
+    Array result;
+    BOOST_FOREACH(const CMalleablePubKey &key, keyList)
+    {
+        result.push_back(key.ToString());
+    }
+
+    return result;
+}