A KeyChain that implements the simplest model possible: it can have keys imported into it, and just acts as a dumb bag of keys. It will, left to its own devices, always return the same key for usage by the wallet, although it will automatically add one to itself if it's empty or if encryptio
| 58 | * it will automatically add one to itself if it's empty or if encryption is requested. |
| 59 | */ |
| 60 | public class BasicKeyChain implements EncryptableKeyChain { |
| 61 | private final ReentrantLock lock = Threading.lock(BasicKeyChain.class); |
| 62 | |
| 63 | // Maps used to let us quickly look up a key given data we find in transactions or the block chain. |
| 64 | private final LinkedHashMap<ByteString, ECKey> hashToKeys; |
| 65 | private final LinkedHashMap<ByteString, ECKey> pubkeyToKeys; |
| 66 | @Nullable private final KeyCrypter keyCrypter; |
| 67 | private boolean isWatching; |
| 68 | |
| 69 | private final CopyOnWriteArrayList<ListenerRegistration<KeyChainEventListener>> listeners; |
| 70 | |
| 71 | public BasicKeyChain() { |
| 72 | this(null); |
| 73 | } |
| 74 | |
| 75 | public BasicKeyChain(@Nullable KeyCrypter crypter) { |
| 76 | this.keyCrypter = crypter; |
| 77 | hashToKeys = new LinkedHashMap<>(); |
| 78 | pubkeyToKeys = new LinkedHashMap<>(); |
| 79 | listeners = new CopyOnWriteArrayList<>(); |
| 80 | } |
| 81 | |
| 82 | /** Returns the {@link KeyCrypter} in use or null if the key chain is not encrypted. */ |
| 83 | @Override |
| 84 | @Nullable |
| 85 | public KeyCrypter getKeyCrypter() { |
| 86 | lock.lock(); |
| 87 | try { |
| 88 | return keyCrypter; |
| 89 | } finally { |
| 90 | lock.unlock(); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | @Override |
| 95 | public ECKey getKey(@Nullable KeyPurpose ignored) { |
| 96 | lock.lock(); |
| 97 | try { |
| 98 | if (hashToKeys.isEmpty()) { |
| 99 | checkState(keyCrypter == null); // We will refuse to encrypt an empty key chain. |
| 100 | final ECKey key = new ECKey(); |
| 101 | importKeyLocked(key); |
| 102 | queueOnKeysAdded(Collections.singletonList(key)); |
| 103 | } |
| 104 | return hashToKeys.values().iterator().next(); |
| 105 | } finally { |
| 106 | lock.unlock(); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | @Override |
| 111 | public List<ECKey> getKeys(@Nullable KeyPurpose purpose, int numberOfKeys) { |
| 112 | checkArgument(numberOfKeys > 0); |
| 113 | lock.lock(); |
| 114 | try { |
| 115 | if (hashToKeys.size() < numberOfKeys) { |
| 116 | checkState(keyCrypter == null); |
| 117 |