diff --git a/core/src/main/java/com/google/bitcoin/core/Wallet.java b/core/src/main/java/com/google/bitcoin/core/Wallet.java
index 99ac6244..ea983ef0 100644
--- a/core/src/main/java/com/google/bitcoin/core/Wallet.java
+++ b/core/src/main/java/com/google/bitcoin/core/Wallet.java
@@ -21,6 +21,7 @@ import com.google.bitcoin.core.WalletTransaction.Pool;
import com.google.bitcoin.store.WalletProtobufSerializer;
import com.google.bitcoin.utils.EventListenerInvoker;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,6 +36,17 @@ import java.util.concurrent.TimeUnit;
import static com.google.bitcoin.core.Utils.bitcoinValueToFriendlyString;
import static com.google.common.base.Preconditions.*;
+// To do list:
+//
+// - Make the keychain member protected and switch it to be a hashmap of some kind so key lookup ops are faster.
+// - Refactor how keys are managed to better handle things like deterministic wallets in future.
+// - Decompose the class where possible: break logic out into classes that can be customized/replaced by the user.
+// - Coin selection
+// - [Auto]saving to a backing store
+// - Key management
+// - just generally make Wallet smaller and easier to work with
+// - Make clearing of transactions able to only rewind the wallet a certain distance instead of all blocks.
+
/**
*
A Wallet stores keys and a record of transactions that send and receive value from those keys. Using these,
* it is able to create new transactions that spend the recorded transactions, and this is the fundamental operation
@@ -150,7 +162,7 @@ public class Wallet implements Serializable {
final Map dead;
/**
- * A list of public/private EC keys owned by this user.
+ * A list of public/private EC keys owned by this user. Access it using addKey[s], hasKey[s] and findPubKeyFromHash.
*/
public final ArrayList keychain;
@@ -1562,19 +1574,37 @@ public class Wallet implements Serializable {
* Adds the given ECKey to the wallet. There is currently no way to delete keys (that would result in coin loss).
* If {@link Wallet#autosaveToFile(java.io.File, long, java.util.concurrent.TimeUnit, com.google.bitcoin.core.Wallet.AutosaveEventListener)}
* has been called, triggers an auto save bypassing the normal coalescing delay and event handlers.
+ * If the key already exists in the wallet, does nothing and returns false.
*/
- public synchronized void addKey(final ECKey key) {
- checkArgument(!keychain.contains(key), "Key already present");
- keychain.add(key);
- EventListenerInvoker.invoke(eventListeners, new EventListenerInvoker() {
- @Override
- public void invoke(WalletEventListener listener) {
- listener.onKeyAdded(key);
- }
- });
+ public synchronized boolean addKey(final ECKey key) {
+ return addKeys(Lists.newArrayList(key)) == 1;
+ }
+
+ /**
+ * Adds the given keys to the wallet. There is currently no way to delete keys (that would result in coin loss).
+ * If {@link Wallet#autosaveToFile(java.io.File, long, java.util.concurrent.TimeUnit, com.google.bitcoin.core.Wallet.AutosaveEventListener)}
+ * has been called, triggers an auto save bypassing the normal coalescing delay and event handlers.
+ * Returns the number of keys added, after duplicates are ignored. The onKeyAdded event will be called for each key
+ * in the list that was not already present.
+ */
+ public synchronized int addKeys(final List keys) {
+ // TODO: Consider making keys a sorted list or hashset so membership testing is faster.
+ int added = 0;
+ for (final ECKey key : keys) {
+ if (keychain.contains(key)) continue;
+ keychain.add(key);
+ EventListenerInvoker.invoke(eventListeners, new EventListenerInvoker() {
+ @Override
+ public void invoke(WalletEventListener listener) {
+ listener.onKeyAdded(key);
+ }
+ });
+ added++;
+ }
if (autosaveToFile != null) {
autoSave();
}
+ return added;
}
/**
@@ -1590,6 +1620,11 @@ public class Wallet implements Serializable {
return null;
}
+ /** Returns true if the given key is in the wallet, false otherwise. Currently an O(N) operation. */
+ public boolean hasKey(ECKey key) {
+ return keychain.contains(key);
+ }
+
/**
* Returns true if this wallet contains a public key which hashes to the given hash.
*/