public boolean hasKeyChain(ImmutableList<ChildNumber> path) { boolean hasPath = false; for(DeterministicKeyChain chain : keyChainGroup.getDeterministicKeyChains()) { if(chain.getAccountPath().equals(path)) hasPath = true; } return hasPath; } /**
/** * <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(org.bitcoinj.crypto.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 * be used for signing etc if the private key bytes are available.</p> */ public DeterministicKey getWatchingKey() { return getKeyByPath(getAccountPath()); }
/** * <p>An alias for <code>getKeyByPath(getAccountPath())</code>.</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(org.bitcoinj.crypto.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 * be used for signing etc if the private key bytes are available.</p> */ public DeterministicKey getWatchingKey() { return getKeyByPath(getAccountPath()); }
/** * <p>An alias for <code>getKeyByPath(getAccountPath())</code>.</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(org.bitcoinj.crypto.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 * be used for signing etc if the private key bytes are available.</p> */ public DeterministicKey getWatchingKey() { return getKeyByPath(getAccountPath()); }
/** * <p>An alias for <code>getKeyByPath(getAccountPath())</code>.</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(org.bitcoinj.crypto.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 * be used for signing etc if the private key bytes are available.</p> */ public DeterministicKey getWatchingKey() { return getKeyByPath(getAccountPath()); }
/** * Returns leaf keys issued by this chain (including lookahead zone) */ public List<DeterministicKey> getLeafKeys() { ImmutableList.Builder<DeterministicKey> keys = ImmutableList.builder(); for (ECKey key : getKeys(true)) { DeterministicKey dKey = (DeterministicKey) key; if (dKey.getPath().size() == getAccountPath().size() + 2) { keys.add(dKey); } } return keys.build(); }
/** * Returns leaf keys issued by this chain (including lookahead zone) */ public List<DeterministicKey> getLeafKeys() { ImmutableList.Builder<DeterministicKey> keys = ImmutableList.builder(); for (ECKey key : getKeys(true, false)) { DeterministicKey dKey = (DeterministicKey) key; if (dKey.getPath().size() == getAccountPath().size() + 2) { keys.add(dKey); } } return keys.build(); }
/** * Returns leaf keys issued by this chain (including lookahead zone) */ public List<DeterministicKey> getLeafKeys() { ImmutableList.Builder<DeterministicKey> keys = ImmutableList.builder(); for (ECKey key : getKeys(true, false)) { DeterministicKey dKey = (DeterministicKey) key; if (dKey.getPath().size() == getAccountPath().size() + 2) { keys.add(dKey); } } return keys.build(); }
/** * Returns leaf keys issued by this chain (including lookahead zone) */ public List<DeterministicKey> getLeafKeys() { ImmutableList.Builder<DeterministicKey> keys = ImmutableList.builder(); for (ECKey key : getKeys(true)) { DeterministicKey dKey = (DeterministicKey) key; if (dKey.getPath().size() == getAccountPath().size() + 2) { keys.add(dKey); } } return keys.build(); }
private void initializeHierarchyUnencrypted(DeterministicKey baseKey) { externalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ZERO); internalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ONE); addToBasicChain(externalParentKey); addToBasicChain(internalParentKey); }
private void initializeHierarchyUnencrypted(DeterministicKey baseKey) { externalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ZERO); internalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ONE); basicKeyChain.importKey(externalParentKey); basicKeyChain.importKey(internalParentKey); }
private void initializeHierarchyUnencrypted(DeterministicKey baseKey) { externalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ZERO); internalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ONE); addToBasicChain(externalParentKey); addToBasicChain(internalParentKey); }
private void initializeHierarchyUnencrypted(DeterministicKey baseKey) { externalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ZERO); internalParentKey = hierarchy.deriveChild(getAccountPath(), false, false, ChildNumber.ONE); basicKeyChain.importKey(externalParentKey); basicKeyChain.importKey(internalParentKey); }
/** * 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. Currently you can't use * this method to watch an arbitrary fragment of some other tree, this limitation may be removed in future. */ 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."); checkArgument(watchingKey.getPath().size() == getAccountPath().size(), "You can only watch an account key currently"); basicKeyChain = new BasicKeyChain(); this.seed = null; this.rootKey = null; basicKeyChain.importKey(watchingKey); hierarchy = new DeterministicHierarchy(watchingKey); initializeHierarchyUnencrypted(watchingKey); }
/** * 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. Currently you can't use * this method to watch an arbitrary fragment of some other tree, this limitation may be removed in future. */ 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."); checkArgument(watchingKey.getPath().size() == getAccountPath().size(), "You can only watch an account key currently"); basicKeyChain = new BasicKeyChain(); this.seed = null; rootKey = null; addToBasicChain(watchingKey); hierarchy = new DeterministicHierarchy(watchingKey); initializeHierarchyUnencrypted(watchingKey); }
/** * 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. Currently you can't use * this method to watch an arbitrary fragment of some other tree, this limitation may be removed in future. */ public DeterministicKeyChain(DeterministicKey watchingKey, boolean useSegwit) { checkArgument(watchingKey.isPubKeyOnly(), "Private subtrees not currently supported: if you got this key from DKC.getWatchingKey() then use .dropPrivate().dropParent() on it first."); checkArgument(watchingKey.getPath().size() == getAccountPath().size(), "You can only watch an account key currently"); this.useSegwit = useSegwit; basicKeyChain = new BasicKeyChain(useSegwit); this.seed = null; this.rootKey = null; basicKeyChain.importKey(watchingKey); hierarchy = new DeterministicHierarchy(watchingKey); initializeHierarchyUnencrypted(watchingKey); }
private static EnumMap<KeyChain.KeyPurpose, DeterministicKey> createCurrentKeysMap(List<DeterministicKeyChain> chains) { DeterministicKeyChain activeChain = chains.get(chains.size() - 1); EnumMap<KeyChain.KeyPurpose, DeterministicKey> currentKeys = new EnumMap<KeyChain.KeyPurpose, DeterministicKey>(KeyChain.KeyPurpose.class); // assuming that only RECEIVE and CHANGE keys are being used at the moment, we will treat latest issued external key // as current RECEIVE key and latest issued internal key as CHANGE key. This should be changed as soon as other // kinds of KeyPurpose are introduced. if (activeChain.getIssuedExternalKeys() > 0) { DeterministicKey currentExternalKey = activeChain.getKeyByPath( HDUtils.append( HDUtils.concat(activeChain.getAccountPath(), DeterministicKeyChain.EXTERNAL_SUBPATH), new ChildNumber(activeChain.getIssuedExternalKeys() - 1))); currentKeys.put(KeyChain.KeyPurpose.RECEIVE_FUNDS, currentExternalKey); } if (activeChain.getIssuedInternalKeys() > 0) { DeterministicKey currentInternalKey = activeChain.getKeyByPath( HDUtils.append( HDUtils.concat(activeChain.getAccountPath(), DeterministicKeyChain.INTERNAL_SUBPATH), new ChildNumber(activeChain.getIssuedInternalKeys() - 1))); currentKeys.put(KeyChain.KeyPurpose.CHANGE, currentInternalKey); } return currentKeys; }
/** * For use in {@link KeyChainFactory} during deserialization. */ protected DeterministicKeyChain(DeterministicSeed seed, @Nullable KeyCrypter crypter) { this.seed = seed; basicKeyChain = new BasicKeyChain(crypter); if (!seed.isEncrypted()) { rootKey = HDKeyDerivation.createMasterPrivateKey(checkNotNull(seed.getSeedBytes())); rootKey.setCreationTimeSeconds(seed.getCreationTimeSeconds()); addToBasicChain(rootKey); hierarchy = new DeterministicHierarchy(rootKey); for (int i = 1; i <= getAccountPath().size(); i++) { addToBasicChain(hierarchy.get(getAccountPath().subList(0, i), false, true)); } initializeHierarchyUnencrypted(rootKey); } // Else... // We can't initialize ourselves with just an encrypted seed, so we expected deserialization code to do the // rest of the setup (loading the root key). }
/** * For use in {@link KeyChainFactory} during deserialization. */ protected DeterministicKeyChain(DeterministicSeed seed, @Nullable KeyCrypter crypter, boolean useSegwit) { this.seed = seed; this.useSegwit = useSegwit; basicKeyChain = new BasicKeyChain(crypter, useSegwit); if (!seed.isEncrypted()) { rootKey = HDKeyDerivation.createMasterPrivateKey(checkNotNull(seed.getSeedBytes())); rootKey.setCreationTimeSeconds(seed.getCreationTimeSeconds()); basicKeyChain.importKey(rootKey); hierarchy = new DeterministicHierarchy(rootKey); for (int i = 1; i <= getAccountPath().size(); i++) { basicKeyChain.importKey(hierarchy.get(getAccountPath().subList(0, i), false, true)); } initializeHierarchyUnencrypted(rootKey); } // Else... // We can't initialize ourselves with just an encrypted seed, so we expected deserialization code to do the // rest of the setup (loading the root key). }
@Test public void freshAddress() throws Exception { group = createMarriedKeyChainGroup(); Address a1 = group.freshAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS); Address a2 = group.freshAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS); assertTrue(a1.isP2SHAddress()); assertNotEquals(a1, a2); group.getBloomFilterElementCount(); assertEquals(((group.getLookaheadSize() + group.getLookaheadThreshold()) * 2) // * 2 because of internal/external + (2 - group.getLookaheadThreshold()) // keys issued + group.getActiveKeyChain().getAccountPath().size() + 3 /* master, account, int, ext */, group.numKeys()); Address a3 = group.currentAddress(KeyChain.KeyPurpose.RECEIVE_FUNDS); assertEquals(a2, a3); }