All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.bitcoin.core.Wallet Maven / Gradle / Ivy

There is a newer version: 0.11.3
Show newest version
/**
 * Copyright 2013 Google Inc.
 * Copyright 2014 Andreas Schildbach
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.bitcoin.core;

import com.google.bitcoin.core.TransactionConfidence.ConfidenceType;
import com.google.bitcoin.crypto.KeyCrypter;
import com.google.bitcoin.crypto.KeyCrypterException;
import com.google.bitcoin.crypto.KeyCrypterScrypt;
import com.google.bitcoin.script.Script;
import com.google.bitcoin.script.ScriptBuilder;
import com.google.bitcoin.script.ScriptChunk;
import com.google.bitcoin.store.UnreadableWalletException;
import com.google.bitcoin.store.WalletProtobufSerializer;
import com.google.bitcoin.utils.ListenerRegistration;
import com.google.bitcoin.utils.Threading;
import com.google.bitcoin.wallet.*;
import com.google.bitcoin.wallet.WalletTransaction.Pool;
import com.google.common.collect.*;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import org.bitcoinj.wallet.Protos.Wallet.EncryptionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.crypto.params.KeyParameter;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import java.io.*;
import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

import static com.google.bitcoin.core.Utils.bitcoinValueToFriendlyString;
import static com.google.bitcoin.core.Utils.bitcoinValueToPlainString;
import static com.google.common.base.Preconditions.*;

// To do list:
//
// This whole class has evolved over a period of years and needs a ground-up rewrite.
//
// - Take all wallet-relevant data out of Transaction and put it into WalletTransaction. Make Transaction immutable.
// - Only store relevant transaction outputs, don't bother storing the rest of the data.
// - Split block chain and tx output tracking into a superclass that doesn't have any key or spending related code.
// - Simplify how transactions are tracked and stored: in particular, have the wallet maintain positioning information
//   for transactions independent of the transactions themselves, so the timeline can be walked without having to
//   process and sort every single transaction.
// - Decompose the class where possible: break logic out into classes that can be customized/replaced by the user.
//     - [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.
// - Make it scale:
//     - eliminate all the algorithms with quadratic complexity (or worse)
//     - don't require everything to be held in RAM at once
//     - consider allowing eviction of no longer re-orgable transactions or keys that were used up

/**
 * 

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 * of the Bitcoin protocol.

* *

To learn more about this class, read * working with the wallet.

* *

To fill up a Wallet with transactions, you need to use it in combination with a {@link BlockChain} and various * other objects, see the Getting started tutorial * on the website to learn more about how to set everything up.

* *

Wallets can be serialized using either Java serialization - this is not compatible across versions of bitcoinj, * or protocol buffer serialization. You need to save the wallet whenever it changes, there is an auto-save feature * that simplifies this for you although you're still responsible for manually triggering a save when your app is about * to quit because the auto-save feature waits a moment before actually committing to disk to avoid IO thrashing when * the wallet is changing very fast (eg due to a block chain sync). See * {@link Wallet#autosaveToFile(java.io.File, long, java.util.concurrent.TimeUnit, com.google.bitcoin.wallet.WalletFiles.Listener)} * for more information about this.

*/ public class Wallet implements Serializable, BlockChainListener, PeerFilterProvider { private static final Logger log = LoggerFactory.getLogger(Wallet.class); private static final long serialVersionUID = 2L; private static final int MINIMUM_BLOOM_DATA_LENGTH = 8; protected final ReentrantLock lock = Threading.lock("wallet"); // The various pools below give quick access to wallet-relevant transactions by the state they're in: // // Pending: Transactions that didn't make it into the best chain yet. Pending transactions can be killed if a // double-spend against them appears in the best chain, in which case they move to the dead pool. // If a double-spend appears in the pending state as well, currently we just ignore the second // and wait for the miners to resolve the race. // Unspent: Transactions that appeared in the best chain and have outputs we can spend. Note that we store the // entire transaction in memory even though for spending purposes we only really need the outputs, the // reason being that this simplifies handling of re-orgs. It would be worth fixing this in future. // Spent: Transactions that appeared in the best chain but don't have any spendable outputs. They're stored here // for history browsing/auditing reasons only and in future will probably be flushed out to some other // kind of cold storage or just removed. // Dead: Transactions that we believe will never confirm get moved here, out of pending. Note that the Satoshi // client has no notion of dead-ness: the assumption is that double spends won't happen so there's no // need to notify the user about them. We take a more pessimistic approach and try to track the fact that // transactions have been double spent so applications can do something intelligent (cancel orders, show // to the user in the UI, etc). A transaction can leave dead and move into spent/unspent if there is a // re-org to a chain that doesn't include the double spend. final Map pending; final Map unspent; final Map spent; final Map dead; // All transactions together. final Map transactions; // A list of public/private EC keys owned by this user. Access it using addKey[s], hasKey[s] and findPubKeyFromHash. private ArrayList keychain; // A list of scripts watched by this wallet. private Set