mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-14 11:15:51 +00:00
HD Wallets: mark the DeterministicKeys as issued, if seen in a Transaction
If a Transaction contains a DeterministicKey of our DeterministicKeyChains, then we should mark this key as issued. This can happen, when we replay/resync the blockchain or when another device uses one of our keys. Signed-off-by: Harald Hoyer <harald@harald-hoyer.de>
This commit is contained in:
parent
534a1e3a5c
commit
5726b97f70
@ -637,6 +637,33 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||||||
return findKeyFromPubKey(pubkey) != null;
|
return findKeyFromPubKey(pubkey) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks all keys used in the transaction output as used in the wallet.
|
||||||
|
* See {@link com.google.bitcoin.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this.
|
||||||
|
*/
|
||||||
|
private void markKeysAsUsed(Transaction tx) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
for (TransactionOutput o : tx.getOutputs()) {
|
||||||
|
try {
|
||||||
|
Script script = o.getScriptPubKey();
|
||||||
|
if (script.isSentToRawPubKey()) {
|
||||||
|
byte[] pubkey = script.getPubKey();
|
||||||
|
keychain.markPubKeyAsUsed(pubkey);
|
||||||
|
} else if (script.isSentToAddress()) {
|
||||||
|
byte[] pubkeyHash = script.getPubKeyHash();
|
||||||
|
keychain.markPubKeyHashAsUsed(pubkeyHash);
|
||||||
|
}
|
||||||
|
} catch (ScriptException e) {
|
||||||
|
// Just means we didn't understand the output of this transaction: ignore it.
|
||||||
|
log.warn("Could not parse tx output script: {}", e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the immutable seed for the current active HD chain.
|
* Returns the immutable seed for the current active HD chain.
|
||||||
* @throws com.google.bitcoin.core.ECKey.MissingPrivateKeyException if the seed is unavailable (watching wallet)
|
* @throws com.google.bitcoin.core.ECKey.MissingPrivateKeyException if the seed is unavailable (watching wallet)
|
||||||
@ -1230,6 +1257,9 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
|
|||||||
bitcoinValueToFriendlyString(valueDifference), tx.getHashAsString(), relativityOffset,
|
bitcoinValueToFriendlyString(valueDifference), tx.getHashAsString(), relativityOffset,
|
||||||
block != null ? block.getHeader().getHash() : "(unit test)");
|
block != null ? block.getHeader().getHash() : "(unit test)");
|
||||||
|
|
||||||
|
// mark the deterministic keys in this transaction as used
|
||||||
|
markKeysAsUsed(tx);
|
||||||
|
|
||||||
onWalletChangedSuppressions++;
|
onWalletChangedSuppressions++;
|
||||||
|
|
||||||
// If this transaction is already in the wallet we may need to move it into a different pool. At the very
|
// If this transaction is already in the wallet we may need to move it into a different pool. At the very
|
||||||
|
@ -295,6 +295,28 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
|||||||
basicKeyChain.importKeys(ImmutableList.of(key));
|
basicKeyChain.importKeys(ImmutableList.of(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the DeterministicKey as used.
|
||||||
|
* Also correct the issued{Internal|External}Keys counter, because all lower children seem to be requested already.
|
||||||
|
* If the counter was updated, we also might want to update the lookahead keys.
|
||||||
|
*/
|
||||||
|
public DeterministicKey markKeyAsUsed(DeterministicKey k) {
|
||||||
|
int numchilds = k.getChildNumber().i() + 1;
|
||||||
|
|
||||||
|
if (k.getParent() == internalKey) {
|
||||||
|
if (issuedInternalKeys < numchilds) {
|
||||||
|
issuedInternalKeys = numchilds;
|
||||||
|
maybeLookAhead();
|
||||||
|
}
|
||||||
|
} else if (k.getParent() == externalKey) {
|
||||||
|
if (issuedExternalKeys < numchilds) {
|
||||||
|
issuedExternalKeys = numchilds;
|
||||||
|
maybeLookAhead();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DeterministicKey findKeyFromPubHash(byte[] pubkeyHash) {
|
public DeterministicKey findKeyFromPubHash(byte[] pubkeyHash) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
@ -315,6 +337,38 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the DeterministicKeys as used, if they match the pubkeyHash
|
||||||
|
* See {@link com.google.bitcoin.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this.
|
||||||
|
*/
|
||||||
|
public boolean markPubHashAsUsed(byte[] pubkeyHash) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
DeterministicKey k = (DeterministicKey) basicKeyChain.findKeyFromPubHash(pubkeyHash);
|
||||||
|
if (k != null)
|
||||||
|
markKeyAsUsed(k);
|
||||||
|
return k != null;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the DeterministicKeys as used, if they match the pubkey
|
||||||
|
* See {@link com.google.bitcoin.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this.
|
||||||
|
*/
|
||||||
|
public boolean markPubKeyAsUsed(byte[] pubkey) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
DeterministicKey k = (DeterministicKey) basicKeyChain.findKeyFromPubKey(pubkey);
|
||||||
|
if (k != null)
|
||||||
|
markKeyAsUsed(k);
|
||||||
|
return k != null;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasKey(ECKey key) {
|
public boolean hasKey(ECKey key) {
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
@ -227,6 +227,18 @@ public class KeyChainGroup {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the DeterministicKeys as used, if they match the pubkeyHash
|
||||||
|
* See {@link com.google.bitcoin.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this.
|
||||||
|
*/
|
||||||
|
public void markPubKeyHashAsUsed(byte[] pubkeyHash) {
|
||||||
|
for (DeterministicKeyChain chain : chains) {
|
||||||
|
if (chain.markPubHashAsUsed(pubkeyHash))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean hasKey(ECKey key) {
|
public boolean hasKey(ECKey key) {
|
||||||
if (basic.hasKey(key))
|
if (basic.hasKey(key))
|
||||||
return true;
|
return true;
|
||||||
@ -248,6 +260,17 @@ public class KeyChainGroup {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark the DeterministicKeys as used, if they match the pubkey
|
||||||
|
* See {@link com.google.bitcoin.wallet.DeterministicKeyChain#markKeyAsUsed(DeterministicKey)} for more info on this.
|
||||||
|
*/
|
||||||
|
public void markPubKeyAsUsed(byte[] pubkey) {
|
||||||
|
for (DeterministicKeyChain chain : chains) {
|
||||||
|
if (chain.markPubKeyAsUsed(pubkey))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the number of keys managed by this group, including the lookahead buffers. */
|
/** Returns the number of keys managed by this group, including the lookahead buffers. */
|
||||||
public int numKeys() {
|
public int numKeys() {
|
||||||
int result = basic.numKeys();
|
int result = basic.numKeys();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user