Skip to content

Commit

Permalink
Bech32 addresses in dumpwallet
Browse files Browse the repository at this point in the history
Output bech32 addresses in dumpwallet if address type is not as legacy

Github-Pull: #12315
Rebased-From: 45eea40
Tree-SHA512: 3426292ddaeaafebc25fe84802011f5569a0cbb47fcc3209e7f00f64fc6eb1e637732722bbd02dce8d46be87d0f3687ce8370e71e9286bf7d00afc0a895faecb
  • Loading branch information
fivepiece authored and laanwj committed Feb 8, 2018
1 parent 3f5012b commit 758a41e
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 7 deletions.
29 changes: 26 additions & 3 deletions src/wallet/rpcdump.cpp
Expand Up @@ -71,6 +71,28 @@ std::string DecodeDumpString(const std::string &str) {
return ret.str();
}

bool GetWalletAddressesForKey(CWallet * const pwallet, const CKeyID &keyid, std::string &strAddr, std::string &strLabel)
{
bool fLabelFound = false;
CKey key;
pwallet->GetKey(keyid, key);
for (const auto& dest : GetAllDestinationsForKey(key.GetPubKey())) {
if (pwallet->mapAddressBook.count(dest)) {
if (!strAddr.empty()) {
strAddr += ",";
}
strAddr += EncodeDestination(dest);
strLabel = EncodeDumpString(pwallet->mapAddressBook[dest].name);
fLabelFound = true;
}
}
if (!fLabelFound) {
strAddr = EncodeDestination(GetDestinationForKey(key.GetPubKey(), g_address_type));
}
return fLabelFound;
}


UniValue importprivkey(const JSONRPCRequest& request)
{
CWallet * const pwallet = GetWalletForJSONRPCRequest(request);
Expand Down Expand Up @@ -729,12 +751,13 @@ UniValue dumpwallet(const JSONRPCRequest& request)
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 = EncodeDestination(keyid);
std::string strAddr;
std::string strLabel;
CKey key;
if (pwallet->GetKey(keyid, key)) {
file << strprintf("%s %s ", CBitcoinSecret(key).ToString(), strTime);
if (pwallet->mapAddressBook.count(keyid)) {
file << strprintf("label=%s", EncodeDumpString(pwallet->mapAddressBook[keyid].name));
if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) {
file << strprintf("label=%s", strLabel);
} else if (keyid == masterKeyID) {
file << "hdmaster=1";
} else if (mapKeyPool.count(keyid)) {
Expand Down
20 changes: 16 additions & 4 deletions test/functional/wallet_dump.py
Expand Up @@ -20,6 +20,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_script_addr = 0
found_addr_chg = 0
found_addr_rsv = 0
witness_addr_ret = None
hd_master_addr_ret = None
for line in inputfile:
# only read non comment lines
Expand Down Expand Up @@ -47,7 +48,14 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):

# count key types
for addrObj in addrs:
if addrObj['address'] == addr and addrObj['hdkeypath'] == keypath and keytype == "label=":
if addrObj['address'] == addr.split(",")[0] and addrObj['hdkeypath'] == keypath and keytype == "label=":
# a labled entry in the wallet should contain both a native address
# and the p2sh-p2wpkh address that was added at wallet setup
if len(addr.split(",")) == 2:
addr_list = addr.split(",")
# the entry should be of the first key in the wallet
assert_equal(addrs[0]['address'], addr_list[0])
witness_addr_ret = addr_list[1]
found_addr += 1
break
elif keytype == "change=1":
Expand All @@ -63,7 +71,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old):
found_script_addr += 1
break

return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret
return found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_ret, witness_addr_ret


class WalletDumpTest(BitcoinTestFramework):
Expand All @@ -83,6 +91,8 @@ def run_test (self):
tmpdir = self.options.tmpdir

# generate 20 addresses to compare against the dump
# but since we add a p2sh-p2wpkh address for the first pubkey in the
# wallet, we will expect 21 addresses in the dump
test_addr_count = 20
addrs = []
for i in range(0,test_addr_count):
Expand All @@ -101,12 +111,13 @@ def run_test (self):
result = self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.unencrypted.dump")
assert_equal(result['filename'], os.path.abspath(tmpdir + "/node0/wallet.unencrypted.dump"))

found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc = \
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, hd_master_addr_unenc, witness_addr_ret = \
read_dump(tmpdir + "/node0/wallet.unencrypted.dump", addrs, script_addrs, None)
assert_equal(found_addr, test_addr_count) # all keys must be in the dump
assert_equal(found_script_addr, 2) # all scripts must be in the dump
assert_equal(found_addr_chg, 50) # 50 blocks where mined
assert_equal(found_addr_rsv, 90*2) # 90 keys plus 100% internal keys
assert_equal(witness_addr_ret, witness_addr) # p2sh-p2wsh address added to the first key

#encrypt wallet, restart, unlock and dump
self.nodes[0].node_encrypt_wallet('test')
Expand All @@ -116,12 +127,13 @@ def run_test (self):
self.nodes[0].keypoolrefill()
self.nodes[0].dumpwallet(tmpdir + "/node0/wallet.encrypted.dump")

found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _ = \
found_addr, found_script_addr, found_addr_chg, found_addr_rsv, _, witness_addr_ret = \
read_dump(tmpdir + "/node0/wallet.encrypted.dump", addrs, script_addrs, hd_master_addr_unenc)
assert_equal(found_addr, test_addr_count)
assert_equal(found_script_addr, 2)
assert_equal(found_addr_chg, 90*2 + 50) # old reserve keys are marked as change now
assert_equal(found_addr_rsv, 90*2)
assert_equal(witness_addr_ret, witness_addr)

# Overwriting should fail
assert_raises_rpc_error(-8, "already exists", self.nodes[0].dumpwallet, tmpdir + "/node0/wallet.unencrypted.dump")
Expand Down

0 comments on commit 758a41e

Please sign in to comment.