mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-23 14:40:40 +01:00
KeyChainGroup: Remove most constructors. Those that remain are considered an unstable API.
Migrate all use of constructors to use a builder instead.
This commit is contained in:
parent
d1ec4b5901
commit
691a3b1de8
10 changed files with 130 additions and 103 deletions
|
@ -434,17 +434,17 @@ public class WalletAppKit extends AbstractIdleService {
|
|||
}
|
||||
|
||||
protected Wallet createWallet() {
|
||||
KeyChainGroup kcg;
|
||||
KeyChainGroup.Builder kcg = KeyChainGroup.builder(params);
|
||||
if (restoreFromSeed != null)
|
||||
kcg = new KeyChainGroup(params, restoreFromSeed);
|
||||
kcg.addChain(DeterministicKeyChain.builder().seed(restoreFromSeed).build());
|
||||
else if (restoreFromKey != null)
|
||||
kcg = new KeyChainGroup(params, restoreFromKey, false);
|
||||
kcg.addChain(DeterministicKeyChain.builder().spend(restoreFromKey).build());
|
||||
else
|
||||
kcg = new KeyChainGroup(params);
|
||||
kcg.fromRandom();
|
||||
if (walletFactory != null) {
|
||||
return walletFactory.create(params, kcg);
|
||||
return walletFactory.create(params, kcg.build());
|
||||
} else {
|
||||
return new Wallet(params, kcg); // default
|
||||
return new Wallet(params, kcg.build()); // default
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,62 @@ import static com.google.common.base.Preconditions.*;
|
|||
*/
|
||||
public class KeyChainGroup implements KeyBag {
|
||||
|
||||
/**
|
||||
* Builder for {@link KeyChainGroup}. Use {@link KeyChainGroup#builder(NetworkParameters)} to acquire an instance.
|
||||
*/
|
||||
public static class Builder {
|
||||
private final NetworkParameters params;
|
||||
private final List<DeterministicKeyChain> chains = new LinkedList<DeterministicKeyChain>();
|
||||
|
||||
private Builder(NetworkParameters params) {
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add chain from a random source.
|
||||
*/
|
||||
public Builder fromRandom() {
|
||||
this.chains.clear();
|
||||
DeterministicKeyChain chain = DeterministicKeyChain.builder().random(new SecureRandom()).build();
|
||||
this.chains.add(chain);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add chain from a given seed.
|
||||
* @param seed deterministic seed to derive all keys from
|
||||
*/
|
||||
public Builder fromSeed(DeterministicSeed seed) {
|
||||
this.chains.clear();
|
||||
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).build();
|
||||
this.chains.add(chain);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single chain.
|
||||
* @param chain to add
|
||||
*/
|
||||
public Builder addChain(DeterministicKeyChain chain) {
|
||||
this.chains.add(chain);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple chains.
|
||||
* @param chains to add
|
||||
*/
|
||||
public Builder chains(List<DeterministicKeyChain> chains) {
|
||||
this.chains.clear();
|
||||
this.chains.addAll(chains);
|
||||
return this;
|
||||
}
|
||||
|
||||
public KeyChainGroup build() {
|
||||
return new KeyChainGroup(params, null, chains, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
// Init proper random number generator, as some old Android installations have bugs that make it unsecure.
|
||||
if (Utils.isAndroidRuntime())
|
||||
|
@ -71,7 +127,7 @@ public class KeyChainGroup implements KeyBag {
|
|||
private static final Logger log = LoggerFactory.getLogger(KeyChainGroup.class);
|
||||
|
||||
private BasicKeyChain basic;
|
||||
private NetworkParameters params;
|
||||
private final NetworkParameters params;
|
||||
// Keychains for deterministically derived keys. If this is null, no chains should be created automatically.
|
||||
protected final @Nullable LinkedList<DeterministicKeyChain> chains;
|
||||
// currentKeys is used for normal, non-multisig/married wallets. currentAddresses is used when we're handing out
|
||||
|
@ -87,41 +143,8 @@ public class KeyChainGroup implements KeyBag {
|
|||
return new KeyChainGroup(params, new BasicKeyChain(), null, null, null);
|
||||
}
|
||||
|
||||
/** Creates a keychain group with no basic chain, and a single, lazily created HD chain. */
|
||||
public KeyChainGroup(NetworkParameters params) {
|
||||
this(params, null, new ArrayList<DeterministicKeyChain>(1), null, null);
|
||||
}
|
||||
|
||||
/** 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(DeterministicKeyChain.builder().seed(seed).build()), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keychain group with no basic chain, and an HD chain initialized from the given seed. Account path is
|
||||
* provided.
|
||||
*/
|
||||
public KeyChainGroup(NetworkParameters params, DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
|
||||
this(params, null,
|
||||
ImmutableList.of(DeterministicKeyChain.builder().seed(seed).accountPath(accountPath).build()), null,
|
||||
null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keychain group with no basic chain, and an HD chain that is watching the given watching key.
|
||||
* 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.builder().watch(watchKey).build()), null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a keychain group with no basic chain, and an HD chain that is watching or spending the given key.
|
||||
* 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.builder().watch(accountKey).build()
|
||||
: DeterministicKeyChain.builder().spend(accountKey).build()), null, null);
|
||||
public static KeyChainGroup.Builder builder(NetworkParameters params) {
|
||||
return new Builder(params);
|
||||
}
|
||||
|
||||
private KeyChainGroup(NetworkParameters params, @Nullable BasicKeyChain basicKeyChain, @Nullable List<DeterministicKeyChain> chains,
|
||||
|
|
|
@ -262,7 +262,7 @@ public class Wallet extends BaseTaggableObject
|
|||
* {@link #loadFromFile}.
|
||||
*/
|
||||
public Wallet(Context context) {
|
||||
this(context, new KeyChainGroup(context.getParams()));
|
||||
this(context, KeyChainGroup.builder(context.getParams()).fromRandom().build());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,7 +281,8 @@ public class Wallet extends BaseTaggableObject
|
|||
* {@link DeterministicKeyChain#ACCOUNT_ZERO_PATH 0 hardened path}
|
||||
*/
|
||||
public static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed) {
|
||||
return new Wallet(params, new KeyChainGroup(params, seed));
|
||||
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).build();
|
||||
return new Wallet(params, KeyChainGroup.builder(params).addChain(chain).build());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -291,14 +292,17 @@ public class Wallet extends BaseTaggableObject
|
|||
* @return an instance of a wallet from a deterministic seed.
|
||||
*/
|
||||
public static Wallet fromSeed(NetworkParameters params, DeterministicSeed seed, ImmutableList<ChildNumber> accountPath) {
|
||||
return new Wallet(params, new KeyChainGroup(params, seed, accountPath));
|
||||
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).accountPath(accountPath).build();
|
||||
return new Wallet(params, KeyChainGroup.builder(params).addChain(chain).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given watching key.
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given watching key. This HAS
|
||||
* to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
|
||||
*/
|
||||
public static Wallet fromWatchingKey(NetworkParameters params, DeterministicKey watchKey) {
|
||||
return new Wallet(params, new KeyChainGroup(params, watchKey));
|
||||
DeterministicKeyChain chain = DeterministicKeyChain.builder().watch(watchKey).build();
|
||||
return new Wallet(params, KeyChainGroup.builder(params).addChain(chain).build());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,11 +317,12 @@ public class Wallet extends BaseTaggableObject
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given spending key.
|
||||
* This wallet can also spend.
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given spending key. This HAS
|
||||
* to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}. This wallet can also spend.
|
||||
*/
|
||||
public static Wallet fromSpendingKey(NetworkParameters params, DeterministicKey spendKey) {
|
||||
return new Wallet(params, new KeyChainGroup(params, spendKey, false));
|
||||
DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(spendKey).build();
|
||||
return new Wallet(params, KeyChainGroup.builder(params).addChain(chain).build());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,13 +337,16 @@ public class Wallet extends BaseTaggableObject
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given spending key.
|
||||
* Creates a wallet that tracks payments to and from the HD key hierarchy rooted by the given spending key. This HAS
|
||||
* to be an account key as returned by {@link DeterministicKeyChain#getWatchingKey()}.
|
||||
*/
|
||||
public static Wallet fromMasterKey(NetworkParameters params, DeterministicKey masterKey, ChildNumber accountNumber) {
|
||||
public static Wallet fromMasterKey(NetworkParameters params, DeterministicKey masterKey,
|
||||
ChildNumber accountNumber) {
|
||||
DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(masterKey, accountNumber);
|
||||
accountKey = accountKey.dropParent();
|
||||
accountKey.setCreationTimeSeconds(masterKey.getCreationTimeSeconds());
|
||||
return new Wallet(params, new KeyChainGroup(params, accountKey, false));
|
||||
DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(accountKey).build();
|
||||
return new Wallet(params, KeyChainGroup.builder(params).addChain(chain).build());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -348,7 +356,7 @@ public class Wallet extends BaseTaggableObject
|
|||
for (ECKey key : keys)
|
||||
checkArgument(!(key instanceof DeterministicKey));
|
||||
|
||||
KeyChainGroup group = new KeyChainGroup(params);
|
||||
KeyChainGroup group = KeyChainGroup.builder(params).build();
|
||||
group.importKeys(keys);
|
||||
return new Wallet(params, group);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ public class BloomFilterTest {
|
|||
Address addr = LegacyAddress.fromKey(MAINNET, privKey.getKey());
|
||||
assertTrue(addr.toString().equals("17Wx1GQfyPTNWpQMHrTwRSMTCAonSiZx9e"));
|
||||
|
||||
KeyChainGroup group = new KeyChainGroup(MAINNET);
|
||||
KeyChainGroup group = KeyChainGroup.builder(MAINNET).build();
|
||||
// Add a random key which happens to have been used in a recent generation
|
||||
group.importKeys(ECKey.fromPublicOnly(privKey.getKey().getPubKeyPoint()), ECKey.fromPublicOnly(HEX.decode("03cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99")));
|
||||
Wallet wallet = new Wallet(MAINNET, group);
|
||||
|
|
|
@ -56,7 +56,7 @@ public class FilteredBlockAndPartialMerkleTreeTests extends TestWithPeerGroup {
|
|||
BigInteger.valueOf(1), 100000));
|
||||
store.setChainHead(store.get(Sha256Hash.wrap("000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506")));
|
||||
|
||||
KeyChainGroup group = new KeyChainGroup(UNITTEST);
|
||||
KeyChainGroup group = KeyChainGroup.builder(UNITTEST).build();
|
||||
group.importKeys(ECKey.fromPublicOnly(HEX.decode("04b27f7e9475ccf5d9a431cb86d665b8302c140144ec2397fce792f4a4e7765fecf8128534eaa71df04f93c74676ae8279195128a1506ebf7379d23dab8fca0f63")),
|
||||
ECKey.fromPublicOnly(HEX.decode("04732012cb962afa90d31b25d8fb0e32c94e513ab7a17805c14ca4c3423e18b4fb5d0e676841733cb83abaf975845c9f6f2a8097b7d04f4908b18368d6fc2d68ec")),
|
||||
ECKey.fromPublicOnly(HEX.decode("04cfb4113b3387637131ebec76871fd2760fc430dd16de0110f0eb07bb31ffac85e2607c189cb8582ea1ccaeb64ffd655409106589778f3000fdfe3263440b0350")),
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.bitcoinj.utils.BriefLogFormatter;
|
|||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.DeterministicKeyChain;
|
||||
import org.bitcoinj.wallet.KeyChain;
|
||||
import org.bitcoinj.wallet.KeyChainGroup;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.protobuf.ByteString;
|
||||
|
@ -92,12 +93,10 @@ public class WalletProtobufSerializerTest {
|
|||
BriefLogFormatter.initVerbose();
|
||||
Context ctx = new Context(UNITTEST);
|
||||
myWatchedKey = new ECKey();
|
||||
myWallet = new Wallet(UNITTEST);
|
||||
myKey = new ECKey();
|
||||
myKey.setCreationTimeSeconds(123456789L);
|
||||
myWallet.importKey(myKey);
|
||||
myAddress = LegacyAddress.fromKey(UNITTEST, myKey);
|
||||
myWallet = new Wallet(UNITTEST);
|
||||
myWallet = new Wallet(UNITTEST, KeyChainGroup.builder(UNITTEST).build());
|
||||
myWallet.importKey(myKey);
|
||||
mScriptCreationTime = new Date().getTime() / 1000 - 1234;
|
||||
myWallet.addWatchedAddress(LegacyAddress.fromKey(UNITTEST, myWatchedKey), mScriptCreationTime);
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.bitcoinj.store.BlockStore;
|
|||
import org.bitcoinj.store.MemoryBlockStore;
|
||||
import org.bitcoinj.utils.BriefLogFormatter;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
import org.bitcoinj.wallet.KeyChainGroup;
|
||||
import org.bitcoinj.wallet.Wallet;
|
||||
|
||||
import com.google.common.util.concurrent.SettableFuture;
|
||||
|
@ -88,7 +89,7 @@ public class TestWithNetworkConnections {
|
|||
this.blockStore = blockStore;
|
||||
// Allow subclasses to override the wallet object with their own.
|
||||
if (wallet == null) {
|
||||
wallet = new Wallet(UNITTEST);
|
||||
wallet = new Wallet(UNITTEST, KeyChainGroup.builder(UNITTEST).build());
|
||||
key = wallet.freshReceiveKey();
|
||||
address = LegacyAddress.fromKey(UNITTEST, key);
|
||||
}
|
||||
|
|
|
@ -555,7 +555,8 @@ public class DeterministicKeyChainTest {
|
|||
DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(coinLevelKey, new ChildNumber(0, true));
|
||||
accountKey = accountKey.dropParent();
|
||||
accountKey.setCreationTimeSeconds(watchingKey.getCreationTimeSeconds());
|
||||
KeyChainGroup group = new KeyChainGroup(params, accountKey, false);
|
||||
KeyChainGroup group = KeyChainGroup.builder(params)
|
||||
.addChain(DeterministicKeyChain.builder().spend(accountKey).build()).build();
|
||||
DeterministicKeyChain fromMasterKeyChain = group.getActiveKeyChain();
|
||||
assertEquals(BIP44_ACCOUNT_ONE_PATH, fromMasterKeyChain.getAccountPath());
|
||||
assertEquals(secs, fromMasterKeyChain.getEarliestKeyCreationTime());
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright 2014 Mike Hearn
|
||||
* Copyright 2019 Andreas Schildbach
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -55,7 +56,7 @@ public class KeyChainGroupTest {
|
|||
public void setup() {
|
||||
BriefLogFormatter.init();
|
||||
Utils.setMockClock();
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).fromRandom().build();
|
||||
group.setLookaheadSize(LOOKAHEAD_SIZE); // Don't want slow tests.
|
||||
group.getActiveKeyChain(); // Force create a chain.
|
||||
|
||||
|
@ -63,7 +64,7 @@ public class KeyChainGroupTest {
|
|||
}
|
||||
|
||||
private KeyChainGroup createMarriedKeyChainGroup() {
|
||||
KeyChainGroup group = new KeyChainGroup(MAINNET);
|
||||
KeyChainGroup group = KeyChainGroup.builder(MAINNET).build();
|
||||
DeterministicKeyChain chain = createMarriedKeyChain();
|
||||
group.addAndActivateHDChain(chain);
|
||||
group.setLookaheadSize(LOOKAHEAD_SIZE);
|
||||
|
@ -301,7 +302,7 @@ public class KeyChainGroupTest {
|
|||
|
||||
@Test
|
||||
public void encryptionWhilstEmpty() throws Exception {
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).fromRandom().build();
|
||||
group.setLookaheadSize(5);
|
||||
KeyCrypterScrypt scrypt = new KeyCrypterScrypt(2);
|
||||
final KeyParameter aesKey = scrypt.deriveKey("password");
|
||||
|
@ -454,7 +455,8 @@ public class KeyChainGroupTest {
|
|||
|
||||
@Test
|
||||
public void serializeWatching() throws Exception {
|
||||
group = new KeyChainGroup(MAINNET, watchingAccountKey);
|
||||
group = KeyChainGroup.builder(MAINNET)
|
||||
.addChain(DeterministicKeyChain.builder().watch(watchingAccountKey).build()).build();
|
||||
group.setLookaheadSize(LOOKAHEAD_SIZE);
|
||||
group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||
group.freshKey(KeyChain.KeyPurpose.CHANGE);
|
||||
|
@ -491,7 +493,8 @@ public class KeyChainGroupTest {
|
|||
public void constructFromSeed() throws Exception {
|
||||
ECKey key1 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||
final DeterministicSeed seed = checkNotNull(group.getActiveKeyChain().getSeed());
|
||||
KeyChainGroup group2 = new KeyChainGroup(MAINNET, seed);
|
||||
KeyChainGroup group2 = KeyChainGroup.builder(MAINNET)
|
||||
.addChain(DeterministicKeyChain.builder().seed(seed).build()).build();
|
||||
group2.setLookaheadSize(5);
|
||||
ECKey key2 = group2.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
|
||||
assertEquals(key1, key2);
|
||||
|
@ -500,7 +503,7 @@ public class KeyChainGroupTest {
|
|||
@Test(expected = DeterministicUpgradeRequiredException.class)
|
||||
public void deterministicUpgradeRequired() throws Exception {
|
||||
// Check that if we try to use HD features in a KCG that only has random keys, we get an exception.
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).build();
|
||||
group.importKeys(new ECKey(), new ECKey());
|
||||
assertTrue(group.isDeterministicUpgradeRequired());
|
||||
group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); // throws
|
||||
|
@ -510,7 +513,7 @@ public class KeyChainGroupTest {
|
|||
public void deterministicUpgradeUnencrypted() throws Exception {
|
||||
// Check that a group that contains only random keys has its HD chain created using the private key bytes of
|
||||
// the oldest random key, so upgrading the same wallet twice gives the same outcome.
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).build();
|
||||
group.setLookaheadSize(LOOKAHEAD_SIZE); // Don't want slow tests.
|
||||
ECKey key1 = new ECKey();
|
||||
Utils.rollMockClock(86400);
|
||||
|
@ -538,7 +541,7 @@ public class KeyChainGroupTest {
|
|||
|
||||
@Test
|
||||
public void deterministicUpgradeRotating() throws Exception {
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).build();
|
||||
group.setLookaheadSize(LOOKAHEAD_SIZE); // Don't want slow tests.
|
||||
long now = Utils.currentTimeSeconds();
|
||||
ECKey key1 = new ECKey();
|
||||
|
@ -557,7 +560,7 @@ public class KeyChainGroupTest {
|
|||
|
||||
@Test
|
||||
public void deterministicUpgradeEncrypted() throws Exception {
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).build();
|
||||
final ECKey key = new ECKey();
|
||||
group.importKeys(key);
|
||||
final KeyCrypterScrypt crypter = new KeyCrypterScrypt();
|
||||
|
@ -594,7 +597,7 @@ public class KeyChainGroupTest {
|
|||
|
||||
@Test
|
||||
public void isNotWatching() {
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).fromRandom().build();
|
||||
final ECKey key = ECKey.fromPrivate(BigInteger.TEN);
|
||||
group.importKeys(key);
|
||||
assertFalse(group.isWatching());
|
||||
|
@ -602,12 +605,11 @@ public class KeyChainGroupTest {
|
|||
|
||||
@Test
|
||||
public void isWatching() {
|
||||
group = new KeyChainGroup(
|
||||
MAINNET,
|
||||
DeterministicKey
|
||||
.deserializeB58(
|
||||
"xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo",
|
||||
MAINNET));
|
||||
group = KeyChainGroup.builder(MAINNET)
|
||||
.addChain(DeterministicKeyChain.builder().watch(DeterministicKey.deserializeB58(
|
||||
"xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo",
|
||||
MAINNET)).build())
|
||||
.build();
|
||||
final ECKey watchingKey = ECKey.fromPublicOnly(new ECKey().getPubKeyPoint());
|
||||
group.importKeys(watchingKey);
|
||||
assertTrue(group.isWatching());
|
||||
|
@ -615,18 +617,17 @@ public class KeyChainGroupTest {
|
|||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void isWatchingNoKeys() {
|
||||
group = new KeyChainGroup(MAINNET);
|
||||
group = KeyChainGroup.builder(MAINNET).build();
|
||||
group.isWatching();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void isWatchingMixedKeys() {
|
||||
group = new KeyChainGroup(
|
||||
MAINNET,
|
||||
DeterministicKey
|
||||
.deserializeB58(
|
||||
"xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo",
|
||||
MAINNET));
|
||||
group = KeyChainGroup.builder(MAINNET)
|
||||
.addChain(DeterministicKeyChain.builder().watch(DeterministicKey.deserializeB58(
|
||||
"xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo",
|
||||
MAINNET)).build())
|
||||
.build();
|
||||
final ECKey key = ECKey.fromPrivate(BigInteger.TEN);
|
||||
group.importKeys(key);
|
||||
group.isWatching();
|
||||
|
|
|
@ -79,7 +79,6 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.bitcoinj.core.Coin.*;
|
||||
import static org.bitcoinj.core.Utils.HEX;
|
||||
|
@ -181,9 +180,10 @@ public class WalletTest extends TestWithWallet {
|
|||
@Test
|
||||
public void encryptDecryptWalletWithArbitraryPath() throws Exception {
|
||||
final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes());
|
||||
KeyChainGroup keyChainGroup = new KeyChainGroup(UNITTEST,
|
||||
new DeterministicSeed(ENTROPY, "", 1389353062L),
|
||||
DeterministicKeyChain.BIP44_ACCOUNT_ZERO_PATH);
|
||||
KeyChainGroup keyChainGroup = KeyChainGroup.builder(UNITTEST)
|
||||
.addChain(DeterministicKeyChain.builder().seed(new DeterministicSeed(ENTROPY, "", 1389353062L))
|
||||
.accountPath(DeterministicKeyChain.BIP44_ACCOUNT_ZERO_PATH).build())
|
||||
.build();
|
||||
Wallet encryptedWallet = new Wallet(UNITTEST, keyChainGroup);
|
||||
encryptedWallet.encrypt(PASSWORD1);
|
||||
encryptedWallet.decrypt(PASSWORD1);
|
||||
|
@ -3040,17 +3040,11 @@ public class WalletTest extends TestWithWallet {
|
|||
goodKey.setCreationTimeSeconds(Utils.currentTimeSeconds());
|
||||
|
||||
// Do an upgrade based on the bad key.
|
||||
final AtomicReference<List<DeterministicKeyChain>> fChains = new AtomicReference<>();
|
||||
KeyChainGroup kcg = new KeyChainGroup(UNITTEST) {
|
||||
|
||||
{
|
||||
fChains.set(chains);
|
||||
}
|
||||
};
|
||||
KeyChainGroup kcg = KeyChainGroup.builder(UNITTEST).build();
|
||||
kcg.importKeys(badKey, goodKey);
|
||||
Utils.rollMockClock(86400);
|
||||
wallet = new Wallet(UNITTEST, kcg); // This avoids the automatic HD initialisation
|
||||
assertTrue(fChains.get().isEmpty());
|
||||
assertTrue(kcg.getDeterministicKeyChains().isEmpty());
|
||||
wallet.upgradeToDeterministic(null);
|
||||
DeterministicKey badWatchingKey = wallet.getWatchingKey();
|
||||
assertEquals(badKey.getCreationTimeSeconds(), badWatchingKey.getCreationTimeSeconds());
|
||||
|
@ -3065,17 +3059,17 @@ public class WalletTest extends TestWithWallet {
|
|||
assertEquals(goodKey.getCreationTimeSeconds(), usedKey.getCreationTimeSeconds());
|
||||
assertEquals(goodKey.getCreationTimeSeconds(), wallet.freshReceiveKey().getCreationTimeSeconds());
|
||||
assertEquals("mrM3TpCnav5YQuVA1xLercCGJH4DXujMtv", LegacyAddress.fromKey(UNITTEST, usedKey).toString());
|
||||
DeterministicKeyChain c = fChains.get().get(1);
|
||||
DeterministicKeyChain c = kcg.getDeterministicKeyChains().get(1);
|
||||
assertEquals(c.getEarliestKeyCreationTime(), goodKey.getCreationTimeSeconds());
|
||||
assertEquals(2, fChains.get().size());
|
||||
assertEquals(2, kcg.getDeterministicKeyChains().size());
|
||||
|
||||
// Commit the maint txns.
|
||||
wallet.commitTx(txns.get(0));
|
||||
|
||||
// Check next maintenance does nothing.
|
||||
assertTrue(wallet.doMaintenance(null, false).get().isEmpty());
|
||||
assertEquals(c, fChains.get().get(1));
|
||||
assertEquals(2, fChains.get().size());
|
||||
assertEquals(c, kcg.getDeterministicKeyChains().get(1));
|
||||
assertEquals(2, kcg.getDeterministicKeyChains().size());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
|
@ -3277,7 +3271,7 @@ public class WalletTest extends TestWithWallet {
|
|||
@Test
|
||||
public void keyEvents() throws Exception {
|
||||
// Check that we can register an event listener, generate some keys and the callbacks are invoked properly.
|
||||
wallet = new Wallet(UNITTEST);
|
||||
wallet = new Wallet(UNITTEST, KeyChainGroup.builder(UNITTEST).build());
|
||||
final List<ECKey> keys = Lists.newLinkedList();
|
||||
wallet.addKeyChainEventListener(Threading.SAME_THREAD, new KeyChainEventListener() {
|
||||
@Override
|
||||
|
@ -3298,7 +3292,7 @@ public class WalletTest extends TestWithWallet {
|
|||
// much where it goes). Wallet on the other hand will try to auto-upgrade you when possible.
|
||||
|
||||
// Create an old-style random wallet.
|
||||
KeyChainGroup group = new KeyChainGroup(UNITTEST);
|
||||
KeyChainGroup group = KeyChainGroup.builder(UNITTEST).build();
|
||||
group.importKeys(new ECKey(), new ECKey());
|
||||
wallet = new Wallet(UNITTEST, group);
|
||||
assertTrue(wallet.isDeterministicUpgradeRequired());
|
||||
|
@ -3310,7 +3304,7 @@ public class WalletTest extends TestWithWallet {
|
|||
@Test
|
||||
public void upgradeToHDEncrypted() throws Exception {
|
||||
// Create an old-style random wallet.
|
||||
KeyChainGroup group = new KeyChainGroup(UNITTEST);
|
||||
KeyChainGroup group = KeyChainGroup.builder(UNITTEST).build();
|
||||
group.importKeys(new ECKey(), new ECKey());
|
||||
wallet = new Wallet(UNITTEST, group);
|
||||
assertTrue(wallet.isDeterministicUpgradeRequired());
|
||||
|
|
Loading…
Add table
Reference in a new issue