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.
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,
DeterministicKey watchKey,
long creationTimeSecondsSecs)
Creates a keychain group with no basic chain, and an HD chain that is watching the given watching key which
was assumed to be first used at the given UNIX time.
|
KeyChainGroup(NetworkParameters params,
DeterministicSeed seed)
Creates a keychain group with no basic chain, and an HD chain initialized from the given seed.
|
KeyChainGroup(NetworkParameters params,
DeterministicSeed seed,
List<DeterministicKey> followingAccountKeys,
int sigsRequiredToSpend)
Creates a keychain group with no basic chain, with an HD chain initialized from the given seed and being followed
by given list of watch keys.
|
Modifier and Type | Method and Description |
---|---|
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.
|
void |
addFollowingAccountKeys(List<DeterministicKey> followingAccountKeys)
Alias for
addFollowingAccountKeys(followingAccountKeys, (followingAccountKeys.size() + 1) / 2 + 1) |
void |
addFollowingAccountKeys(List<DeterministicKey> followingAccountKeys,
int sigsRequiredToSpend)
Makes given account keys follow the account key of the active keychain.
|
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,
int sigsRequiredToSpend,
KeyCrypter crypter) |
static KeyChainGroup |
fromProtobufUnencrypted(NetworkParameters params,
List<Protos.Key> keys,
int sigsRequiredToSpend) |
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.
|
int |
getSigsRequiredToSpend()
Returns the number of signatures required to spend transactions for this KeyChainGroup.
|
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()
An alias for
isMarried(DeterministicKeyChain) called for the active keychain |
boolean |
isMarried(DeterministicKeyChain keychain)
Returns true if the given keychain is being followed by at least one another keychain
|
boolean |
isRequiringUpdateAllBloomFilter() |
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.
|
public KeyChainGroup(NetworkParameters params)
public KeyChainGroup(NetworkParameters params, DeterministicSeed seed)
public KeyChainGroup(NetworkParameters params, DeterministicKey watchKey)
DeterministicKeyChain.getWatchingKey()
.public KeyChainGroup(NetworkParameters params, DeterministicKey watchKey, long creationTimeSecondsSecs)
DeterministicKeyChain.getWatchingKey()
.public KeyChainGroup(NetworkParameters params, DeterministicSeed seed, List<DeterministicKey> followingAccountKeys, int sigsRequiredToSpend)
public void addFollowingAccountKeys(List<DeterministicKey> followingAccountKeys)
Alias for addFollowingAccountKeys(followingAccountKeys, (followingAccountKeys.size() + 1) / 2 + 1)
Creates married keychain requiring majority of keys to spend (2-of-3, 3-of-5 and so on)
IMPORTANT: As of Bitcoin Core 0.9 all multisig transactions which require more than 3 public keys are non-standard and such spends won't be processed by peers with default settings, essentially making such transactions almost nonspendable
public void addFollowingAccountKeys(List<DeterministicKey> followingAccountKeys, int sigsRequiredToSpend)
Makes given account keys follow the account key of the active keychain. After that active keychain will be treated as married and you will be able to get P2SH addresses to receive coins to. Given sigsRequiredToSpend value specifies how many signatures required to spend transactions for this married keychain. This value should not exceed total number of keys involved (one followed key plus number of following keys), otherwise IllegalArgumentException will be thrown.
IMPORTANT: As of Bitcoin Core 0.9 all multisig transactions which require more than 3 public keys are non-standard and such spends won't be processed by peers with default settings, essentially making such transactions almost nonspendable
This method will throw an IllegalStateException, if active keychain is already married or already has leaf keys issued. In future this behaviour may be replaced with key rotation.
public void createAndActivateNewHDChain()
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 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
@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 boolean isMarried(DeterministicKeyChain keychain)
public boolean isMarried()
isMarried(DeterministicKeyChain)
called for the active keychainpublic 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()
@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, int sigsRequiredToSpend) throws UnreadableWalletException
UnreadableWalletException
public static KeyChainGroup fromProtobufEncrypted(NetworkParameters params, List<Protos.Key> keys, int sigsRequiredToSpend, KeyCrypter crypter) throws UnreadableWalletException
UnreadableWalletException
public DeterministicKeyChain upgradeToDeterministic(long keyRotationTimeSecs, @Nullable org.spongycastle.crypto.params.KeyParameter aesKey) throws DeterministicUpgradeRequiresPassword
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.public boolean isDeterministicUpgradeRequired()
public String toString(boolean includePrivateKeys)
public List<DeterministicKeyChain> getDeterministicKeyChains()
public int getSigsRequiredToSpend()
public int getCombinedKeyLookaheadEpochs()
Copyright © 2014. All rights reserved.