WalletTool: allow skipping of mandatory extensions.

This allows it to read MultiBit wallets.
This commit is contained in:
Mike Hearn 2013-11-10 20:03:30 +01:00
parent a68bc627ee
commit 688ba42c45
2 changed files with 24 additions and 3 deletions

View file

@ -66,10 +66,21 @@ public class WalletProtobufSerializer {
// Used for de-serialization // Used for de-serialization
protected Map<ByteString, Transaction> txMap; protected Map<ByteString, Transaction> txMap;
private boolean requireMandatoryExtensions = true;
public WalletProtobufSerializer() { public WalletProtobufSerializer() {
txMap = new HashMap<ByteString, Transaction>(); txMap = new HashMap<ByteString, Transaction>();
} }
/**
* 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.<p> * Formats the given wallet (transactions and keys) to the given output stream in protocol buffer format.<p>
* *
@ -427,22 +438,27 @@ public class WalletProtobufSerializer {
txMap.clear(); 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<String, WalletExtension> extensions = wallet.getExtensions(); final Map<String, WalletExtension> extensions = wallet.getExtensions();
for (Protos.Extension extProto : walletProto.getExtensionList()) { for (Protos.Extension extProto : walletProto.getExtensionList()) {
String id = extProto.getId(); String id = extProto.getId();
WalletExtension extension = extensions.get(id); WalletExtension extension = extensions.get(id);
if (extension == null) { if (extension == null) {
if (extProto.getMandatory()) { 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 { } else {
log.info("Loading wallet extension {}", id); log.info("Loading wallet extension {}", id);
try { try {
extension.deserializeWalletExtension(wallet, extProto.getData().toByteArray()); extension.deserializeWalletExtension(wallet, extProto.getData().toByteArray());
} catch (Exception e) { } catch (Exception e) {
if (extProto.getMandatory()) if (extProto.getMandatory() && requireMandatoryExtensions)
throw new UnreadableWalletException("Could not parse mandatory extension in wallet: " + id); throw new UnreadableWalletException("Could not parse mandatory extension in wallet: " + id);
else
log.error("Error whilst reading extension {}, ignoring: {}", id, e);
} }
} }
} }

View file

@ -74,6 +74,8 @@ public class WalletTool {
" one of the following operators = < > <= >= immediately followed by a number.\n" + " one of the following operators = < > <= >= immediately followed by a number.\n" +
" For example --condition=\">5.10\" or --condition=\"<=1\"\n" + " For example --condition=\">5.10\" or --condition=\"<=1\"\n" +
" --password=... For an encrypted wallet, the password is provided here.\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" + "\n>>> ACTIONS\n" +
" --action=DUMP Loads and prints the given wallet in textual form to stdout.\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("locktime").withRequiredArg();
parser.accepts("allow-unconfirmed"); parser.accepts("allow-unconfirmed");
parser.accepts("offline"); parser.accepts("offline");
parser.accepts("ignore-mandatory-extensions");
OptionSpec<String> passwordFlag = parser.accepts("password").withRequiredArg(); OptionSpec<String> passwordFlag = parser.accepts("password").withRequiredArg();
options = parser.parse(args); options = parser.parse(args);
@ -336,6 +339,8 @@ public class WalletTool {
try { try {
WalletProtobufSerializer loader = new WalletProtobufSerializer(); WalletProtobufSerializer loader = new WalletProtobufSerializer();
if (options.has("ignore-mandatory-extensions"))
loader.setRequireMandatoryExtensions(false);
wallet = loader.readWallet(new BufferedInputStream(new FileInputStream(walletFile))); wallet = loader.readWallet(new BufferedInputStream(new FileInputStream(walletFile)));
if (!wallet.getParams().equals(params)) { if (!wallet.getParams().equals(params)) {
System.err.println("Wallet does not match requested network parameters: " + System.err.println("Wallet does not match requested network parameters: " +