diff --git a/doc/release-notes.md b/doc/release-notes.md --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -3,4 +3,7 @@ This release includes the following features and fixes: - - `dumpwallet` now includes hex-encoded scripts from the wallet in the dumpfile \ No newline at end of file + - `dumpwallet` now includes hex-encoded scripts from the wallet in the dumpfile + - `importwallet` now imports these scripts, but corresponding addresses may not + be added correctly or a manual rescan may be required to find relevant + transactions \ No newline at end of file diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -589,46 +589,64 @@ continue; } CBitcoinSecret vchSecret; - if (!vchSecret.SetString(vstr[0])) { - continue; - } - CKey key = vchSecret.GetKey(); - CPubKey pubkey = key.GetPubKey(); - assert(key.VerifyPubKey(pubkey)); - CKeyID keyid = pubkey.GetID(); - if (pwallet->HaveKey(keyid)) { - LogPrintf("Skipping import of %s (key already present)\n", - EncodeDestination(keyid)); - continue; - } - int64_t nTime = DecodeDumpTime(vstr[1]); - std::string strLabel; - bool fLabel = true; - for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) { - if (boost::algorithm::starts_with(vstr[nStr], "#")) { - break; + if (vchSecret.SetString(vstr[0])) { + CKey key = vchSecret.GetKey(); + CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); + CKeyID keyid = pubkey.GetID(); + if (pwallet->HaveKey(keyid)) { + LogPrintf("Skipping import of %s (key already present)\n", + EncodeDestination(keyid)); + continue; } - if (vstr[nStr] == "change=1") { - fLabel = false; + int64_t nTime = DecodeDumpTime(vstr[1]); + std::string strLabel; + bool fLabel = true; + for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) { + if (boost::algorithm::starts_with(vstr[nStr], "#")) { + break; + } + if (vstr[nStr] == "change=1") { + fLabel = false; + } + if (vstr[nStr] == "reserve=1") { + fLabel = false; + } + if (boost::algorithm::starts_with(vstr[nStr], "label=")) { + strLabel = DecodeDumpString(vstr[nStr].substr(6)); + fLabel = true; + } } - if (vstr[nStr] == "reserve=1") { - fLabel = false; + LogPrintf("Importing %s...\n", EncodeDestination(keyid)); + if (!pwallet->AddKeyPubKey(key, pubkey)) { + fGood = false; + continue; } - if (boost::algorithm::starts_with(vstr[nStr], "label=")) { - strLabel = DecodeDumpString(vstr[nStr].substr(6)); - fLabel = true; + pwallet->mapKeyMetadata[keyid].nCreateTime = nTime; + if (fLabel) { + pwallet->SetAddressBook(keyid, strLabel, "receive"); + } + nTimeBegin = std::min(nTimeBegin, nTime); + } else if (IsHex(vstr[0])) { + std::vector vData(ParseHex(vstr[0])); + CScript script = CScript(vData.begin(), vData.end()); + if (pwallet->HaveCScript(script)) { + LogPrintf("Skipping import of %s (script already present)\n", + vstr[0]); + continue; + } + if (!pwallet->AddCScript(script)) { + LogPrintf("Error importing script %s\n", vstr[0]); + fGood = false; + continue; + } + int64_t birth_time = DecodeDumpTime(vstr[1]); + if (birth_time > 0) { + pwallet->m_script_metadata[CScriptID(script)].nCreateTime = + birth_time; + nTimeBegin = std::min(nTimeBegin, birth_time); } } - LogPrintf("Importing %s...\n", EncodeDestination(keyid)); - if (!pwallet->AddKeyPubKey(key, pubkey)) { - fGood = false; - continue; - } - pwallet->mapKeyMetadata[keyid].nCreateTime = nTime; - if (fLabel) { - pwallet->SetAddressBook(keyid, strLabel, "receive"); - } - nTimeBegin = std::min(nTimeBegin, nTime); } file.close(); @@ -641,7 +659,7 @@ if (!fGood) { throw JSONRPCError(RPC_WALLET_ERROR, - "Error adding some keys to wallet"); + "Error adding some keys/scripts to wallet"); } return NullUniValue; diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py --- a/test/functional/wallet_dump.py +++ b/test/functional/wallet_dump.py @@ -136,6 +136,21 @@ assert_raises_rpc_error(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump") + # Restart node with new wallet, and test importwallet + self.stop_node(0) + self.start_node(0, ['-wallet=w2']) + + # Make sure the address is not IsMine before import + result = self.nodes[0].validateaddress(multisig_addr) + assert(result['ismine'] == False) + + self.nodes[0].importwallet(os.path.abspath( + tmpdir + "/node0/wallet.unencrypted.dump")) + + # Now check IsMine is true + result = self.nodes[0].validateaddress(multisig_addr) + assert(result['ismine'] == True) + if __name__ == '__main__': WalletDumpTest().main()