@Override public DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed, KeyCrypter crypter, boolean isMarried) { DeterministicKeyChain chain; if (isMarried) chain = new MarriedKeyChain(seed, crypter); else chain = new DeterministicKeyChain(seed, crypter); return chain; }
@Override public void maybeLookAheadScripts() { super.maybeLookAheadScripts(); int numLeafKeys = getLeafKeys().size(); checkState(marriedKeysRedeemData.size() <= numLeafKeys, "Number of scripts is greater than number of leaf keys"); if (marriedKeysRedeemData.size() == numLeafKeys) return; maybeLookAhead(); for (DeterministicKey followedKey : getLeafKeys()) { RedeemData redeemData = getRedeemData(followedKey); Script scriptPubKey = ScriptBuilder.createP2SHOutputScript(redeemData.redeemScript); marriedKeysRedeemData.put(ByteString.copyFrom(scriptPubKey.getPubKeyHash()), redeemData); } }
@Override public List<Protos.Key> serializeToProtobuf() { List<Protos.Key> result = newArrayList(); lock.lock(); try { for (DeterministicKeyChain chain : followingKeyChains) { result.addAll(chain.serializeMyselfToProtobuf()); } result.addAll(serializeMyselfToProtobuf()); } finally { lock.unlock(); } return result; }
@Override public int numBloomFilterEntries() { maybeLookAhead(); return getLeafKeys().size() * 2; } }
private void addFollowingAccountKeys(List<DeterministicKey> followingAccountKeys, int sigsRequiredToSpend) { checkArgument(sigsRequiredToSpend <= followingAccountKeys.size() + 1, "Multisig threshold can't exceed total number of keys"); checkState(numLeafKeysIssued() == 0, "Active keychain already has keys in use"); checkState(followingKeyChains == null); List<DeterministicKeyChain> followingKeyChains = Lists.newArrayList(); for (DeterministicKey key : followingAccountKeys) { checkArgument(key.getPath().size() == getAccountPath().size(), "Following keys have to be account keys"); DeterministicKeyChain chain = DeterministicKeyChain.watchAndFollow(key); if (lookaheadSize >= 0) chain.setLookaheadSize(lookaheadSize); if (lookaheadThreshold >= 0) chain.setLookaheadThreshold(lookaheadThreshold); followingKeyChains.add(chain); } this.sigsRequiredToSpend = sigsRequiredToSpend; this.followingKeyChains = followingKeyChains; }
/** Get the redeem data for a key in this married chain */ @Override public RedeemData getRedeemData(DeterministicKey followedKey) { List<ECKey> marriedKeys = getMarriedKeysWithFollowed(followedKey); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return RedeemData.of(marriedKeys, redeemScript); }
@Override protected void formatAddresses(boolean includePrivateKeys, NetworkParameters params, StringBuilder builder2) { for (DeterministicKeyChain followingChain : followingKeyChains) builder2.append("Following chain: ").append(followingChain.getWatchingKey().serializePubB58(params)) .append('\n'); builder2.append('\n'); for (RedeemData redeemData : marriedKeysRedeemData.values()) formatScript(ScriptBuilder.createP2SHOutputScript(redeemData.redeemScript), builder2, params); }
/** Create a new married key and return the matching output script */ @Override public Script freshOutputScript(KeyPurpose purpose) { DeterministicKey followedKey = getKey(purpose); ImmutableList.Builder<ECKey> keys = ImmutableList.<ECKey>builder().add(followedKey); for (DeterministicKeyChain keyChain : followingKeyChains) { DeterministicKey followingKey = keyChain.getKey(purpose); checkState(followedKey.getChildNumber().equals(followingKey.getChildNumber()), "Following keychains should be in sync"); keys.add(followingKey); } List<ECKey> marriedKeys = keys.build(); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return ScriptBuilder.createP2SHOutputScript(redeemScript); }
@Override public int numBloomFilterEntries() { maybeLookAhead(); return getLeafKeys().size() * 2; } }
private void addFollowingAccountKeys(List<DeterministicKey> followingAccountKeys, int sigsRequiredToSpend) { checkArgument(sigsRequiredToSpend <= followingAccountKeys.size() + 1, "Multisig threshold can't exceed total number of keys"); checkState(numLeafKeysIssued() == 0, "Active keychain already has keys in use"); checkState(followingKeyChains == null); List<DeterministicKeyChain> followingKeyChains = Lists.newArrayList(); for (DeterministicKey key : followingAccountKeys) { checkArgument(key.getPath().size() == getAccountPath().size(), "Following keys have to be account keys"); DeterministicKeyChain chain = DeterministicKeyChain.watchAndFollow(key); if (lookaheadSize >= 0) chain.setLookaheadSize(lookaheadSize); if (lookaheadThreshold >= 0) chain.setLookaheadThreshold(lookaheadThreshold); followingKeyChains.add(chain); } this.sigsRequiredToSpend = sigsRequiredToSpend; this.followingKeyChains = followingKeyChains; }
/** Get the redeem data for a key in this married chain */ @Override public RedeemData getRedeemData(DeterministicKey followedKey) { List<ECKey> marriedKeys = getMarriedKeysWithFollowed(followedKey); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return RedeemData.of(marriedKeys, redeemScript); }
@Override protected void formatAddresses(boolean includePrivateKeys, NetworkParameters params, StringBuilder builder2) { for (DeterministicKeyChain followingChain : followingKeyChains) builder2.append("Following chain: ").append(followingChain.getWatchingKey().serializePubB58(params)) .append('\n'); builder2.append('\n'); for (RedeemData redeemData : marriedKeysRedeemData.values()) formatScript(ScriptBuilder.createP2SHOutputScript(redeemData.redeemScript), builder2, params); }
/** Create a new married key and return the matching output script */ @Override public Script freshOutputScript(KeyPurpose purpose) { DeterministicKey followedKey = getKey(purpose); ImmutableList.Builder<ECKey> keys = ImmutableList.<ECKey>builder().add(followedKey); for (DeterministicKeyChain keyChain : followingKeyChains) { DeterministicKey followingKey = keyChain.getKey(purpose); checkState(followedKey.getChildNumber().equals(followingKey.getChildNumber()), "Following keychains should be in sync"); keys.add(followingKey); } List<ECKey> marriedKeys = keys.build(); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return ScriptBuilder.createP2SHOutputScript(redeemScript); }
@Override public void maybeLookAheadScripts() { super.maybeLookAheadScripts(); int numLeafKeys = getLeafKeys().size(); checkState(marriedKeysRedeemData.size() <= numLeafKeys, "Number of scripts is greater than number of leaf keys"); if (marriedKeysRedeemData.size() == numLeafKeys) return; maybeLookAhead(); for (DeterministicKey followedKey : getLeafKeys()) { RedeemData redeemData = getRedeemData(followedKey); Script scriptPubKey = ScriptBuilder.createP2SHOutputScript(redeemData.redeemScript); marriedKeysRedeemData.put(ByteString.copyFrom(scriptPubKey.getPubKeyHash()), redeemData); } }
@Override public int numBloomFilterEntries() { maybeLookAhead(); return getLeafKeys().size() * 2; } }
private void addFollowingAccountKeys(List<DeterministicKey> followingAccountKeys, int sigsRequiredToSpend) { checkArgument(sigsRequiredToSpend <= followingAccountKeys.size() + 1, "Multisig threshold can't exceed total number of keys"); checkState(numLeafKeysIssued() == 0, "Active keychain already has keys in use"); checkState(followingKeyChains == null); List<DeterministicKeyChain> followingKeyChains = Lists.newArrayList(); for (DeterministicKey key : followingAccountKeys) { checkArgument(key.getPath().size() == getAccountPath().size(), "Following keys have to be account keys"); DeterministicKeyChain chain = DeterministicKeyChain.watchAndFollow(key); if (lookaheadSize >= 0) chain.setLookaheadSize(lookaheadSize); if (lookaheadThreshold >= 0) chain.setLookaheadThreshold(lookaheadThreshold); followingKeyChains.add(chain); } this.sigsRequiredToSpend = sigsRequiredToSpend; this.followingKeyChains = followingKeyChains; }
@Override public DeterministicKeyChain makeKeyChain(Protos.Key key, Protos.Key firstSubKey, DeterministicSeed seed, KeyCrypter crypter, boolean isMarried, boolean useSegwit) { DeterministicKeyChain chain; if (isMarried) chain = new MarriedKeyChain(seed, crypter); else chain = new DeterministicKeyChain(seed, crypter, useSegwit); return chain; }
/** Get the redeem data for a key in this married chain */ @Override public RedeemData getRedeemData(DeterministicKey followedKey) { List<ECKey> marriedKeys = getMarriedKeysWithFollowed(followedKey); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return RedeemData.of(marriedKeys, redeemScript); }
@Override protected void formatAddresses(boolean includePrivateKeys, @Nullable KeyParameter aesKey, NetworkParameters params, StringBuilder builder2) { for (DeterministicKeyChain followingChain : followingKeyChains) builder2.append("Following chain: ").append(followingChain.getWatchingKey().serializePubB58(params)) .append('\n'); builder2.append('\n'); for (RedeemData redeemData : marriedKeysRedeemData.values()) formatScript(ScriptBuilder.createP2SHOutputScript(redeemData.redeemScript), builder2, params); }
/** Create a new married key and return the matching output script */ @Override public Script freshOutputScript(KeyPurpose purpose) { DeterministicKey followedKey = getKey(purpose); ImmutableList.Builder<ECKey> keys = ImmutableList.<ECKey>builder().add(followedKey); for (DeterministicKeyChain keyChain : followingKeyChains) { DeterministicKey followingKey = keyChain.getKey(purpose); checkState(followedKey.getChildNumber().equals(followingKey.getChildNumber()), "Following keychains should be in sync"); keys.add(followingKey); } List<ECKey> marriedKeys = keys.build(); Script redeemScript = ScriptBuilder.createRedeemScript(sigsRequiredToSpend, marriedKeys); return ScriptBuilder.createP2SHOutputScript(redeemScript); }