New dump function.
authorCryptoManiac <balthazar@yandex.ru>
Mon, 7 Mar 2016 23:46:59 +0000 (02:46 +0300)
committerCryptoManiac <balthazar@yandex.ru>
Mon, 7 Mar 2016 23:46:59 +0000 (02:46 +0300)
TODO: pubkey pair addresses import.

src/key.h
src/wallet.cpp
src/wallet.h
src/walletdb.cpp

index bc7e2ab..2d8e618 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -224,6 +224,7 @@ public:
         pubKeyL = mpk.pubKeyL;
         pubKeyH = mpk.pubKeyH;
     }
+    CMalleablePubKey(const std::vector<unsigned char> &vchPubKeyPair) { setvch(vchPubKeyPair); }
     CMalleablePubKey(const std::string& strMalleablePubKey) { SetString(strMalleablePubKey); }
     CMalleablePubKey(const CPubKey &pubKeyInL, const CPubKey &pubKeyInH) : pubKeyL(pubKeyInL), pubKeyH(pubKeyInH) { }
 
index 1846d17..beb5d85 100644 (file)
@@ -2741,55 +2741,50 @@ void CWallet::UpdatedTransaction(const uint256 &hashTx)
     }
 }
 
-void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
-    mapKeyBirth.clear();
+void CWallet::GetAddresses(std::map<CBitcoinAddress, int64_t> &mapAddresses) const {
+    mapAddresses.clear();
 
     // get birth times for keys with metadata
-    for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
-        if (it->second.nCreateTime)
-            mapKeyBirth[it->first] = it->second.nCreateTime;
-
-    // map in which we'll infer heights of other keys
-    CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
-    std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
-    std::set<CKeyID> setKeys;
-    GetKeys(setKeys);
-    BOOST_FOREACH(const CKeyID &keyid, setKeys) {
-        if (mapKeyBirth.count(keyid) == 0)
-            mapKeyFirstBlock[keyid] = pindexMax;
-    }
-    setKeys.clear();
-
-    // if there are no such keys, we're done
-    if (mapKeyFirstBlock.empty())
-        return;
+    for (std::map<CMalleableKeyView, CKeyMetadata>::const_iterator it = mapMalleableKeyMetadata.begin(); it != mapMalleableKeyMetadata.end(); it++) {
+        CBitcoinAddress addr(it->first.GetMalleablePubKey());
+        mapAddresses[addr] = it->second.nCreateTime ? it->second.nCreateTime : 0;
+    }
+
+    for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++) {
+        CBitcoinAddress addr(it->first);
+        mapAddresses[addr] = it->second.nCreateTime ? it->second.nCreateTime : 0;
+    }
 
-    // find first block that affects those keys, if there are any left
-    std::vector<CKeyID> vAffected;
     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
         // iterate over all wallet transactions...
         const CWalletTx &wtx = (*it).second;
-        std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
-        if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
-            // ... which are already in a block
-            int nHeight = blit->second->nHeight;
-            BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
-                // iterate over all their outputs
-                ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
-                BOOST_FOREACH(const CKeyID &keyid, vAffected) {
-                    // ... and all their affected keys
-                    std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
-                    if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
-                        rit->second = blit->second;
+        if (wtx.hashBlock == 0)
+            continue; // skip unconfirmed transactions
+
+        for(std::vector<CTxOut>::const_iterator it2 = wtx.vout.begin(); it2 != wtx.vout.end(); it2++) {
+            const CTxOut &out = (*it2);
+            // iterate over all their outputs
+            CBitcoinAddress addressRet;
+            if (const_cast<CWallet*>(this)->ExtractAddress(out.scriptPubKey, addressRet)) {
+                if (mapAddresses.find(addressRet) != mapAddresses.end() && mapAddresses[addressRet] > wtx.nTime)
+                    mapAddresses[addressRet] = wtx.nTime;
+            }
+            else {
+                // multisig output affects more than one key
+                std::vector<CKeyID> vAffected;
+                ::ExtractAffectedKeys(*this, out.scriptPubKey, vAffected);
+
+                for(std::vector<CKeyID>::const_iterator it3 = vAffected.begin(); it3 != vAffected.end(); it3++) {
+                    CBitcoinAddress addrAffected(*it3);
+
+                    if (mapAddresses.find(addrAffected) != mapAddresses.end() && mapAddresses[addrAffected] > wtx.nTime)
+                        mapAddresses[addrAffected] = wtx.nTime;
                 }
                 vAffected.clear();
             }
         }
-    }
 
-    // Extract block timestamps for those keys
-    for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
-        mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
+    }
 }
 
 void CWallet::ClearOrphans()
index aa21944..493e9d9 100644 (file)
@@ -186,7 +186,7 @@ public:
     bool EncryptWallet(const SecureString& strWalletPassphrase);
     bool DecryptWallet(const SecureString& strWalletPassphrase);
 
-    void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const;
+    void GetAddresses(std::map<CBitcoinAddress, int64_t> &mapAddresses) const;
 
 
     /** Increment the next transaction order id
index 5c78ff2..c9e187d 100644 (file)
@@ -784,75 +784,94 @@ bool BackupWallet(const CWallet& wallet, const string& strDest)
 
 bool DumpWallet(CWallet* pwallet, const string& strDest)
 {
+    if (!pwallet->fFileBacked)
+        return false;
 
-  if (!pwallet->fFileBacked)
-      return false;
-  while (!fShutdown)
-  {
-      // Populate maps
-      std::map<CKeyID, int64_t> mapKeyBirth;
-      std::set<CKeyID> setKeyPool;
-      pwallet->GetKeyBirthTimes(mapKeyBirth);
-      pwallet->GetAllReserveKeys(setKeyPool);
-
-      // sort time/key pairs
-      std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
-      for (std::map<CKeyID, int64_t>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
-          vKeyBirth.push_back(std::make_pair(it->second, it->first));
-      }
-      mapKeyBirth.clear();
-      std::sort(vKeyBirth.begin(), vKeyBirth.end());
+    std::map<CBitcoinAddress, int64_t> mapAddresses;
+    std::set<CKeyID> setKeyPool;
 
-      // open outputfile as a stream
-      ofstream file;
-      file.open(strDest.c_str());
-      if (!file.is_open())
-         return false;
-
-      // produce output
-      file << strprintf("# Wallet dump created by NovaCoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
-      file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
-      file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
-      file << strprintf("#   mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
-      file << "\n";
-      for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
-          const CKeyID &keyid = it->second;
-          std::string strTime = EncodeDumpTime(it->first);
-          std::string strAddr = CBitcoinAddress(keyid).ToString();
-          bool IsCompressed;
+    pwallet->GetAddresses(mapAddresses);
+    pwallet->GetAllReserveKeys(setKeyPool);
 
-          CKey key;
-          if (pwallet->GetKey(keyid, key)) {
-              if (pwallet->mapAddressBook.count(keyid)) {
-                  CSecret secret = key.GetSecret(IsCompressed);
-                  file << strprintf("%s %s label=%s # addr=%s\n",
-                                    CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
-                                    strTime.c_str(),
-                                    EncodeDumpString(pwallet->mapAddressBook[keyid]).c_str(),
-                                    strAddr.c_str());
-              } else if (setKeyPool.count(keyid)) {
-                  CSecret secret = key.GetSecret(IsCompressed);
-                  file << strprintf("%s %s reserve=1 # addr=%s\n",
-                                    CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
-                                    strTime.c_str(),
-                                    strAddr.c_str());
-              } else {
-                  CSecret secret = key.GetSecret(IsCompressed);
-                  file << strprintf("%s %s change=1 # addr=%s\n",
-                                    CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
-                                    strTime.c_str(),
-                                    strAddr.c_str());
-              }
-          }
-      }
-      file << "\n";
-      file << "# End of dump\n";
-      file.close();
-      return true;
-     }
-   return false;
-}
+    // sort time/key pairs
+    std::vector<std::pair<int64_t, CBitcoinAddress> > vAddresses;
+    for (std::map<CBitcoinAddress, int64_t>::const_iterator it = mapAddresses.begin(); it != mapAddresses.end(); it++) {
+        vAddresses.push_back(std::make_pair(it->second, it->first));
+    }
+    mapAddresses.clear();
+    std::sort(vAddresses.begin(), vAddresses.end());
 
+    // open outputfile as a stream
+    ofstream file;
+    file.open(strDest.c_str());
+    if (!file.is_open())
+       return false;
+
+    // produce output
+    file << strprintf("# Wallet dump created by NovaCoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
+    file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
+    file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
+    file << strprintf("#   mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
+    file << "\n";
+
+    for (std::vector<std::pair<int64_t, CBitcoinAddress> >::const_iterator it = vAddresses.begin(); it != vAddresses.end(); it++) {
+        const CBitcoinAddress &addr = it->second;
+        std::string strTime = EncodeDumpTime(it->first);
+        std::string strAddr = addr.ToString();
+        bool IsCompressed;
+
+        if (addr.IsPair()) {
+            // Pubkey pair address
+            CMalleableKeyView keyView;
+            CMalleablePubKey mPubKey(addr.GetData());
+            if (pwallet->GetMalleableView(mPubKey, keyView)) {
+                CMalleableKey mKey;
+                pwallet->GetMalleableKey(keyView, mKey);
+
+                file << strprintf("%s %s # addr=%s view=%s\n",
+                                  mKey.ToString().c_str(),
+                                  strTime.c_str(),
+                                  strAddr.c_str(),
+                                  keyView.ToString().c_str());
+            }
+        }
+        else {
+            // Pubkey hash address
+            CKeyID keyid;
+            addr.GetKeyID(keyid);
+
+            CKey key;
+            if (pwallet->GetKey(keyid, key)) {
+                if (pwallet->mapAddressBook.count(keyid)) {
+                    CSecret secret = key.GetSecret(IsCompressed);
+                    file << strprintf("%s %s label=%s # addr=%s\n",
+                                      CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+                                      strTime.c_str(),
+                                      EncodeDumpString(pwallet->mapAddressBook[keyid]).c_str(),
+                                      strAddr.c_str());
+                } else if (setKeyPool.count(keyid)) {
+                    CSecret secret = key.GetSecret(IsCompressed);
+                    file << strprintf("%s %s reserve=1 # addr=%s\n",
+                                      CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+                                      strTime.c_str(),
+                                      strAddr.c_str());
+                } else {
+                    CSecret secret = key.GetSecret(IsCompressed);
+                    file << strprintf("%s %s change=1 # addr=%s\n",
+                                      CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+                                      strTime.c_str(),
+                                      strAddr.c_str());
+                }
+            }
+        }
+    }
+
+    file << "\n";
+    file << "# End of dump\n";
+    file.close();
+
+    return true;
+}
 
 bool ImportWallet(CWallet *pwallet, const string& strLocation)
 {