diff --git a/core/src/main/java/com/google/bitcoin/core/ECKey.java b/core/src/main/java/com/google/bitcoin/core/ECKey.java index 337853c6..3ea67fb3 100644 --- a/core/src/main/java/com/google/bitcoin/core/ECKey.java +++ b/core/src/main/java/com/google/bitcoin/core/ECKey.java @@ -1095,8 +1095,13 @@ public class ECKey implements EncryptableItem, Serializable { private String toString(boolean includePrivate) { final ToStringHelper helper = Objects.toStringHelper(this).omitNullValues(); helper.add("pub", Utils.HEX.encode(pub.getEncoded())); - if (includePrivate && priv != null) - helper.add("priv", Utils.HEX.encode(priv.toByteArray())); + if (includePrivate) { + try { + helper.add("priv", Utils.HEX.encode(getPrivKey().toByteArray())); + } catch (IllegalStateException e) { + // TODO: Make hasPrivKey() work for deterministic keys and fix this. + } + } if (creationTimeSeconds > 0) helper.add("creationTimeSeconds", creationTimeSeconds); helper.add("keyCrypter", keyCrypter); diff --git a/core/src/main/java/com/google/bitcoin/wallet/DeterministicKeyChain.java b/core/src/main/java/com/google/bitcoin/wallet/DeterministicKeyChain.java index 034de0b3..9df87571 100644 --- a/core/src/main/java/com/google/bitcoin/wallet/DeterministicKeyChain.java +++ b/core/src/main/java/com/google/bitcoin/wallet/DeterministicKeyChain.java @@ -1007,18 +1007,33 @@ public class DeterministicKeyChain implements EncryptableKeyChain { } } - // For internal usage only (for printing keys in KeyChainGroup). - /* package */ List getKeys() { - return basicKeyChain.getKeys(); + // For internal usage only + /* package */ List getKeys(boolean includeLookahead) { + List keys = basicKeyChain.getKeys(); + if (!includeLookahead) { + int treeSize = internalKey.getPath().size(); + List issuedKeys = new LinkedList(); + for (ECKey key : keys) { + DeterministicKey detkey = (DeterministicKey) key; + DeterministicKey parent = detkey.getParent(); + if (parent == null) continue; + if (detkey.getPath().size() <= treeSize) continue; + if (parent.equals(internalKey) && detkey.getChildNumber().i() > issuedInternalKeys) continue; + if (parent.equals(externalKey) && detkey.getChildNumber().i() > issuedExternalKeys) continue; + issuedKeys.add(detkey); + } + return issuedKeys; + } + return keys; } /** - * Returns leaf keys issued by this chain (not including lookahead zone) + * Returns leaf keys issued by this chain (including lookahead zone) */ public List getLeafKeys() { ImmutableList.Builder keys = ImmutableList.builder(); - for (ECKey key : getKeys()) { + for (ECKey key : getKeys(true)) { DeterministicKey dKey = (DeterministicKey) key; if (dKey.getPath().size() > 2) { keys.add(dKey); diff --git a/core/src/main/java/com/google/bitcoin/wallet/KeyChainGroup.java b/core/src/main/java/com/google/bitcoin/wallet/KeyChainGroup.java index 13e431c3..dbbbe261 100644 --- a/core/src/main/java/com/google/bitcoin/wallet/KeyChainGroup.java +++ b/core/src/main/java/com/google/bitcoin/wallet/KeyChainGroup.java @@ -872,7 +872,7 @@ public class KeyChainGroup implements KeyBag { for (RedeemData redeemData : marriedKeysRedeemData.values()) formatScript(ScriptBuilder.createP2SHOutputScript(redeemData.redeemScript), builder2); } else { - for (ECKey key : chain.getKeys()) + for (ECKey key : chain.getKeys(false)) formatKeyWithAddress(includePrivateKeys, key, builder2); } chainStrs.add(builder2.toString()); @@ -895,9 +895,17 @@ public class KeyChainGroup implements KeyBag { builder.append(address.toString()); builder.append(" hash160:"); builder.append(Utils.HEX.encode(key.getPubKeyHash())); - builder.append("\n "); - builder.append(includePrivateKeys ? key.toStringWithPrivate() : key.toString()); + if (key instanceof DeterministicKey) { + builder.append(" ("); + builder.append((((DeterministicKey) key).getPathAsString())); + builder.append(")"); + } builder.append("\n"); + if (includePrivateKeys) { + builder.append(" "); + builder.append(key.toStringWithPrivate()); + builder.append("\n"); + } } /** Returns a copy of the current list of chains. */ diff --git a/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java b/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java index f358531c..686be808 100644 --- a/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java +++ b/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java @@ -222,6 +222,7 @@ public class WalletTool { OptionSpec paymentRequestLocation = parser.accepts("payment-request").withRequiredArg(); parser.accepts("no-pki"); parser.accepts("tor"); + parser.accepts("dump-privkeys"); options = parser.parse(args); final String HELP_TEXT = Resources.toString(WalletTool.class.getResource("wallet-tool-help.txt"), Charsets.UTF_8); @@ -1057,6 +1058,6 @@ public class WalletTool { // there just for the dump case. if (chainFileName.exists()) setup(); - System.out.println(wallet.toString(true, true, true, chain)); + System.out.println(wallet.toString(options.has("dump-privkeys"), true, true, chain)); } } diff --git a/tools/src/main/resources/com/google/bitcoin/tools/wallet-tool-help.txt b/tools/src/main/resources/com/google/bitcoin/tools/wallet-tool-help.txt index 6491b1a0..a466566c 100644 --- a/tools/src/main/resources/com/google/bitcoin/tools/wallet-tool-help.txt +++ b/tools/src/main/resources/com/google/bitcoin/tools/wallet-tool-help.txt @@ -4,7 +4,8 @@ Usage: wallet-tool --flags action-name wallet-tool action-name --flags >>> ACTIONS - dump Loads and prints the given wallet in textual form to stdout. + dump Loads and prints the given wallet in textual form to stdout. Private keys are only printed + if --dump-privkeys is specified. raw-dump Prints the wallet as a raw protobuf with no parsing or sanity checking applied. create Makes a new wallet in the file specified by --wallet. Will complain and require --force if the wallet already exists.