DeterministicKeyChain, MarriedKeyChain: Remove most constructors and static constructors. Those that remain are considered an unstable API.

Migrate all use of constructors to use the builders instead.
This commit is contained in:
Andreas Schildbach
2019-01-26 16:03:35 +01:00
parent 16c7d03e1f
commit 2dd2acd4a8
7 changed files with 99 additions and 162 deletions

View File

@@ -41,8 +41,10 @@ public class DefaultKeyChainFactory implements KeyChainFactory {
DeterministicKeyChain chain;
if (isMarried)
chain = new MarriedKeyChain(accountKey);
else if (isFollowingKey)
chain = DeterministicKeyChain.builder().watchAndFollow(accountKey).build();
else
chain = new DeterministicKeyChain(accountKey, isFollowingKey);
chain = DeterministicKeyChain.builder().watch(accountKey).build();
return chain;
}
@@ -53,7 +55,7 @@ public class DefaultKeyChainFactory implements KeyChainFactory {
if (isMarried)
chain = new MarriedKeyChain(accountKey);
else
chain = DeterministicKeyChain.spend(accountKey);
chain = DeterministicKeyChain.builder().spend(accountKey).build();
return chain;
}
}

View File

@@ -65,7 +65,7 @@ import static com.google.common.collect.Lists.newLinkedList;
* sufficient information about the account key to create a watching chain via
* {@link DeterministicKey#deserializeB58(DeterministicKey, String, NetworkParameters)}
* (with null as the first parameter) and then
* {@link DeterministicKeyChain#DeterministicKeyChain(DeterministicKey)}.</p>
* {@link Builder#watch(DeterministicKey)}.</p>
*
* <p>This class builds on {@link DeterministicHierarchy} and
* {@link DeterministicKey} by adding support for serialization to and from protobufs,
@@ -164,10 +164,12 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
protected SecureRandom random;
protected int bits = DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS;
protected String passphrase;
protected long creationTimeSecs;
protected long creationTimeSecs = 0;
protected byte[] entropy;
protected DeterministicSeed seed;
protected DeterministicKey watchingKey = null;
protected boolean isFollowing = false;
protected DeterministicKey spendingKey = null;
protected ImmutableList<ChildNumber> accountPath = null;
protected Builder() {
@@ -222,9 +224,34 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
return self();
}
public T watchingKey(DeterministicKey watchingKey) {
checkState(accountPath == null, "either watchingKey or accountPath");
this.watchingKey = watchingKey;
/**
* Creates a key chain that watches the given account key.
*/
public T watch(DeterministicKey accountKey) {
checkState(accountPath == null, "either watch or accountPath");
this.watchingKey = accountKey;
this.isFollowing = false;
return self();
}
/**
* Creates a deterministic key chain with the given watch key and that follows some other keychain. In a married
* wallet following keychain represents "spouse". Watch key has to be an account key.
*/
public T watchAndFollow(DeterministicKey accountKey) {
checkState(accountPath == null, "either watchAndFollow or accountPath");
this.watchingKey = accountKey;
this.isFollowing = true;
return self();
}
/**
* Creates a key chain that can spend from the given account key.
*/
public T spend(DeterministicKey accountKey) {
checkState(accountPath == null, "either spend or accountPath");
this.spendingKey = accountKey;
this.isFollowing = false;
return self();
}
@@ -239,7 +266,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
* Use an account path other than the default {@link DeterministicKeyChain#ACCOUNT_ZERO_PATH}.
*/
public T accountPath(ImmutableList<ChildNumber> accountPath) {
checkState(watchingKey == null, "either watchingKey or accountPath");
checkState(watchingKey == null, "either watch or accountPath");
this.accountPath = accountPath;
return self();
}
@@ -260,7 +287,9 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
else if (seed != null)
return new DeterministicKeyChain(seed, null, accountPath);
else if (watchingKey != null)
return new DeterministicKeyChain(watchingKey);
return new DeterministicKeyChain(watchingKey, isFollowing, true);
else if (spendingKey != null)
return new DeterministicKeyChain(spendingKey, false, false);
else
throw new IllegalStateException();
}
@@ -275,77 +304,19 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
}
/**
* Generates a new key chain with entropy selected randomly from the given {@link SecureRandom}
* object and the default entropy size.
*/
public DeterministicKeyChain(SecureRandom random) {
this(random, DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS, DEFAULT_PASSPHRASE_FOR_MNEMONIC);
}
/**
* Generates a new key chain with entropy selected randomly from the given {@link SecureRandom}
* object and of the requested size in bits.
*/
public DeterministicKeyChain(SecureRandom random, int bits) {
this(random, bits, DEFAULT_PASSPHRASE_FOR_MNEMONIC);
}
/**
* Generates a new key chain with entropy selected randomly from the given {@link SecureRandom}
* object and of the requested size in bits. The derived seed is further protected with a user selected passphrase
* (see BIP 39).
*/
public DeterministicKeyChain(SecureRandom random, int bits, String passphrase) {
this(new DeterministicSeed(random, bits, passphrase));
}
/**
* Creates a deterministic key chain starting from the given entropy. All keys yielded by this chain will be the same
* if the starting seed is the same. You should provide the creation time in seconds since the UNIX epoch for the
* seed: this lets us know from what part of the chain we can expect to see derived keys appear.
*/
public DeterministicKeyChain(byte[] entropy, String passphrase, long seedCreationTimeSecs) {
this(new DeterministicSeed(entropy, passphrase, seedCreationTimeSecs));
}
/**
* 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, ACCOUNT_ZERO_PATH);
}
/**
* Creates a deterministic key chain starting from the given seed. This deterministic Key chain
* will follow the account path defined.
*/
public DeterministicKeyChain(DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
this(seed, null, accountPath);
}
/**
* Creates a deterministic key chain that watches the given (public only) root key. You can use this to calculate
* balances and generally follow along, but spending is not possible with such a chain.
*/
public DeterministicKeyChain(DeterministicKey watchingKey) {
checkArgument(watchingKey.isPubKeyOnly(), "Private subtrees not currently supported: if you got this key from DKC.getWatchingKey() then use .dropPrivate().dropParent() on it first.");
this.accountPath = watchingKey.getPath();
basicKeyChain = new BasicKeyChain();
this.seed = null;
this.rootKey = null;
basicKeyChain.importKey(watchingKey);
hierarchy = new DeterministicHierarchy(watchingKey);
initializeHierarchyUnencrypted(watchingKey);
}
/**
* Creates a deterministic key chain from a watched or spendable account key. If {@code isWatching} flag is set,
* then creates a deterministic key chain that watches the given (public only) root key. You can use this to calculate
* balances and generally follow along, but spending is not possible with such a chain. If it is not set, then this
* creates a deterministic key chain that allows spending. If {@code isFollowing} flag is set(only allowed
* if {@code isWatching} is set) then this keychain follows some other keychain. In a married wallet following
* <p>
* Creates a deterministic key chain from a watched or spendable account key. If {@code isWatching} flag is set,
* then creates a deterministic key chain that watches the given (public only) root key. You can use this to
* calculate balances and generally follow along, but spending is not possible with such a chain. If it is not set,
* then this creates a deterministic key chain that allows spending. If {@code isFollowing} flag is set(only allowed
* if {@code isWatching} is set) then this keychain follows some other keychain. In a married wallet following
* keychain represents "spouse's" keychain.
* </p>
*
* <p>
* This constructor is not stable across releases! If you need a stable API, use {@link #builder()} to use a
* {@link Builder}.
* </p>
*/
public DeterministicKeyChain(DeterministicKey key, boolean isFollowing, boolean isWatching) {
if (isWatching)
@@ -365,48 +336,15 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
}
/**
* <p>Creates a deterministic key chain with the given watch key. If {@code isFollowing} flag is set then this keychain follows
* some other keychain. In a married wallet following keychain represents "spouse's" keychain.</p>
* <p>Watch key has to be an account key.</p>
*/
protected DeterministicKeyChain(DeterministicKey watchKey, boolean isFollowing) {
this(watchKey);
this.isFollowing = isFollowing;
}
/**
* Creates a deterministic key chain with the given watch key and that follows some other keychain. In a married
* wallet following keychain represents "spouse"
* Watch key has to be an account key.
*/
public static DeterministicKeyChain watchAndFollow(DeterministicKey watchKey) {
return new DeterministicKeyChain(watchKey, true);
}
/**
* Creates a key chain that watches the given account key.
*/
public static DeterministicKeyChain watch(DeterministicKey accountKey) {
return new DeterministicKeyChain(accountKey);
}
/**
* Creates a key chain that can spend from the given account key.
*/
public static DeterministicKeyChain spend(DeterministicKey accountKey) {
return new DeterministicKeyChain(accountKey, false, false);
}
/**
* For use in {@link KeyChainFactory} during deserialization.
*/
protected DeterministicKeyChain(DeterministicSeed seed, @Nullable KeyCrypter crypter) {
this(seed, crypter, ACCOUNT_ZERO_PATH);
}
/**
* Creates a deterministic key chain with an encrypted deterministic seed using the provided account path.
* Using {@link KeyCrypter KeyCrypter} to decrypt.
* <p>
* Creates a deterministic key chain with an encrypted deterministic seed using the provided account path. Using
* {@link KeyCrypter KeyCrypter} to decrypt.
* </p>
*
* <p>
* This constructor is not stable across releases! If you need a stable API, use {@link #builder()} to use a
* {@link Builder}.
* </p>
*/
protected DeterministicKeyChain(DeterministicSeed seed, @Nullable KeyCrypter crypter,
ImmutableList<ChildNumber> accountPath) {
@@ -676,7 +614,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
* <p>An alias for {@code getKeyByPath(getAccountPath())}.</p>
*
* <p>Use this when you would like to create a watching key chain that follows this one, but can't spend money from it.
* The returned key can be serialized and then passed into {@link #watch(DeterministicKey)}
* The returned key can be serialized and then passed into {@link Builder#watch(DeterministicKey)}
* on another system to watch the hierarchy.</p>
*
* <p>Note that the returned key is not pubkey only unless this key chain already is: the returned key can still
@@ -1077,7 +1015,7 @@ public class DeterministicKeyChain implements EncryptableKeyChain {
* This is used in encryption/decryption.
*/
protected DeterministicKeyChain makeKeyChainFromSeed(DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
return new DeterministicKeyChain(seed, accountPath);
return new DeterministicKeyChain(seed, null, accountPath);
}
@Override

View File

@@ -88,7 +88,7 @@ public class KeyChainGroup implements KeyBag {
/** Creates a keychain group with no basic chain, and an HD chain initialized from the given seed. */
public KeyChainGroup(NetworkParameters params, DeterministicSeed seed) {
this(params, null, ImmutableList.of(new DeterministicKeyChain(seed)), null, null);
this(params, null, ImmutableList.of(DeterministicKeyChain.builder().seed(seed).build()), null, null);
}
/**
@@ -96,7 +96,9 @@ public class KeyChainGroup implements KeyBag {
* provided.
*/
public KeyChainGroup(NetworkParameters params, DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
this(params, null, ImmutableList.of(new DeterministicKeyChain(seed, accountPath)), null, null);
this(params, null,
ImmutableList.of(DeterministicKeyChain.builder().seed(seed).accountPath(accountPath).build()), null,
null);
}
/**
@@ -104,7 +106,7 @@ public class KeyChainGroup implements KeyBag {
* This HAS to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
*/
public KeyChainGroup(NetworkParameters params, DeterministicKey watchKey) {
this(params, null, ImmutableList.of(DeterministicKeyChain.watch(watchKey)), null, null);
this(params, null, ImmutableList.of(DeterministicKeyChain.builder().watch(watchKey).build()), null, null);
}
/**
@@ -112,7 +114,8 @@ public class KeyChainGroup implements KeyBag {
* This HAS to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
*/
public KeyChainGroup(NetworkParameters params, DeterministicKey accountKey, boolean watch) {
this(params, null, ImmutableList.of(watch ? DeterministicKeyChain.watch(accountKey) : DeterministicKeyChain.spend(accountKey)), null, null);
this(params, null, ImmutableList.of(watch ? DeterministicKeyChain.builder().watch(accountKey).build()
: DeterministicKeyChain.builder().spend(accountKey).build()), null, null);
}
private KeyChainGroup(NetworkParameters params, @Nullable BasicKeyChain basicKeyChain, List<DeterministicKeyChain> chains,
@@ -145,7 +148,7 @@ public class KeyChainGroup implements KeyBag {
/** Adds a new HD chain to the chains list, and make it the default chain (from which keys are issued). */
public void createAndActivateNewHDChain() {
// We can't do auto upgrade here because we don't know the rotation time, if any.
final DeterministicKeyChain chain = new DeterministicKeyChain(new SecureRandom());
final DeterministicKeyChain chain = DeterministicKeyChain.builder().random(new SecureRandom()).build();
addAndActivateHDChain(chain);
}
@@ -752,7 +755,8 @@ public class KeyChainGroup implements KeyBag {
entropy = Arrays.copyOfRange(entropy, 0, DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS / 8); // final argument is exclusive range.
checkState(entropy.length == DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS / 8);
String passphrase = ""; // FIXME allow non-empty passphrase
DeterministicKeyChain chain = new DeterministicKeyChain(entropy, passphrase, keyToUse.getCreationTimeSeconds());
DeterministicKeyChain chain = DeterministicKeyChain.builder()
.entropy(entropy, keyToUse.getCreationTimeSeconds()).passphrase(passphrase).build();
if (aesKey != null) {
chain = chain.toEncrypted(checkNotNull(basic.getKeyCrypter()), aesKey);
}

View File

@@ -31,7 +31,6 @@ import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptBuilder;
import org.bouncycastle.crypto.params.KeyParameter;
import java.security.SecureRandom;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -122,28 +121,22 @@ public class MarriedKeyChain extends DeterministicKeyChain {
return new Builder();
}
// Protobuf deserialization constructors
MarriedKeyChain(DeterministicKey accountKey) {
super(accountKey, false);
/**
* This constructor is not stable across releases! If you need a stable API, use {@link #builder()} to use a
* {@link Builder}.
*/
protected MarriedKeyChain(DeterministicKey accountKey) {
super(accountKey, false, true);
}
/**
* This constructor is not stable across releases! If you need a stable API, use {@link #builder()} to use a
* {@link Builder}.
*/
protected MarriedKeyChain(DeterministicSeed seed, KeyCrypter crypter, ImmutableList<ChildNumber> accountPath) {
super(seed, crypter, accountPath);
}
// Builder constructors
private MarriedKeyChain(SecureRandom random, int bits, String passphrase) {
super(random, bits, passphrase);
}
private MarriedKeyChain(byte[] entropy, String passphrase, long seedCreationTimeSecs) {
super(entropy, passphrase, seedCreationTimeSecs);
}
private MarriedKeyChain(DeterministicSeed seed) {
super(seed);
}
void setFollowingKeyChains(List<DeterministicKeyChain> followingKeyChains) {
checkArgument(!followingKeyChains.isEmpty());
this.followingKeyChains = followingKeyChains;
@@ -196,7 +189,7 @@ public class MarriedKeyChain extends DeterministicKeyChain {
for (DeterministicKey key : followingAccountKeys) {
checkArgument(key.getPath().size() == getAccountPath().size(), "Following keys have to be account keys");
DeterministicKeyChain chain = DeterministicKeyChain.watchAndFollow(key);
DeterministicKeyChain chain = DeterministicKeyChain.builder().watchAndFollow(key).build();
if (lookaheadSize >= 0)
chain.setLookaheadSize(lookaheadSize);
if (lookaheadThreshold >= 0)

View File

@@ -362,7 +362,7 @@ public class WalletProtobufSerializerTest {
public void testRoundTripMarriedWallet() throws Exception {
// create 2-of-2 married wallet
myWallet = new Wallet(UNITTEST);
final DeterministicKeyChain partnerChain = new DeterministicKeyChain(new SecureRandom());
final DeterministicKeyChain partnerChain = DeterministicKeyChain.builder().random(new SecureRandom()).build();
DeterministicKey partnerKey = DeterministicKey.deserializeB58(null, partnerChain.getWatchingKey().serializePubB58(UNITTEST), UNITTEST);
MarriedKeyChain chain = MarriedKeyChain.builder()
.random(new SecureRandom())

View File

@@ -63,11 +63,11 @@ public class DeterministicKeyChainTest {
// You should use a random seed instead. The secs constant comes from the unit test file, so we can compare
// serialized data properly.
long secs = 1389353062L;
chain = new DeterministicKeyChain(ENTROPY, "", secs);
chain = DeterministicKeyChain.builder().entropy(ENTROPY, secs).build();
chain.setLookaheadSize(10);
assertEquals(secs, checkNotNull(chain.getSeed()).getCreationTimeSeconds());
bip44chain = new DeterministicKeyChain(new DeterministicSeed(ENTROPY, "", secs), BIP44_ACCOUNT_ONE_PATH);
bip44chain = DeterministicKeyChain.builder().entropy(ENTROPY, secs).accountPath(BIP44_ACCOUNT_ONE_PATH).build();
bip44chain.setLookaheadSize(10);
assertEquals(secs, checkNotNull(bip44chain.getSeed()).getCreationTimeSeconds());
}
@@ -167,7 +167,7 @@ public class DeterministicKeyChainTest {
// Check that we get the right events at the right time.
final List<List<ECKey>> listenerKeys = Lists.newArrayList();
long secs = 1389353062L;
chain = new DeterministicKeyChain(ENTROPY, "", secs);
chain = DeterministicKeyChain.builder().entropy(ENTROPY, secs).build();
chain.addEventListener(new AbstractKeyChainEventListener() {
@Override
public void onKeysAdded(List<ECKey> keys) {
@@ -203,7 +203,7 @@ public class DeterministicKeyChainTest {
public void random() {
// Can't test much here but verify the constructor worked and the class is functional. The other tests rely on
// a fixed seed to be deterministic.
chain = new DeterministicKeyChain(new SecureRandom(), 384);
chain = DeterministicKeyChain.builder().random(new SecureRandom(), 384).build();
chain.setLookaheadSize(10);
chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).sign(Sha256Hash.ZERO_HASH);
chain.getKey(KeyChain.KeyPurpose.CHANGE).sign(Sha256Hash.ZERO_HASH);
@@ -358,7 +358,7 @@ public class DeterministicKeyChainTest {
assertEquals("xpub69KR9epSNBM59KLuasxMU5CyKytMJjBP5HEZ5p8YoGUCpM6cM9hqxB9DDPCpUUtqmw5duTckvPfwpoWGQUFPmRLpxs5jYiTf2u6xRMcdhDf", pub58);
watchingKey = DeterministicKey.deserializeB58(null, pub58, MAINNET);
watchingKey.setCreationTimeSeconds(100000);
chain = DeterministicKeyChain.watch(watchingKey);
chain = DeterministicKeyChain.builder().watch(watchingKey).build();
assertEquals(100000, chain.getEarliestKeyCreationTime());
chain.setLookaheadSize(10);
chain.maybeLookAhead();
@@ -394,7 +394,7 @@ public class DeterministicKeyChainTest {
DeterministicKey watchingKey = bip44chain.getWatchingKey();
watchingKey = watchingKey.dropPrivateBytes().dropParent();
watchingKey.setCreationTimeSeconds(100000);
chain = DeterministicKeyChain.watch(watchingKey);
chain = DeterministicKeyChain.builder().watch(watchingKey).build();
assertEquals(100000, chain.getEarliestKeyCreationTime());
chain.setLookaheadSize(10);
chain.maybeLookAhead();
@@ -435,7 +435,7 @@ public class DeterministicKeyChainTest {
assertEquals("xpub69KR9epJ2Wp6ywiv4Xu5WfBUpX4GLu6D5NUMd4oUkCFoZoRNyk3ZCxfKPDkkGvCPa16dPgEdY63qoyLqEa5TQQy1nmfSmgWcagRzimyV7uA", pub58);
watchingKey = DeterministicKey.deserializeB58(null, pub58, MAINNET);
watchingKey.setCreationTimeSeconds(100000);
chain = DeterministicKeyChain.watch(watchingKey);
chain = DeterministicKeyChain.builder().watch(watchingKey).build();
assertEquals(accountOne, chain.getAccountPath());
assertEquals(100000, chain.getEarliestKeyCreationTime());
chain.setLookaheadSize(10);
@@ -475,7 +475,7 @@ public class DeterministicKeyChainTest {
assertEquals("xprv9vL4k9HYXonmvqGSUrRM6wGEmx3ruGTXi4JxHRiwEvwDwYmTocPbQNpjN89gpqPrFofmfvALwgnNFBCH2grse1YDf8ERAwgdvbjRtoMfsbV", prv58);
watchingKey = DeterministicKey.deserializeB58(null, prv58, params);
watchingKey.setCreationTimeSeconds(100000);
chain = DeterministicKeyChain.spend(watchingKey);
chain = DeterministicKeyChain.builder().spend(watchingKey).build();
assertEquals(100000, chain.getEarliestKeyCreationTime());
chain.setLookaheadSize(10);
chain.maybeLookAhead();
@@ -517,7 +517,7 @@ public class DeterministicKeyChainTest {
assertEquals("xprv9vL4k9HYXonmzR7UC1ngJ3hTjxkmjLLUo3RexSfUGSWcACHzghWBLJAwW6xzs59XeFizQxFQWtscoTfrF9PSXrUgAtBgr13Nuojax8xTBRz", prv58);
watchingKey = DeterministicKey.deserializeB58(null, prv58, params);
watchingKey.setCreationTimeSeconds(secs);
chain = DeterministicKeyChain.spend(watchingKey);
chain = DeterministicKeyChain.builder().spend(watchingKey).build();
assertEquals(accountTwo, chain.getAccountPath());
assertEquals(secs, chain.getEarliestKeyCreationTime());
chain.setLookaheadSize(10);
@@ -544,7 +544,7 @@ public class DeterministicKeyChainTest {
assertEquals("xprv9yYQhynAmWWuz62PScx5Q2frBET2F1raaXna5A2E9Lj8XWgmKBL7S98Yand8F736j9UCTNWQeiB4yL5pLZP7JDY2tY8eszGQkiKDwBkezeS", prv58);
watchingKey = DeterministicKey.deserializeB58(null, prv58, params);
watchingKey.setCreationTimeSeconds(secs);
DeterministicKeyChain fromPrivBase58Chain = DeterministicKeyChain.spend(watchingKey);
DeterministicKeyChain fromPrivBase58Chain = DeterministicKeyChain.builder().spend(watchingKey).build();
assertEquals(secs, fromPrivBase58Chain.getEarliestKeyCreationTime());
fromPrivBase58Chain.setLookaheadSize(10);
fromPrivBase58Chain.maybeLookAhead();
@@ -610,7 +610,7 @@ public class DeterministicKeyChainTest {
@Test(expected = IllegalStateException.class)
public void watchingCannotEncrypt() throws Exception {
final DeterministicKey accountKey = chain.getKeyByPath(DeterministicKeyChain.ACCOUNT_ZERO_PATH);
chain = DeterministicKeyChain.watch(accountKey.dropPrivateBytes().dropParent());
chain = DeterministicKeyChain.builder().watch(accountKey.dropPrivateBytes().dropParent()).build();
assertEquals(DeterministicKeyChain.ACCOUNT_ZERO_PATH, chain.getAccountPath());
chain = chain.toEncrypted("this doesn't make any sense");
}
@@ -641,7 +641,7 @@ public class DeterministicKeyChainTest {
DeterministicKey[] keys = new DeterministicKey[100];
for (int i = 0; i < keys.length; i++)
keys[i] = chain.getKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
chain = DeterministicKeyChain.watch(chain.getWatchingKey().dropPrivateBytes().dropParent());
chain = DeterministicKeyChain.builder().watch(chain.getWatchingKey().dropPrivateBytes().dropParent()).build();
int e = chain.numBloomFilterEntries();
BloomFilter filter = chain.getFilter(e, 0.001, 1);
for (DeterministicKey key : keys)

View File

@@ -120,7 +120,7 @@ public class WalletTest extends TestWithWallet {
List<DeterministicKey> followingKeys = Lists.newArrayList();
for (int i = 0; i < numKeys - 1; i++) {
final DeterministicKeyChain keyChain = new DeterministicKeyChain(new SecureRandom());
final DeterministicKeyChain keyChain = DeterministicKeyChain.builder().random(new SecureRandom()).build();
DeterministicKey partnerKey = DeterministicKey.deserializeB58(null, keyChain.getWatchingKey().serializePubB58(UNITTEST), UNITTEST);
followingKeys.add(partnerKey);
if (addSigners && i < threshold - 1)
@@ -3326,7 +3326,7 @@ public class WalletTest extends TestWithWallet {
blockStore = new MemoryBlockStore(UNITTEST);
chain = new BlockChain(UNITTEST, wallet, blockStore);
final DeterministicKeyChain keyChain = new DeterministicKeyChain(new SecureRandom());
final DeterministicKeyChain keyChain = DeterministicKeyChain.builder().random(new SecureRandom()).build();
DeterministicKey partnerKey = DeterministicKey.deserializeB58(null, keyChain.getWatchingKey().serializePubB58(UNITTEST), UNITTEST);
TransactionSigner signer = new TransactionSigner() {