3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-14 11:15:51 +00:00

Add some Javadocs and clean up the watching key API a tiny bit. Default creation time is now BIP32 standardisation time.

This commit is contained in:
Mike Hearn 2014-05-19 16:40:22 +02:00
parent 9ff7a91c8c
commit 42bfbb9b1c
5 changed files with 33 additions and 9 deletions

View File

@ -1,4 +1,5 @@
- Switch to the tree format agreed on with slush/stick
- Switch to the tree format agreed on with slush/stick.
- Store the account key creation time for an HD hierarchy.
- Support seeds up to 512 bits in size. Test compatibility with greenaddress, at least for some keys.
- Make Wallet notify key chains when a key has been observed in a transaction.
- Make DeterministicKeyChain auto-extend when a key was observed, to keep a gap limit in place.

View File

@ -52,6 +52,8 @@ public class DeterministicHierarchy implements Serializable {
// Keep track of how many child keys each node has. This is kind of weak.
private final Map<ImmutableList<ChildNumber>, ChildNumber> lastChildNumbers = Maps.newHashMap();
public static final int BIP32_STANDARDISATION_TIME_SECS = 1369267200;
/**
* Constructs a new hierarchy rooted at the given key. Note that this does not have to be the top of the tree.
* You can construct a DeterministicHierarchy for a subtree of a larger tree that you may not own.

View File

@ -81,6 +81,8 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
private DeterministicHierarchy hierarchy;
private DeterministicKey rootKey;
private DeterministicSeed seed;
// Ignored if seed != null. Useful for watching hierarchies.
private long creationTimeSeconds = MnemonicCode.BIP39_STANDARDISATION_TIME_SECS;
// Paths through the key tree. External keys are ones that are communicated to other parties. Internal keys are
@ -133,7 +135,11 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
this(new DeterministicSeed(seed, seedCreationTimeSecs));
}
public DeterministicKeyChain(DeterministicSeed seed) {
/**
* Creates a deterministic key chain starting from the given seed. All keys yielded by this chain will be the same
* if the starting seed is the same.
*/
protected DeterministicKeyChain(DeterministicSeed seed) {
this(seed, null);
}
@ -155,10 +161,19 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
this(watchingKey, Utils.currentTimeSeconds());
}
/**
* Creates a key chain that watches the given account key. The creation time is taken to be the time that BIP 32
* was standardised: most likely, you can optimise by selecting a more accurate creation time for your key and
* using the other watch method.
*/
public static DeterministicKeyChain watch(DeterministicKey accountKey) {
return new DeterministicKeyChain(accountKey);
return watch(accountKey, DeterministicHierarchy.BIP32_STANDARDISATION_TIME_SECS);
}
/**
* Creates a key chain that watches the given account key, and assumes there are no transactions involving it until
* the given time (this is an optimisation for chain scanning purposes).
*/
public static DeterministicKeyChain watch(DeterministicKey accountKey, long seedCreationTimeSecs) {
return new DeterministicKeyChain(accountKey, seedCreationTimeSecs);
}

View File

@ -73,11 +73,16 @@ public class KeyChainGroup {
* This HAS to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
*/
public KeyChainGroup(DeterministicKey watchKey) {
this(null, ImmutableList.of(new DeterministicKeyChain(watchKey)), null);
this(null, ImmutableList.of(DeterministicKeyChain.watch(watchKey)), null);
}
public KeyChainGroup(DeterministicKey watchKey, long creationTimeSeconds) {
this(null, ImmutableList.of(new DeterministicKeyChain(watchKey, creationTimeSeconds)), null);
/**
* Creates a keychain group with no basic chain, and an HD chain that is watching the given watching key which
* was assumed to be first used at the given UNIX time.
* This HAS to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
*/
public KeyChainGroup(DeterministicKey watchKey, long creationTimeSecondsSecs) {
this(null, ImmutableList.of(DeterministicKeyChain.watch(watchKey, creationTimeSecondsSecs)), null);
}
// Used for deserialization.

View File

@ -17,6 +17,7 @@
package com.google.bitcoin.wallet;
import com.google.bitcoin.core.*;
import com.google.bitcoin.crypto.DeterministicHierarchy;
import com.google.bitcoin.crypto.DeterministicKey;
import com.google.bitcoin.params.UnitTestParams;
import com.google.bitcoin.store.UnreadableWalletException;
@ -228,8 +229,8 @@ public class DeterministicKeyChainTest {
final String pub58 = watchingKey.serializePubB58();
assertEquals("xpub68KFnj3bqUx1s7mHejLDBPywCAKdJEu1b49uniEEn2WSbHmZ7xbLqFTjJbtx1LUcAt1DwhoqWHmo2s5WMJp6wi38CiF2hYD49qVViKVvAoi", pub58);
watchingKey = DeterministicKey.deserializeB58(null, pub58);
chain = new DeterministicKeyChain(watchingKey);
assertEquals(Utils.currentTimeSeconds(), chain.getEarliestKeyCreationTime());
chain = DeterministicKeyChain.watch(watchingKey);
assertEquals(DeterministicHierarchy.BIP32_STANDARDISATION_TIME_SECS, chain.getEarliestKeyCreationTime());
chain.setLookaheadSize(10);
assertEquals(key1.getPubKeyPoint(), chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).getPubKeyPoint());
@ -254,7 +255,7 @@ public class DeterministicKeyChainTest {
@Test(expected = IllegalStateException.class)
public void watchingCannotEncrypt() throws Exception {
final DeterministicKey accountKey = chain.getKeyByPath(DeterministicKeyChain.ACCOUNT_ZERO_PATH);
chain = new DeterministicKeyChain(accountKey.getPubOnly());
chain = DeterministicKeyChain.watch(accountKey.getPubOnly());
chain = chain.toEncrypted("this doesn't make any sense");
}