3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-31 15:22:16 +00:00

HD Wallets: do auto upgrade when possible on all inbound codepaths, and make DeterministicUpgradeRequiresPassword extend RuntimeException.

This commit is contained in:
Mike Hearn 2014-06-17 16:20:38 +02:00
parent 7f68c3472f
commit 523b3018cb
2 changed files with 23 additions and 15 deletions

View File

@ -288,6 +288,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
public DeterministicKey currentKey(KeyChain.KeyPurpose purpose) { public DeterministicKey currentKey(KeyChain.KeyPurpose purpose) {
lock.lock(); lock.lock();
try { try {
maybeUpgradeToHD();
return keychain.currentKey(purpose); return keychain.currentKey(purpose);
} finally { } finally {
lock.unlock(); lock.unlock();
@ -308,6 +309,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
public Address currentAddress(KeyChain.KeyPurpose purpose) { public Address currentAddress(KeyChain.KeyPurpose purpose) {
lock.lock(); lock.lock();
try { try {
maybeUpgradeToHD();
return keychain.currentAddress(purpose, params); return keychain.currentAddress(purpose, params);
} finally { } finally {
lock.unlock(); lock.unlock();
@ -345,20 +347,8 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
public List<DeterministicKey> freshKeys(KeyChain.KeyPurpose purpose, int numberOfKeys) { public List<DeterministicKey> freshKeys(KeyChain.KeyPurpose purpose, int numberOfKeys) {
lock.lock(); lock.lock();
try { try {
List<DeterministicKey> keys; maybeUpgradeToHD();
try { List<DeterministicKey> keys = keychain.freshKeys(purpose, numberOfKeys);
keys = keychain.freshKeys(purpose, numberOfKeys);
} catch (DeterministicUpgradeRequiredException e) {
log.info("Attempt to request a fresh HD key on a non-upgraded wallet, trying to upgrade ...");
try {
upgradeToDeterministic(null);
keys = keychain.freshKeys(purpose, numberOfKeys);
} catch (DeterministicUpgradeRequiresPassword e2) {
// Nope, can't do it. Rethrow the original exception.
log.error("Failed to auto upgrade because wallet is encrypted, giving up. You should call wallet.upgradeToDeterministic yourself to avoid this situation.");
throw e;
}
}
// Do we really need an immediate hard save? Arguably all this is doing is saving the 'current' key // Do we really need an immediate hard save? Arguably all this is doing is saving the 'current' key
// and that's not quite so important, so we could coalesce for more performance. // and that's not quite so important, so we could coalesce for more performance.
saveNow(); saveNow();
@ -382,6 +372,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
public Address freshAddress(KeyChain.KeyPurpose purpose) { public Address freshAddress(KeyChain.KeyPurpose purpose) {
lock.lock(); lock.lock();
try { try {
maybeUpgradeToHD();
Address key = keychain.freshAddress(purpose, params); Address key = keychain.freshAddress(purpose, params);
saveNow(); saveNow();
return key; return key;
@ -429,6 +420,20 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
} }
} }
private void maybeUpgradeToHD() throws DeterministicUpgradeRequiresPassword {
checkState(lock.isHeldByCurrentThread());
if (keychain.isDeterministicUpgradeRequired()) {
log.info("Upgrade to HD wallets is required, attempting to do so.");
try {
upgradeToDeterministic(null);
} catch (DeterministicUpgradeRequiresPassword e) {
log.error("Failed to auto upgrade due to encryption. You should call wallet.upgradeToDeterministic " +
"with the users AES key to avoid this error.");
throw e;
}
}
}
/** /**
* Returns a snapshot of the watched scripts. This view is not live. * Returns a snapshot of the watched scripts. This view is not live.
*/ */
@ -569,6 +574,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
public void setKeychainLookaheadThreshold(int num) { public void setKeychainLookaheadThreshold(int num) {
lock.lock(); lock.lock();
try { try {
maybeUpgradeToHD();
keychain.setLookaheadThreshold(num); keychain.setLookaheadThreshold(num);
} finally { } finally {
lock.unlock(); lock.unlock();
@ -579,6 +585,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
public int getKeychainLookaheadThreshold() { public int getKeychainLookaheadThreshold() {
lock.lock(); lock.lock();
try { try {
maybeUpgradeToHD();
return keychain.getLookaheadThreshold(); return keychain.getLookaheadThreshold();
} finally { } finally {
lock.unlock(); lock.unlock();
@ -593,6 +600,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
public DeterministicKey getWatchingKey() { public DeterministicKey getWatchingKey() {
lock.lock(); lock.lock();
try { try {
maybeUpgradeToHD();
return keychain.getActiveKeyChain().getWatchingKey(); return keychain.getActiveKeyChain().getWatchingKey();
} finally { } finally {
lock.unlock(); lock.unlock();

View File

@ -5,4 +5,4 @@ package com.google.bitcoin.wallet;
* users password. This is required because HD wallets are upgraded from random using the private key bytes of * users password. This is required because HD wallets are upgraded from random using the private key bytes of
* the oldest non-rotating key, in order to make the upgrade process itself deterministic. * the oldest non-rotating key, in order to make the upgrade process itself deterministic.
*/ */
public class DeterministicUpgradeRequiresPassword extends Exception {} public class DeterministicUpgradeRequiresPassword extends RuntimeException {}