public class KeyChainGroup extends Object implements KeyBag
A KeyChainGroup is used by the Wallet
and
manages: a BasicKeyChain
object (which will normally be empty), and zero or more
DeterministicKeyChain
s. A deterministic key chain will be created lazily/on demand
when a fresh or current key is requested, possibly being initialized from the private key bytes of the earliest non
rotating key in the basic key chain if one is available, or from a fresh random seed if not.
If a key rotation time is set, it may be necessary to add a new DeterministicKeyChain with a fresh seed and also preserve the old one, so funds can be swept from the rotating keys. In this case, there may be more than one deterministic chain. The latest chain is called the active chain and is where new keys are served from.
The wallet delegates most key management tasks to this class. It is not thread safe and requires external locking, i.e. by the wallet lock. The group then in turn delegates most operations to the key chain objects, combining their responses together when necessary.
Deterministic key chains have a concept of a lookahead size and threshold. Please see the discussion in the
class docs for DeterministicKeyChain
for more information on this topic.
Modifier and Type | Field and Description |
---|---|
protected LinkedList<DeterministicKeyChain> |
chains |
Constructor and Description |
---|
KeyChainGroup(NetworkParameters params)
Creates a keychain group with no basic chain, and a single, lazily created HD chain.
|
KeyChainGroup(NetworkParameters params,
DeterministicKey watchKey)
Creates a keychain group with no basic chain, and an HD chain that is watching the given watching key.
|
KeyChainGroup(NetworkParameters params,
DeterministicSeed seed)
Creates a keychain group with no basic chain, and an HD chain initialized from the given seed.
|
Modifier and Type | Method and Description |
---|---|
void |
addAndActivateHDChain(DeterministicKeyChain chain)
Adds an HD chain to the chains list, and make it the default chain (from which keys are issued).
|
void |
addEventListener(KeyChainEventListener listener)
Adds a listener for events that are run when keys are added, on the user thread.
|
void |
addEventListener(KeyChainEventListener listener,
Executor executor)
Adds a listener for events that are run when keys are added, on the given executor.
|
boolean |
checkAESKey(org.spongycastle.crypto.params.KeyParameter aesKey) |
boolean |
checkPassword(CharSequence password) |
void |
createAndActivateNewHDChain()
Adds a new HD chain to the chains list, and make it the default chain (from which keys are issued).
|
Address |
currentAddress(KeyChain.KeyPurpose purpose)
Returns address for a
currentKey(KeyChain.KeyPurpose) |
DeterministicKey |
currentKey(KeyChain.KeyPurpose purpose)
Returns a key that hasn't been seen in a transaction yet, and which is suitable for displaying in a wallet
user interface as "a convenient key to receive funds on" when the purpose parameter is
KeyChain.KeyPurpose.RECEIVE_FUNDS . |
void |
decrypt(org.spongycastle.crypto.params.KeyParameter aesKey)
Decrypt the keys in the group using the previously given key crypter and the AES key.
|
void |
encrypt(KeyCrypter keyCrypter,
org.spongycastle.crypto.params.KeyParameter aesKey)
Encrypt the keys in the group using the KeyCrypter and the AES key.
|
ECKey |
findKeyFromPubHash(byte[] pubkeyHash)
Locates a keypair from the keychain given the hash of the public key.
|
ECKey |
findKeyFromPubKey(byte[] pubkey)
Locates a keypair from the keychain given the raw public key bytes.
|
RedeemData |
findRedeemDataFromScriptHash(byte[] scriptHash)
Locates a redeem data (redeem script and keys) from the keychain given the hash of the script.
|
Address |
freshAddress(KeyChain.KeyPurpose purpose)
Returns address for a
freshKey(KeyChain.KeyPurpose) |
DeterministicKey |
freshKey(KeyChain.KeyPurpose purpose)
Returns a key that has not been returned by this method before (fresh).
|
List<DeterministicKey> |
freshKeys(KeyChain.KeyPurpose purpose,
int numberOfKeys)
Returns a key/s that have not been returned by this method before (fresh).
|
static KeyChainGroup |
fromProtobufEncrypted(NetworkParameters params,
List<Protos.Key> keys,
KeyCrypter crypter,
KeyChainFactory factory) |
static KeyChainGroup |
fromProtobufUnencrypted(NetworkParameters params,
List<Protos.Key> keys,
KeyChainFactory factory) |
DeterministicKeyChain |
getActiveKeyChain()
Returns the key chain that's used for generation of fresh/current keys.
|
BloomFilter |
getBloomFilter(int size,
double falsePositiveRate,
long nTweak) |
int |
getBloomFilterElementCount() |
int |
getCombinedKeyLookaheadEpochs()
Returns a counter that increases (by an arbitrary amount) each time new keys have been calculated due to
lookahead and thus the Bloom filter that was previously calculated has become stale.
|
List<DeterministicKeyChain> |
getDeterministicKeyChains()
Returns a copy of the current list of chains.
|
long |
getEarliestKeyCreationTime() |
List<ECKey> |
getImportedKeys()
Returns a list of the non-deterministic keys that have been imported into the wallet, or the empty list if none.
|
KeyCrypter |
getKeyCrypter()
Returns the key crypter or null if the group is not encrypted.
|
int |
getLookaheadSize()
Gets the current lookahead size being used for ALL deterministic key chains.
|
int |
getLookaheadThreshold()
Gets the current lookahead threshold being used for ALL deterministic key chains.
|
boolean |
hasKey(ECKey key) |
int |
importKeys(ECKey... keys)
Imports the given keys into the basic chain, creating it if necessary.
|
int |
importKeys(List<ECKey> keys)
Imports the given keys into the basic chain, creating it if necessary.
|
int |
importKeysAndEncrypt(List<ECKey> keys,
org.spongycastle.crypto.params.KeyParameter aesKey)
Imports the given unencrypted keys into the basic chain, encrypting them along the way with the given key.
|
boolean |
isDeterministicUpgradeRequired()
Returns true if the group contains random keys but no HD chains.
|
boolean |
isEncrypted()
Returns true if the group is encrypted.
|
boolean |
isMarried()
Whether the active keychain is married.
|
boolean |
isRequiringUpdateAllBloomFilter() |
boolean |
isWatching()
Returns whether this chain has only watching keys (unencrypted keys with no private part).
|
void |
markP2SHAddressAsUsed(Address address) |
void |
markPubKeyAsUsed(byte[] pubkey)
Mark the DeterministicKeys as used, if they match the pubkey
See
DeterministicKeyChain.markKeyAsUsed(DeterministicKey) for more info on this. |
void |
markPubKeyHashAsUsed(byte[] pubkeyHash)
Mark the DeterministicKeys as used, if they match the pubkeyHash
See
DeterministicKeyChain.markKeyAsUsed(DeterministicKey) for more info on this. |
int |
numKeys()
Returns the number of keys managed by this group, including the lookahead buffers.
|
boolean |
removeEventListener(KeyChainEventListener listener)
Removes a listener for events that are run when keys are added.
|
boolean |
removeImportedKey(ECKey key)
Removes a key that was imported into the basic key chain.
|
List<Protos.Key> |
serializeToProtobuf()
Returns a list of key protobufs obtained by merging the chains.
|
void |
setLookaheadSize(int lookaheadSize)
Sets the lookahead buffer size for ALL deterministic key chains as well as for following key chains if any exist,
see
DeterministicKeyChain.setLookaheadSize(int)
for more information. |
void |
setLookaheadThreshold(int num)
Sets the lookahead buffer threshold for ALL deterministic key chains, see
DeterministicKeyChain.setLookaheadThreshold(int)
for more information. |
String |
toString(boolean includePrivateKeys) |
DeterministicKeyChain |
upgradeToDeterministic(long keyRotationTimeSecs,
org.spongycastle.crypto.params.KeyParameter aesKey)
If the key chain contains only random keys and no deterministic key chains, this method will create a chain
based on the oldest non-rotating private key (i.e.
|
protected final LinkedList<DeterministicKeyChain> chains
public KeyChainGroup(NetworkParameters params)
public KeyChainGroup(NetworkParameters params, DeterministicSeed seed)
public KeyChainGroup(NetworkParameters params, DeterministicKey watchKey)
DeterministicKeyChain.getWatchingKey()
.public void createAndActivateNewHDChain()
public void addAndActivateHDChain(DeterministicKeyChain chain)
public DeterministicKey currentKey(KeyChain.KeyPurpose purpose)
KeyChain.KeyPurpose.RECEIVE_FUNDS
. The returned key is stable until
it's actually seen in a pending or confirmed transaction, at which point this method will start returning
a different key (for each purpose independently).
This method is not supposed to be used for married keychains and will throw UnsupportedOperationException if
the active chain is married.
For married keychains use currentAddress(KeyChain.KeyPurpose)
to get a proper P2SH address
public Address currentAddress(KeyChain.KeyPurpose purpose)
currentKey(KeyChain.KeyPurpose)
public DeterministicKey freshKey(KeyChain.KeyPurpose purpose)
DeterministicKeyChain
. When the parameter is
KeyChain.KeyPurpose.RECEIVE_FUNDS
the returned key is suitable for being put
into a receive coins wizard type UI. You should use this when the user is definitely going to hand this key out
to someone who wishes to send money.
This method is not supposed to be used for married keychains and will throw UnsupportedOperationException if
the active chain is married.
For married keychains use freshAddress(KeyChain.KeyPurpose)
to get a proper P2SH address
public List<DeterministicKey> freshKeys(KeyChain.KeyPurpose purpose, int numberOfKeys)
DeterministicKeyChain
. When the parameter is
KeyChain.KeyPurpose.RECEIVE_FUNDS
the returned key is suitable for being put
into a receive coins wizard type UI. You should use this when the user is definitely going to hand this key out
to someone who wishes to send money.
This method is not supposed to be used for married keychains and will throw UnsupportedOperationException if
the active chain is married.
For married keychains use freshAddress(KeyChain.KeyPurpose)
to get a proper P2SH address
public Address freshAddress(KeyChain.KeyPurpose purpose)
freshKey(KeyChain.KeyPurpose)
public final DeterministicKeyChain getActiveKeyChain()
public void setLookaheadSize(int lookaheadSize)
DeterministicKeyChain.setLookaheadSize(int)
for more information.public int getLookaheadSize()
DeterministicKeyChain.setLookaheadSize(int)
for more information.public void setLookaheadThreshold(int num)
DeterministicKeyChain.setLookaheadThreshold(int)
for more information.public int getLookaheadThreshold()
DeterministicKeyChain.setLookaheadThreshold(int)
for more information.public int importKeys(List<ECKey> keys)
public int importKeys(ECKey... keys)
public boolean checkPassword(CharSequence password)
public boolean checkAESKey(org.spongycastle.crypto.params.KeyParameter aesKey)
public int importKeysAndEncrypt(List<ECKey> keys, org.spongycastle.crypto.params.KeyParameter aesKey)
@Nullable public RedeemData findRedeemDataFromScriptHash(byte[] scriptHash)
KeyBag
findRedeemDataFromScriptHash
in interface KeyBag
public void markP2SHAddressAsUsed(Address address)
@Nullable public ECKey findKeyFromPubHash(byte[] pubkeyHash)
KeyBag
findKeyFromPubHash
in interface KeyBag
public void markPubKeyHashAsUsed(byte[] pubkeyHash)
DeterministicKeyChain.markKeyAsUsed(DeterministicKey)
for more info on this.public boolean hasKey(ECKey key)
@Nullable public ECKey findKeyFromPubKey(byte[] pubkey)
KeyBag
findKeyFromPubKey
in interface KeyBag
public void markPubKeyAsUsed(byte[] pubkey)
DeterministicKeyChain.markKeyAsUsed(DeterministicKey)
for more info on this.public int numKeys()
public boolean removeImportedKey(ECKey key)
IllegalArgumentException
- if the key is deterministic.public final boolean isMarried()
MarriedKeyChain
public void encrypt(KeyCrypter keyCrypter, org.spongycastle.crypto.params.KeyParameter aesKey)
KeyCrypterScrypt
.KeyCrypterException
- Thrown if the wallet encryption fails for some reason,
leaving the group unchanged.DeterministicUpgradeRequiredException
- Thrown if there are random keys but no HD chain.public void decrypt(org.spongycastle.crypto.params.KeyParameter aesKey)
KeyCrypterScrypt
.KeyCrypterException
- Thrown if the wallet decryption fails for some reason, leaving the group unchanged.public boolean isEncrypted()
public boolean isWatching()
IllegalStateException
- if there are no keys, or if there is a mix between watching and non-watching keys.@Nullable public KeyCrypter getKeyCrypter()
public List<ECKey> getImportedKeys()
public long getEarliestKeyCreationTime()
public int getBloomFilterElementCount()
public BloomFilter getBloomFilter(int size, double falsePositiveRate, long nTweak)
public boolean isRequiringUpdateAllBloomFilter()
public void addEventListener(KeyChainEventListener listener)
public void addEventListener(KeyChainEventListener listener, Executor executor)
public boolean removeEventListener(KeyChainEventListener listener)
public List<Protos.Key> serializeToProtobuf()
public static KeyChainGroup fromProtobufUnencrypted(NetworkParameters params, List<Protos.Key> keys, KeyChainFactory factory) throws UnreadableWalletException
UnreadableWalletException
public static KeyChainGroup fromProtobufEncrypted(NetworkParameters params, List<Protos.Key> keys, KeyCrypter crypter, KeyChainFactory factory) throws UnreadableWalletException
UnreadableWalletException
public DeterministicKeyChain upgradeToDeterministic(long keyRotationTimeSecs, @Nullable org.spongycastle.crypto.params.KeyParameter aesKey) throws DeterministicUpgradeRequiresPassword, AllRandomKeysRotating
keyRotationTimeSecs
- If non-zero, UNIX time for which keys created before this are assumed to be
compromised or weak, those keys will not be used for deterministic upgrade.aesKey
- If non-null, the encryption key the keychain is encrypted under. If the keychain is encrypted
and this is not supplied, an exception is thrown letting you know you should ask the user for
their password, turn it into a key, and then try again.IllegalStateException
- if there is already a deterministic key chain present or if there are
no random keys (i.e. this is not an upgrade scenario), or if aesKey is
provided but the wallet is not encrypted.IllegalArgumentException
- if the rotation time specified excludes all keys.DeterministicUpgradeRequiresPassword
- if the key chain group is encrypted
and you should provide the users encryption key.AllRandomKeysRotating
public boolean isDeterministicUpgradeRequired()
public String toString(boolean includePrivateKeys)
public List<DeterministicKeyChain> getDeterministicKeyChains()
public int getCombinedKeyLookaheadEpochs()
Copyright © 2016. All rights reserved.