KeyChainGroup: migrate to Network from NetworkParameters

This commit is contained in:
Andreas Schildbach 2023-04-19 12:54:19 +02:00
parent 3e7761c81c
commit e7017bfc2f
10 changed files with 98 additions and 81 deletions

View file

@ -508,7 +508,7 @@ public class WalletAppKit extends AbstractIdleService implements Closeable {
} }
protected Wallet createWallet() { protected Wallet createWallet() {
KeyChainGroup.Builder kcg = KeyChainGroup.builder(params, structure); KeyChainGroup.Builder kcg = KeyChainGroup.builder(network, structure);
if (restoreFromSeed != null) if (restoreFromSeed != null)
kcg.fromSeed(restoreFromSeed, preferredOutputScriptType); kcg.fromSeed(restoreFromSeed, preferredOutputScriptType);
else if (restoreFromKey != null) else if (restoreFromKey != null)

View file

@ -20,6 +20,7 @@ package org.bitcoinj.wallet;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import org.bitcoinj.base.BitcoinNetwork; import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.Address; import org.bitcoinj.base.Address;
import org.bitcoinj.base.Network;
import org.bitcoinj.base.internal.TimeUtils; import org.bitcoinj.base.internal.TimeUtils;
import org.bitcoinj.crypto.AesKey; import org.bitcoinj.crypto.AesKey;
import org.bitcoinj.core.BloomFilter; import org.bitcoinj.core.BloomFilter;
@ -90,16 +91,16 @@ import static org.bitcoinj.base.internal.Preconditions.checkState;
public class KeyChainGroup implements KeyBag { public class KeyChainGroup implements KeyBag {
/** /**
* Builder for {@link KeyChainGroup}. Use {@link KeyChainGroup#builder(NetworkParameters)} to acquire an instance. * Builder for {@link KeyChainGroup}. Use {@link KeyChainGroup#builder(Network)} to acquire an instance.
*/ */
public static class Builder { public static class Builder {
private final NetworkParameters params; private final Network network;
private final KeyChainGroupStructure structure; private final KeyChainGroupStructure structure;
private final List<DeterministicKeyChain> chains = new LinkedList<>(); private final List<DeterministicKeyChain> chains = new LinkedList<>();
private int lookaheadSize = -1, lookaheadThreshold = -1; private int lookaheadSize = -1, lookaheadThreshold = -1;
private Builder(NetworkParameters params, KeyChainGroupStructure structure) { private Builder(Network network, KeyChainGroupStructure structure) {
this.params = params; this.network = network;
this.structure = structure; this.structure = structure;
} }
@ -133,16 +134,16 @@ public class KeyChainGroup implements KeyBag {
if (outputScriptType == ScriptType.P2PKH) { if (outputScriptType == ScriptType.P2PKH) {
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed) DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed)
.outputScriptType(ScriptType.P2PKH) .outputScriptType(ScriptType.P2PKH)
.accountPath(structure.accountPathFor(ScriptType.P2PKH, params)).build(); .accountPath(structure.accountPathFor(ScriptType.P2PKH, network)).build();
this.chains.clear(); this.chains.clear();
this.chains.add(chain); this.chains.add(chain);
} else if (outputScriptType == ScriptType.P2WPKH) { } else if (outputScriptType == ScriptType.P2WPKH) {
DeterministicKeyChain fallbackChain = DeterministicKeyChain.builder().seed(seed) DeterministicKeyChain fallbackChain = DeterministicKeyChain.builder().seed(seed)
.outputScriptType(ScriptType.P2PKH) .outputScriptType(ScriptType.P2PKH)
.accountPath(structure.accountPathFor(ScriptType.P2PKH, params)).build(); .accountPath(structure.accountPathFor(ScriptType.P2PKH, network)).build();
DeterministicKeyChain defaultChain = DeterministicKeyChain.builder().seed(seed) DeterministicKeyChain defaultChain = DeterministicKeyChain.builder().seed(seed)
.outputScriptType(ScriptType.P2WPKH) .outputScriptType(ScriptType.P2WPKH)
.accountPath(structure.accountPathFor(ScriptType.P2WPKH, params)).build(); .accountPath(structure.accountPathFor(ScriptType.P2WPKH, network)).build();
this.chains.clear(); this.chains.clear();
this.chains.add(fallbackChain); this.chains.add(fallbackChain);
this.chains.add(defaultChain); this.chains.add(defaultChain);
@ -166,16 +167,16 @@ public class KeyChainGroup implements KeyBag {
if (outputScriptType == ScriptType.P2PKH) { if (outputScriptType == ScriptType.P2PKH) {
DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(accountKey) DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(accountKey)
.outputScriptType(ScriptType.P2PKH) .outputScriptType(ScriptType.P2PKH)
.accountPath(structure.accountPathFor(ScriptType.P2PKH, params)).build(); .accountPath(structure.accountPathFor(ScriptType.P2PKH, network)).build();
this.chains.clear(); this.chains.clear();
this.chains.add(chain); this.chains.add(chain);
} else if (outputScriptType == ScriptType.P2WPKH) { } else if (outputScriptType == ScriptType.P2WPKH) {
DeterministicKeyChain fallbackChain = DeterministicKeyChain.builder().spend(accountKey) DeterministicKeyChain fallbackChain = DeterministicKeyChain.builder().spend(accountKey)
.outputScriptType(ScriptType.P2PKH) .outputScriptType(ScriptType.P2PKH)
.accountPath(structure.accountPathFor(ScriptType.P2PKH, params)).build(); .accountPath(structure.accountPathFor(ScriptType.P2PKH, network)).build();
DeterministicKeyChain defaultChain = DeterministicKeyChain.builder().spend(accountKey) DeterministicKeyChain defaultChain = DeterministicKeyChain.builder().spend(accountKey)
.outputScriptType(ScriptType.P2WPKH) .outputScriptType(ScriptType.P2WPKH)
.accountPath(structure.accountPathFor(ScriptType.P2WPKH, params)).build(); .accountPath(structure.accountPathFor(ScriptType.P2WPKH, network)).build();
this.chains.clear(); this.chains.clear();
this.chains.add(fallbackChain); this.chains.add(fallbackChain);
this.chains.add(defaultChain); this.chains.add(defaultChain);
@ -223,14 +224,14 @@ public class KeyChainGroup implements KeyBag {
} }
public KeyChainGroup build() { public KeyChainGroup build() {
return new KeyChainGroup(params, null, chains, lookaheadSize, lookaheadThreshold, null, null); return new KeyChainGroup(network, null, chains, lookaheadSize, lookaheadThreshold, null, null);
} }
} }
private static final Logger log = LoggerFactory.getLogger(KeyChainGroup.class); private static final Logger log = LoggerFactory.getLogger(KeyChainGroup.class);
private BasicKeyChain basic; private BasicKeyChain basic;
private final NetworkParameters params; private final Network network;
// Keychains for deterministically derived keys. // Keychains for deterministically derived keys.
protected final @Nullable LinkedList<DeterministicKeyChain> chains; protected final @Nullable LinkedList<DeterministicKeyChain> chains;
// currentKeys is used for normal, non-multisig/married wallets. currentAddresses is used when we're handing out // currentKeys is used for normal, non-multisig/married wallets. currentAddresses is used when we're handing out
@ -244,22 +245,40 @@ public class KeyChainGroup implements KeyBag {
private final CopyOnWriteArrayList<ListenerRegistration<CurrentKeyChangeEventListener>> currentKeyChangeListeners = new CopyOnWriteArrayList<>(); private final CopyOnWriteArrayList<ListenerRegistration<CurrentKeyChangeEventListener>> currentKeyChangeListeners = new CopyOnWriteArrayList<>();
/** Creates a keychain group with just a basic chain. No deterministic chains will be created automatically. */ /** Creates a keychain group with just a basic chain. No deterministic chains will be created automatically. */
public static KeyChainGroup createBasic(Network network) {
return new KeyChainGroup(network, new BasicKeyChain(), null, -1, -1, null, null);
}
/** @deprecated use {@link #createBasic(Network)} */
@Deprecated
public static KeyChainGroup createBasic(NetworkParameters params) { public static KeyChainGroup createBasic(NetworkParameters params) {
return new KeyChainGroup(params, new BasicKeyChain(), null, -1, -1, null, null); return createBasic(params.network());
} }
public static KeyChainGroup.Builder builder(Network network) {
return new Builder(network, KeyChainGroupStructure.BIP32);
}
/** @deprecated use {@link #builder(Network)} */
@Deprecated
public static KeyChainGroup.Builder builder(NetworkParameters params) { public static KeyChainGroup.Builder builder(NetworkParameters params) {
return new Builder(params, KeyChainGroupStructure.BIP32); return builder(params.network());
} }
public static KeyChainGroup.Builder builder(Network network, KeyChainGroupStructure structure) {
return new Builder(network, structure);
}
/** @deprecated use {@link #builder(Network, KeyChainGroupStructure)} */
@Deprecated
public static KeyChainGroup.Builder builder(NetworkParameters params, KeyChainGroupStructure structure) { public static KeyChainGroup.Builder builder(NetworkParameters params, KeyChainGroupStructure structure) {
return new Builder(params, structure); return builder(params.network(), structure);
} }
private KeyChainGroup(NetworkParameters params, @Nullable BasicKeyChain basicKeyChain, private KeyChainGroup(Network network, @Nullable BasicKeyChain basicKeyChain,
@Nullable List<DeterministicKeyChain> chains, int lookaheadSize, int lookaheadThreshold, @Nullable List<DeterministicKeyChain> chains, int lookaheadSize, int lookaheadThreshold,
@Nullable EnumMap<KeyChain.KeyPurpose, DeterministicKey> currentKeys, @Nullable KeyCrypter crypter) { @Nullable EnumMap<KeyChain.KeyPurpose, DeterministicKey> currentKeys, @Nullable KeyCrypter crypter) {
this.params = params; this.network = network;
this.basic = basicKeyChain == null ? new BasicKeyChain() : basicKeyChain; this.basic = basicKeyChain == null ? new BasicKeyChain() : basicKeyChain;
if (chains != null) { if (chains != null) {
if (lookaheadSize > -1) if (lookaheadSize > -1)
@ -287,7 +306,7 @@ public class KeyChainGroup implements KeyBag {
for (Map.Entry<KeyChain.KeyPurpose, DeterministicKey> entry : this.currentKeys.entrySet()) { for (Map.Entry<KeyChain.KeyPurpose, DeterministicKey> entry : this.currentKeys.entrySet()) {
Address address = ScriptBuilder Address address = ScriptBuilder
.createP2SHOutputScript(getActiveKeyChain().getRedeemData(entry.getValue()).redeemScript) .createP2SHOutputScript(getActiveKeyChain().getRedeemData(entry.getValue()).redeemScript)
.getToAddress(params.network()); .getToAddress(network);
currentAddresses.put(entry.getKey(), address); currentAddresses.put(entry.getKey(), address);
} }
} }
@ -376,7 +395,7 @@ public class KeyChainGroup implements KeyBag {
} }
return current; return current;
} else if (outputScriptType == ScriptType.P2PKH || outputScriptType == ScriptType.P2WPKH) { } else if (outputScriptType == ScriptType.P2PKH || outputScriptType == ScriptType.P2WPKH) {
return currentKey(purpose).toAddress(outputScriptType, params.network()); return currentKey(purpose).toAddress(outputScriptType, network);
} else { } else {
throw new IllegalStateException(chain.getOutputScriptType().toString()); throw new IllegalStateException(chain.getOutputScriptType().toString());
} }
@ -428,7 +447,7 @@ public class KeyChainGroup implements KeyBag {
*/ */
public Address freshAddress(KeyChain.KeyPurpose purpose, ScriptType outputScriptType, @Nullable Instant keyRotationTime) { public Address freshAddress(KeyChain.KeyPurpose purpose, ScriptType outputScriptType, @Nullable Instant keyRotationTime) {
DeterministicKeyChain chain = getActiveKeyChain(outputScriptType, keyRotationTime); DeterministicKeyChain chain = getActiveKeyChain(outputScriptType, keyRotationTime);
return chain.getKey(purpose).toAddress(outputScriptType, params.network()); return chain.getKey(purpose).toAddress(outputScriptType, network);
} }
/** @deprecated use {@link #freshAddress(KeyChain.KeyPurpose, ScriptType, Instant)} */ /** @deprecated use {@link #freshAddress(KeyChain.KeyPurpose, ScriptType, Instant)} */
@ -447,13 +466,13 @@ public class KeyChainGroup implements KeyBag {
if (chain.isMarried()) { if (chain.isMarried()) {
Script outputScript = chain.freshOutputScript(purpose); Script outputScript = chain.freshOutputScript(purpose);
checkState(ScriptPattern.isP2SH(outputScript)); // Only handle P2SH for now checkState(ScriptPattern.isP2SH(outputScript)); // Only handle P2SH for now
Address freshAddress = LegacyAddress.fromScriptHash(params.network(), Address freshAddress = LegacyAddress.fromScriptHash(network,
ScriptPattern.extractHashFromP2SH(outputScript)); ScriptPattern.extractHashFromP2SH(outputScript));
maybeLookaheadScripts(); maybeLookaheadScripts();
currentAddresses.put(purpose, freshAddress); currentAddresses.put(purpose, freshAddress);
return freshAddress; return freshAddress;
} else if (outputScriptType == ScriptType.P2PKH || outputScriptType == ScriptType.P2WPKH) { } else if (outputScriptType == ScriptType.P2PKH || outputScriptType == ScriptType.P2WPKH) {
return freshKey(purpose).toAddress(outputScriptType, params.network()); return freshKey(purpose).toAddress(outputScriptType, network);
} else { } else {
throw new IllegalStateException(chain.getOutputScriptType().toString()); throw new IllegalStateException(chain.getOutputScriptType().toString());
} }
@ -968,11 +987,11 @@ public class KeyChainGroup implements KeyBag {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
static KeyChainGroup fromProtobufUnencrypted(NetworkParameters params, List<Protos.Key> keys) throws UnreadableWalletException { static KeyChainGroup fromProtobufUnencrypted(Network network, List<Protos.Key> keys) throws UnreadableWalletException {
return fromProtobufUnencrypted(params, keys, new DefaultKeyChainFactory()); return fromProtobufUnencrypted(network, keys, new DefaultKeyChainFactory());
} }
public static KeyChainGroup fromProtobufUnencrypted(NetworkParameters params, List<Protos.Key> keys, KeyChainFactory factory) throws UnreadableWalletException { public static KeyChainGroup fromProtobufUnencrypted(Network network, List<Protos.Key> keys, KeyChainFactory factory) throws UnreadableWalletException {
BasicKeyChain basicKeyChain = BasicKeyChain.fromProtobufUnencrypted(keys); BasicKeyChain basicKeyChain = BasicKeyChain.fromProtobufUnencrypted(keys);
List<DeterministicKeyChain> chains = DeterministicKeyChain.fromProtobuf(keys, null, factory); List<DeterministicKeyChain> chains = DeterministicKeyChain.fromProtobuf(keys, null, factory);
int lookaheadSize = -1, lookaheadThreshold = -1; int lookaheadSize = -1, lookaheadThreshold = -1;
@ -984,14 +1003,14 @@ public class KeyChainGroup implements KeyBag {
currentKeys = createCurrentKeysMap(chains); currentKeys = createCurrentKeysMap(chains);
} }
extractFollowingKeychains(chains); extractFollowingKeychains(chains);
return new KeyChainGroup(params, basicKeyChain, chains, lookaheadSize, lookaheadThreshold, currentKeys, null); return new KeyChainGroup(network, basicKeyChain, chains, lookaheadSize, lookaheadThreshold, currentKeys, null);
} }
static KeyChainGroup fromProtobufEncrypted(NetworkParameters params, List<Protos.Key> keys, KeyCrypter crypter) throws UnreadableWalletException { static KeyChainGroup fromProtobufEncrypted(Network network, List<Protos.Key> keys, KeyCrypter crypter) throws UnreadableWalletException {
return fromProtobufEncrypted(params, keys, crypter, new DefaultKeyChainFactory()); return fromProtobufEncrypted(network, keys, crypter, new DefaultKeyChainFactory());
} }
public static KeyChainGroup fromProtobufEncrypted(NetworkParameters params, List<Protos.Key> keys, KeyCrypter crypter, KeyChainFactory factory) throws UnreadableWalletException { public static KeyChainGroup fromProtobufEncrypted(Network network, List<Protos.Key> keys, KeyCrypter crypter, KeyChainFactory factory) throws UnreadableWalletException {
Objects.requireNonNull(crypter); Objects.requireNonNull(crypter);
BasicKeyChain basicKeyChain = BasicKeyChain.fromProtobufEncrypted(keys, crypter); BasicKeyChain basicKeyChain = BasicKeyChain.fromProtobufEncrypted(keys, crypter);
List<DeterministicKeyChain> chains = DeterministicKeyChain.fromProtobuf(keys, crypter, factory); List<DeterministicKeyChain> chains = DeterministicKeyChain.fromProtobuf(keys, crypter, factory);
@ -1004,7 +1023,7 @@ public class KeyChainGroup implements KeyBag {
currentKeys = createCurrentKeysMap(chains); currentKeys = createCurrentKeysMap(chains);
} }
extractFollowingKeychains(chains); extractFollowingKeychains(chains);
return new KeyChainGroup(params, basicKeyChain, chains, lookaheadSize, lookaheadThreshold, currentKeys, crypter); return new KeyChainGroup(network, basicKeyChain, chains, lookaheadSize, lookaheadThreshold, currentKeys, crypter);
} }
/** /**
@ -1134,10 +1153,10 @@ public class KeyChainGroup implements KeyBag {
public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable AesKey aesKey) { public String toString(boolean includeLookahead, boolean includePrivateKeys, @Nullable AesKey aesKey) {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
if (basic != null) if (basic != null)
builder.append(basic.toString(includePrivateKeys, aesKey, params.network())); builder.append(basic.toString(includePrivateKeys, aesKey, network));
if (chains != null) if (chains != null)
for (DeterministicKeyChain chain : chains) for (DeterministicKeyChain chain : chains)
builder.append(chain.toString(includeLookahead, includePrivateKeys, aesKey, params.network())).append('\n'); builder.append(chain.toString(includeLookahead, includePrivateKeys, aesKey, network)).append('\n');
return builder.toString(); return builder.toString();
} }

View file

@ -343,7 +343,7 @@ public class Wallet extends BaseTaggableObject
* @return A new empty wallet * @return A new empty wallet
*/ */
public static Wallet createDeterministic(Network network, ScriptType outputScriptType, KeyChainGroupStructure keyChainGroupStructure) { public static Wallet createDeterministic(Network network, ScriptType outputScriptType, KeyChainGroupStructure keyChainGroupStructure) {
return new Wallet(network, KeyChainGroup.builder(NetworkParameters.of(network), keyChainGroupStructure).fromRandom(outputScriptType).build()); return new Wallet(network, KeyChainGroup.builder(network, keyChainGroupStructure).fromRandom(outputScriptType).build());
} }
/** /**
@ -351,7 +351,7 @@ public class Wallet extends BaseTaggableObject
*/ */
@Deprecated @Deprecated
public static Wallet createDeterministic(NetworkParameters params, ScriptType outputScriptType, KeyChainGroupStructure keyChainGroupStructure) { public static Wallet createDeterministic(NetworkParameters params, ScriptType outputScriptType, KeyChainGroupStructure keyChainGroupStructure) {
return new Wallet(params.network(), KeyChainGroup.builder(params, keyChainGroupStructure).fromRandom(outputScriptType).build()); return new Wallet(params.network(), KeyChainGroup.builder(params.network(), keyChainGroupStructure).fromRandom(outputScriptType).build());
} }
/** /**
@ -360,7 +360,7 @@ public class Wallet extends BaseTaggableObject
* @param network network wallet will operate on * @param network network wallet will operate on
*/ */
public static Wallet createBasic(Network network) { public static Wallet createBasic(Network network) {
return new Wallet(network, KeyChainGroup.createBasic(NetworkParameters.of(network))); return new Wallet(network, KeyChainGroup.createBasic(network));
} }
/** /**
@ -400,7 +400,7 @@ public class Wallet extends BaseTaggableObject
*/ */
public static Wallet fromSeed(Network network, DeterministicSeed seed, ScriptType outputScriptType, public static Wallet fromSeed(Network network, DeterministicSeed seed, ScriptType outputScriptType,
KeyChainGroupStructure structure) { KeyChainGroupStructure structure) {
return new Wallet(network, KeyChainGroup.builder(NetworkParameters.of(network), structure).fromSeed(seed, outputScriptType).build()); return new Wallet(network, KeyChainGroup.builder(network, structure).fromSeed(seed, outputScriptType).build());
} }
/** /**
@ -423,7 +423,7 @@ public class Wallet extends BaseTaggableObject
List<ChildNumber> accountPath) { List<ChildNumber> accountPath) {
DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).outputScriptType(outputScriptType) DeterministicKeyChain chain = DeterministicKeyChain.builder().seed(seed).outputScriptType(outputScriptType)
.accountPath(accountPath).build(); .accountPath(accountPath).build();
return new Wallet(network, KeyChainGroup.builder(NetworkParameters.of(network)).addChain(chain).build()); return new Wallet(network, KeyChainGroup.builder(network).addChain(chain).build());
} }
/** /**
@ -443,7 +443,7 @@ public class Wallet extends BaseTaggableObject
ScriptType outputScriptType) { ScriptType outputScriptType) {
DeterministicKeyChain chain = DeterministicKeyChain.builder().watch(watchKey).outputScriptType(outputScriptType) DeterministicKeyChain chain = DeterministicKeyChain.builder().watch(watchKey).outputScriptType(outputScriptType)
.build(); .build();
return new Wallet(network, KeyChainGroup.builder(NetworkParameters.of(network)).addChain(chain).build()); return new Wallet(network, KeyChainGroup.builder(network).addChain(chain).build());
} }
/** /**
@ -515,7 +515,7 @@ public class Wallet extends BaseTaggableObject
ScriptType outputScriptType) { ScriptType outputScriptType) {
DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(spendKey).outputScriptType(outputScriptType) DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(spendKey).outputScriptType(outputScriptType)
.build(); .build();
return new Wallet(network, KeyChainGroup.builder(NetworkParameters.of(network)).addChain(chain).build()); return new Wallet(network, KeyChainGroup.builder(network).addChain(chain).build());
} }
/** /**
@ -526,7 +526,7 @@ public class Wallet extends BaseTaggableObject
ScriptType outputScriptType) { ScriptType outputScriptType) {
DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(spendKey).outputScriptType(outputScriptType) DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(spendKey).outputScriptType(outputScriptType)
.build(); .build();
return new Wallet(params.network(), KeyChainGroup.builder(params).addChain(chain).build()); return new Wallet(params.network(), KeyChainGroup.builder(params.network()).addChain(chain).build());
} }
/** /**
@ -595,7 +595,7 @@ public class Wallet extends BaseTaggableObject
accountKey.clearCreationTime(); accountKey.clearCreationTime();
DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(accountKey) DeterministicKeyChain chain = DeterministicKeyChain.builder().spend(accountKey)
.outputScriptType(outputScriptType).build(); .outputScriptType(outputScriptType).build();
return new Wallet(network, KeyChainGroup.builder(NetworkParameters.of(network)).addChain(chain).build()); return new Wallet(network, KeyChainGroup.builder(network).addChain(chain).build());
} }
/** /**
@ -5749,7 +5749,7 @@ public class Wallet extends BaseTaggableObject
log.info( log.info(
"All deterministic chains are currently rotating and we have no random keys, creating fresh {} chain: backup required after this.", "All deterministic chains are currently rotating and we have no random keys, creating fresh {} chain: backup required after this.",
preferredScriptType); preferredScriptType);
KeyChainGroup newChains = KeyChainGroup.builder(params, structure).fromRandom(preferredScriptType) KeyChainGroup newChains = KeyChainGroup.builder(network, structure).fromRandom(preferredScriptType)
.build(); .build();
if (keyChainGroup.isEncrypted()) { if (keyChainGroup.isEncrypted()) {
if (aesKey == null) if (aesKey == null)
@ -5772,7 +5772,7 @@ public class Wallet extends BaseTaggableObject
log.info( log.info(
"No non-rotating random keys available, generating entirely new {} tree: backup required after this.", "No non-rotating random keys available, generating entirely new {} tree: backup required after this.",
preferredScriptType); preferredScriptType);
KeyChainGroup newChains = KeyChainGroup.builder(params, structure).fromRandom(preferredScriptType) KeyChainGroup newChains = KeyChainGroup.builder(network, structure).fromRandom(preferredScriptType)
.build(); .build();
if (keyChainGroup.isEncrypted()) { if (keyChainGroup.isEncrypted()) {
if (aesKey == null) if (aesKey == null)

View file

@ -499,9 +499,9 @@ public class WalletProtobufSerializer {
if (walletProto.hasEncryptionParameters()) { if (walletProto.hasEncryptionParameters()) {
Protos.ScryptParameters encryptionParameters = walletProto.getEncryptionParameters(); Protos.ScryptParameters encryptionParameters = walletProto.getEncryptionParameters();
final KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(encryptionParameters); final KeyCrypterScrypt keyCrypter = new KeyCrypterScrypt(encryptionParameters);
keyChainGroup = KeyChainGroup.fromProtobufEncrypted(params, walletProto.getKeyList(), keyCrypter, keyChainFactory); keyChainGroup = KeyChainGroup.fromProtobufEncrypted(params.network(), walletProto.getKeyList(), keyCrypter, keyChainFactory);
} else { } else {
keyChainGroup = KeyChainGroup.fromProtobufUnencrypted(params, walletProto.getKeyList(), keyChainFactory); keyChainGroup = KeyChainGroup.fromProtobufUnencrypted(params.network(), walletProto.getKeyList(), keyChainFactory);
} }
Wallet wallet = factory.create(params.network(), keyChainGroup); Wallet wallet = factory.create(params.network(), keyChainGroup);

View file

@ -85,7 +85,7 @@ public class BloomFilterTest {
Address addr = privKey.getKey().toAddress(ScriptType.P2PKH, BitcoinNetwork.MAINNET); Address addr = privKey.getKey().toAddress(ScriptType.P2PKH, BitcoinNetwork.MAINNET);
assertEquals("17Wx1GQfyPTNWpQMHrTwRSMTCAonSiZx9e", addr.toString()); assertEquals("17Wx1GQfyPTNWpQMHrTwRSMTCAonSiZx9e", addr.toString());
KeyChainGroup group = KeyChainGroup.builder(MAINNET).build(); KeyChainGroup group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).build();
// Add a random key which happens to have been used in a recent generation // Add a random key which happens to have been used in a recent generation
group.importKeys(ECKey.fromPublicOnly(privKey.getKey()), ECKey.fromPublicOnly(ByteUtils.parseHex("03cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99"))); group.importKeys(ECKey.fromPublicOnly(privKey.getKey()), ECKey.fromPublicOnly(ByteUtils.parseHex("03cb219f69f1b49468bd563239a86667e74a06fcba69ac50a08a5cbc42a5808e99")));
Wallet wallet = new Wallet(BitcoinNetwork.MAINNET, group); Wallet wallet = new Wallet(BitcoinNetwork.MAINNET, group);

View file

@ -109,7 +109,7 @@ public class WalletProtobufSerializerTest {
myKey = new ECKey(); myKey = new ECKey();
myKey.setCreationTime(Instant.ofEpochSecond(123456789L)); myKey.setCreationTime(Instant.ofEpochSecond(123456789L));
myAddress = myKey.toAddress(ScriptType.P2PKH, BitcoinNetwork.TESTNET); myAddress = myKey.toAddress(ScriptType.P2PKH, BitcoinNetwork.TESTNET);
myWallet = new Wallet(BitcoinNetwork.TESTNET, KeyChainGroup.builder(TESTNET).fromRandom(ScriptType.P2PKH).build()); myWallet = new Wallet(BitcoinNetwork.TESTNET, KeyChainGroup.builder(BitcoinNetwork.TESTNET).fromRandom(ScriptType.P2PKH).build());
myWallet.importKey(myKey); myWallet.importKey(myKey);
mScriptCreationTime = TimeUtils.currentTime().minusSeconds(1234); mScriptCreationTime = TimeUtils.currentTime().minusSeconds(1234);
myWallet.addWatchedAddress(myWatchedKey.toAddress(ScriptType.P2PKH, BitcoinNetwork.TESTNET), mScriptCreationTime); myWallet.addWatchedAddress(myWatchedKey.toAddress(ScriptType.P2PKH, BitcoinNetwork.TESTNET), mScriptCreationTime);

View file

@ -657,7 +657,7 @@ public class DeterministicKeyChainTest {
DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(coinLevelKey, new ChildNumber(0, true)); DeterministicKey accountKey = HDKeyDerivation.deriveChildKey(coinLevelKey, new ChildNumber(0, true));
accountKey = accountKey.dropParent(); accountKey = accountKey.dropParent();
accountKey.setCreationTime(watchingKey.creationTime().get()); accountKey.setCreationTime(watchingKey.creationTime().get());
KeyChainGroup group = KeyChainGroup.builder(NetworkParameters.of(network)).addChain(DeterministicKeyChain.builder().spend(accountKey) KeyChainGroup group = KeyChainGroup.builder(network).addChain(DeterministicKeyChain.builder().spend(accountKey)
.outputScriptType(bip44chain.getOutputScriptType()).build()).build(); .outputScriptType(bip44chain.getOutputScriptType()).build()).build();
DeterministicKeyChain fromMasterKeyChain = group.getActiveKeyChain(); DeterministicKeyChain fromMasterKeyChain = group.getActiveKeyChain();
assertEquals(BIP44_COIN_1_ACCOUNT_ZERO_PATH, fromMasterKeyChain.getAccountPath()); assertEquals(BIP44_COIN_1_ACCOUNT_ZERO_PATH, fromMasterKeyChain.getAccountPath());

View file

@ -23,7 +23,6 @@ import org.bitcoinj.base.internal.TimeUtils;
import org.bitcoinj.crypto.AesKey; import org.bitcoinj.crypto.AesKey;
import org.bitcoinj.core.BloomFilter; import org.bitcoinj.core.BloomFilter;
import org.bitcoinj.crypto.ECKey; import org.bitcoinj.crypto.ECKey;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.base.Sha256Hash; import org.bitcoinj.base.Sha256Hash;
import org.bitcoinj.crypto.DeterministicKey; import org.bitcoinj.crypto.DeterministicKey;
import org.bitcoinj.crypto.KeyCrypterException; import org.bitcoinj.crypto.KeyCrypterException;
@ -60,7 +59,6 @@ public class KeyChainGroupTest {
// Number of initial keys in this tests HD wallet, including interior keys. // Number of initial keys in this tests HD wallet, including interior keys.
private static final int INITIAL_KEYS = 4; private static final int INITIAL_KEYS = 4;
private static final int LOOKAHEAD_SIZE = 5; private static final int LOOKAHEAD_SIZE = 5;
private static final NetworkParameters MAINNET = MainNetParams.get();
private static final String XPUB = "xpub68KFnj3bqUx1s7mHejLDBPywCAKdJEu1b49uniEEn2WSbHmZ7xbLqFTjJbtx1LUcAt1DwhoqWHmo2s5WMJp6wi38CiF2hYD49qVViKVvAoi"; private static final String XPUB = "xpub68KFnj3bqUx1s7mHejLDBPywCAKdJEu1b49uniEEn2WSbHmZ7xbLqFTjJbtx1LUcAt1DwhoqWHmo2s5WMJp6wi38CiF2hYD49qVViKVvAoi";
private static final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes()); private static final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes());
private static final KeyCrypterScrypt KEY_CRYPTER = new KeyCrypterScrypt(2); private static final KeyCrypterScrypt KEY_CRYPTER = new KeyCrypterScrypt(2);
@ -73,7 +71,7 @@ public class KeyChainGroupTest {
public void setup() { public void setup() {
BriefLogFormatter.init(); BriefLogFormatter.init();
TimeUtils.setMockClock(); TimeUtils.setMockClock();
group = KeyChainGroup.builder(MAINNET).lookaheadSize(LOOKAHEAD_SIZE).fromRandom(ScriptType.P2PKH) group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).lookaheadSize(LOOKAHEAD_SIZE).fromRandom(ScriptType.P2PKH)
.build(); .build();
group.getActiveKeyChain(); // Force create a chain. group.getActiveKeyChain(); // Force create a chain.
@ -82,7 +80,7 @@ public class KeyChainGroupTest {
@Test @Test
public void createDeterministic_P2PKH() { public void createDeterministic_P2PKH() {
KeyChainGroup kcg = KeyChainGroup.builder(MAINNET).fromRandom(ScriptType.P2PKH).build(); KeyChainGroup kcg = KeyChainGroup.builder(BitcoinNetwork.MAINNET).fromRandom(ScriptType.P2PKH).build();
// check default // check default
Address address = kcg.currentAddress(KeyPurpose.RECEIVE_FUNDS); Address address = kcg.currentAddress(KeyPurpose.RECEIVE_FUNDS);
assertEquals(ScriptType.P2PKH, address.getOutputScriptType()); assertEquals(ScriptType.P2PKH, address.getOutputScriptType());
@ -90,7 +88,7 @@ public class KeyChainGroupTest {
@Test @Test
public void createDeterministic_P2WPKH() { public void createDeterministic_P2WPKH() {
KeyChainGroup kcg = KeyChainGroup.builder(MAINNET).fromRandom(ScriptType.P2WPKH).build(); KeyChainGroup kcg = KeyChainGroup.builder(BitcoinNetwork.MAINNET).fromRandom(ScriptType.P2WPKH).build();
// check default // check default
Address address = kcg.currentAddress(KeyPurpose.RECEIVE_FUNDS); Address address = kcg.currentAddress(KeyPurpose.RECEIVE_FUNDS);
assertEquals(ScriptType.P2WPKH, address.getOutputScriptType()); assertEquals(ScriptType.P2WPKH, address.getOutputScriptType());
@ -101,7 +99,7 @@ public class KeyChainGroupTest {
private KeyChainGroup createMarriedKeyChainGroup() { private KeyChainGroup createMarriedKeyChainGroup() {
DeterministicKeyChain chain = createMarriedKeyChain(); DeterministicKeyChain chain = createMarriedKeyChain();
KeyChainGroup group = KeyChainGroup.builder(MAINNET).lookaheadSize(LOOKAHEAD_SIZE).addChain(chain).build(); KeyChainGroup group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).lookaheadSize(LOOKAHEAD_SIZE).addChain(chain).build();
group.getActiveKeyChain(); group.getActiveKeyChain();
return group; return group;
} }
@ -334,7 +332,7 @@ public class KeyChainGroupTest {
@Test @Test
public void encryptionWhilstEmpty() { public void encryptionWhilstEmpty() {
group = KeyChainGroup.builder(MAINNET).lookaheadSize(5).fromRandom(ScriptType.P2PKH).build(); group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).lookaheadSize(5).fromRandom(ScriptType.P2PKH).build();
group.encrypt(KEY_CRYPTER, AES_KEY); group.encrypt(KEY_CRYPTER, AES_KEY);
assertTrue(group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).isEncrypted()); assertTrue(group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS).isEncrypted());
final ECKey key = group.currentKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); final ECKey key = group.currentKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
@ -447,7 +445,7 @@ public class KeyChainGroupTest {
public void serialization() throws Exception { public void serialization() throws Exception {
int initialKeys = INITIAL_KEYS + group.getActiveKeyChain().getAccountPath().size() - 1; int initialKeys = INITIAL_KEYS + group.getActiveKeyChain().getAccountPath().size() - 1;
assertEquals(initialKeys + 1 /* for the seed */, group.serializeToProtobuf().size()); assertEquals(initialKeys + 1 /* for the seed */, group.serializeToProtobuf().size());
group = KeyChainGroup.fromProtobufUnencrypted(MAINNET, group.serializeToProtobuf()); group = KeyChainGroup.fromProtobufUnencrypted(BitcoinNetwork.MAINNET, group.serializeToProtobuf());
group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
DeterministicKey key1 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); DeterministicKey key1 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
DeterministicKey key2 = group.freshKey(KeyChain.KeyPurpose.CHANGE); DeterministicKey key2 = group.freshKey(KeyChain.KeyPurpose.CHANGE);
@ -458,20 +456,20 @@ public class KeyChainGroupTest {
List<Protos.Key> protoKeys2 = group.serializeToProtobuf(); List<Protos.Key> protoKeys2 = group.serializeToProtobuf();
assertEquals(initialKeys + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 2, protoKeys2.size()); assertEquals(initialKeys + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 2, protoKeys2.size());
group = KeyChainGroup.fromProtobufUnencrypted(MAINNET, protoKeys1); group = KeyChainGroup.fromProtobufUnencrypted(BitcoinNetwork.MAINNET, protoKeys1);
assertEquals(initialKeys + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 1, protoKeys1.size()); assertEquals(initialKeys + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 1, protoKeys1.size());
assertTrue(group.hasKey(key1)); assertTrue(group.hasKey(key1));
assertTrue(group.hasKey(key2)); assertTrue(group.hasKey(key2));
assertEquals(key2, group.currentKey(KeyChain.KeyPurpose.CHANGE)); assertEquals(key2, group.currentKey(KeyChain.KeyPurpose.CHANGE));
assertEquals(key1, group.currentKey(KeyChain.KeyPurpose.RECEIVE_FUNDS)); assertEquals(key1, group.currentKey(KeyChain.KeyPurpose.RECEIVE_FUNDS));
group = KeyChainGroup.fromProtobufUnencrypted(MAINNET, protoKeys2); group = KeyChainGroup.fromProtobufUnencrypted(BitcoinNetwork.MAINNET, protoKeys2);
assertEquals(initialKeys + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 2, protoKeys2.size()); assertEquals(initialKeys + ((LOOKAHEAD_SIZE + 1) * 2) + 1 /* for the seed */ + 2, protoKeys2.size());
assertTrue(group.hasKey(key1)); assertTrue(group.hasKey(key1));
assertTrue(group.hasKey(key2)); assertTrue(group.hasKey(key2));
group.encrypt(KEY_CRYPTER, AES_KEY); group.encrypt(KEY_CRYPTER, AES_KEY);
List<Protos.Key> protoKeys3 = group.serializeToProtobuf(); List<Protos.Key> protoKeys3 = group.serializeToProtobuf();
group = KeyChainGroup.fromProtobufEncrypted(MAINNET, protoKeys3, KEY_CRYPTER); group = KeyChainGroup.fromProtobufEncrypted(BitcoinNetwork.MAINNET, protoKeys3, KEY_CRYPTER);
assertTrue(group.isEncrypted()); assertTrue(group.isEncrypted());
assertTrue(group.checkPassword("password")); assertTrue(group.checkPassword("password"));
group.decrypt(AES_KEY); group.decrypt(AES_KEY);
@ -481,14 +479,14 @@ public class KeyChainGroupTest {
@Test @Test
public void serializeWatching() throws Exception { public void serializeWatching() throws Exception {
group = KeyChainGroup.builder(MAINNET).lookaheadSize(LOOKAHEAD_SIZE).addChain(DeterministicKeyChain.builder() group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).lookaheadSize(LOOKAHEAD_SIZE).addChain(DeterministicKeyChain.builder()
.watch(watchingAccountKey).outputScriptType(ScriptType.P2PKH).build()).build(); .watch(watchingAccountKey).outputScriptType(ScriptType.P2PKH).build()).build();
group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
group.freshKey(KeyChain.KeyPurpose.CHANGE); group.freshKey(KeyChain.KeyPurpose.CHANGE);
group.getBloomFilterElementCount(); // Force lookahead. group.getBloomFilterElementCount(); // Force lookahead.
List<Protos.Key> protoKeys1 = group.serializeToProtobuf(); List<Protos.Key> protoKeys1 = group.serializeToProtobuf();
assertEquals(3 + (group.getLookaheadSize() + group.getLookaheadThreshold() + 1) * 2, protoKeys1.size()); assertEquals(3 + (group.getLookaheadSize() + group.getLookaheadThreshold() + 1) * 2, protoKeys1.size());
group = KeyChainGroup.fromProtobufUnencrypted(MAINNET, protoKeys1); group = KeyChainGroup.fromProtobufUnencrypted(BitcoinNetwork.MAINNET, protoKeys1);
assertEquals(3 + (group.getLookaheadSize() + group.getLookaheadThreshold() + 1) * 2, group.serializeToProtobuf().size()); assertEquals(3 + (group.getLookaheadSize() + group.getLookaheadThreshold() + 1) * 2, group.serializeToProtobuf().size());
} }
@ -500,7 +498,7 @@ public class KeyChainGroupTest {
assertEquals(2, group.getActiveKeyChain().getSigsRequiredToSpend()); assertEquals(2, group.getActiveKeyChain().getSigsRequiredToSpend());
List<Protos.Key> protoKeys = group.serializeToProtobuf(); List<Protos.Key> protoKeys = group.serializeToProtobuf();
KeyChainGroup group2 = KeyChainGroup.fromProtobufUnencrypted(MAINNET, protoKeys); KeyChainGroup group2 = KeyChainGroup.fromProtobufUnencrypted(BitcoinNetwork.MAINNET, protoKeys);
assertTrue(group2.isMarried()); assertTrue(group2.isMarried());
assertEquals(2, group.getActiveKeyChain().getSigsRequiredToSpend()); assertEquals(2, group.getActiveKeyChain().getSigsRequiredToSpend());
Address address2 = group2.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS); Address address2 = group2.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS);
@ -518,7 +516,7 @@ public class KeyChainGroupTest {
public void constructFromSeed() { public void constructFromSeed() {
ECKey key1 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); ECKey key1 = group.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
final DeterministicSeed seed = Objects.requireNonNull(group.getActiveKeyChain().getSeed()); final DeterministicSeed seed = Objects.requireNonNull(group.getActiveKeyChain().getSeed());
KeyChainGroup group2 = KeyChainGroup.builder(MAINNET).lookaheadSize(5) KeyChainGroup group2 = KeyChainGroup.builder(BitcoinNetwork.MAINNET).lookaheadSize(5)
.addChain(DeterministicKeyChain.builder().seed(seed).outputScriptType(ScriptType.P2PKH).build()) .addChain(DeterministicKeyChain.builder().seed(seed).outputScriptType(ScriptType.P2PKH).build())
.build(); .build();
ECKey key2 = group2.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS); ECKey key2 = group2.freshKey(KeyChain.KeyPurpose.RECEIVE_FUNDS);
@ -530,7 +528,7 @@ public class KeyChainGroupTest {
DeterministicSeed seed = DeterministicSeed.ofEntropy(ENTROPY, ""); DeterministicSeed seed = DeterministicSeed.ofEntropy(ENTROPY, "");
DeterministicKeyChain chain1 = DeterministicKeyChain.builder().seed(seed) DeterministicKeyChain chain1 = DeterministicKeyChain.builder().seed(seed)
.accountPath(DeterministicKeyChain.ACCOUNT_ZERO_PATH).outputScriptType(ScriptType.P2PKH).build(); .accountPath(DeterministicKeyChain.ACCOUNT_ZERO_PATH).outputScriptType(ScriptType.P2PKH).build();
group = KeyChainGroup.builder(MAINNET).addChain(chain1).build(); group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).addChain(chain1).build();
assertEquals("1M5T5k9yKtGWRtWYMjQtGx3K2sshrABzCT", group.currentAddress(KeyPurpose.RECEIVE_FUNDS).toString()); assertEquals("1M5T5k9yKtGWRtWYMjQtGx3K2sshrABzCT", group.currentAddress(KeyPurpose.RECEIVE_FUNDS).toString());
final DeterministicKeyChain chain2 = DeterministicKeyChain.builder().seed(seed) final DeterministicKeyChain chain2 = DeterministicKeyChain.builder().seed(seed)
@ -549,7 +547,7 @@ public class KeyChainGroupTest {
@Test(expected = DeterministicUpgradeRequiredException.class) @Test(expected = DeterministicUpgradeRequiredException.class)
public void deterministicUpgradeRequired() { public void deterministicUpgradeRequired() {
// Check that if we try to use HD features in a KCG that only has random keys, we get an exception. // Check that if we try to use HD features in a KCG that only has random keys, we get an exception.
group = KeyChainGroup.builder(MAINNET).build(); group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).build();
group.importKeys(new ECKey(), new ECKey()); group.importKeys(new ECKey(), new ECKey());
assertTrue(group.isDeterministicUpgradeRequired(ScriptType.P2PKH, null)); assertTrue(group.isDeterministicUpgradeRequired(ScriptType.P2PKH, null));
assertTrue(group.isDeterministicUpgradeRequired(ScriptType.P2WPKH, null)); assertTrue(group.isDeterministicUpgradeRequired(ScriptType.P2WPKH, null));
@ -558,7 +556,7 @@ public class KeyChainGroupTest {
@Test @Test
public void deterministicUpgradeUnencrypted() throws Exception { public void deterministicUpgradeUnencrypted() throws Exception {
group = KeyChainGroup.builder(MAINNET).fromRandom(ScriptType.P2PKH).lookaheadSize(LOOKAHEAD_SIZE).build(); group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).fromRandom(ScriptType.P2PKH).lookaheadSize(LOOKAHEAD_SIZE).build();
List<Protos.Key> protobufs = group.serializeToProtobuf(); List<Protos.Key> protobufs = group.serializeToProtobuf();
group.upgradeToDeterministic(ScriptType.P2PKH, KeyChainGroupStructure.BIP32, null, null); group.upgradeToDeterministic(ScriptType.P2PKH, KeyChainGroupStructure.BIP32, null, null);
@ -569,7 +567,7 @@ public class KeyChainGroupTest {
DeterministicSeed seed1 = group.getActiveKeyChain().getSeed(); DeterministicSeed seed1 = group.getActiveKeyChain().getSeed();
assertNotNull(seed1); assertNotNull(seed1);
group = KeyChainGroup.fromProtobufUnencrypted(MAINNET, protobufs); group = KeyChainGroup.fromProtobufUnencrypted(BitcoinNetwork.MAINNET, protobufs);
group.upgradeToDeterministic(ScriptType.P2PKH, KeyChainGroupStructure.BIP32, null, null); // Should give same result as last time. group.upgradeToDeterministic(ScriptType.P2PKH, KeyChainGroupStructure.BIP32, null, null); // Should give same result as last time.
assertFalse(group.isEncrypted()); assertFalse(group.isEncrypted());
assertFalse(group.isDeterministicUpgradeRequired(ScriptType.P2PKH, null)); assertFalse(group.isDeterministicUpgradeRequired(ScriptType.P2PKH, null));
@ -582,7 +580,7 @@ public class KeyChainGroupTest {
@Test @Test
public void deterministicUpgradeEncrypted() throws Exception { public void deterministicUpgradeEncrypted() throws Exception {
group = KeyChainGroup.builder(MAINNET).fromRandom(ScriptType.P2PKH).build(); group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).fromRandom(ScriptType.P2PKH).build();
group.encrypt(KEY_CRYPTER, AES_KEY); group.encrypt(KEY_CRYPTER, AES_KEY);
assertTrue(group.isEncrypted()); assertTrue(group.isEncrypted());
assertFalse(group.isDeterministicUpgradeRequired(ScriptType.P2PKH, null)); assertFalse(group.isDeterministicUpgradeRequired(ScriptType.P2PKH, null));
@ -605,7 +603,7 @@ public class KeyChainGroupTest {
@Test @Test
public void isNotWatching() { public void isNotWatching() {
group = KeyChainGroup.builder(MAINNET).fromRandom(ScriptType.P2PKH).build(); group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).fromRandom(ScriptType.P2PKH).build();
final ECKey key = ECKey.fromPrivate(BigInteger.TEN); final ECKey key = ECKey.fromPrivate(BigInteger.TEN);
group.importKeys(key); group.importKeys(key);
assertFalse(group.isWatching()); assertFalse(group.isWatching());
@ -613,7 +611,7 @@ public class KeyChainGroupTest {
@Test @Test
public void isWatching() { public void isWatching() {
group = KeyChainGroup.builder(MAINNET) group = KeyChainGroup.builder(BitcoinNetwork.MAINNET)
.addChain(DeterministicKeyChain.builder().watch(DeterministicKey.deserializeB58( .addChain(DeterministicKeyChain.builder().watch(DeterministicKey.deserializeB58(
"xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo", "xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo",
BitcoinNetwork.MAINNET)).outputScriptType(ScriptType.P2PKH).build()) BitcoinNetwork.MAINNET)).outputScriptType(ScriptType.P2PKH).build())
@ -625,13 +623,13 @@ public class KeyChainGroupTest {
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void isWatchingNoKeys() { public void isWatchingNoKeys() {
group = KeyChainGroup.builder(MAINNET).build(); group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).build();
group.isWatching(); group.isWatching();
} }
@Test(expected = IllegalStateException.class) @Test(expected = IllegalStateException.class)
public void isWatchingMixedKeys() { public void isWatchingMixedKeys() {
group = KeyChainGroup.builder(MAINNET) group = KeyChainGroup.builder(BitcoinNetwork.MAINNET)
.addChain(DeterministicKeyChain.builder().watch(DeterministicKey.deserializeB58( .addChain(DeterministicKeyChain.builder().watch(DeterministicKey.deserializeB58(
"xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo", "xpub69bjfJ91ikC5ghsqsVDHNq2dRGaV2HHVx7Y9LXi27LN9BWWAXPTQr4u8U3wAtap8bLdHdkqPpAcZmhMS5SnrMQC4ccaoBccFhh315P4UYzo",
BitcoinNetwork.MAINNET)).outputScriptType(ScriptType.P2PKH).build()) BitcoinNetwork.MAINNET)).outputScriptType(ScriptType.P2PKH).build())
@ -643,7 +641,7 @@ public class KeyChainGroupTest {
@Test @Test
public void segwitKeyChainGroup() throws Exception { public void segwitKeyChainGroup() throws Exception {
group = KeyChainGroup.builder(MAINNET).lookaheadSize(LOOKAHEAD_SIZE) group = KeyChainGroup.builder(BitcoinNetwork.MAINNET).lookaheadSize(LOOKAHEAD_SIZE)
.addChain(DeterministicKeyChain.builder().entropy(ENTROPY, TimeUtils.currentTime()).outputScriptType(ScriptType.P2WPKH) .addChain(DeterministicKeyChain.builder().entropy(ENTROPY, TimeUtils.currentTime()).outputScriptType(ScriptType.P2WPKH)
.accountPath(DeterministicKeyChain.ACCOUNT_ONE_PATH).build()) .accountPath(DeterministicKeyChain.ACCOUNT_ONE_PATH).build())
.build(); .build();
@ -653,7 +651,7 @@ public class KeyChainGroupTest {
assertEquals("bc1qw8sf3mwuwn74qnhj83gjg0cwkk78fun2pxl9t2", group.currentAddress(KeyPurpose.CHANGE).toString()); assertEquals("bc1qw8sf3mwuwn74qnhj83gjg0cwkk78fun2pxl9t2", group.currentAddress(KeyPurpose.CHANGE).toString());
// round-trip through protobuf // round-trip through protobuf
group = KeyChainGroup.fromProtobufUnencrypted(MAINNET, group.serializeToProtobuf()); group = KeyChainGroup.fromProtobufUnencrypted(BitcoinNetwork.MAINNET, group.serializeToProtobuf());
assertEquals(ScriptType.P2WPKH, group.getActiveKeyChain().getOutputScriptType()); assertEquals(ScriptType.P2WPKH, group.getActiveKeyChain().getOutputScriptType());
assertEquals("bc1qhcurdec849thpjjp3e27atvya43gy2snrechd9", assertEquals("bc1qhcurdec849thpjjp3e27atvya43gy2snrechd9",
group.currentAddress(KeyPurpose.RECEIVE_FUNDS).toString()); group.currentAddress(KeyPurpose.RECEIVE_FUNDS).toString());
@ -667,7 +665,7 @@ public class KeyChainGroupTest {
assertEquals("bc1qw8sf3mwuwn74qnhj83gjg0cwkk78fun2pxl9t2", group.currentAddress(KeyPurpose.CHANGE).toString()); assertEquals("bc1qw8sf3mwuwn74qnhj83gjg0cwkk78fun2pxl9t2", group.currentAddress(KeyPurpose.CHANGE).toString());
// round-trip encrypted again, then dectypt // round-trip encrypted again, then dectypt
group = KeyChainGroup.fromProtobufEncrypted(MAINNET, group.serializeToProtobuf(), KEY_CRYPTER); group = KeyChainGroup.fromProtobufEncrypted(BitcoinNetwork.MAINNET, group.serializeToProtobuf(), KEY_CRYPTER);
group.decrypt(AES_KEY); group.decrypt(AES_KEY);
assertEquals(ScriptType.P2WPKH, group.getActiveKeyChain().getOutputScriptType()); assertEquals(ScriptType.P2WPKH, group.getActiveKeyChain().getOutputScriptType());
assertEquals("bc1qhcurdec849thpjjp3e27atvya43gy2snrechd9", assertEquals("bc1qhcurdec849thpjjp3e27atvya43gy2snrechd9",
@ -677,7 +675,7 @@ public class KeyChainGroupTest {
@Test @Test
public void onlyBasicKeyEncryptionAndDecryption() { public void onlyBasicKeyEncryptionAndDecryption() {
group = KeyChainGroup.createBasic(MAINNET); group = KeyChainGroup.createBasic(BitcoinNetwork.MAINNET);
final ECKey key = ECKey.fromPrivate(BigInteger.TEN); final ECKey key = ECKey.fromPrivate(BigInteger.TEN);
group.importKeys(key); group.importKeys(key);
group.encrypt(KEY_CRYPTER, AES_KEY); group.encrypt(KEY_CRYPTER, AES_KEY);

View file

@ -220,7 +220,7 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void encryptDecryptWalletWithArbitraryPathAndScriptType() throws Exception { public void encryptDecryptWalletWithArbitraryPathAndScriptType() throws Exception {
final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes()); final byte[] ENTROPY = Sha256Hash.hash("don't use a string seed like this in real life".getBytes());
KeyChainGroup keyChainGroup = KeyChainGroup.builder(TESTNET) KeyChainGroup keyChainGroup = KeyChainGroup.builder(BitcoinNetwork.TESTNET)
.addChain(DeterministicKeyChain.builder().seed(DeterministicSeed.ofEntropy(ENTROPY, "", Instant.ofEpochSecond(1389353062L))) .addChain(DeterministicKeyChain.builder().seed(DeterministicSeed.ofEntropy(ENTROPY, "", Instant.ofEpochSecond(1389353062L)))
.outputScriptType(ScriptType.P2WPKH) .outputScriptType(ScriptType.P2WPKH)
.accountPath(DeterministicKeyChain.BIP44_ACCOUNT_ZERO_PATH).build()) .accountPath(DeterministicKeyChain.BIP44_ACCOUNT_ZERO_PATH).build())
@ -3220,7 +3220,7 @@ public class WalletTest extends TestWithWallet {
@Test @Test
public void keyEvents() { public void keyEvents() {
// Check that we can register an event listener, generate some keys and the callbacks are invoked properly. // Check that we can register an event listener, generate some keys and the callbacks are invoked properly.
wallet = new Wallet(BitcoinNetwork.TESTNET, KeyChainGroup.builder(TESTNET).fromRandom(ScriptType.P2PKH).build()); wallet = new Wallet(BitcoinNetwork.TESTNET, KeyChainGroup.builder(BitcoinNetwork.TESTNET).fromRandom(ScriptType.P2PKH).build());
final List<ECKey> keys = new LinkedList<>(); final List<ECKey> keys = new LinkedList<>();
wallet.addKeyChainEventListener(Threading.SAME_THREAD, keys::addAll); wallet.addKeyChainEventListener(Threading.SAME_THREAD, keys::addAll);
wallet.freshReceiveKey(); wallet.freshReceiveKey();
@ -3504,7 +3504,7 @@ public class WalletTest extends TestWithWallet {
.outputScriptType(ScriptType.P2PKH).build(); .outputScriptType(ScriptType.P2PKH).build();
DeterministicKeyChain p2wpkhChain = DeterministicKeyChain.builder().random(new SecureRandom()) DeterministicKeyChain p2wpkhChain = DeterministicKeyChain.builder().random(new SecureRandom())
.outputScriptType(ScriptType.P2WPKH).build(); .outputScriptType(ScriptType.P2WPKH).build();
KeyChainGroup kcg = KeyChainGroup.builder(TESTNET).addChain(p2pkhChain).addChain(p2wpkhChain).build(); KeyChainGroup kcg = KeyChainGroup.builder(BitcoinNetwork.TESTNET).addChain(p2pkhChain).addChain(p2wpkhChain).build();
Wallet wallet = new Wallet(BitcoinNetwork.TESTNET, kcg); Wallet wallet = new Wallet(BitcoinNetwork.TESTNET, kcg);
// Set up one key from each chain. // Set up one key from each chain.

View file

@ -111,7 +111,7 @@ public class TestWithNetworkConnections {
// Allow subclasses to override the wallet object with their own. // Allow subclasses to override the wallet object with their own.
if (wallet == null) { if (wallet == null) {
// Reduce the number of keys we need to work with to speed up these tests. // Reduce the number of keys we need to work with to speed up these tests.
KeyChainGroup kcg = KeyChainGroup.builder(UNITTEST).lookaheadSize(4).lookaheadThreshold(2) KeyChainGroup kcg = KeyChainGroup.builder(UNITTEST.network()).lookaheadSize(4).lookaheadThreshold(2)
.fromRandom(ScriptType.P2PKH).build(); .fromRandom(ScriptType.P2PKH).build();
wallet = new Wallet(UNITTEST.network(), kcg); wallet = new Wallet(UNITTEST.network(), kcg);
address = wallet.freshReceiveAddress(ScriptType.P2PKH); address = wallet.freshReceiveAddress(ScriptType.P2PKH);