diff --git a/core/src/main/java/com/google/bitcoin/store/WalletProtobufSerializer.java b/core/src/main/java/com/google/bitcoin/store/WalletProtobufSerializer.java index 219ea7ad..cbd2dcd8 100644 --- a/core/src/main/java/com/google/bitcoin/store/WalletProtobufSerializer.java +++ b/core/src/main/java/com/google/bitcoin/store/WalletProtobufSerializer.java @@ -66,10 +66,21 @@ public class WalletProtobufSerializer { // Used for de-serialization protected Map txMap; + private boolean requireMandatoryExtensions = true; + public WalletProtobufSerializer() { txMap = new HashMap(); } + /** + * If this property is set to false, then unknown mandatory extensions will be ignored instead of causing load + * errors. You should only use this if you know exactly what you are doing, as the extension data will NOT be + * round-tripped, possibly resulting in a corrupted wallet if you save it back out again. + */ + public void setRequireMandatoryExtensions(boolean value) { + requireMandatoryExtensions = value; + } + /** * Formats the given wallet (transactions and keys) to the given output stream in protocol buffer format.

* @@ -427,22 +438,27 @@ public class WalletProtobufSerializer { txMap.clear(); } - private static void loadExtensions(Wallet wallet, Protos.Wallet walletProto) throws UnreadableWalletException { + private void loadExtensions(Wallet wallet, Protos.Wallet walletProto) throws UnreadableWalletException { final Map extensions = wallet.getExtensions(); for (Protos.Extension extProto : walletProto.getExtensionList()) { String id = extProto.getId(); WalletExtension extension = extensions.get(id); if (extension == null) { if (extProto.getMandatory()) { - throw new UnreadableWalletException("Unknown mandatory extension in wallet: " + id); + if (requireMandatoryExtensions) + throw new UnreadableWalletException("Unknown mandatory extension in wallet: " + id); + else + log.error("Unknown extension in wallet {}, ignoring", id); } } else { log.info("Loading wallet extension {}", id); try { extension.deserializeWalletExtension(wallet, extProto.getData().toByteArray()); } catch (Exception e) { - if (extProto.getMandatory()) + if (extProto.getMandatory() && requireMandatoryExtensions) throw new UnreadableWalletException("Could not parse mandatory extension in wallet: " + id); + else + log.error("Error whilst reading extension {}, ignoring: {}", id, e); } } } 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 d04ebc65..aa52cf31 100644 --- a/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java +++ b/tools/src/main/java/com/google/bitcoin/tools/WalletTool.java @@ -74,6 +74,8 @@ public class WalletTool { " one of the following operators = < > <= >= immediately followed by a number.\n" + " For example --condition=\">5.10\" or --condition=\"<=1\"\n" + " --password=... For an encrypted wallet, the password is provided here.\n" + + " --ignore-mandatory-extensions If a wallet has unknown required extensions that would otherwise cause\n" + + " load failures, this overrides that.\n" + "\n>>> ACTIONS\n" + " --action=DUMP Loads and prints the given wallet in textual form to stdout.\n" + @@ -261,6 +263,7 @@ public class WalletTool { parser.accepts("locktime").withRequiredArg(); parser.accepts("allow-unconfirmed"); parser.accepts("offline"); + parser.accepts("ignore-mandatory-extensions"); OptionSpec passwordFlag = parser.accepts("password").withRequiredArg(); options = parser.parse(args); @@ -336,6 +339,8 @@ public class WalletTool { try { WalletProtobufSerializer loader = new WalletProtobufSerializer(); + if (options.has("ignore-mandatory-extensions")) + loader.setRequireMandatoryExtensions(false); wallet = loader.readWallet(new BufferedInputStream(new FileInputStream(walletFile))); if (!wallet.getParams().equals(params)) { System.err.println("Wallet does not match requested network parameters: " +