From 4c1212750112eb9296f71f89cd2e8502c829960d Mon Sep 17 00:00:00 2001
From: Mike Hearn
Date: Sun, 5 Apr 2015 19:52:58 +0200
Subject: [PATCH] Context: add c'tors that take a context to
[Abstract/FullPruned/]BlockChain and PeerGroup. The existing c'tors now do a
consistency check against the existing context or create a new one on the
fly.
---
.../org/bitcoinj/core/AbstractBlockChain.java | 9 ++-
.../java/org/bitcoinj/core/BlockChain.java | 29 ++++++---
.../bitcoinj/core/FullPrunedBlockChain.java | 40 ++++++++----
.../java/org/bitcoinj/core/PeerGroup.java | 61 ++++++++++++-------
.../main/java/org/bitcoinj/core/Wallet.java | 2 +-
.../AbstractFullPrunedBlockChainTest.java | 3 +-
.../org/bitcoinj/core/BlockChainTest.java | 2 +-
7 files changed, 98 insertions(+), 48 deletions(-)
diff --git a/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java b/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java
index 176df42d..2cd928b5 100644
--- a/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java
+++ b/core/src/main/java/org/bitcoinj/core/AbstractBlockChain.java
@@ -137,16 +137,21 @@ public abstract class AbstractBlockChain {
private double falsePositiveTrend;
private double previousFalsePositiveRate;
+ /** See {@link #AbstractBlockChain(Context, List, BlockStore)} */
+ public AbstractBlockChain(NetworkParameters params, List listeners,
+ BlockStore blockStore) throws BlockStoreException {
+ this(Context.getOrCreate(params), listeners, blockStore);
+ }
/**
* Constructs a BlockChain connected to the given list of listeners (eg, wallets) and a store.
*/
- public AbstractBlockChain(NetworkParameters params, List listeners,
+ public AbstractBlockChain(Context context, List listeners,
BlockStore blockStore) throws BlockStoreException {
this.blockStore = blockStore;
chainHead = blockStore.getChainHead();
log.info("chain head is at height {}:\n{}", chainHead.getHeight(), chainHead.getHeader());
- this.params = params;
+ this.params = context.getParams();
this.listeners = new CopyOnWriteArrayList>();
for (BlockChainListener l : listeners) addListener(l, Threading.SAME_THREAD);
}
diff --git a/core/src/main/java/org/bitcoinj/core/BlockChain.java b/core/src/main/java/org/bitcoinj/core/BlockChain.java
index 00df286e..8db28b1b 100644
--- a/core/src/main/java/org/bitcoinj/core/BlockChain.java
+++ b/core/src/main/java/org/bitcoinj/core/BlockChain.java
@@ -25,11 +25,12 @@ import org.bitcoinj.store.BlockStoreException;
import java.util.ArrayList;
import java.util.List;
+// TODO: Rename this class to SPVBlockChain at some point.
+
/**
- * A BlockChain implements the simplified payment verification mode of the Bitcoin protocol. It is the right
+ * A BlockChain implements the simplified payment verification mode of the Bitcoin protocol. It is the right
* choice to use for programs that have limited resources as it won't verify transactions signatures or attempt to store
* all of the block chain. Really, this class should be called SPVBlockChain but for backwards compatibility it is not.
- *
*/
public class BlockChain extends AbstractBlockChain {
/** Keeps a map of block hashes to StoredBlocks. */
@@ -44,17 +45,25 @@ public class BlockChain extends AbstractBlockChain {
* {@link org.bitcoinj.store.MemoryBlockStore} if you want to hold all headers in RAM and don't care about
* disk serialization (this is rare).
*/
+ public BlockChain(Context context, Wallet wallet, BlockStore blockStore) throws BlockStoreException {
+ this(context, new ArrayList(), blockStore);
+ addWallet(wallet);
+ }
+
+ /** See {@link #BlockChain(Context, Wallet, BlockStore)}} */
public BlockChain(NetworkParameters params, Wallet wallet, BlockStore blockStore) throws BlockStoreException {
- this(params, new ArrayList(), blockStore);
- Context.getOrCreate(params);
- if (wallet != null)
- addWallet(wallet);
+ this(Context.getOrCreate(params), wallet, blockStore);
}
/**
* Constructs a BlockChain that has no wallet at all. This is helpful when you don't actually care about sending
* and receiving coins but rather, just want to explore the network data structures.
*/
+ public BlockChain(Context context, BlockStore blockStore) throws BlockStoreException {
+ this(context, new ArrayList(), blockStore);
+ }
+
+ /** See {@link #BlockChain(Context, BlockStore)} */
public BlockChain(NetworkParameters params, BlockStore blockStore) throws BlockStoreException {
this(params, new ArrayList(), blockStore);
}
@@ -62,12 +71,16 @@ public class BlockChain extends AbstractBlockChain {
/**
* Constructs a BlockChain connected to the given list of listeners and a store.
*/
- public BlockChain(NetworkParameters params, List wallets,
- BlockStore blockStore) throws BlockStoreException {
+ public BlockChain(Context params, List wallets, BlockStore blockStore) throws BlockStoreException {
super(params, wallets, blockStore);
this.blockStore = blockStore;
}
+ /** See {@link #BlockChain(Context, List, BlockStore)} */
+ public BlockChain(NetworkParameters params, List wallets, BlockStore blockStore) throws BlockStoreException {
+ this(Context.getOrCreate(params), wallets, blockStore);
+ }
+
@Override
protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block blockHeader, TransactionOutputChanges txOutChanges)
throws BlockStoreException, VerificationException {
diff --git a/core/src/main/java/org/bitcoinj/core/FullPrunedBlockChain.java b/core/src/main/java/org/bitcoinj/core/FullPrunedBlockChain.java
index 93625b61..23ddb120 100644
--- a/core/src/main/java/org/bitcoinj/core/FullPrunedBlockChain.java
+++ b/core/src/main/java/org/bitcoinj/core/FullPrunedBlockChain.java
@@ -54,34 +54,48 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
private boolean runScripts = true;
/**
- * Constructs a BlockChain connected to the given wallet and store. To obtain a {@link Wallet} you can construct
+ * Constructs a block chain connected to the given wallet and store. To obtain a {@link Wallet} you can construct
+ * one from scratch, or you can deserialize a saved wallet from disk using {@link Wallet#loadFromFile(java.io.File)}
+ */
+ public FullPrunedBlockChain(Context context, Wallet wallet, FullPrunedBlockStore blockStore) throws BlockStoreException {
+ this(context, new ArrayList(), blockStore);
+ addWallet(wallet);
+ }
+
+ /**
+ * Constructs a block chain connected to the given wallet and store. To obtain a {@link Wallet} you can construct
* one from scratch, or you can deserialize a saved wallet from disk using {@link Wallet#loadFromFile(java.io.File)}
*/
public FullPrunedBlockChain(NetworkParameters params, Wallet wallet, FullPrunedBlockStore blockStore) throws BlockStoreException {
- this(params, new ArrayList(), blockStore);
- if (wallet != null)
- addWallet(wallet);
+ this(Context.getOrCreate(params), wallet, blockStore);
}
- /**
- * Constructs a BlockChain that has no wallet at all. This is helpful when you don't actually care about sending
- * and receiving coins but rather, just want to explore the network data structures.
- */
+ /** Constructs a block chain connected to the given store. */
+ public FullPrunedBlockChain(Context context, FullPrunedBlockStore blockStore) throws BlockStoreException {
+ this(context, new ArrayList(), blockStore);
+ }
+
+ /** See {@link #FullPrunedBlockChain(Context, Wallet, FullPrunedBlockStore)} */
public FullPrunedBlockChain(NetworkParameters params, FullPrunedBlockStore blockStore) throws BlockStoreException {
- this(params, new ArrayList(), blockStore);
+ this(Context.getOrCreate(params), blockStore);
}
/**
- * Constructs a BlockChain connected to the given list of wallets and a store.
+ * Constructs a block chain connected to the given list of wallets and a store.
*/
- public FullPrunedBlockChain(NetworkParameters params, List listeners,
- FullPrunedBlockStore blockStore) throws BlockStoreException {
- super(params, listeners, blockStore);
+ public FullPrunedBlockChain(Context context, List listeners, FullPrunedBlockStore blockStore) throws BlockStoreException {
+ super(context, listeners, blockStore);
this.blockStore = blockStore;
// Ignore upgrading for now
this.chainHead = blockStore.getVerifiedChainHead();
}
+ /** See {@link #FullPrunedBlockChain(Context, List, FullPrunedBlockStore)} */
+ public FullPrunedBlockChain(NetworkParameters params, List listeners,
+ FullPrunedBlockStore blockStore) throws BlockStoreException {
+ this(Context.getOrCreate(params), listeners, blockStore);
+ }
+
@Override
protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block header, TransactionOutputChanges txOutChanges)
throws BlockStoreException, VerificationException {
diff --git a/core/src/main/java/org/bitcoinj/core/PeerGroup.java b/core/src/main/java/org/bitcoinj/core/PeerGroup.java
index 4e16e725..757439a9 100644
--- a/core/src/main/java/org/bitcoinj/core/PeerGroup.java
+++ b/core/src/main/java/org/bitcoinj/core/PeerGroup.java
@@ -249,24 +249,36 @@ public class PeerGroup implements TransactionBroadcaster {
/** Whether bloom filter support is enabled when using a non FullPrunedBlockchain*/
private volatile boolean vBloomFilteringEnabled = true;
- /**
- * Creates a PeerGroup with the given parameters. No chain is provided so this node will report its chain height
- * as zero to other peers. This constructor is useful if you just want to explore the network but aren't interested
- * in downloading block data.
- *
- * @param params Network parameters
- */
-
+ /** See {@link #PeerGroup(Context)} */
public PeerGroup(NetworkParameters params) {
this(params, null);
}
/**
- * Creates a PeerGroup for the given network and chain. Blocks will be passed to the chain as they are broadcast
+ * Creates a PeerGroup with the given context. No chain is provided so this node will report its chain height
+ * as zero to other peers. This constructor is useful if you just want to explore the network but aren't interested
+ * in downloading block data.
+ */
+ public PeerGroup(Context context) {
+ this(context, null);
+ }
+
+ /** See {@link #PeerGroup(Context, AbstractBlockChain)} */
+ public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain) {
+ this(Context.getOrCreate(params), chain, new NioClientManager());
+ }
+
+ /**
+ * Creates a PeerGroup for the given context and chain. Blocks will be passed to the chain as they are broadcast
* and downloaded. This is probably the constructor you want to use.
*/
- public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain) {
- this(params, chain, new NioClientManager());
+ public PeerGroup(Context context, @Nullable AbstractBlockChain chain) {
+ this(context, chain, new NioClientManager());
+ }
+
+ /** See {@link #newWithTor(Context, AbstractBlockChain, TorClient)} */
+ public static PeerGroup newWithTor(NetworkParameters params, @Nullable AbstractBlockChain chain, TorClient torClient) throws TimeoutException {
+ return newWithTor(Context.getOrCreate(params), chain, torClient);
}
/**
@@ -283,33 +295,38 @@ public class PeerGroup implements TransactionBroadcaster {
*
* @throws java.util.concurrent.TimeoutException if Tor fails to start within 20 seconds.
*/
- public static PeerGroup newWithTor(NetworkParameters params, @Nullable AbstractBlockChain chain, TorClient torClient) throws TimeoutException {
+ public static PeerGroup newWithTor(Context context, @Nullable AbstractBlockChain chain, TorClient torClient) throws TimeoutException {
checkNotNull(torClient);
DRMWorkaround.maybeDisableExportControls();
BlockingClientManager manager = new BlockingClientManager(torClient.getSocketFactory());
final int CONNECT_TIMEOUT_MSEC = TOR_TIMEOUT_SECONDS * 1000;
manager.setConnectTimeoutMillis(CONNECT_TIMEOUT_MSEC);
- PeerGroup result = new PeerGroup(params, chain, manager, torClient);
+ PeerGroup result = new PeerGroup(context, chain, manager, torClient);
result.setConnectTimeoutMillis(CONNECT_TIMEOUT_MSEC);
- result.addPeerDiscovery(new TorDiscovery(params, torClient));
+ result.addPeerDiscovery(new TorDiscovery(context.getParams(), torClient));
return result;
}
- /**
- * Creates a new PeerGroup allowing you to specify the {@link ClientConnectionManager} which is used to create new
- * connections and keep track of existing ones.
- */
+ /** See {@link #PeerGroup(Context, AbstractBlockChain, ClientConnectionManager)} */
public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager) {
- this(params, chain, connectionManager, null);
+ this(Context.getOrCreate(params), chain, connectionManager, null);
}
/**
* Creates a new PeerGroup allowing you to specify the {@link ClientConnectionManager} which is used to create new
* connections and keep track of existing ones.
*/
- private PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager, @Nullable TorClient torClient) {
- this.params = checkNotNull(params);
- this.context = Context.getOrCreate(params);
+ public PeerGroup(Context context, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager) {
+ this(context, chain, connectionManager, null);
+ }
+
+ /**
+ * Creates a new PeerGroup allowing you to specify the {@link ClientConnectionManager} which is used to create new
+ * connections and keep track of existing ones.
+ */
+ private PeerGroup(Context context, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager, @Nullable TorClient torClient) {
+ this.context = checkNotNull(context);
+ this.params = context.getParams();
this.chain = chain;
fastCatchupTimeSecs = params.getGenesisBlock().getTimeSeconds();
wallets = new CopyOnWriteArrayList();
diff --git a/core/src/main/java/org/bitcoinj/core/Wallet.java b/core/src/main/java/org/bitcoinj/core/Wallet.java
index 0ce0ef6c..0280df71 100644
--- a/core/src/main/java/org/bitcoinj/core/Wallet.java
+++ b/core/src/main/java/org/bitcoinj/core/Wallet.java
@@ -209,7 +209,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* {@link #loadFromFile}.
*/
public Wallet(NetworkParameters params) {
- this(params, new KeyChainGroup(params));
+ this(Context.getOrCreate(params));
}
/**
diff --git a/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java b/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java
index 32e8eaf4..26af981d 100644
--- a/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java
+++ b/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java
@@ -214,12 +214,13 @@ public abstract class AbstractFullPrunedBlockChainTest {
@Test
public void testFirst100KBlocks() throws Exception {
NetworkParameters params = MainNetParams.get();
+ Context context = new Context(params);
File blockFile = new File(getClass().getResource("first-100k-blocks.dat").getFile());
BlockFileLoader loader = new BlockFileLoader(params, Arrays.asList(blockFile));
store = createStore(params, 10);
resetStore(store);
- chain = new FullPrunedBlockChain(params, store);
+ chain = new FullPrunedBlockChain(context, store);
for (Block block : loader)
chain.add(block);
try {
diff --git a/core/src/test/java/org/bitcoinj/core/BlockChainTest.java b/core/src/test/java/org/bitcoinj/core/BlockChainTest.java
index e3834a31..8031de49 100644
--- a/core/src/test/java/org/bitcoinj/core/BlockChainTest.java
+++ b/core/src/test/java/org/bitcoinj/core/BlockChainTest.java
@@ -396,7 +396,7 @@ public class BlockChainTest {
@Test
public void estimatedBlockTime() throws Exception {
NetworkParameters params = MainNetParams.get();
- BlockChain prod = new BlockChain(params, new MemoryBlockStore(params));
+ BlockChain prod = new BlockChain(new Context(params), new MemoryBlockStore(params));
Date d = prod.estimateBlockTime(200000);
// The actual date of block 200,000 was 2012-09-22 10:47:00
assertEquals(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US).parse("2012-10-23T08:35:05.000-0700"), d);