From fe0f38a9dd454d2847bedc08c2bcad720b36116c Mon Sep 17 00:00:00 2001 From: 0xDEADFACE Date: Sat, 13 Feb 2016 13:25:37 -0800 Subject: [PATCH] ListMalleablePubKeys method --- src/bitcoinrpc.cpp | 1 + src/bitcoinrpc.h | 1 + src/key.cpp | 49 +++++++++++++++++++++++++++++++------------------ src/key.h | 19 ++++++++++++------- src/keystore.cpp | 5 ++--- src/keystore.h | 35 +++++++++++++++++++++++++++-------- src/rpcwallet.cpp | 19 +++++++++++++++++++ 7 files changed, 93 insertions(+), 36 deletions(-) diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 719aef0..92042d0 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -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}, }; diff --git a/src/bitcoinrpc.h b/src/bitcoinrpc.h index 3b0e199..226007b 100644 --- a/src/bitcoinrpc.h +++ b/src/bitcoinrpc.h @@ -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); diff --git a/src/key.cpp b/src/key.cpp index 89c0dcc..dafffcf 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -592,6 +592,12 @@ bool CPoint::setBytes(const std::vector &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 &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 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 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; diff --git a/src/key.h b/src/key.h index ca78c72..a829834 100644 --- a/src/key.h +++ b/src/key.h @@ -191,6 +191,9 @@ public: // Initialize from octets stream bool setBytes(const std::vector &vchBytes); + // Initialize from pubkey + bool setPubKey(const CPubKey &vchPubKey); + // Serialize to octets stream bool getBytes(std::vector &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 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 diff --git a/src/keystore.cpp b/src/keystore.cpp index 197b73e..fdba291 100644 --- a/src/keystore.cpp +++ b/src/keystore.cpp @@ -111,9 +111,8 @@ CCryptoKeyStore::CCryptoKeyStore() : fUseCrypto(false) else malleableKey.MakeNewKeys(); - CMalleableKeyView keyView(malleableKey); - - malleableKeyPair = std::pair(keyView, malleableKey); + const CMalleableKeyView& keyView(malleableKey); + mapMalleableKeys[keyView] = malleableKey; } bool CCryptoKeyStore::SetCrypted() diff --git a/src/keystore.h b/src/keystore.h index 7dc3464..7d49735 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -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 &malleablePubKeyList) const =0; }; typedef std::map > KeyMap; typedef std::map ScriptMap; typedef std::set WatchOnlySet; -typedef std::pair MalleableKeyPair; +typedef std::map 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(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(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 &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; } }; diff --git a/src/rpcwallet.cpp b/src/rpcwallet.cpp index c2b43c7..6a7a3b1 100644 --- a/src/rpcwallet.cpp +++ b/src/rpcwallet.cpp @@ -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 keyList; + pwalletMain->ListMalleablePubKeys(keyList); + + Array result; + BOOST_FOREACH(const CMalleablePubKey &key, keyList) + { + result.push_back(key.ToString()); + } + + return result; +} -- 1.7.1