Merge branch 'patch' of ssh://github.com/svost/novacoin into svost-patch
authorCryptoManiac <balthazar@yandex.ru>
Sat, 5 Mar 2016 17:45:37 +0000 (20:45 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Sat, 5 Mar 2016 17:45:37 +0000 (20:45 +0300)
15 files changed:
novacoin-qt.pro
src/db.cpp
src/key.cpp
src/key.h
src/keystore.cpp
src/keystore.h
src/main.cpp
src/qt/coincontroldialog.cpp
src/qt/transactionrecord.cpp
src/qt/walletmodel.cpp
src/rpcdump.cpp
src/wallet.cpp
src/wallet.h
src/walletdb.cpp
src/walletdb.h

index 52f9959..abafeb7 100644 (file)
@@ -51,6 +51,14 @@ contains(RELEASE, 1) {
     }
 }
 
+contains(DEBUG, 1) {
+    QMAKE_CXXFLAGS_RELEASE -= -O2
+    QMAKE_CFLAGS_RELEASE -= -O2
+
+    QMAKE_CFLAGS += -g -O0
+    QMAKE_CXXCFLAGS += -g -O0
+}
+
 !win32 {
 # for extra security against potential buffer overflows: enable GCCs Stack Smashing Protection
 QMAKE_CXXFLAGS *= -fstack-protector-all --param ssp-buffer-size=1
index 757a18e..68d19fe 100644 (file)
@@ -397,7 +397,6 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
 
                     Dbc* pcursor = db.GetCursor();
                     if (pcursor) {
-                        size_t pszSkipLen = strlen(pszSkip);
                         while (fSuccess)
                         {
                             CDataStream ssKey(SER_DISK, CLIENT_VERSION);
@@ -414,9 +413,14 @@ bool CDB::Rewrite(const string& strFile, const char* pszSkip)
                                 fSuccess = false;
                                 break;
                             }
-                            if (pszSkip &&
-                                strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), pszSkipLen)) == 0)
-                                continue;
+
+                            if (pszSkip != NULL)
+                            {
+                                size_t pszSkipLen = strlen(pszSkip);
+                                if (strncmp(&ssKey[0], pszSkip, std::min(ssKey.size(), pszSkipLen)) == 0)
+                                    continue;
+                            }
+
                             if (strncmp(&ssKey[0], "\x07version", 8) == 0)
                             {
                                 // Update version:
index c11da92..6c0a57d 100644 (file)
@@ -1002,6 +1002,11 @@ bool CMalleableKey::SetString(const std::string& strMutableKey)
 
 // CMalleableKeyView
 
+CMalleableKeyView::CMalleableKeyView(const std::string &strMalleableKey)
+{
+    SetString(strMalleableKey);
+}
+
 CMalleableKeyView::CMalleableKeyView(const CMalleableKey &b)
 {
     if (b.vchSecretL.size() != 32)
index a9ac6c7..c3dea57 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -324,6 +324,7 @@ private:
 public:
     CMalleableKeyView() { nVersion = 0; };
     CMalleableKeyView(const CMalleableKey &b);
+    CMalleableKeyView(const std::string &strMalleableKey);
 
     CMalleableKeyView(const CMalleableKeyView &b);
     CMalleableKeyView& operator=(const CMalleableKey &b);
index fdbecba..215590e 100644 (file)
@@ -29,11 +29,11 @@ bool CBasicKeyStore::AddKey(const CKey& key)
     return true;
 }
 
-bool CBasicKeyStore::AddMalleableKey(const CMalleableKey& mKey)
+bool CBasicKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH)
 {
     {
         LOCK(cs_KeyStore);
-        mapMalleableKeys[CMalleableKeyView(mKey)] = mKey;
+        mapMalleableKeys[CMalleableKeyView(keyView)] = vchSecretH;
     }
     return true;
 }
@@ -199,6 +199,28 @@ bool CCryptoKeyStore::AddKey(const CKey& key)
     return true;
 }
 
+bool CCryptoKeyStore::AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH)
+{
+    {
+        LOCK(cs_KeyStore);
+        if (!SetCrypted())
+            return CBasicKeyStore::AddMalleableKey(keyView, vchSecretH);
+
+        if (IsLocked())
+            return false;
+
+        CKey keyH;
+        keyH.SetSecret(vchSecretH, true);
+
+        std::vector<unsigned char> vchCryptedSecretH;
+        if (!EncryptSecret(vMasterKey, vchSecretH, keyH.GetPubKey().GetHash(), vchCryptedSecretH))
+            return false;
+
+        if (!AddCryptedMalleableKey(keyView, vchCryptedSecretH))
+            return false;
+    }
+    return true;
+}
 
 bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret)
 {
@@ -212,6 +234,71 @@ bool CCryptoKeyStore::AddCryptedKey(const CPubKey &vchPubKey, const std::vector<
     return true;
 }
 
+bool CCryptoKeyStore::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char>  &vchCryptedSecretH)
+{
+    {
+        LOCK(cs_KeyStore);
+        if (!SetCrypted())
+            return false;
+
+        mapCryptedMalleableKeys[CMalleableKeyView(keyView)] = vchCryptedSecretH;
+    }
+    return true;
+}
+
+bool CCryptoKeyStore::CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const
+{
+    {
+        LOCK(cs_KeyStore);
+        if (!IsCrypted())
+            return CBasicKeyStore::CreatePrivKey(pubKeyVariant, R, privKey);
+
+        for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+        {
+            if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+            {
+                const CPubKey H = mi->first.GetMalleablePubKey().GetH();
+
+                CSecret vchSecretH;
+                if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
+                    return false;
+                if (vchSecretH.size() != 32)
+                    return false;
+
+                CMalleableKey mKey = mi->first.GetMalleableKey(vchSecretH);
+                return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);;
+            }
+        }
+
+    }
+    return true;
+}
+
+bool CCryptoKeyStore::GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
+{
+    {
+        LOCK(cs_KeyStore);
+        if (!IsCrypted())
+            return CBasicKeyStore::GetMalleableKey(keyView, mKey);
+        CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.find(keyView);
+        if (mi != mapCryptedMalleableKeys.end())
+        {
+            const CPubKey H = keyView.GetMalleablePubKey().GetH();
+
+            CSecret vchSecretH;
+            if (!DecryptSecret(vMasterKey, mi->second, H.GetHash(), vchSecretH))
+                return false;
+
+            if (vchSecretH.size() != 32)
+                return false;
+            mKey = mi->first.GetMalleableKey(vchSecretH);
+
+            return true;
+        }
+    }
+    return false;
+}
+
 bool CCryptoKeyStore::GetKey(const CKeyID &address, CKey& keyOut) const
 {
     {
@@ -276,6 +363,17 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
                 return false;
         }
         mapKeys.clear();
+
+        BOOST_FOREACH(MalleableKeyMap::value_type& mKey, mapMalleableKeys)
+        {
+            const CPubKey vchPubKeyH = mKey.first.GetMalleablePubKey().GetH();
+            std::vector<unsigned char> vchCryptedSecretH;
+            if (!EncryptSecret(vMasterKeyIn, mKey.second, vchPubKeyH.GetHash(), vchCryptedSecretH))
+                return false;
+            if (!AddCryptedMalleableKey(mKey.first, vchCryptedSecretH))
+                return false;
+        }
+        mapMalleableKeys.clear();
     }
     return true;
 }
@@ -305,6 +403,22 @@ bool CCryptoKeyStore::DecryptKeys(const CKeyingMaterial& vMasterKeyIn)
         }
 
         mapCryptedKeys.clear();
+
+        CryptedMalleableKeyMap::const_iterator mi2 = mapCryptedMalleableKeys.begin();
+        for(; mi2 != mapCryptedMalleableKeys.end(); ++mi2)
+        {
+            const CPubKey vchPubKeyH = mi2->first.GetMalleablePubKey().GetH();
+
+            CSecret vchSecretH;
+            if(!DecryptSecret(vMasterKeyIn, mi2->second, vchPubKeyH.GetHash(), vchSecretH))
+                return false;
+            if (vchSecretH.size() != 32)
+                return false;
+
+            if (!CBasicKeyStore::AddMalleableKey(mi2->first, vchSecretH))
+                return false;
+        }
+        mapCryptedMalleableKeys.clear();
     }
 
     return true;
index fa4f33c..438752f 100644 (file)
@@ -40,7 +40,7 @@ public:
     virtual bool AddKey(const CKey& key) =0;
 
     // Add a malleable key to store.
-    virtual bool AddMalleableKey(const CMalleableKey& mKey) =0;
+    virtual bool AddMalleableKey(const CMalleableKeyView &keyView, const CSecret &vchSecretH) =0;
     virtual bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const =0;
 
     // Check whether a key corresponding to a given address is present in the store.
@@ -78,7 +78,7 @@ public:
 typedef std::map<CKeyID, std::pair<CSecret, bool> > KeyMap;
 typedef std::map<CScriptID, CScript > ScriptMap;
 typedef std::set<CScript> WatchOnlySet;
-typedef std::map<CMalleableKeyView, CMalleableKey> MalleableKeyMap;
+typedef std::map<CMalleableKeyView, CSecret> MalleableKeyMap;
 
 /** Basic key store, that keeps keys in an address->secret map */
 class CBasicKeyStore : public CKeyStore
@@ -92,7 +92,7 @@ protected:
 
 public:
     bool AddKey(const CKey& key);
-    bool AddMalleableKey(const CMalleableKey& mKey);
+    bool AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH);
     bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const
     {
         {
@@ -100,7 +100,7 @@ public:
             MalleableKeyMap::const_iterator mi = mapMalleableKeys.find(keyView);
             if (mi != mapMalleableKeys.end())
             {
-                mKey = mi->second;
+                mKey = mi->first.GetMalleableKey(mi->second);
                 return true;
             }
         }
@@ -183,8 +183,11 @@ public:
             LOCK(cs_KeyStore);
             for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
             {
-                if (mi->second.CheckKeyVariant(R, pubKeyVariant, privKey))
-                    return true;
+                if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+                {
+                    CMalleableKey mKey = mi->first.GetMalleableKey(mi->second);
+                    return mKey.CheckKeyVariant(R, pubKeyVariant, privKey);
+                }
             }
         }
         return false;
@@ -193,7 +196,6 @@ public:
     void ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
     {
         malleableViewList.clear();
-
         {
             LOCK(cs_KeyStore);
             for (MalleableKeyMap::const_iterator mi = mapMalleableKeys.begin(); mi != mapMalleableKeys.end(); mi++)
@@ -219,6 +221,7 @@ public:
 };
 
 typedef std::map<CKeyID, std::pair<CPubKey, std::vector<unsigned char> > > CryptedKeyMap;
+typedef std::map<CMalleableKeyView, std::vector<unsigned char> > CryptedMalleableKeyMap;
 
 /** Keystore which keeps the private keys encrypted.
  * It derives from the basic key store, which is used if no encryption is active.
@@ -227,6 +230,7 @@ class CCryptoKeyStore : public CBasicKeyStore
 {
 private:
     CryptedKeyMap mapCryptedKeys;
+    CryptedMalleableKeyMap mapCryptedMalleableKeys;
 
     CKeyingMaterial vMasterKey;
 
@@ -266,7 +270,10 @@ public:
     bool Lock();
 
     virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+    virtual bool AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char>  &vchCryptedSecretH);
+
     bool AddKey(const CKey& key);
+    bool AddMalleableKey(const CMalleableKeyView& keyView, const CSecret &vchSecretH);
     bool HaveKey(const CKeyID &address) const
     {
         {
@@ -294,6 +301,73 @@ public:
         }
     }
 
+    bool GetMalleableKey(const CMalleableKeyView &keyView, CMalleableKey &mKey) const;
+
+    bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R) const
+    {
+        {
+            LOCK(cs_KeyStore);
+            if (!IsCrypted())
+                return CBasicKeyStore::CheckOwnership(pubKeyVariant, R);
+            for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+            {
+                if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+                    return true;
+            }
+        }
+        return false;
+    }
+
+    bool CheckOwnership(const CPubKey &pubKeyVariant, const CPubKey &R, CMalleableKeyView &view) const
+    {
+        {
+            LOCK(cs_KeyStore);
+            if (!IsCrypted())
+                return CBasicKeyStore::CheckOwnership(pubKeyVariant, R, view);
+            for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+            {
+                if (mi->first.CheckKeyVariant(R, pubKeyVariant))
+                {
+                    view = mi->first;
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    bool CreatePrivKey(const CPubKey &pubKeyVariant, const CPubKey &R, CKey &privKey) const;
+
+    void ListMalleableViews(std::list<CMalleableKeyView> &malleableViewList) const
+    {
+        malleableViewList.clear();
+        {
+            LOCK(cs_KeyStore);
+            if (!IsCrypted())
+                return CBasicKeyStore::ListMalleableViews(malleableViewList);
+            for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+                malleableViewList.push_back(CMalleableKeyView(mi->first));
+        }
+    }
+
+    bool GetMalleableView(const CMalleablePubKey &mpk, CMalleableKeyView &view)
+    {
+        const CKeyID &mpkID = mpk.GetID();
+        {
+            LOCK(cs_KeyStore);
+            if (!IsCrypted())
+                return CBasicKeyStore::GetMalleableView(mpk, view);
+            for (CryptedMalleableKeyMap::const_iterator mi = mapCryptedMalleableKeys.begin(); mi != mapCryptedMalleableKeys.end(); mi++)
+                if (mi->first.GetID() == mpkID)
+                {
+                    view = CMalleableKeyView(mi->first);
+                    return true;
+                }
+        }
+
+        return false;
+    }
+
     /* Wallet status (encrypted, locked) changed.
      * Note: Called without locks held.
      */
index 970dd7e..3ab03f2 100644 (file)
@@ -510,10 +510,6 @@ bool CTransaction::CheckTransaction() const
         return DoS(10, error("CTransaction::CheckTransaction() : vin empty"));
     if (vout.empty())
         return DoS(10, error("CTransaction::CheckTransaction() : vout empty"));
-    // Time (prevent mempool memory exhaustion attack)
-    // Comes into force since 20 December 2015.
-    if (nTime > 1450569600 && nTime > FutureDrift(GetAdjustedTime()))
-        return DoS(10, error("CTransaction::CheckTransaction() : timestamp is too far into the future"));
     // Size limits
     if (::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
         return DoS(100, error("CTransaction::CheckTransaction() : size limits failed"));
@@ -622,6 +618,10 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs,
     if (pfMissingInputs)
         *pfMissingInputs = false;
 
+    // Time (prevent mempool memory exhaustion attack)
+    if (tx.nTime > FutureDrift(GetAdjustedTime()))
+        return tx.DoS(10, error("CTxMemPool::accept() : transaction timestamp is too far in the future"));
+
     if (!tx.CheckTransaction())
         return error("CTxMemPool::accept() : CheckTransaction failed");
 
@@ -2348,8 +2348,8 @@ bool CBlock::AcceptBlock()
 
     int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
     int nMaxOffset = 12 * nOneHour; // 12 hours
-    if (pindexPrev->nTime < 1450569600)
-        nMaxOffset = nOneWeek; // One week until 20 Dec, 2015
+    if (fTestNet || pindexPrev->nTime < 1450569600)
+        nMaxOffset = 7 * nOneWeek; // One week (permanently on testNet or until 20 Dec, 2015 on mainNet)
 
     // Check timestamp against prev
     if (GetBlockTime() <= nMedianTimePast || FutureDrift(GetBlockTime()) < pindexPrev->GetBlockTime())
index ae73042..998a992 100644 (file)
@@ -631,6 +631,7 @@ void CoinControlDialog::updateView()
             itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked);
 
             // address
+/*
             CTxDestination outputAddress;
             QString sAddress = "";
             if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress))
@@ -646,6 +647,52 @@ void CoinControlDialog::updateView()
                 if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed())
                     nInputSize = 180;
             }
+*/
+            QString sAddress = "";
+            txnouttype whichType;
+            std::vector<valtype> vSolutions;
+            if (Solver(out.tx->vout[out.i].scriptPubKey, whichType, vSolutions))
+            {
+                CTxDestination address;
+                if (whichType == TX_PUBKEY)
+                {
+                    // Pay-to-Pubkey
+                    CPubKey pubKey = CPubKey(vSolutions[0]);
+                    address = pubKey.GetID();
+                    sAddress = CBitcoinAddress(address).ToString().c_str();
+
+                    if (!pubKey.IsCompressed())
+                        nInputSize = 180;
+                }
+                else if (whichType == TX_PUBKEYHASH)
+                {
+                    // Pay-to-PubkeyHash
+                    address = CKeyID(uint160(vSolutions[0]));
+                    sAddress = CBitcoinAddress(address).ToString().c_str();
+
+                    CPubKey pubkey;
+                    CKeyID *keyid = boost::get< CKeyID >(&address);
+                    if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed())
+                        nInputSize = 180;
+                }
+                else if (whichType == TX_SCRIPTHASH)
+                {
+                    // Pay-to-ScriptHash
+                    address = CScriptID(uint160(vSolutions[0]));
+                    sAddress = CBitcoinAddress(address).ToString().c_str();
+                }
+                else if (whichType == TX_PUBKEY_DROP)
+                {
+                    // Pay-to-Pubkey-R
+                    CMalleableKeyView view;
+                    pwalletMain->CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view);
+                    sAddress = view.GetMalleablePubKey().ToString().c_str();
+                }
+
+                // if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
+                if (!treeMode || (!(sAddress == sWalletAddress)))
+                    itemOutput->setText(COLUMN_ADDRESS, sAddress);
+            }
 
             // label
             if (!(sAddress == sWalletAddress)) // change
index 34d3edf..e28a64b 100644 (file)
@@ -3,6 +3,8 @@
 #include "wallet.h"
 #include "base58.h"
 
+extern CWallet* pwalletMain;
+
 /* Return positive answer if transaction should be shown in list.
  */
 bool TransactionRecord::showTransaction(const CWalletTx &wtx)
@@ -41,14 +43,14 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
             if(wallet->IsMine(txout))
             {
                 TransactionRecord sub(hash, nTime);
-                CTxDestination address;
                 sub.idx = parts.size(); // sequence number
                 sub.credit = txout.nValue;
-                if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*wallet, address))
+
+                std::string address;
+                if (pwalletMain->ExtractAddress(txout.scriptPubKey, address))
                 {
-                    // Received by Bitcoin Address
                     sub.type = TransactionRecord::RecvWithAddress;
-                    sub.address = CBitcoinAddress(address).ToString();
+                    sub.address = address;
                 }
                 else
                 {
@@ -56,6 +58,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
                     sub.type = TransactionRecord::RecvFromOther;
                     sub.address = mapValue["from"];
                 }
+
                 if (wtx.IsCoinBase())
                 {
                     // Generated (proof-of-work)
index 4769fda..47b12e9 100644 (file)
@@ -495,10 +495,11 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
             cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true);
         }
 
-        CTxDestination address;
-        if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address))
+        std::string address;
+        if(!out.fSpendable || !wallet->ExtractAddress(cout.tx->vout[cout.i].scriptPubKey, address))
             continue;
-        mapCoins[CBitcoinAddress(address).ToString().c_str()].push_back(out);
+
+        mapCoins[address.c_str()].push_back(out);
     }
 }
 
index b0693ed..6a83604 100644 (file)
@@ -39,6 +39,8 @@ Value importprivkey(const Array& params, bool fHelp)
             "importprivkey <novacoinprivkey> [label] [rescan=true]\n"
             "Adds a private key (as returned by dumpprivkey) to your wallet.");
 
+    EnsureWalletIsUnlocked();
+
     string strSecret = params[0].get_str();
     string strLabel = "";
     if (params.size() > 1)
@@ -247,6 +249,8 @@ Value dumpmalleablekey(const Array& params, bool fHelp)
             "dumpmalleablekey <Key view>\n"
             "Dump the private and public key pairs, which correspond to provided key view.\n");
 
+    EnsureWalletIsUnlocked();
+
     CMalleableKey mKey;
     CMalleableKeyView keyView;
     keyView.SetString(params[0].get_str());
@@ -268,6 +272,9 @@ Value importmalleablekey(const Array& params, bool fHelp)
             "importmalleablekey <Key data>\n"
             "Imports the private key pair into your wallet.\n");
 
+
+    EnsureWalletIsUnlocked();
+
     CMalleableKey mKey;
     bool fSuccess = mKey.SetString(params[0].get_str());
 
index 12000be..ee601ca 100644 (file)
@@ -94,12 +94,32 @@ bool CWallet::AddKey(const CKey& key)
 bool CWallet::AddMalleableKey(const CMalleableKey& mKey)
 {
     CMalleableKeyView keyView = CMalleableKeyView(mKey);
-    if (!CCryptoKeyStore::AddMalleableKey(mKey))
+    CSecret vchSecretH = mKey.GetSecretH();
+    if (!CCryptoKeyStore::AddMalleableKey(keyView, vchSecretH))
         return false;
     if (!fFileBacked)
         return true;
     if (!IsCrypted())
-        return CWalletDB(strWalletFile).WriteMalleableKey(keyView, mKey, mapMalleableKeyMetadata[keyView]);
+        return CWalletDB(strWalletFile).WriteMalleableKey(keyView, vchSecretH, mapMalleableKeyMetadata[keyView]);
+    return true;
+}
+
+bool CWallet::AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH)
+{
+    if (!CCryptoKeyStore::AddCryptedMalleableKey(keyView, vchCryptedSecretH))
+        return false;
+
+    if (!fFileBacked)
+        return true;
+
+    {
+        LOCK(cs_wallet);
+        if (pwalletdbEncryption)
+            return pwalletdbEncryption->WriteCryptedMalleableKey(keyView, vchCryptedSecretH, mapMalleableKeyMetadata[keyView]);
+        else
+            return CWalletDB(strWalletFile).WriteCryptedMalleableKey(keyView, vchCryptedSecretH, mapMalleableKeyMetadata[keyView]);
+    }
+
     return true;
 }
 
@@ -460,6 +480,16 @@ bool CWallet::DecryptWallet(const SecureString& strWalletPassphrase)
                 mi++;
             }
 
+            MalleableKeyMap::const_iterator mi2 = mapMalleableKeys.begin();
+            while (mi2 != mapMalleableKeys.end())
+            {
+                const CSecret &vchSecretH = mi2->second;
+                const CMalleableKeyView &keyView = mi2->first;
+                pwalletdbDecryption->EraseCryptedMalleableKey(keyView);
+                pwalletdbDecryption->WriteMalleableKey(keyView, vchSecretH, mapMalleableKeyMetadata[keyView]);
+                mi2++;
+            }
+
             // Erase master keys
             MasterKeyMap::const_iterator mk = mapMasterKeys.begin();
             while (mk != mapMasterKeys.end())
@@ -2779,3 +2809,39 @@ void CWallet::ClearOrphans()
     for(list<uint256>::const_iterator it = orphans.begin(); it != orphans.end(); ++it)
         EraseFromWallet(*it);
 }
+
+bool CWallet::ExtractAddress(const CScript& scriptPubKey, std::string& addressRet)
+{
+    vector<valtype> vSolutions;
+    txnouttype whichType;
+    if (!Solver(scriptPubKey, whichType, vSolutions))
+        return false;
+
+    if (whichType == TX_PUBKEY)
+    {
+        addressRet = CBitcoinAddress(CPubKey(vSolutions[0]).GetID()).ToString();
+        return true;
+    }
+    if (whichType == TX_PUBKEY_DROP)
+    {
+        // Pay-to-Pubkey-R
+        CMalleableKeyView view;
+        if (!CheckOwnership(CPubKey(vSolutions[0]), CPubKey(vSolutions[1]), view))
+            return false;
+
+        addressRet = view.GetMalleablePubKey().ToString();
+        return true;
+    }
+    else if (whichType == TX_PUBKEYHASH)
+    {
+        addressRet = CBitcoinAddress(CKeyID(uint160(vSolutions[0]))).ToString();
+        return true;
+    }
+    else if (whichType == TX_SCRIPTHASH)
+    {
+        addressRet = CBitcoinAddress(CScriptID(uint160(vSolutions[0]))).ToString();
+        return true;
+    }
+    // Multisig txns have more than one address...
+    return false;
+}
index bc8afa8..d07aa7c 100644 (file)
@@ -161,12 +161,14 @@ public:
     bool LoadMalleableKeyMetadata(const CMalleableKeyView &keyView, const CKeyMetadata &metadata);
 
     // Load malleable key without saving it to disk (used by LoadWallet)
-    bool LoadMalleableKey(const CMalleableKey &mKey) { return CCryptoKeyStore::AddMalleableKey(mKey); }
+    bool LoadMalleableKey(const CMalleableKeyView &keyView, const CSecret &vchSecretH) { return CCryptoKeyStore::AddMalleableKey(keyView, vchSecretH); }
+    bool LoadCryptedMalleableKey(const CMalleableKeyView &keyView, const std::vector<unsigned char> &vchCryptedSecretH) { return CCryptoKeyStore::AddCryptedMalleableKey(keyView, vchCryptedSecretH); }
 
     bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
 
     // Adds an encrypted key to the store, and saves it to disk.
     bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
+    bool AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH);
     // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
     bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
     bool AddCScript(const CScript& redeemScript);
@@ -337,6 +339,8 @@ public:
 
     bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
 
+    bool ExtractAddress(const CScript& scriptPubKey, std::string& addressRet);
+
     bool SetDefaultKey(const CPubKey &vchPubKey);
 
     // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
index 64168ee..a072f18 100644 (file)
@@ -304,31 +304,31 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
         }
         else if (strType == "malpair")
         {
-            string strKey, strKeyView;
-
-            CMalleableKey mKey;
-            CMalleableKeyView keyView;
+            string strKeyView;
 
+            CSecret vchSecret;
             ssKey >> strKeyView;
-            ssValue >> strKey;
-
-            keyView.SetString(strKeyView);
-            mKey.SetString(strKey);
+            ssValue >> vchSecret;
 
-            if (mKey.IsNull())
-            {
-                strErr = "Error reading wallet database: CMalleableKey is corrupt";
-                return false;
-            }
-            if (mKey.GetID() != keyView.GetID())
+            CMalleableKeyView keyView(strKeyView);
+            if (!pwallet->LoadMalleableKey(keyView, vchSecret))
             {
-                strErr = "Error reading wallet database: CMalleableKey view inconsistency";
+                strErr = "Error reading wallet database: LoadMalleableKey failed";
                 return false;
             }
+        }
+        else if (strType == "malcpair")
+        {
+            string strKeyView;
 
-            if (!pwallet->LoadMalleableKey(mKey))
+            std::vector<unsigned char> vchCryptedSecret;
+            ssKey >> strKeyView;
+            ssValue >> vchCryptedSecret;
+
+            CMalleableKeyView keyView(strKeyView);
+            if (!pwallet->LoadCryptedMalleableKey(keyView, vchCryptedSecret))
             {
-                strErr = "Error reading wallet database: LoadMalleableKey failed";
+                strErr = "Error reading wallet database: LoadCryptedMalleableKey failed";
                 return false;
             }
         }
@@ -497,7 +497,7 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
 static bool IsKeyType(string strType)
 {
     return (strType== "key" || strType == "wkey" ||
-            strType == "mkey" || strType == "ckey" || strType == "malpair");
+            strType == "mkey" || strType == "ckey" || strType == "malpair" || strType == "malcpair");
 }
 
 DBErrors CWalletDB::LoadWallet(CWallet* pwallet)
index fe2b225..94b355f 100644 (file)
@@ -95,18 +95,32 @@ public:
         return true;
     }
 
-    bool WriteMalleableKey(const CMalleableKeyView& keyView, const CMalleableKey& malleableKey, const CKeyMetadata &keyMeta)
+    bool WriteMalleableKey(const CMalleableKeyView& keyView, const CSecret& vchSecretH, const CKeyMetadata &keyMeta)
     {
         nWalletDBUpdated++;
         if(!Write(std::make_pair(std::string("malmeta"), keyView.ToString()), keyMeta))
             return false;
 
-        if(!Write(std::make_pair(std::string("malpair"), keyView.ToString()), malleableKey.ToString(), false))
+        if(!Write(std::make_pair(std::string("malpair"), keyView.ToString()), vchSecretH, false))
             return false;
 
         return true;
     }
 
+    bool WriteCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char>& vchCryptedSecretH, const CKeyMetadata &keyMeta)
+    {
+        nWalletDBUpdated++;
+        if(!Write(std::make_pair(std::string("malmeta"), keyView.ToString()), keyMeta))
+            return false;
+
+        if(!Write(std::make_pair(std::string("malcpair"), keyView.ToString()), vchCryptedSecretH, false))
+            return false;
+
+        Erase(std::make_pair(std::string("malpair"), keyView.ToString()));
+
+        return true;
+    }
+
 
     bool WriteCryptedKey(const CPubKey& vchPubKey, const std::vector<unsigned char>& vchCryptedSecret, const CKeyMetadata &keyMeta)
     {
@@ -143,6 +157,11 @@ public:
         return Erase(std::make_pair(std::string("ckey"), vchPubKey.Raw()));
     }
 
+    bool EraseCryptedMalleableKey(const CMalleableKeyView& keyView)
+    {
+        return Erase(std::make_pair(std::string("malcpair"), keyView.ToString()));
+    }
+
     bool WriteCScript(const uint160& hash, const CScript& redeemScript)
     {
         nWalletDBUpdated++;