Experimental support for TX_PUBKEY_DROP spending.
author0xDEADFACE <masmfan@gmail.com>
Fri, 12 Feb 2016 23:43:57 +0000 (15:43 -0800)
committer0xDEADFACE <masmfan@gmail.com>
Fri, 12 Feb 2016 23:43:57 +0000 (15:43 -0800)
src/key.cpp
src/key.h
src/keystore.cpp
src/keystore.h
src/script.cpp

index eb4f5c4..9503f95 100644 (file)
@@ -1004,6 +1004,14 @@ CMalleableKeyView::CMalleableKeyView(const CMalleableKey &b)
     vchPubKeyH = H.GetPubKey().Raw();
 }
 
+CMalleableKeyView::CMalleableKeyView(const CMalleableKeyView &b)
+{
+    assert(b.nVersion == CURRENT_VERSION);
+    vchSecretL = b.vchSecretL;
+    vchPubKeyH = b.vchPubKeyH;
+    nVersion = CURRENT_VERSION;
+}
+
 CMalleableKeyView::CMalleableKeyView(const CSecret &L, const CPubKey &pvchPubKeyH)
 {
     vchSecretL = L;
@@ -1095,6 +1103,33 @@ bool CMalleableKeyView::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubK
     return true;
 }
 
+std::string CMalleableKeyView::ToString()
+{
+    CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
+    ssKey << *this;
+    std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
+
+    return EncodeBase58Check(vch);
+}
+
+bool CMalleableKeyView::SetString(const std::string& strMutableKey)
+{
+    std::vector<unsigned char> vchTemp;
+    if (!DecodeBase58Check(strMutableKey, vchTemp)) {
+        throw key_error("CMalleableKeyView::SetString() : Provided key data seems corrupted.");
+    }
+
+    CDataStream ssKey(vchTemp, SER_NETWORK, PROTOCOL_VERSION);
+    ssKey >> *this;
+
+    return IsNull();
+}
+
+bool CMalleableKeyView::IsNull() const
+{
+    return nVersion != CURRENT_VERSION;
+}
+
 //// Asymmetric encryption
 
 void CPubKey::EncryptData(const std::vector<unsigned char>& data, std::vector<unsigned char>& encrypted)
index f8404db..ca78c72 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -277,7 +277,6 @@ 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);
 };
@@ -285,15 +284,14 @@ public:
 class CMalleableKeyView
 {
 private:
+    unsigned char nVersion;
     CSecret vchSecretL;
     std::vector<unsigned char> vchPubKeyH;
 
-    // disabled constructor
-    CMalleableKeyView() { };
-
     static const unsigned char CURRENT_VERSION = 1;
 
 public:
+    CMalleableKeyView() { nVersion = 0; };
     CMalleableKeyView(const CMalleableKey &b);
     CMalleableKeyView(const CSecret &L, const CPubKey &pvchPubKeyH);
 
@@ -301,8 +299,19 @@ public:
     CMalleableKeyView& operator=(const CMalleableKey &b);
     ~CMalleableKeyView();
 
-    CMalleablePubKey GetMalleablePubKey() const;
 
+    IMPLEMENT_SERIALIZE(
+        READWRITE(this->nVersion);
+        nVersion = this->nVersion;
+        READWRITE(vchSecretL);
+        READWRITE(vchPubKeyH);
+    )
+
+    bool IsNull() const;
+    std::string ToString();
+    bool SetString(const std::string& strMalleablePubKey);
+
+    CMalleablePubKey GetMalleablePubKey() const;
     bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant);
 };
 
index ef61748..197b73e 100644 (file)
@@ -102,6 +102,20 @@ bool CBasicKeyStore::HaveWatchOnly() const
     return (!setWatchOnly.empty());
 }
 
+CCryptoKeyStore::CCryptoKeyStore() : fUseCrypto(false)
+{
+    std::string strMalleableKey = GetArg("-masterkey", "");
+    CMalleableKey malleableKey;
+    if (strMalleableKey != "")
+        malleableKey.SetString(strMalleableKey);
+    else
+        malleableKey.MakeNewKeys();
+
+    CMalleableKeyView keyView(malleableKey);
+
+    malleableKeyPair = std::pair<CMalleableKeyView, CMalleableKey>(keyView, malleableKey);
+}
+
 bool CCryptoKeyStore::SetCrypted()
 {
     {
@@ -154,6 +168,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
                 break;
             return false;
         }
+
         vMasterKey = vMasterKeyIn;
     }
     NotifyStatusChanged(this);
index 96285fb..7dc3464 100644 (file)
@@ -64,11 +64,15 @@ public:
         vchSecret = key.GetSecret(fCompressed);
         return true;
     }
+
+    virtual bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const =0;
+    virtual bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) 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;
 
 /** Basic key store, that keeps keys in an address->secret map */
 class CBasicKeyStore : public CKeyStore
@@ -77,6 +81,7 @@ protected:
     KeyMap mapKeys;
     ScriptMap mapScripts;
     WatchOnlySet setWatchOnly;
+    MalleableKeyPair malleableKeyPair;
 
 public:
     bool AddKey(const CKey& key);
@@ -124,6 +129,26 @@ public:
     virtual bool RemoveWatchOnly(const CScript &dest);
     virtual bool HaveWatchOnly(const CScript &dest) const;
     virtual bool HaveWatchOnly() const;
+
+    bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
+    {
+        bool result;
+        {
+            LOCK(cs_KeyStore);
+            result = const_cast<CBasicKeyStore*>(this)->malleableKeyPair.first.CheckKeyVariant(R, pubKeyVariant);
+        }
+        return result;
+    }
+
+    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);
+        }
+        return result;
+    }
 };
 
 typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
@@ -152,9 +177,7 @@ protected:
     bool Unlock(const CKeyingMaterial& vMasterKeyIn);
 
 public:
-    CCryptoKeyStore() : fUseCrypto(false)
-    {
-    }
+    CCryptoKeyStore();
 
     bool IsCrypted() const
     {
index 9079102..26b7c94 100644 (file)
@@ -1328,6 +1328,21 @@ bool Sign1(const CKeyID& address, const CKeyStore& keystore, const uint256& hash
     return true;
 }
 
+bool SignR(const CPubKey& pubKey, const CPubKey& R, const CKeyStore& keystore, const uint256& hash, int nHashType, CScript& scriptSigRet)
+{
+    CKey key;
+    if (!keystore.CreatePrivKey(pubKey, R, key))
+        return false;
+
+    vector<unsigned char> vchSig;
+    if (!key.Sign(hash, vchSig))
+        return false;
+    vchSig.push_back((unsigned char)nHashType);
+    scriptSigRet << vchSig;
+
+    return true;
+}
+
 bool SignN(const vector<valtype>& multisigdata, const CKeyStore& keystore, const uint256& hash, int nHashType, CScript& scriptSigRet)
 {
     int nSigned = 0;
@@ -1364,9 +1379,14 @@ bool Solver(const CKeyStore& keystore, const CScript& scriptPubKey, const uint25
     case TX_NULL_DATA:
         return false;
     case TX_PUBKEY:
-    case TX_PUBKEY_DROP:
         keyID = CPubKey(vSolutions[0]).GetID();
         return Sign1(keyID, keystore, hash, nHashType, scriptSigRet);
+    case TX_PUBKEY_DROP:
+        {
+            CPubKey key = CPubKey(vSolutions[0]);
+            CPubKey R = CPubKey(vSolutions[1]);
+            return SignR(key, R, keystore, hash, nHashType, scriptSigRet);
+        }
     case TX_PUBKEYHASH:
         keyID = CKeyID(uint160(vSolutions[0]));
         if (!Sign1(keyID, keystore, hash, nHashType, scriptSigRet))
@@ -1480,11 +1500,23 @@ isminetype IsMine(const CKeyStore &keystore, const CScript& scriptPubKey)
     case TX_NULL_DATA:
         break;
     case TX_PUBKEY:
-    case TX_PUBKEY_DROP:
         keyID = CPubKey(vSolutions[0]).GetID();
         if (keystore.HaveKey(keyID))
             return MINE_SPENDABLE;
         break;
+    case TX_PUBKEY_DROP:
+        {
+            CPubKey key = CPubKey(vSolutions[0]);
+            if (keystore.HaveKey(key.GetID()))
+                return MINE_SPENDABLE;
+            else
+            {
+                CPubKey R = CPubKey(vSolutions[1]);
+                if (keystore.CheckOwnership(key, R))
+                    return MINE_SPENDABLE;
+            }
+        }
+        break;
     case TX_PUBKEYHASH:
         keyID = CKeyID(uint160(vSolutions[0]));
         if (keystore.HaveKey(keyID))
@@ -1527,7 +1559,7 @@ bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet)
     if (!Solver(scriptPubKey, whichType, vSolutions))
         return false;
 
-    if (whichType == TX_PUBKEY)
+    if (whichType == TX_PUBKEY || whichType == TX_PUBKEY_DROP)
     {
         addressRet = CPubKey(vSolutions[0]).GetID();
         return true;