3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-13 02:35:52 +00:00

Wallet: Rename attribute "keychain" to "keyChainGroup".

This commit is contained in:
Oscar Guindzberg 2015-08-11 13:20:30 -03:00 committed by Andreas Schildbach
parent 200f2368c6
commit fe7b703237
6 changed files with 194 additions and 194 deletions

View File

@ -96,10 +96,10 @@ public class Wallet extends BaseTaggableObject
private static final Logger log = LoggerFactory.getLogger(Wallet.class); private static final Logger log = LoggerFactory.getLogger(Wallet.class);
private static final int MINIMUM_BLOOM_DATA_LENGTH = 8; private static final int MINIMUM_BLOOM_DATA_LENGTH = 8;
// Ordering: lock > keychainLock. Keychain is protected separately to allow fast querying of current receive address // Ordering: lock > keyChainGroupLock. KeyChainGroup is protected separately to allow fast querying of current receive address
// even if the wallet itself is busy e.g. saving or processing a big reorg. Useful for reducing UI latency. // even if the wallet itself is busy e.g. saving or processing a big reorg. Useful for reducing UI latency.
protected final ReentrantLock lock = Threading.lock("wallet"); protected final ReentrantLock lock = Threading.lock("wallet");
protected final ReentrantLock keychainLock = Threading.lock("wallet-keychain"); protected final ReentrantLock keyChainGroupLock = Threading.lock("wallet-keychaingroup");
// The various pools below give quick access to wallet-relevant transactions by the state they're in: // The various pools below give quick access to wallet-relevant transactions by the state they're in:
// //
@ -148,10 +148,10 @@ public class Wallet extends BaseTaggableObject
// The key chain group is not thread safe, and generally the whole hierarchy of objects should not be mutated // The key chain group is not thread safe, and generally the whole hierarchy of objects should not be mutated
// outside the wallet lock. So don't expose this object directly via any accessors! // outside the wallet lock. So don't expose this object directly via any accessors!
@GuardedBy("keychainLock") protected KeyChainGroup keychain; @GuardedBy("keyChainGroupLock") protected KeyChainGroup keyChainGroup;
// A list of scripts watched by this wallet. // A list of scripts watched by this wallet.
@GuardedBy("keychainLock") private Set<Script> watchedScripts; @GuardedBy("keyChainGroupLock") private Set<Script> watchedScripts;
protected final Context context; protected final Context context;
protected final NetworkParameters params; protected final NetworkParameters params;
@ -267,14 +267,14 @@ public class Wallet extends BaseTaggableObject
public Wallet(Context context, KeyChainGroup keyChainGroup) { public Wallet(Context context, KeyChainGroup keyChainGroup) {
this.context = context; this.context = context;
this.params = context.getParams(); this.params = context.getParams();
this.keychain = checkNotNull(keyChainGroup); this.keyChainGroup = checkNotNull(keyChainGroup);
if (params == UnitTestParams.get()) if (params == UnitTestParams.get())
this.keychain.setLookaheadSize(5); // Cut down excess computation for unit tests. this.keyChainGroup.setLookaheadSize(5); // Cut down excess computation for unit tests.
// If this keychain was created fresh just now (new wallet), make HD so a backup can be made immediately // If this keyChainGroup was created fresh just now (new wallet), make HD so a backup can be made immediately
// without having to call current/freshReceiveKey. If there are already keys in the chain of any kind then // without having to call current/freshReceiveKey. If there are already keys in the chain of any kind then
// we're probably being deserialized so leave things alone: the API user can upgrade later. // we're probably being deserialized so leave things alone: the API user can upgrade later.
if (this.keychain.numKeys() == 0) if (this.keyChainGroup.numKeys() == 0)
this.keychain.createAndActivateNewHDChain(); this.keyChainGroup.createAndActivateNewHDChain();
watchedScripts = Sets.newHashSet(); watchedScripts = Sets.newHashSet();
unspent = new HashMap<Sha256Hash, Transaction>(); unspent = new HashMap<Sha256Hash, Transaction>();
spent = new HashMap<Sha256Hash, Transaction>(); spent = new HashMap<Sha256Hash, Transaction>();
@ -325,8 +325,8 @@ public class Wallet extends BaseTaggableObject
/** /**
* Gets the active keychain via {@link KeyChainGroup#getActiveKeyChain()} * Gets the active keychain via {@link KeyChainGroup#getActiveKeyChain()}
*/ */
public DeterministicKeyChain getActiveKeychain() { public DeterministicKeyChain getActiveKeyChain() {
return keychain.getActiveKeyChain(); return keyChainGroup.getActiveKeyChain();
} }
/** /**
@ -368,12 +368,12 @@ public class Wallet extends BaseTaggableObject
* a different key (for each purpose independently). * a different key (for each purpose independently).
*/ */
public DeterministicKey currentKey(KeyChain.KeyPurpose purpose) { public DeterministicKey currentKey(KeyChain.KeyPurpose purpose) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
return keychain.currentKey(purpose); return keyChainGroup.currentKey(purpose);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -389,12 +389,12 @@ public class Wallet extends BaseTaggableObject
* Returns address for a {@link #currentKey(org.bitcoinj.wallet.KeyChain.KeyPurpose)} * Returns address for a {@link #currentKey(org.bitcoinj.wallet.KeyChain.KeyPurpose)}
*/ */
public Address currentAddress(KeyChain.KeyPurpose purpose) { public Address currentAddress(KeyChain.KeyPurpose purpose) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
return keychain.currentAddress(purpose); return keyChainGroup.currentAddress(purpose);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -428,12 +428,12 @@ public class Wallet extends BaseTaggableObject
*/ */
public List<DeterministicKey> freshKeys(KeyChain.KeyPurpose purpose, int numberOfKeys) { public List<DeterministicKey> freshKeys(KeyChain.KeyPurpose purpose, int numberOfKeys) {
List<DeterministicKey> keys; List<DeterministicKey> keys;
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
keys = keychain.freshKeys(purpose, numberOfKeys); keys = keyChainGroup.freshKeys(purpose, numberOfKeys);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
// 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.
@ -454,11 +454,11 @@ public class Wallet extends BaseTaggableObject
*/ */
public Address freshAddress(KeyChain.KeyPurpose purpose) { public Address freshAddress(KeyChain.KeyPurpose purpose) {
Address key; Address key;
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
key = keychain.freshAddress(purpose); key = keyChainGroup.freshAddress(purpose);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
saveNow(); saveNow();
return key; return key;
@ -477,11 +477,11 @@ public class Wallet extends BaseTaggableObject
* {@link #currentReceiveKey()} or {@link #currentReceiveAddress()}. * {@link #currentReceiveKey()} or {@link #currentReceiveAddress()}.
*/ */
public List<ECKey> getIssuedReceiveKeys() { public List<ECKey> getIssuedReceiveKeys() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.getActiveKeyChain().getIssuedReceiveKeys(); return keyChainGroup.getActiveKeyChain().getIssuedReceiveKeys();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -505,11 +505,11 @@ public class Wallet extends BaseTaggableObject
* you automatically the first time a new key is requested (this happens when spending due to the change address). * you automatically the first time a new key is requested (this happens when spending due to the change address).
*/ */
public void upgradeToDeterministic(@Nullable KeyParameter aesKey) throws DeterministicUpgradeRequiresPassword { public void upgradeToDeterministic(@Nullable KeyParameter aesKey) throws DeterministicUpgradeRequiresPassword {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
keychain.upgradeToDeterministic(vKeyRotationTimestamp, aesKey); keyChainGroup.upgradeToDeterministic(vKeyRotationTimestamp, aesKey);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -519,11 +519,11 @@ public class Wallet extends BaseTaggableObject
* that would require a new address or key. * that would require a new address or key.
*/ */
public boolean isDeterministicUpgradeRequired() { public boolean isDeterministicUpgradeRequired() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.isDeterministicUpgradeRequired(); return keyChainGroup.isDeterministicUpgradeRequired();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -531,10 +531,10 @@ public class Wallet extends BaseTaggableObject
maybeUpgradeToHD(null); maybeUpgradeToHD(null);
} }
@GuardedBy("keychainLock") @GuardedBy("keyChainGroupLock")
private void maybeUpgradeToHD(@Nullable KeyParameter aesKey) throws DeterministicUpgradeRequiresPassword { private void maybeUpgradeToHD(@Nullable KeyParameter aesKey) throws DeterministicUpgradeRequiresPassword {
checkState(keychainLock.isHeldByCurrentThread()); checkState(keyChainGroupLock.isHeldByCurrentThread());
if (keychain.isDeterministicUpgradeRequired()) { if (keyChainGroup.isDeterministicUpgradeRequired()) {
log.info("Upgrade to HD wallets is required, attempting to do so."); log.info("Upgrade to HD wallets is required, attempting to do so.");
try { try {
upgradeToDeterministic(aesKey); upgradeToDeterministic(aesKey);
@ -550,11 +550,11 @@ public class Wallet extends BaseTaggableObject
* Returns a snapshot of the watched scripts. This view is not live. * Returns a snapshot of the watched scripts. This view is not live.
*/ */
public List<Script> getWatchedScripts() { public List<Script> getWatchedScripts() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return new ArrayList<Script>(watchedScripts); return new ArrayList<Script>(watchedScripts);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -564,23 +564,23 @@ public class Wallet extends BaseTaggableObject
* @return Whether the key was removed or not. * @return Whether the key was removed or not.
*/ */
public boolean removeKey(ECKey key) { public boolean removeKey(ECKey key) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.removeImportedKey(key); return keyChainGroup.removeImportedKey(key);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** /**
* Returns the number of keys in the key chain, including lookahead keys. * Returns the number of keys in the key chain group, including lookahead keys.
*/ */
public int getKeychainSize() { public int getKeyChainGroupSize() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.numKeys(); return keyChainGroup.numKeys();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -588,11 +588,11 @@ public class Wallet extends BaseTaggableObject
* Returns a list of the non-deterministic keys that have been imported into the wallet, or the empty list if none. * Returns a list of the non-deterministic keys that have been imported into the wallet, or the empty list if none.
*/ */
public List<ECKey> getImportedKeys() { public List<ECKey> getImportedKeys() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.getImportedKeys(); return keyChainGroup.getImportedKeys();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -639,11 +639,11 @@ public class Wallet extends BaseTaggableObject
// API usage check. // API usage check.
checkNoDeterministicKeys(keys); checkNoDeterministicKeys(keys);
int result; int result;
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
result = keychain.importKeys(keys); result = keyChainGroup.importKeys(keys);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
saveNow(); saveNow();
return result; return result;
@ -658,23 +658,23 @@ public class Wallet extends BaseTaggableObject
/** Takes a list of keys and a password, then encrypts and imports them in one step using the current keycrypter. */ /** Takes a list of keys and a password, then encrypts and imports them in one step using the current keycrypter. */
public int importKeysAndEncrypt(final List<ECKey> keys, CharSequence password) { public int importKeysAndEncrypt(final List<ECKey> keys, CharSequence password) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
checkNotNull(getKeyCrypter(), "Wallet is not encrypted"); checkNotNull(getKeyCrypter(), "Wallet is not encrypted");
return importKeysAndEncrypt(keys, getKeyCrypter().deriveKey(password)); return importKeysAndEncrypt(keys, getKeyCrypter().deriveKey(password));
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** Takes a list of keys and an AES key, then encrypts and imports them in one step using the current keycrypter. */ /** Takes a list of keys and an AES key, then encrypts and imports them in one step using the current keycrypter. */
public int importKeysAndEncrypt(final List<ECKey> keys, KeyParameter aesKey) { public int importKeysAndEncrypt(final List<ECKey> keys, KeyParameter aesKey) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
checkNoDeterministicKeys(keys); checkNoDeterministicKeys(keys);
return keychain.importKeysAndEncrypt(keys, aesKey); return keyChainGroup.importKeysAndEncrypt(keys, aesKey);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -690,53 +690,53 @@ public class Wallet extends BaseTaggableObject
* </p> * </p>
*/ */
public void addAndActivateHDChain(DeterministicKeyChain chain) { public void addAndActivateHDChain(DeterministicKeyChain chain) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
keychain.addAndActivateHDChain(chain); keyChainGroup.addAndActivateHDChain(chain);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadSize(int)} for more info on this. */ /** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadSize(int)} for more info on this. */
public void setKeychainLookaheadSize(int lookaheadSize) { public void setKeyChainGroupLookaheadSize(int lookaheadSize) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
keychain.setLookaheadSize(lookaheadSize); keyChainGroup.setLookaheadSize(lookaheadSize);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadSize(int)} for more info on this. */ /** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadSize(int)} for more info on this. */
public int getKeychainLookaheadSize() { public int getKeyChainGroupLookaheadSize() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.getLookaheadSize(); return keyChainGroup.getLookaheadSize();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadThreshold(int)} for more info on this. */ /** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadThreshold(int)} for more info on this. */
public void setKeychainLookaheadThreshold(int num) { public void setKeyChainGroupLookaheadThreshold(int num) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
keychain.setLookaheadThreshold(num); keyChainGroup.setLookaheadThreshold(num);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadThreshold(int)} for more info on this. */ /** See {@link org.bitcoinj.wallet.DeterministicKeyChain#setLookaheadThreshold(int)} for more info on this. */
public int getKeychainLookaheadThreshold() { public int getKeyChainGroupLookaheadThreshold() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
return keychain.getLookaheadThreshold(); return keyChainGroup.getLookaheadThreshold();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -747,12 +747,12 @@ public class Wallet extends BaseTaggableObject
* zero key in the recommended BIP32 hierarchy. * zero key in the recommended BIP32 hierarchy.
*/ */
public DeterministicKey getWatchingKey() { public DeterministicKey getWatchingKey() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
return keychain.getActiveKeyChain().getWatchingKey(); return keyChainGroup.getActiveKeyChain().getWatchingKey();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -764,12 +764,12 @@ public class Wallet extends BaseTaggableObject
* if there are no keys, or if there is a mix between watching and non-watching keys. * if there are no keys, or if there is a mix between watching and non-watching keys.
*/ */
public boolean isWatching() { public boolean isWatching() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
return keychain.isWatching(); return keyChainGroup.isWatching();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -828,7 +828,7 @@ public class Wallet extends BaseTaggableObject
*/ */
public int addWatchedScripts(final List<Script> scripts) { public int addWatchedScripts(final List<Script> scripts) {
int added = 0; int added = 0;
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
for (final Script script : scripts) { for (final Script script : scripts) {
// Script.equals/hashCode() only takes into account the program bytes, so this step lets the user replace // Script.equals/hashCode() only takes into account the program bytes, so this step lets the user replace
@ -841,7 +841,7 @@ public class Wallet extends BaseTaggableObject
added++; added++;
} }
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
if (added > 0) { if (added > 0) {
queueOnScriptsChanged(scripts, true); queueOnScriptsChanged(scripts, true);
@ -902,7 +902,7 @@ public class Wallet extends BaseTaggableObject
* Returns all addresses watched by this wallet. * Returns all addresses watched by this wallet.
*/ */
public List<Address> getWatchedAddresses() { public List<Address> getWatchedAddresses() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
List<Address> addresses = new LinkedList<Address>(); List<Address> addresses = new LinkedList<Address>();
for (Script script : watchedScripts) for (Script script : watchedScripts)
@ -910,7 +910,7 @@ public class Wallet extends BaseTaggableObject
addresses.add(script.getToAddress(params)); addresses.add(script.getToAddress(params));
return addresses; return addresses;
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -923,21 +923,21 @@ public class Wallet extends BaseTaggableObject
@Override @Override
@Nullable @Nullable
public ECKey findKeyFromPubHash(byte[] pubkeyHash) { public ECKey findKeyFromPubHash(byte[] pubkeyHash) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.findKeyFromPubHash(pubkeyHash); return keyChainGroup.findKeyFromPubHash(pubkeyHash);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** Returns true if the given key is in the wallet, false otherwise. Currently an O(N) operation. */ /** Returns true if the given key is in the wallet, false otherwise. Currently an O(N) operation. */
public boolean hasKey(ECKey key) { public boolean hasKey(ECKey key) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.hasKey(key); return keyChainGroup.hasKey(key);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -950,11 +950,11 @@ public class Wallet extends BaseTaggableObject
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
public boolean isWatchedScript(Script script) { public boolean isWatchedScript(Script script) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return watchedScripts.contains(script); return watchedScripts.contains(script);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -965,11 +965,11 @@ public class Wallet extends BaseTaggableObject
@Override @Override
@Nullable @Nullable
public ECKey findKeyFromPubKey(byte[] pubkey) { public ECKey findKeyFromPubKey(byte[] pubkey) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.findKeyFromPubKey(pubkey); return keyChainGroup.findKeyFromPubKey(pubkey);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -980,17 +980,17 @@ public class Wallet extends BaseTaggableObject
} }
/** /**
* Locates a redeem data (redeem script and keys) from the keychain given the hash of the script. * Locates a redeem data (redeem script and keys) from the keyChainGroup given the hash of the script.
* Returns RedeemData object or null if no such data was found. * Returns RedeemData object or null if no such data was found.
*/ */
@Nullable @Nullable
@Override @Override
public RedeemData findRedeemDataFromScriptHash(byte[] payToScriptHash) { public RedeemData findRedeemDataFromScriptHash(byte[] payToScriptHash) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.findRedeemDataFromScriptHash(payToScriptHash); return keyChainGroup.findRedeemDataFromScriptHash(payToScriptHash);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1005,20 +1005,20 @@ public class Wallet extends BaseTaggableObject
* See {@link org.bitcoinj.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this. * See {@link org.bitcoinj.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this.
*/ */
private void markKeysAsUsed(Transaction tx) { private void markKeysAsUsed(Transaction tx) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
for (TransactionOutput o : tx.getOutputs()) { for (TransactionOutput o : tx.getOutputs()) {
try { try {
Script script = o.getScriptPubKey(); Script script = o.getScriptPubKey();
if (script.isSentToRawPubKey()) { if (script.isSentToRawPubKey()) {
byte[] pubkey = script.getPubKey(); byte[] pubkey = script.getPubKey();
keychain.markPubKeyAsUsed(pubkey); keyChainGroup.markPubKeyAsUsed(pubkey);
} else if (script.isSentToAddress()) { } else if (script.isSentToAddress()) {
byte[] pubkeyHash = script.getPubKeyHash(); byte[] pubkeyHash = script.getPubKeyHash();
keychain.markPubKeyHashAsUsed(pubkeyHash); keyChainGroup.markPubKeyHashAsUsed(pubkeyHash);
} else if (script.isPayToScriptHash()) { } else if (script.isPayToScriptHash()) {
Address a = Address.fromP2SHScript(tx.getParams(), script); Address a = Address.fromP2SHScript(tx.getParams(), script);
keychain.markP2SHAddressAsUsed(a); keyChainGroup.markP2SHAddressAsUsed(a);
} }
} catch (ScriptException e) { } catch (ScriptException e) {
// Just means we didn't understand the output of this transaction: ignore it. // Just means we didn't understand the output of this transaction: ignore it.
@ -1026,7 +1026,7 @@ public class Wallet extends BaseTaggableObject
} }
} }
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1035,14 +1035,14 @@ public class Wallet extends BaseTaggableObject
* @throws org.bitcoinj.core.ECKey.MissingPrivateKeyException if the seed is unavailable (watching wallet) * @throws org.bitcoinj.core.ECKey.MissingPrivateKeyException if the seed is unavailable (watching wallet)
*/ */
public DeterministicSeed getKeyChainSeed() { public DeterministicSeed getKeyChainSeed() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
DeterministicSeed seed = keychain.getActiveKeyChain().getSeed(); DeterministicSeed seed = keyChainGroup.getActiveKeyChain().getSeed();
if (seed == null) if (seed == null)
throw new ECKey.MissingPrivateKeyException(); throw new ECKey.MissingPrivateKeyException();
return seed; return seed;
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1051,12 +1051,12 @@ public class Wallet extends BaseTaggableObject
* use currentReceiveKey/freshReceiveKey instead. * use currentReceiveKey/freshReceiveKey instead.
*/ */
public DeterministicKey getKeyByPath(List<ChildNumber> path) { public DeterministicKey getKeyByPath(List<ChildNumber> path) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
maybeUpgradeToHD(); maybeUpgradeToHD();
return keychain.getActiveKeyChain().getKeyByPath(path, false); return keyChainGroup.getActiveKeyChain().getKeyByPath(path, false);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1066,12 +1066,12 @@ public class Wallet extends BaseTaggableObject
* parameters to derive a key from the given password. * parameters to derive a key from the given password.
*/ */
public void encrypt(CharSequence password) { public void encrypt(CharSequence password) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
final KeyCrypterScrypt scrypt = new KeyCrypterScrypt(); final KeyCrypterScrypt scrypt = new KeyCrypterScrypt();
keychain.encrypt(scrypt, scrypt.deriveKey(password)); keyChainGroup.encrypt(scrypt, scrypt.deriveKey(password));
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
saveNow(); saveNow();
} }
@ -1085,11 +1085,11 @@ public class Wallet extends BaseTaggableObject
* @throws KeyCrypterException Thrown if the wallet encryption fails. If so, the wallet state is unchanged. * @throws KeyCrypterException Thrown if the wallet encryption fails. If so, the wallet state is unchanged.
*/ */
public void encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) { public void encrypt(KeyCrypter keyCrypter, KeyParameter aesKey) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
keychain.encrypt(keyCrypter, aesKey); keyChainGroup.encrypt(keyCrypter, aesKey);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
saveNow(); saveNow();
} }
@ -1099,13 +1099,13 @@ public class Wallet extends BaseTaggableObject
* @throws KeyCrypterException Thrown if the wallet decryption fails. If so, the wallet state is unchanged. * @throws KeyCrypterException Thrown if the wallet decryption fails. If so, the wallet state is unchanged.
*/ */
public void decrypt(CharSequence password) { public void decrypt(CharSequence password) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
final KeyCrypter crypter = keychain.getKeyCrypter(); final KeyCrypter crypter = keyChainGroup.getKeyCrypter();
checkState(crypter != null, "Not encrypted"); checkState(crypter != null, "Not encrypted");
keychain.decrypt(crypter.deriveKey(password)); keyChainGroup.decrypt(crypter.deriveKey(password));
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
saveNow(); saveNow();
} }
@ -1117,11 +1117,11 @@ public class Wallet extends BaseTaggableObject
* @throws KeyCrypterException Thrown if the wallet decryption fails. If so, the wallet state is unchanged. * @throws KeyCrypterException Thrown if the wallet decryption fails. If so, the wallet state is unchanged.
*/ */
public void decrypt(KeyParameter aesKey) { public void decrypt(KeyParameter aesKey) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
keychain.decrypt(aesKey); keyChainGroup.decrypt(aesKey);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
saveNow(); saveNow();
} }
@ -1134,11 +1134,11 @@ public class Wallet extends BaseTaggableObject
* @throws IllegalStateException if the wallet is not encrypted. * @throws IllegalStateException if the wallet is not encrypted.
*/ */
public boolean checkPassword(CharSequence password) { public boolean checkPassword(CharSequence password) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.checkPassword(password); return keyChainGroup.checkPassword(password);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1148,11 +1148,11 @@ public class Wallet extends BaseTaggableObject
* @return boolean true if AES key supplied can decrypt the first encrypted private key in the wallet, false otherwise. * @return boolean true if AES key supplied can decrypt the first encrypted private key in the wallet, false otherwise.
*/ */
public boolean checkAESKey(KeyParameter aesKey) { public boolean checkAESKey(KeyParameter aesKey) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.checkAESKey(aesKey); return keyChainGroup.checkAESKey(aesKey);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1162,11 +1162,11 @@ public class Wallet extends BaseTaggableObject
*/ */
@Nullable @Nullable
public KeyCrypter getKeyCrypter() { public KeyCrypter getKeyCrypter() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.getKeyCrypter(); return keyChainGroup.getKeyCrypter();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1176,15 +1176,15 @@ public class Wallet extends BaseTaggableObject
* (This is a convenience method - the encryption type is actually stored in the keyCrypter). * (This is a convenience method - the encryption type is actually stored in the keyCrypter).
*/ */
public EncryptionType getEncryptionType() { public EncryptionType getEncryptionType() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
KeyCrypter crypter = keychain.getKeyCrypter(); KeyCrypter crypter = keyChainGroup.getKeyCrypter();
if (crypter != null) if (crypter != null)
return crypter.getUnderstoodEncryptionType(); return crypter.getUnderstoodEncryptionType();
else else
return EncryptionType.UNENCRYPTED; return EncryptionType.UNENCRYPTED;
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1195,23 +1195,23 @@ public class Wallet extends BaseTaggableObject
/** Changes wallet encryption password, this is atomic operation. */ /** Changes wallet encryption password, this is atomic operation. */
public void changeEncryptionPassword(CharSequence currentPassword, CharSequence newPassword){ public void changeEncryptionPassword(CharSequence currentPassword, CharSequence newPassword){
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
decrypt(currentPassword); decrypt(currentPassword);
encrypt(newPassword); encrypt(newPassword);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
/** Changes wallet AES encryption key, this is atomic operation. */ /** Changes wallet AES encryption key, this is atomic operation. */
public void changeEncryptionKey(KeyCrypter keyCrypter, KeyParameter currentAesKey, KeyParameter newAesKey){ public void changeEncryptionKey(KeyCrypter keyCrypter, KeyParameter currentAesKey, KeyParameter newAesKey){
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
decrypt(currentAesKey); decrypt(currentAesKey);
encrypt(keyCrypter, newAesKey); encrypt(keyCrypter, newAesKey);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -1223,12 +1223,12 @@ public class Wallet extends BaseTaggableObject
// TODO: Make this package private once the classes finish moving around. // TODO: Make this package private once the classes finish moving around.
/** Internal use only. */ /** Internal use only. */
public List<Protos.Key> serializeKeychainToProtobuf() { public List<Protos.Key> serializeKeyChainGroupToProtobuf() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return keychain.serializeToProtobuf(); return keyChainGroup.serializeToProtobuf();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -2320,7 +2320,7 @@ public class Wallet extends BaseTaggableObject
public void addChangeEventListener(Executor executor, WalletChangeEventListener listener) { public void addChangeEventListener(Executor executor, WalletChangeEventListener listener) {
// This is thread safe, so we don't need to take the lock. // This is thread safe, so we don't need to take the lock.
changeListeners.add(new ListenerRegistration<WalletChangeEventListener>(executor, listener)); changeListeners.add(new ListenerRegistration<WalletChangeEventListener>(executor, listener));
keychain.addEventListener(listener, executor); keyChainGroup.addEventListener(listener, executor);
} }
/** /**
@ -2355,7 +2355,7 @@ public class Wallet extends BaseTaggableObject
* was never added. * was never added.
*/ */
public boolean removeChangeEventListener(WalletChangeEventListener listener) { public boolean removeChangeEventListener(WalletChangeEventListener listener) {
keychain.removeEventListener(listener); keyChainGroup.removeEventListener(listener);
return ListenerRegistration.removeFromList(listener, changeListeners); return ListenerRegistration.removeFromList(listener, changeListeners);
} }
@ -2672,7 +2672,7 @@ public class Wallet extends BaseTaggableObject
*/ */
public List<TransactionOutput> getWatchedOutputs(boolean excludeImmatureCoinbases) { public List<TransactionOutput> getWatchedOutputs(boolean excludeImmatureCoinbases) {
lock.lock(); lock.lock();
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
LinkedList<TransactionOutput> candidates = Lists.newLinkedList(); LinkedList<TransactionOutput> candidates = Lists.newLinkedList();
for (Transaction tx : Iterables.concat(unspent.values(), pending.values())) { for (Transaction tx : Iterables.concat(unspent.values(), pending.values())) {
@ -2690,7 +2690,7 @@ public class Wallet extends BaseTaggableObject
} }
return candidates; return candidates;
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
lock.unlock(); lock.unlock();
} }
} }
@ -2807,7 +2807,7 @@ public class Wallet extends BaseTaggableObject
public String toString(boolean includePrivateKeys, boolean includeTransactions, boolean includeExtensions, public String toString(boolean includePrivateKeys, boolean includeTransactions, boolean includeExtensions,
@Nullable AbstractBlockChain chain) { @Nullable AbstractBlockChain chain) {
lock.lock(); lock.lock();
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
Coin estimatedBalance = getBalance(BalanceType.ESTIMATED); Coin estimatedBalance = getBalance(BalanceType.ESTIMATED);
@ -2822,7 +2822,7 @@ public class Wallet extends BaseTaggableObject
final String lastBlockSeenTimeStr = lastBlockSeenTime == null ? "time unknown" : lastBlockSeenTime.toString(); final String lastBlockSeenTimeStr = lastBlockSeenTime == null ? "time unknown" : lastBlockSeenTime.toString();
builder.append(String.format("Last seen best block: %d (%s): %s%n", builder.append(String.format("Last seen best block: %d (%s): %s%n",
getLastBlockSeenHeight(), lastBlockSeenTimeStr, getLastBlockSeenHash())); getLastBlockSeenHeight(), lastBlockSeenTimeStr, getLastBlockSeenHash()));
final KeyCrypter crypter = keychain.getKeyCrypter(); final KeyCrypter crypter = keyChainGroup.getKeyCrypter();
if (crypter != null) if (crypter != null)
builder.append(String.format("Encryption: %s%n", crypter)); builder.append(String.format("Encryption: %s%n", crypter));
if (isWatching()) if (isWatching())
@ -2833,7 +2833,7 @@ public class Wallet extends BaseTaggableObject
final long keyRotationTime = vKeyRotationTimestamp * 1000; final long keyRotationTime = vKeyRotationTimestamp * 1000;
if (keyRotationTime > 0) if (keyRotationTime > 0)
builder.append(String.format("Key rotation time: %s\n", Utils.dateTimeFormat(keyRotationTime))); builder.append(String.format("Key rotation time: %s\n", Utils.dateTimeFormat(keyRotationTime)));
builder.append(keychain.toString(includePrivateKeys)); builder.append(keyChainGroup.toString(includePrivateKeys));
if (!watchedScripts.isEmpty()) { if (!watchedScripts.isEmpty()) {
builder.append("\nWatched scripts:\n"); builder.append("\nWatched scripts:\n");
@ -2869,7 +2869,7 @@ public class Wallet extends BaseTaggableObject
} }
return builder.toString(); return builder.toString();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
lock.unlock(); lock.unlock();
} }
} }
@ -2928,16 +2928,16 @@ public class Wallet extends BaseTaggableObject
*/ */
@Override @Override
public long getEarliestKeyCreationTime() { public long getEarliestKeyCreationTime() {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
long earliestTime = keychain.getEarliestKeyCreationTime(); long earliestTime = keyChainGroup.getEarliestKeyCreationTime();
for (Script script : watchedScripts) for (Script script : watchedScripts)
earliestTime = Math.min(script.getCreationTimeSeconds(), earliestTime); earliestTime = Math.min(script.getCreationTimeSeconds(), earliestTime);
if (earliestTime == Long.MAX_VALUE) if (earliestTime == Long.MAX_VALUE)
return Utils.currentTimeSeconds(); return Utils.currentTimeSeconds();
return earliestTime; return earliestTime;
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -3976,7 +3976,7 @@ public class Wallet extends BaseTaggableObject
protected List<UTXO> getStoredOutputsFromUTXOProvider() throws UTXOProviderException { protected List<UTXO> getStoredOutputsFromUTXOProvider() throws UTXOProviderException {
UTXOProvider utxoProvider = checkNotNull(vUTXOProvider, "No UTXO provider has been set"); UTXOProvider utxoProvider = checkNotNull(vUTXOProvider, "No UTXO provider has been set");
List<UTXO> candidates = new ArrayList<UTXO>(); List<UTXO> candidates = new ArrayList<UTXO>();
List<DeterministicKey> keys = getActiveKeychain().getLeafKeys(); List<DeterministicKey> keys = getActiveKeyChain().getLeafKeys();
List<Address> addresses = new ArrayList<Address>(); List<Address> addresses = new ArrayList<Address>();
for (ECKey key : keys) { for (ECKey key : keys) {
Address address = new Address(params, key.getPubKeyHash()); Address address = new Address(params, key.getPubKeyHash());
@ -4309,7 +4309,7 @@ public class Wallet extends BaseTaggableObject
if (bloomFilterGuard.incrementAndGet() > 1) if (bloomFilterGuard.incrementAndGet() > 1)
return; return;
lock.lock(); lock.lock();
keychainLock.lock(); keyChainGroupLock.lock();
//noinspection FieldAccessNotGuarded //noinspection FieldAccessNotGuarded
calcBloomOutPointsLocked(); calcBloomOutPointsLocked();
} }
@ -4334,12 +4334,12 @@ public class Wallet extends BaseTaggableObject
} }
} }
@Override @GuardedBy("keychainLock") @Override @GuardedBy("keyChainGroupLock")
public void endBloomFilterCalculation() { public void endBloomFilterCalculation() {
if (bloomFilterGuard.decrementAndGet() > 0) if (bloomFilterGuard.decrementAndGet() > 0)
return; return;
bloomOutPoints.clear(); bloomOutPoints.clear();
keychainLock.unlock(); keyChainGroupLock.unlock();
lock.unlock(); lock.unlock();
} }
@ -4352,7 +4352,7 @@ public class Wallet extends BaseTaggableObject
beginBloomFilterCalculation(); beginBloomFilterCalculation();
try { try {
int size = bloomOutPoints.size(); int size = bloomOutPoints.size();
size += keychain.getBloomFilterElementCount(); size += keyChainGroup.getBloomFilterElementCount();
// Some scripts may have more than one bloom element. That should normally be okay, because under-counting // Some scripts may have more than one bloom element. That should normally be okay, because under-counting
// just increases false-positive rate. // just increases false-positive rate.
size += watchedScripts.size(); size += watchedScripts.size();
@ -4371,11 +4371,11 @@ public class Wallet extends BaseTaggableObject
public boolean isRequiringUpdateAllBloomFilter() { public boolean isRequiringUpdateAllBloomFilter() {
// This is typically called by the PeerGroup, in which case it will have already explicitly taken the lock // This is typically called by the PeerGroup, in which case it will have already explicitly taken the lock
// before calling, but because this is public API we must still lock again regardless. // before calling, but because this is public API we must still lock again regardless.
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
return !watchedScripts.isEmpty(); return !watchedScripts.isEmpty();
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -4403,11 +4403,11 @@ public class Wallet extends BaseTaggableObject
* <p>See the docs for {@link BloomFilter(int, double)} for a brief explanation of anonymity when using bloom * <p>See the docs for {@link BloomFilter(int, double)} for a brief explanation of anonymity when using bloom
* filters.</p> * filters.</p>
*/ */
@Override @GuardedBy("keychainLock") @Override @GuardedBy("keyChainGroupLock")
public BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak) { public BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak) {
beginBloomFilterCalculation(); beginBloomFilterCalculation();
try { try {
BloomFilter filter = keychain.getBloomFilter(size, falsePositiveRate, nTweak); BloomFilter filter = keyChainGroup.getBloomFilter(size, falsePositiveRate, nTweak);
for (Script script : watchedScripts) { for (Script script : watchedScripts) {
for (ScriptChunk chunk : script.getChunks()) { for (ScriptChunk chunk : script.getChunks()) {
// Only add long (at least 64 bit) data to the bloom filter. // Only add long (at least 64 bit) data to the bloom filter.
@ -4439,20 +4439,20 @@ public class Wallet extends BaseTaggableObject
* sequence within it to reliably find relevant transactions. * sequence within it to reliably find relevant transactions.
*/ */
public boolean checkForFilterExhaustion(FilteredBlock block) { public boolean checkForFilterExhaustion(FilteredBlock block) {
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
int epoch = keychain.getCombinedKeyLookaheadEpochs(); int epoch = keyChainGroup.getCombinedKeyLookaheadEpochs();
for (Transaction tx : block.getAssociatedTransactions().values()) { for (Transaction tx : block.getAssociatedTransactions().values()) {
markKeysAsUsed(tx); markKeysAsUsed(tx);
} }
int newEpoch = keychain.getCombinedKeyLookaheadEpochs(); int newEpoch = keyChainGroup.getCombinedKeyLookaheadEpochs();
checkState(newEpoch >= epoch); checkState(newEpoch >= epoch);
// If the key lookahead epoch has advanced, there was a call to addKeys and the PeerGroup already has a // If the key lookahead epoch has advanced, there was a call to addKeys and the PeerGroup already has a
// pending request to recalculate the filter queued up on another thread. The calling Peer should abandon // pending request to recalculate the filter queued up on another thread. The calling Peer should abandon
// block at this point and await a new filter before restarting the download. // block at this point and await a new filter before restarting the download.
return newEpoch > epoch; return newEpoch > epoch;
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
} }
} }
@ -4531,7 +4531,7 @@ public class Wallet extends BaseTaggableObject
*/ */
public void deserializeExtension(WalletExtension extension, byte[] data) throws Exception { public void deserializeExtension(WalletExtension extension, byte[] data) throws Exception {
lock.lock(); lock.lock();
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
// This method exists partly to establish a lock ordering of wallet > extension. // This method exists partly to establish a lock ordering of wallet > extension.
extension.deserializeWalletExtension(this, data); extension.deserializeWalletExtension(this, data);
@ -4541,7 +4541,7 @@ public class Wallet extends BaseTaggableObject
extensions.remove(extension.getWalletExtensionID()); extensions.remove(extension.getWalletExtensionID());
Throwables.propagate(throwable); Throwables.propagate(throwable);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
lock.unlock(); lock.unlock();
} }
} }
@ -4895,13 +4895,13 @@ public class Wallet extends BaseTaggableObject
public ListenableFuture<List<Transaction>> doMaintenance(@Nullable KeyParameter aesKey, boolean signAndSend) throws DeterministicUpgradeRequiresPassword { public ListenableFuture<List<Transaction>> doMaintenance(@Nullable KeyParameter aesKey, boolean signAndSend) throws DeterministicUpgradeRequiresPassword {
List<Transaction> txns; List<Transaction> txns;
lock.lock(); lock.lock();
keychainLock.lock(); keyChainGroupLock.lock();
try { try {
txns = maybeRotateKeys(aesKey, signAndSend); txns = maybeRotateKeys(aesKey, signAndSend);
if (!signAndSend) if (!signAndSend)
return Futures.immediateFuture(txns); return Futures.immediateFuture(txns);
} finally { } finally {
keychainLock.unlock(); keyChainGroupLock.unlock();
lock.unlock(); lock.unlock();
} }
checkState(!lock.isHeldByCurrentThread()); checkState(!lock.isHeldByCurrentThread());
@ -4930,10 +4930,10 @@ public class Wallet extends BaseTaggableObject
} }
// Checks to see if any coins are controlled by rotating keys and if so, spends them. // Checks to see if any coins are controlled by rotating keys and if so, spends them.
@GuardedBy("keychainLock") @GuardedBy("keyChainGroupLock")
private List<Transaction> maybeRotateKeys(@Nullable KeyParameter aesKey, boolean sign) throws DeterministicUpgradeRequiresPassword { private List<Transaction> maybeRotateKeys(@Nullable KeyParameter aesKey, boolean sign) throws DeterministicUpgradeRequiresPassword {
checkState(lock.isHeldByCurrentThread()); checkState(lock.isHeldByCurrentThread());
checkState(keychainLock.isHeldByCurrentThread()); checkState(keyChainGroupLock.isHeldByCurrentThread());
List<Transaction> results = Lists.newLinkedList(); List<Transaction> results = Lists.newLinkedList();
// TODO: Handle chain replays here. // TODO: Handle chain replays here.
final long keyRotationTimestamp = vKeyRotationTimestamp; final long keyRotationTimestamp = vKeyRotationTimestamp;
@ -4941,7 +4941,7 @@ public class Wallet extends BaseTaggableObject
// We might have to create a new HD hierarchy if the previous ones are now rotating. // We might have to create a new HD hierarchy if the previous ones are now rotating.
boolean allChainsRotating = true; boolean allChainsRotating = true;
for (DeterministicKeyChain chain : keychain.getDeterministicKeyChains()) { for (DeterministicKeyChain chain : keyChainGroup.getDeterministicKeyChains()) {
if (chain.getEarliestKeyCreationTime() >= keyRotationTimestamp) { if (chain.getEarliestKeyCreationTime() >= keyRotationTimestamp) {
allChainsRotating = false; allChainsRotating = false;
break; break;
@ -4949,17 +4949,17 @@ public class Wallet extends BaseTaggableObject
} }
if (allChainsRotating) { if (allChainsRotating) {
try { try {
if (keychain.getImportedKeys().isEmpty()) { if (keyChainGroup.getImportedKeys().isEmpty()) {
log.info("All HD chains are currently rotating and we have no random keys, creating fresh HD chain ..."); log.info("All HD chains are currently rotating and we have no random keys, creating fresh HD chain ...");
keychain.createAndActivateNewHDChain(); keyChainGroup.createAndActivateNewHDChain();
} else { } else {
log.info("All HD chains are currently rotating, attempting to create a new one from the next oldest non-rotating key material ..."); log.info("All HD chains are currently rotating, attempting to create a new one from the next oldest non-rotating key material ...");
keychain.upgradeToDeterministic(keyRotationTimestamp, aesKey); keyChainGroup.upgradeToDeterministic(keyRotationTimestamp, aesKey);
log.info(" ... upgraded to HD again, based on next best oldest key."); log.info(" ... upgraded to HD again, based on next best oldest key.");
} }
} catch (AllRandomKeysRotating rotating) { } catch (AllRandomKeysRotating rotating) {
log.info(" ... no non-rotating random keys available, generating entirely new HD tree: backup required after this."); log.info(" ... no non-rotating random keys available, generating entirely new HD tree: backup required after this.");
keychain.createAndActivateNewHDChain(); keyChainGroup.createAndActivateNewHDChain();
} }
saveNow(); saveNow();
} }

View File

@ -156,7 +156,7 @@ public class WalletProtobufSerializer {
walletBuilder.addTransaction(txProto); walletBuilder.addTransaction(txProto);
} }
walletBuilder.addAllKey(wallet.serializeKeychainToProtobuf()); walletBuilder.addAllKey(wallet.serializeKeyChainGroupToProtobuf());
for (Script script : wallet.getWatchedScripts()) { for (Script script : wallet.getWatchedScripts()) {
Protos.Script protoScript = Protos.Script protoScript =
@ -422,15 +422,15 @@ public class WalletProtobufSerializer {
throw new UnreadableWalletException.WrongNetwork(); throw new UnreadableWalletException.WrongNetwork();
// Read the scrypt parameters that specify how encryption and decryption is performed. // Read the scrypt parameters that specify how encryption and decryption is performed.
KeyChainGroup chain; KeyChainGroup keyChainGroup;
if (walletProto.hasEncryptionParameters()) { if (walletProto.hasEncryptionParameters()) {
Protos.ScryptParameters encryptionParameters = walletProto.getEncryptionParameters(); Protos.ScryptParameters encryptionParameters = walletProto.getEncryptionParameters();
final KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(encryptionParameters); final KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(encryptionParameters);
chain = KeyChainGroup.fromProtobufEncrypted(params, walletProto.getKeyList(), keyCrypter, keyChainFactory); keyChainGroup = KeyChainGroup.fromProtobufEncrypted(params, walletProto.getKeyList(), keyCrypter, keyChainFactory);
} else { } else {
chain = KeyChainGroup.fromProtobufUnencrypted(params, walletProto.getKeyList(), keyChainFactory); keyChainGroup = KeyChainGroup.fromProtobufUnencrypted(params, walletProto.getKeyList(), keyChainFactory);
} }
Wallet wallet = factory.create(params, chain); Wallet wallet = factory.create(params, keyChainGroup);
List<Script> scripts = Lists.newArrayList(); List<Script> scripts = Lists.newArrayList();
for (Protos.Script protoScript : walletProto.getWatchedScriptList()) { for (Protos.Script protoScript : walletProto.getWatchedScriptList()) {

View File

@ -156,7 +156,7 @@ public class FilteredBlockAndPartialMerkleTreeTests extends TestWithPeerGroup {
assertTrue(tx3.getHash().equals(Sha256Hash.wrap("c5abc61566dbb1c4bce5e1fda7b66bed22eb2130cea4b721690bc1488465abc9"))); assertTrue(tx3.getHash().equals(Sha256Hash.wrap("c5abc61566dbb1c4bce5e1fda7b66bed22eb2130cea4b721690bc1488465abc9")));
assertEquals(tx3.getHash(),txHashList.get(3)); assertEquals(tx3.getHash(),txHashList.get(3));
BloomFilter filter = wallet.getBloomFilter(wallet.getKeychainSize()*2, 0.001, 0xDEADBEEF); BloomFilter filter = wallet.getBloomFilter(wallet.getKeyChainGroupSize()*2, 0.001, 0xDEADBEEF);
// Compare the serialized bloom filter to a known-good value // Compare the serialized bloom filter to a known-good value
assertArrayEquals(filter.bitcoinSerialize(), HEX.decode("0e1b091ca195e45a9164889b6bc46a09000000efbeadde02")); assertArrayEquals(filter.bitcoinSerialize(), HEX.decode("0e1b091ca195e45a9164889b6bc46a09000000efbeadde02"));

View File

@ -629,8 +629,8 @@ public class PeerGroupTest extends TestWithPeerGroup {
public void testBloomResendOnNewKey() throws Exception { public void testBloomResendOnNewKey() throws Exception {
// Check that when we add a new key to the wallet, the Bloom filter is re-calculated and re-sent but only once // Check that when we add a new key to the wallet, the Bloom filter is re-calculated and re-sent but only once
// we exceed the lookahead threshold. // we exceed the lookahead threshold.
wallet.setKeychainLookaheadSize(5); wallet.setKeyChainGroupLookaheadSize(5);
wallet.setKeychainLookaheadThreshold(4); wallet.setKeyChainGroupLookaheadThreshold(4);
peerGroup.start(); peerGroup.start();
// Create a couple of peers. // Create a couple of peers.
InboundMessageQueuer p1 = connectPeer(1); InboundMessageQueuer p1 = connectPeer(1);
@ -639,7 +639,7 @@ public class PeerGroupTest extends TestWithPeerGroup {
BloomFilter f1 = p1.lastReceivedFilter; BloomFilter f1 = p1.lastReceivedFilter;
ECKey key = null; ECKey key = null;
// We have to run ahead of the lookahead zone for this test. There should only be one bloom filter recalc. // We have to run ahead of the lookahead zone for this test. There should only be one bloom filter recalc.
for (int i = 0; i < wallet.getKeychainLookaheadSize() + wallet.getKeychainLookaheadThreshold() + 1; i++) { for (int i = 0; i < wallet.getKeyChainGroupLookaheadSize() + wallet.getKeyChainGroupLookaheadThreshold() + 1; i++) {
key = wallet.freshReceiveKey(); key = wallet.freshReceiveKey();
} }
peerGroup.waitForJobQueue(); peerGroup.waitForJobQueue();
@ -775,8 +775,8 @@ public class PeerGroupTest extends TestWithPeerGroup {
keys.add(shadow.freshReceiveKey()); keys.add(shadow.freshReceiveKey());
} }
// Reduce the number of keys we need to work with to speed up this test. // Reduce the number of keys we need to work with to speed up this test.
wallet.setKeychainLookaheadSize(4); wallet.setKeyChainGroupLookaheadSize(4);
wallet.setKeychainLookaheadThreshold(2); wallet.setKeyChainGroupLookaheadThreshold(2);
peerGroup.start(); peerGroup.start();
InboundMessageQueuer p1 = connectPeer(1); InboundMessageQueuer p1 = connectPeer(1);
@ -800,13 +800,13 @@ public class PeerGroupTest extends TestWithPeerGroup {
// Send the chain that doesn't have all the transactions in it. The blocks after the exhaustion point should all // Send the chain that doesn't have all the transactions in it. The blocks after the exhaustion point should all
// be ignored. // be ignored.
int epoch = wallet.keychain.getCombinedKeyLookaheadEpochs(); int epoch = wallet.keyChainGroup.getCombinedKeyLookaheadEpochs();
BloomFilter filter = new BloomFilter(params, p1.lastReceivedFilter.bitcoinSerialize()); BloomFilter filter = new BloomFilter(params, p1.lastReceivedFilter.bitcoinSerialize());
filterAndSend(p1, blocks, filter); filterAndSend(p1, blocks, filter);
Block exhaustionPoint = blocks.get(3); Block exhaustionPoint = blocks.get(3);
pingAndWait(p1); pingAndWait(p1);
assertNotEquals(epoch, wallet.keychain.getCombinedKeyLookaheadEpochs()); assertNotEquals(epoch, wallet.keyChainGroup.getCombinedKeyLookaheadEpochs());
// 4th block was end of the lookahead zone and thus was discarded, so we got 3 blocks worth of money (50 each). // 4th block was end of the lookahead zone and thus was discarded, so we got 3 blocks worth of money (50 each).
assertEquals(Coin.FIFTY_COINS.multiply(3), wallet.getBalance()); assertEquals(Coin.FIFTY_COINS.multiply(3), wallet.getBalance());
assertEquals(exhaustionPoint.getPrevBlockHash(), blockChain.getChainHead().getHeader().getHash()); assertEquals(exhaustionPoint.getPrevBlockHash(), blockChain.getChainHead().getHeader().getHash());

View File

@ -316,7 +316,7 @@ public class WalletProtobufSerializerTest {
Wallet wallet1 = roundTrip(myWallet); Wallet wallet1 = roundTrip(myWallet);
assertEquals(0, wallet1.getTransactions(true).size()); assertEquals(0, wallet1.getTransactions(true).size());
assertEquals(Coin.ZERO, wallet1.getBalance()); assertEquals(Coin.ZERO, wallet1.getBalance());
assertEquals(2, wallet1.getActiveKeychain().getSigsRequiredToSpend()); assertEquals(2, wallet1.getActiveKeyChain().getSigsRequiredToSpend());
assertEquals(myAddress, wallet1.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS)); assertEquals(myAddress, wallet1.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS));
} }

View File

@ -947,7 +947,7 @@ public class WalletTool {
if (options.has(lookaheadSize)) { if (options.has(lookaheadSize)) {
Integer size = options.valueOf(lookaheadSize); Integer size = options.valueOf(lookaheadSize);
log.info("Setting keychain lookahead size to {}", size); log.info("Setting keychain lookahead size to {}", size);
wallet.setKeychainLookaheadSize(size); wallet.setKeyChainGroupLookaheadSize(size);
} }
ECKey key; ECKey key;
try { try {