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

Rename ExtendedHierarchicKey to DeterministicKey. Add annotations and rewrite a bit of code to satisfy static analysis.

This commit is contained in:
Mike Hearn 2013-07-11 13:41:46 +02:00
parent 50dd5af0c8
commit 000d81d54f
7 changed files with 82 additions and 68 deletions

View File

@ -23,6 +23,7 @@ package com.google.bitcoin.crypto.hd;
*/ */
public class ChildNumber { public class ChildNumber {
public static final int PRIV_BIT = 0x80000000; public static final int PRIV_BIT = 0x80000000;
public static final ChildNumber ZERO = new ChildNumber(0);
/** Integer i as per BIP 32 spec, including the MSB denoting derivation type (0 = public, 1 = private) **/ /** Integer i as per BIP 32 spec, including the MSB denoting derivation type (0 = public, 1 = private) **/
private final int i; private final int i;

View File

@ -31,7 +31,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* Bitcoin's privacy system require new keys to be created for each transaction, but managing all these * Bitcoin's privacy system require new keys to be created for each transaction, but managing all these
* keys quickly becomes unwieldy. In particular it becomes hard to back up and distribute them. By having * keys quickly becomes unwieldy. In particular it becomes hard to back up and distribute them. By having
* a way to derive random-looking but deterministic keys we can make wallet backup simpler and gain the * a way to derive random-looking but deterministic keys we can make wallet backup simpler and gain the
* ability to hand out {@link ExtendedHierarchicKey}s to other people who can then create new addresses * ability to hand out {@link DeterministicKey}s to other people who can then create new addresses
* on the fly, without having to contact us.</p> * on the fly, without having to contact us.</p>
* *
* <p>The hierarchy is started from a single root key, and a location in the tree is given by a path which * <p>The hierarchy is started from a single root key, and a location in the tree is given by a path which
@ -44,7 +44,7 @@ public class DeterministicHierarchy implements Serializable {
*/ */
private static final int MAX_CHILD_DERIVATION_ATTEMPTS = 100; private static final int MAX_CHILD_DERIVATION_ATTEMPTS = 100;
private final Map<ImmutableList<ChildNumber>, ExtendedHierarchicKey> keys = Maps.newHashMap(); private final Map<ImmutableList<ChildNumber>, DeterministicKey> keys = Maps.newHashMap();
private final ImmutableList<ChildNumber> rootPath; private final ImmutableList<ChildNumber> rootPath;
private final Map<ImmutableList<ChildNumber>, ChildNumber> lastPrivDerivedNumbers = Maps.newHashMap(); private final Map<ImmutableList<ChildNumber>, ChildNumber> lastPrivDerivedNumbers = Maps.newHashMap();
private final Map<ImmutableList<ChildNumber>, ChildNumber> lastPubDerivedNumbers = Maps.newHashMap(); private final Map<ImmutableList<ChildNumber>, ChildNumber> lastPubDerivedNumbers = Maps.newHashMap();
@ -53,12 +53,12 @@ public class DeterministicHierarchy implements Serializable {
* Constructs a new hierarchy rooted at the given key. Note that this does not have to be the top of the tree. * 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. * You can construct a DeterministicHierarchy for a subtree of a larger tree that you may not own.
*/ */
public DeterministicHierarchy(ExtendedHierarchicKey rootKey) { public DeterministicHierarchy(DeterministicKey rootKey) {
putKey(rootKey); putKey(rootKey);
rootPath = rootKey.getChildNumberPath(); rootPath = rootKey.getChildNumberPath();
} }
private void putKey(ExtendedHierarchicKey key) { private void putKey(DeterministicKey key) {
keys.put(key.getChildNumberPath(), key); keys.put(key.getChildNumberPath(), key);
} }
@ -71,14 +71,14 @@ public class DeterministicHierarchy implements Serializable {
* @return next newly created key using the child derivation function * @return next newly created key using the child derivation function
* @throws IllegalArgumentException if create is false and the path was not found. * @throws IllegalArgumentException if create is false and the path was not found.
*/ */
public ExtendedHierarchicKey get(List<ChildNumber> path, boolean relativePath, boolean create) { public DeterministicKey get(List<ChildNumber> path, boolean relativePath, boolean create) {
ImmutableList<ChildNumber> absolutePath = relativePath ImmutableList<ChildNumber> absolutePath = relativePath
? ImmutableList.<ChildNumber>builder().addAll(rootPath).addAll(path).build() ? ImmutableList.<ChildNumber>builder().addAll(rootPath).addAll(path).build()
: ImmutableList.copyOf(path); : ImmutableList.copyOf(path);
if (!keys.containsKey(absolutePath)) { if (!keys.containsKey(absolutePath)) {
checkArgument(create, "No key found for {} path {}.", relativePath ? "relative" : "absolute", path); checkArgument(create, "No key found for {} path {}.", relativePath ? "relative" : "absolute", path);
checkArgument(absolutePath.size() > 0, "Can't derive the master key: nothing to derive from."); checkArgument(absolutePath.size() > 0, "Can't derive the master key: nothing to derive from.");
ExtendedHierarchicKey parent = get(absolutePath.subList(0, absolutePath.size() - 1), relativePath, true); DeterministicKey parent = get(absolutePath.subList(0, absolutePath.size() - 1), relativePath, true);
putKey(HDKeyDerivation.deriveChildKey(parent, absolutePath.get(absolutePath.size() - 1))); putKey(HDKeyDerivation.deriveChildKey(parent, absolutePath.get(absolutePath.size() - 1)));
} }
return keys.get(absolutePath); return keys.get(absolutePath);
@ -95,8 +95,8 @@ public class DeterministicHierarchy implements Serializable {
* @return next newly created key using the child derivation funtcion * @return next newly created key using the child derivation funtcion
* @throws IllegalArgumentException if the parent doesn't exist and createParent is false. * @throws IllegalArgumentException if the parent doesn't exist and createParent is false.
*/ */
public ExtendedHierarchicKey deriveNextChild(ImmutableList<ChildNumber> parentPath, boolean relative, boolean createParent, boolean privateDerivation) { public DeterministicKey deriveNextChild(ImmutableList<ChildNumber> parentPath, boolean relative, boolean createParent, boolean privateDerivation) {
ExtendedHierarchicKey parent = get(parentPath, relative, createParent); DeterministicKey parent = get(parentPath, relative, createParent);
int nAttempts = 0; int nAttempts = 0;
while (nAttempts++ < MAX_CHILD_DERIVATION_ATTEMPTS) { while (nAttempts++ < MAX_CHILD_DERIVATION_ATTEMPTS) {
try { try {
@ -125,12 +125,12 @@ public class DeterministicHierarchy implements Serializable {
* @return the requested key. * @return the requested key.
* @throws IllegalArgumentException if the parent doesn't exist and createParent is false. * @throws IllegalArgumentException if the parent doesn't exist and createParent is false.
*/ */
public ExtendedHierarchicKey deriveChild(List<ChildNumber> parentPath, boolean relative, boolean createParent, ChildNumber createChildNumber) { public DeterministicKey deriveChild(List<ChildNumber> parentPath, boolean relative, boolean createParent, ChildNumber createChildNumber) {
return deriveChild(get(parentPath, relative, createParent), createChildNumber); return deriveChild(get(parentPath, relative, createParent), createChildNumber);
} }
private ExtendedHierarchicKey deriveChild(ExtendedHierarchicKey parent, ChildNumber createChildNumber) { private DeterministicKey deriveChild(DeterministicKey parent, ChildNumber createChildNumber) {
ExtendedHierarchicKey childKey = HDKeyDerivation.deriveChildKey(parent, createChildNumber); DeterministicKey childKey = HDKeyDerivation.deriveChildKey(parent, createChildNumber);
putKey(childKey); putKey(childKey);
return childKey; return childKey;
} }
@ -138,7 +138,7 @@ public class DeterministicHierarchy implements Serializable {
/** /**
* Returns the root key that the {@link DeterministicHierarchy} was created with. * Returns the root key that the {@link DeterministicHierarchy} was created with.
*/ */
public ExtendedHierarchicKey getRootKey() { public DeterministicKey getRootKey() {
return get(rootPath, false, false); return get(rootPath, false, false);
} }

View File

@ -24,6 +24,7 @@ import com.google.common.collect.Iterables;
import org.spongycastle.math.ec.ECPoint; import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.util.encoders.Hex; import org.spongycastle.util.encoders.Hex;
import javax.annotation.Nullable;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -31,27 +32,30 @@ import java.text.MessageFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* An extended key is a node in a {@link DeterministicHierarchy}. As per * An extended key is a node in a {@link DeterministicHierarchy}. As per
* <a href="https://en.bitcoin.it/wiki/BIP_0032">the BIP 32 specification</a> it is a pair (key, chaincode). If you * <a href="https://en.bitcoin.it/wiki/BIP_0032">the BIP 32 specification</a> it is a pair (key, chaincode). If you
* know its path in the tree you can derive more keys from this. * know its path in the tree you can derive more keys from this.
*/ */
public class ExtendedHierarchicKey implements Serializable { public class DeterministicKey implements Serializable {
public static final ChildNumber MASTER_CHILD_NUMBER = new ChildNumber(0);
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Joiner PATH_JOINER = Joiner.on("/"); private static final Joiner PATH_JOINER = Joiner.on("/");
private final ExtendedHierarchicKey parent; private final DeterministicKey parent;
private ECPoint publicAsPoint; private ECPoint publicAsPoint;
private final BigInteger privateAsFieldElement; private final BigInteger privateAsFieldElement;
private final ImmutableList<ChildNumber> childNumberPath; private final ImmutableList<ChildNumber> childNumberPath;
/** 32 bytes */ /** 32 bytes */
private byte[] chainCode; private final byte[] chainCode;
ExtendedHierarchicKey(ImmutableList<ChildNumber> childNumberPath, byte[] chainCode, ECPoint publicAsPoint, BigInteger privateKeyFieldElt, ExtendedHierarchicKey parent) { DeterministicKey(ImmutableList<ChildNumber> childNumberPath, byte[] chainCode,
assert chainCode.length == 32 : chainCode.length; @Nullable ECPoint publicAsPoint, @Nullable BigInteger privateKeyFieldElt,
@Nullable DeterministicKey parent) {
checkArgument(chainCode.length == 32);
this.parent = parent; this.parent = parent;
this.childNumberPath = childNumberPath; this.childNumberPath = childNumberPath;
this.chainCode = Arrays.copyOf(chainCode, chainCode.length); this.chainCode = Arrays.copyOf(chainCode, chainCode.length);
@ -73,10 +77,10 @@ public class ExtendedHierarchicKey implements Serializable {
} }
/** /**
* Returns the last element of the path returned by {@link com.google.bitcoin.crypto.hd.ExtendedHierarchicKey#getChildNumberPath()} * Returns the last element of the path returned by {@link DeterministicKey#getChildNumberPath()}
*/ */
public ChildNumber getChildNumber() { public ChildNumber getChildNumber() {
return getDepth() == 0 ? MASTER_CHILD_NUMBER : childNumberPath.get(childNumberPath.size() - 1); return getDepth() == 0 ? ChildNumber.ZERO : childNumberPath.get(childNumberPath.size() - 1);
} }
/** /**
@ -101,7 +105,8 @@ public class ExtendedHierarchicKey implements Serializable {
} }
ECPoint getPubPoint() { ECPoint getPubPoint() {
if (publicAsPoint == null && privateAsFieldElement != null) { if (publicAsPoint == null) {
checkNotNull(privateAsFieldElement);
publicAsPoint = HDUtils.getEcParams().getG().multiply(privateAsFieldElement); publicAsPoint = HDUtils.getEcParams().getG().multiply(privateAsFieldElement);
} }
return HDUtils.compressedCopy(publicAsPoint); return HDUtils.compressedCopy(publicAsPoint);
@ -118,14 +123,20 @@ public class ExtendedHierarchicKey implements Serializable {
return Arrays.copyOfRange(getIdentifier(), 0, 4); return Arrays.copyOfRange(getIdentifier(), 0, 4);
} }
@Nullable
public BigInteger getPrivAsFieldElement() { public BigInteger getPrivAsFieldElement() {
return privateAsFieldElement; return privateAsFieldElement;
} }
public ExtendedHierarchicKey getParent() { @Nullable
public DeterministicKey getParent() {
return parent; return parent;
} }
/**
* Returns the private key bytes, if they were provided during construction.
*/
@Nullable
public byte[] getPrivKeyBytes() { public byte[] getPrivKeyBytes() {
return privateAsFieldElement == null ? null : privateAsFieldElement.toByteArray(); return privateAsFieldElement == null ? null : privateAsFieldElement.toByteArray();
} }
@ -135,16 +146,18 @@ public class ExtendedHierarchicKey implements Serializable {
*/ */
public byte[] getPrivKeyBytes33() { public byte[] getPrivKeyBytes33() {
byte[] bytes33 = new byte[33]; byte[] bytes33 = new byte[33];
byte[] priv = getPrivKeyBytes(); byte[] priv = checkNotNull(getPrivKeyBytes(), "Private key missing");
System.arraycopy(priv, 0, bytes33, 33 - priv.length, priv.length); System.arraycopy(priv, 0, bytes33, 33 - priv.length, priv.length);
return bytes33; return bytes33;
} }
/** /**
* @return The same key with the private part removed. May return the same instance. * Returns the same key with the private part removed. May return the same instance.
*/ */
public ExtendedHierarchicKey getPubOnly() { public DeterministicKey getPubOnly() {
return hasPrivate() ? new ExtendedHierarchicKey(getChildNumberPath(), getChainCode(), getPubPoint(), null, getParent() == null ? null : getParent().getPubOnly()) : this; if (!hasPrivate()) return this;
final DeterministicKey parentPub = getParent() == null ? null : getParent().getPubOnly();
return new DeterministicKey(getChildNumberPath(), getChainCode(), getPubPoint(), null, parentPub);
} }
public boolean hasPrivate() { public boolean hasPrivate() {

View File

@ -43,7 +43,7 @@ public final class HDKeyDerivation {
* *
* @throws HDDerivationException if generated master key is invalid (private key 0 or >= n). * @throws HDDerivationException if generated master key is invalid (private key 0 or >= n).
*/ */
public static ExtendedHierarchicKey createMasterPrivateKey(byte[] seed) throws HDDerivationException { public static DeterministicKey createMasterPrivateKey(byte[] seed) throws HDDerivationException {
// Calculate I = HMAC-SHA512(key="Bitcoin seed", msg=S) // Calculate I = HMAC-SHA512(key="Bitcoin seed", msg=S)
byte[] i = HDUtils.hmacSha256(MASTER_HMAC_SHA256, seed); byte[] i = HDUtils.hmacSha256(MASTER_HMAC_SHA256, seed);
// Split I into two 32-byte sequences, Il and Ir. // Split I into two 32-byte sequences, Il and Ir.
@ -52,7 +52,7 @@ public final class HDKeyDerivation {
byte[] il = Arrays.copyOfRange(i, 0, 32); byte[] il = Arrays.copyOfRange(i, 0, 32);
byte[] ir = Arrays.copyOfRange(i, 32, 64); byte[] ir = Arrays.copyOfRange(i, 32, 64);
Arrays.fill(i, (byte)0); Arrays.fill(i, (byte)0);
ExtendedHierarchicKey masterPrivKey = createMasterPrivKeyFromBytes(il, ir); DeterministicKey masterPrivKey = createMasterPrivKeyFromBytes(il, ir);
Arrays.fill(il, (byte)0); Arrays.fill(il, (byte)0);
Arrays.fill(ir, (byte)0); Arrays.fill(ir, (byte)0);
return masterPrivKey; return masterPrivKey;
@ -61,21 +61,21 @@ public final class HDKeyDerivation {
/** /**
* @throws HDDerivationException if privKeyBytes is invalid (0 or >= n). * @throws HDDerivationException if privKeyBytes is invalid (0 or >= n).
*/ */
static ExtendedHierarchicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode) throws HDDerivationException { static DeterministicKey createMasterPrivKeyFromBytes(byte[] privKeyBytes, byte[] chainCode) throws HDDerivationException {
BigInteger privateKeyFieldElt = HDUtils.toBigInteger(privKeyBytes); BigInteger privateKeyFieldElt = HDUtils.toBigInteger(privKeyBytes);
assertNonZero(privateKeyFieldElt, "Generated master key is invalid."); assertNonZero(privateKeyFieldElt, "Generated master key is invalid.");
assertLessThanN(privateKeyFieldElt, "Generated master key is invalid."); assertLessThanN(privateKeyFieldElt, "Generated master key is invalid.");
return new ExtendedHierarchicKey(ImmutableList.<ChildNumber>of(), chainCode, null, privateKeyFieldElt, null); return new DeterministicKey(ImmutableList.<ChildNumber>of(), chainCode, null, privateKeyFieldElt, null);
} }
public static ExtendedHierarchicKey createMasterPubKeyFromBytes(byte[] pubKeyBytes, byte[] chainCode) { public static DeterministicKey createMasterPubKeyFromBytes(byte[] pubKeyBytes, byte[] chainCode) {
return new ExtendedHierarchicKey(ImmutableList.<ChildNumber>of(), chainCode, HDUtils.getCurve().decodePoint(pubKeyBytes), null, null); return new DeterministicKey(ImmutableList.<ChildNumber>of(), chainCode, HDUtils.getCurve().decodePoint(pubKeyBytes), null, null);
} }
/** /**
* @param childNumber the "extended" child number, ie. with the 0x80000000 bit specifying private/public derivation. * @param childNumber the "extended" child number, ie. with the 0x80000000 bit specifying private/public derivation.
*/ */
public static ExtendedHierarchicKey deriveChildKey(ExtendedHierarchicKey parent, int childNumber) { public static DeterministicKey deriveChildKey(DeterministicKey parent, int childNumber) {
return deriveChildKey(parent, new ChildNumber(childNumber)); return deriveChildKey(parent, new ChildNumber(childNumber));
} }
@ -83,11 +83,11 @@ public final class HDKeyDerivation {
* @throws HDDerivationException if private derivation is attempted for a public-only parent key, or * @throws HDDerivationException if private derivation is attempted for a public-only parent key, or
* if the resulting derived key is invalid (eg. private key == 0). * if the resulting derived key is invalid (eg. private key == 0).
*/ */
public static ExtendedHierarchicKey deriveChildKey(ExtendedHierarchicKey parent, ChildNumber childNumber) public static DeterministicKey deriveChildKey(DeterministicKey parent, ChildNumber childNumber)
throws HDDerivationException { throws HDDerivationException {
RawKeyBytes rawKey = deriveChildKeyBytes(parent, childNumber); RawKeyBytes rawKey = deriveChildKeyBytes(parent, childNumber);
return new ExtendedHierarchicKey( return new DeterministicKey(
HDUtils.append(parent.getChildNumberPath(), childNumber), HDUtils.append(parent.getChildNumberPath(), childNumber),
rawKey.chainCode, rawKey.chainCode,
parent.hasPrivate() ? null : HDUtils.getCurve().decodePoint(rawKey.keyBytes), parent.hasPrivate() ? null : HDUtils.getCurve().decodePoint(rawKey.keyBytes),
@ -95,7 +95,7 @@ public final class HDKeyDerivation {
parent); parent);
} }
private static RawKeyBytes deriveChildKeyBytes(ExtendedHierarchicKey parent, ChildNumber childNumber) private static RawKeyBytes deriveChildKeyBytes(DeterministicKey parent, ChildNumber childNumber)
throws HDDerivationException { throws HDDerivationException {
byte[] parentPublicKey = HDUtils.getBytes(parent.getPubPoint()); byte[] parentPublicKey = HDUtils.getBytes(parent.getPubPoint());

View File

@ -126,7 +126,7 @@ public class BIP32Test {
private void testVector(int testCase) throws AddressFormatException { private void testVector(int testCase) throws AddressFormatException {
log.info("======= Test vector {}", testCase); log.info("======= Test vector {}", testCase);
HDWTestVector tv = tvs[testCase]; HDWTestVector tv = tvs[testCase];
ExtendedHierarchicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(Hex.decode(tv.seed)); DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(Hex.decode(tv.seed));
Assert.assertEquals(testEncode(tv.priv), testEncode(masterPrivateKey.serializePrivB58())); Assert.assertEquals(testEncode(tv.priv), testEncode(masterPrivateKey.serializePrivB58()));
Assert.assertEquals(testEncode(tv.pub), testEncode(masterPrivateKey.serializePubB58())); Assert.assertEquals(testEncode(tv.pub), testEncode(masterPrivateKey.serializePubB58()));
DeterministicHierarchy dh = new DeterministicHierarchy(masterPrivateKey); DeterministicHierarchy dh = new DeterministicHierarchy(masterPrivateKey);
@ -135,7 +135,7 @@ public class BIP32Test {
log.info("{}", tc.name); log.info("{}", tc.name);
Assert.assertEquals(tc.name, String.format("Test%d %s", testCase + 1, tc.getPathDescription())); Assert.assertEquals(tc.name, String.format("Test%d %s", testCase + 1, tc.getPathDescription()));
int depth = tc.path.length - 1; int depth = tc.path.length - 1;
ExtendedHierarchicKey ehkey = dh.deriveChild(Arrays.asList(tc.path).subList(0, depth), false, true, tc.path[depth]); DeterministicKey ehkey = dh.deriveChild(Arrays.asList(tc.path).subList(0, depth), false, true, tc.path[depth]);
Assert.assertEquals(testEncode(tc.priv), testEncode(ehkey.serializePrivB58())); Assert.assertEquals(testEncode(tc.priv), testEncode(ehkey.serializePrivB58()));
Assert.assertEquals(testEncode(tc.pub), testEncode(ehkey.serializePubB58())); Assert.assertEquals(testEncode(tc.pub), testEncode(ehkey.serializePubB58()));
} }

View File

@ -53,56 +53,56 @@ public class ChildKeyDerivationTest {
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Start with an extended PRIVATE key // Start with an extended PRIVATE key
ExtendedHierarchicKey ekprv = HDKeyDerivation.createMasterPrivKeyFromBytes(priv, chain); DeterministicKey ekprv = HDKeyDerivation.createMasterPrivKeyFromBytes(priv, chain);
// Create two accounts // Create two accounts
ExtendedHierarchicKey ekprv_0 = HDKeyDerivation.deriveChildKey(ekprv, 0); DeterministicKey ekprv_0 = HDKeyDerivation.deriveChildKey(ekprv, 0);
ExtendedHierarchicKey ekprv_1 = HDKeyDerivation.deriveChildKey(ekprv, 1); DeterministicKey ekprv_1 = HDKeyDerivation.deriveChildKey(ekprv, 1);
// Create internal and external chain on Account 0 // Create internal and external chain on Account 0
ExtendedHierarchicKey ekprv_0_EX = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_EXTERNAL); DeterministicKey ekprv_0_EX = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_EXTERNAL);
ExtendedHierarchicKey ekprv_0_IN = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_INTERNAL); DeterministicKey ekprv_0_IN = HDKeyDerivation.deriveChildKey(ekprv_0, HDW_CHAIN_INTERNAL);
// Create three addresses on external chain // Create three addresses on external chain
ExtendedHierarchicKey ekprv_0_EX_0 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 0); DeterministicKey ekprv_0_EX_0 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 0);
ExtendedHierarchicKey ekprv_0_EX_1 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 1); DeterministicKey ekprv_0_EX_1 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 1);
ExtendedHierarchicKey ekprv_0_EX_2 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 2); DeterministicKey ekprv_0_EX_2 = HDKeyDerivation.deriveChildKey(ekprv_0_EX, 2);
// Create three addresses on internal chain // Create three addresses on internal chain
ExtendedHierarchicKey ekprv_0_IN_0 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 0); DeterministicKey ekprv_0_IN_0 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 0);
ExtendedHierarchicKey ekprv_0_IN_1 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 1); DeterministicKey ekprv_0_IN_1 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 1);
ExtendedHierarchicKey ekprv_0_IN_2 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 2); DeterministicKey ekprv_0_IN_2 = HDKeyDerivation.deriveChildKey(ekprv_0_IN, 2);
// Now add a few more addresses with very large indices // Now add a few more addresses with very large indices
ExtendedHierarchicKey ekprv_1_IN = HDKeyDerivation.deriveChildKey(ekprv_1, HDW_CHAIN_INTERNAL); DeterministicKey ekprv_1_IN = HDKeyDerivation.deriveChildKey(ekprv_1, HDW_CHAIN_INTERNAL);
ExtendedHierarchicKey ekprv_1_IN_4095 = HDKeyDerivation.deriveChildKey(ekprv_1_IN, 4095); DeterministicKey ekprv_1_IN_4095 = HDKeyDerivation.deriveChildKey(ekprv_1_IN, 4095);
// ExtendedHierarchicKey ekprv_1_IN_4bil = HDKeyDerivation.deriveChildKey(ekprv_1_IN, 4294967295L); // ExtendedHierarchicKey ekprv_1_IN_4bil = HDKeyDerivation.deriveChildKey(ekprv_1_IN, 4294967295L);
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Repeat the above with PUBLIC key // Repeat the above with PUBLIC key
ExtendedHierarchicKey ekpub = HDKeyDerivation.createMasterPubKeyFromBytes(HDUtils.toCompressed(pub), chain); DeterministicKey ekpub = HDKeyDerivation.createMasterPubKeyFromBytes(HDUtils.toCompressed(pub), chain);
// Create two accounts // Create two accounts
ExtendedHierarchicKey ekpub_0 = HDKeyDerivation.deriveChildKey(ekpub, 0); DeterministicKey ekpub_0 = HDKeyDerivation.deriveChildKey(ekpub, 0);
ExtendedHierarchicKey ekpub_1 = HDKeyDerivation.deriveChildKey(ekpub, 1); DeterministicKey ekpub_1 = HDKeyDerivation.deriveChildKey(ekpub, 1);
// Create internal and external chain on Account 0 // Create internal and external chain on Account 0
ExtendedHierarchicKey ekpub_0_EX = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_EXTERNAL); DeterministicKey ekpub_0_EX = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_EXTERNAL);
ExtendedHierarchicKey ekpub_0_IN = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_INTERNAL); DeterministicKey ekpub_0_IN = HDKeyDerivation.deriveChildKey(ekpub_0, HDW_CHAIN_INTERNAL);
// Create three addresses on external chain // Create three addresses on external chain
ExtendedHierarchicKey ekpub_0_EX_0 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 0); DeterministicKey ekpub_0_EX_0 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 0);
ExtendedHierarchicKey ekpub_0_EX_1 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 1); DeterministicKey ekpub_0_EX_1 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 1);
ExtendedHierarchicKey ekpub_0_EX_2 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 2); DeterministicKey ekpub_0_EX_2 = HDKeyDerivation.deriveChildKey(ekpub_0_EX, 2);
// Create three addresses on internal chain // Create three addresses on internal chain
ExtendedHierarchicKey ekpub_0_IN_0 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 0); DeterministicKey ekpub_0_IN_0 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 0);
ExtendedHierarchicKey ekpub_0_IN_1 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 1); DeterministicKey ekpub_0_IN_1 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 1);
ExtendedHierarchicKey ekpub_0_IN_2 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 2); DeterministicKey ekpub_0_IN_2 = HDKeyDerivation.deriveChildKey(ekpub_0_IN, 2);
// Now add a few more addresses with very large indices // Now add a few more addresses with very large indices
ExtendedHierarchicKey ekpub_1_IN = HDKeyDerivation.deriveChildKey(ekpub_1, HDW_CHAIN_INTERNAL); DeterministicKey ekpub_1_IN = HDKeyDerivation.deriveChildKey(ekpub_1, HDW_CHAIN_INTERNAL);
ExtendedHierarchicKey ekpub_1_IN_4095 = HDKeyDerivation.deriveChildKey(ekpub_1_IN, 4095); DeterministicKey ekpub_1_IN_4095 = HDKeyDerivation.deriveChildKey(ekpub_1_IN, 4095);
// ExtendedHierarchicKey ekpub_1_IN_4bil = HDKeyDerivation.deriveChildKey(ekpub_1_IN, 4294967295L); // ExtendedHierarchicKey ekpub_1_IN_4bil = HDKeyDerivation.deriveChildKey(ekpub_1_IN, 4294967295L);
assertEquals(hexEncodePub(ekprv.getPubOnly()), hexEncodePub(ekpub)); assertEquals(hexEncodePub(ekprv.getPubOnly()), hexEncodePub(ekpub));
@ -121,7 +121,7 @@ public class ChildKeyDerivationTest {
} }
} }
private static String hexEncodePub(ExtendedHierarchicKey pubKey) { private static String hexEncodePub(DeterministicKey pubKey) {
return hexEncode(pubKey.getPubKeyBytes()); return hexEncode(pubKey.getPubKeyBytes());
} }

View File

@ -30,10 +30,10 @@ public class DeterministicHierarchyTest {
*/ */
@Test @Test
public void testHierarchy() throws Exception { public void testHierarchy() throws Exception {
ExtendedHierarchicKey m = HDKeyDerivation.createMasterPrivateKey(new SecureRandom().generateSeed(32)); DeterministicKey m = HDKeyDerivation.createMasterPrivateKey(new SecureRandom().generateSeed(32));
for (int iWallet = 0; iWallet < 3; iWallet++) { for (int iWallet = 0; iWallet < 3; iWallet++) {
ExtendedHierarchicKey walletRootKey = HDKeyDerivation.deriveChildKey(m, iWallet); DeterministicKey walletRootKey = HDKeyDerivation.deriveChildKey(m, iWallet);
DeterministicKeyGenerator hdWalletKeyGen = new DeterministicKeyGenerator(walletRootKey); DeterministicKeyGenerator hdWalletKeyGen = new DeterministicKeyGenerator(walletRootKey);
assertEquals(walletRootKey.getChildNumber().getChildNumber(), iWallet); assertEquals(walletRootKey.getChildNumber().getChildNumber(), iWallet);