3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-13 10:45:51 +00:00

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.

This commit is contained in:
Mike Hearn 2015-04-05 19:52:58 +02:00
parent 960e58343e
commit 4c12127501
7 changed files with 98 additions and 48 deletions

View File

@ -137,16 +137,21 @@ public abstract class AbstractBlockChain {
private double falsePositiveTrend; private double falsePositiveTrend;
private double previousFalsePositiveRate; private double previousFalsePositiveRate;
/** See {@link #AbstractBlockChain(Context, List, BlockStore)} */
public AbstractBlockChain(NetworkParameters params, List<BlockChainListener> 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. * Constructs a BlockChain connected to the given list of listeners (eg, wallets) and a store.
*/ */
public AbstractBlockChain(NetworkParameters params, List<BlockChainListener> listeners, public AbstractBlockChain(Context context, List<BlockChainListener> listeners,
BlockStore blockStore) throws BlockStoreException { BlockStore blockStore) throws BlockStoreException {
this.blockStore = blockStore; this.blockStore = blockStore;
chainHead = blockStore.getChainHead(); chainHead = blockStore.getChainHead();
log.info("chain head is at height {}:\n{}", chainHead.getHeight(), chainHead.getHeader()); log.info("chain head is at height {}:\n{}", chainHead.getHeight(), chainHead.getHeader());
this.params = params; this.params = context.getParams();
this.listeners = new CopyOnWriteArrayList<ListenerRegistration<BlockChainListener>>(); this.listeners = new CopyOnWriteArrayList<ListenerRegistration<BlockChainListener>>();
for (BlockChainListener l : listeners) addListener(l, Threading.SAME_THREAD); for (BlockChainListener l : listeners) addListener(l, Threading.SAME_THREAD);
} }

View File

@ -25,11 +25,12 @@ import org.bitcoinj.store.BlockStoreException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
// TODO: Rename this class to SPVBlockChain at some point.
/** /**
* <p>A BlockChain implements the <i>simplified payment verification</i> mode of the Bitcoin protocol. It is the right * A BlockChain implements the <i>simplified payment verification</i> 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 * 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. * all of the block chain. Really, this class should be called SPVBlockChain but for backwards compatibility it is not.
* </p>
*/ */
public class BlockChain extends AbstractBlockChain { public class BlockChain extends AbstractBlockChain {
/** Keeps a map of block hashes to StoredBlocks. */ /** 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 * {@link org.bitcoinj.store.MemoryBlockStore} if you want to hold all headers in RAM and don't care about
* disk serialization (this is rare).</p> * disk serialization (this is rare).</p>
*/ */
public BlockChain(Context context, Wallet wallet, BlockStore blockStore) throws BlockStoreException {
this(context, new ArrayList<BlockChainListener>(), blockStore);
addWallet(wallet);
}
/** See {@link #BlockChain(Context, Wallet, BlockStore)}} */
public BlockChain(NetworkParameters params, Wallet wallet, BlockStore blockStore) throws BlockStoreException { public BlockChain(NetworkParameters params, Wallet wallet, BlockStore blockStore) throws BlockStoreException {
this(params, new ArrayList<BlockChainListener>(), blockStore); this(Context.getOrCreate(params), wallet, blockStore);
Context.getOrCreate(params);
if (wallet != null)
addWallet(wallet);
} }
/** /**
* Constructs a BlockChain that has no wallet at all. This is helpful when you don't actually care about sending * 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. * 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<BlockChainListener>(), blockStore);
}
/** See {@link #BlockChain(Context, BlockStore)} */
public BlockChain(NetworkParameters params, BlockStore blockStore) throws BlockStoreException { public BlockChain(NetworkParameters params, BlockStore blockStore) throws BlockStoreException {
this(params, new ArrayList<BlockChainListener>(), blockStore); this(params, new ArrayList<BlockChainListener>(), blockStore);
} }
@ -62,12 +71,16 @@ public class BlockChain extends AbstractBlockChain {
/** /**
* Constructs a BlockChain connected to the given list of listeners and a store. * Constructs a BlockChain connected to the given list of listeners and a store.
*/ */
public BlockChain(NetworkParameters params, List<BlockChainListener> wallets, public BlockChain(Context params, List<BlockChainListener> wallets, BlockStore blockStore) throws BlockStoreException {
BlockStore blockStore) throws BlockStoreException {
super(params, wallets, blockStore); super(params, wallets, blockStore);
this.blockStore = blockStore; this.blockStore = blockStore;
} }
/** See {@link #BlockChain(Context, List, BlockStore)} */
public BlockChain(NetworkParameters params, List<BlockChainListener> wallets, BlockStore blockStore) throws BlockStoreException {
this(Context.getOrCreate(params), wallets, blockStore);
}
@Override @Override
protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block blockHeader, TransactionOutputChanges txOutChanges) protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block blockHeader, TransactionOutputChanges txOutChanges)
throws BlockStoreException, VerificationException { throws BlockStoreException, VerificationException {

View File

@ -54,34 +54,48 @@ public class FullPrunedBlockChain extends AbstractBlockChain {
private boolean runScripts = true; 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<BlockChainListener>(), 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)} * 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 { public FullPrunedBlockChain(NetworkParameters params, Wallet wallet, FullPrunedBlockStore blockStore) throws BlockStoreException {
this(params, new ArrayList<BlockChainListener>(), blockStore); this(Context.getOrCreate(params), wallet, blockStore);
if (wallet != null)
addWallet(wallet);
} }
/** /** Constructs a block chain connected to the given store. */
* Constructs a BlockChain that has no wallet at all. This is helpful when you don't actually care about sending public FullPrunedBlockChain(Context context, FullPrunedBlockStore blockStore) throws BlockStoreException {
* and receiving coins but rather, just want to explore the network data structures. this(context, new ArrayList<BlockChainListener>(), blockStore);
*/ }
/** See {@link #FullPrunedBlockChain(Context, Wallet, FullPrunedBlockStore)} */
public FullPrunedBlockChain(NetworkParameters params, FullPrunedBlockStore blockStore) throws BlockStoreException { public FullPrunedBlockChain(NetworkParameters params, FullPrunedBlockStore blockStore) throws BlockStoreException {
this(params, new ArrayList<BlockChainListener>(), 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<BlockChainListener> listeners, public FullPrunedBlockChain(Context context, List<BlockChainListener> listeners, FullPrunedBlockStore blockStore) throws BlockStoreException {
FullPrunedBlockStore blockStore) throws BlockStoreException { super(context, listeners, blockStore);
super(params, listeners, blockStore);
this.blockStore = blockStore; this.blockStore = blockStore;
// Ignore upgrading for now // Ignore upgrading for now
this.chainHead = blockStore.getVerifiedChainHead(); this.chainHead = blockStore.getVerifiedChainHead();
} }
/** See {@link #FullPrunedBlockChain(Context, List, FullPrunedBlockStore)} */
public FullPrunedBlockChain(NetworkParameters params, List<BlockChainListener> listeners,
FullPrunedBlockStore blockStore) throws BlockStoreException {
this(Context.getOrCreate(params), listeners, blockStore);
}
@Override @Override
protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block header, TransactionOutputChanges txOutChanges) protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block header, TransactionOutputChanges txOutChanges)
throws BlockStoreException, VerificationException { throws BlockStoreException, VerificationException {

View File

@ -249,24 +249,36 @@ public class PeerGroup implements TransactionBroadcaster {
/** Whether bloom filter support is enabled when using a non FullPrunedBlockchain*/ /** Whether bloom filter support is enabled when using a non FullPrunedBlockchain*/
private volatile boolean vBloomFilteringEnabled = true; private volatile boolean vBloomFilteringEnabled = true;
/** /** See {@link #PeerGroup(Context)} */
* 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
*/
public PeerGroup(NetworkParameters params) { public PeerGroup(NetworkParameters params) {
this(params, null); 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. * and downloaded. This is probably the constructor you want to use.
*/ */
public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain) { public PeerGroup(Context context, @Nullable AbstractBlockChain chain) {
this(params, chain, new NioClientManager()); 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. * @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); checkNotNull(torClient);
DRMWorkaround.maybeDisableExportControls(); DRMWorkaround.maybeDisableExportControls();
BlockingClientManager manager = new BlockingClientManager(torClient.getSocketFactory()); BlockingClientManager manager = new BlockingClientManager(torClient.getSocketFactory());
final int CONNECT_TIMEOUT_MSEC = TOR_TIMEOUT_SECONDS * 1000; final int CONNECT_TIMEOUT_MSEC = TOR_TIMEOUT_SECONDS * 1000;
manager.setConnectTimeoutMillis(CONNECT_TIMEOUT_MSEC); 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.setConnectTimeoutMillis(CONNECT_TIMEOUT_MSEC);
result.addPeerDiscovery(new TorDiscovery(params, torClient)); result.addPeerDiscovery(new TorDiscovery(context.getParams(), torClient));
return result; return result;
} }
/** /** See {@link #PeerGroup(Context, AbstractBlockChain, ClientConnectionManager)} */
* Creates a new PeerGroup allowing you to specify the {@link ClientConnectionManager} which is used to create new
* connections and keep track of existing ones.
*/
public PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager) { 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 * Creates a new PeerGroup allowing you to specify the {@link ClientConnectionManager} which is used to create new
* connections and keep track of existing ones. * connections and keep track of existing ones.
*/ */
private PeerGroup(NetworkParameters params, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager, @Nullable TorClient torClient) { public PeerGroup(Context context, @Nullable AbstractBlockChain chain, ClientConnectionManager connectionManager) {
this.params = checkNotNull(params); this(context, chain, connectionManager, null);
this.context = Context.getOrCreate(params); }
/**
* 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; this.chain = chain;
fastCatchupTimeSecs = params.getGenesisBlock().getTimeSeconds(); fastCatchupTimeSecs = params.getGenesisBlock().getTimeSeconds();
wallets = new CopyOnWriteArrayList<Wallet>(); wallets = new CopyOnWriteArrayList<Wallet>();

View File

@ -209,7 +209,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha
* {@link #loadFromFile}. * {@link #loadFromFile}.
*/ */
public Wallet(NetworkParameters params) { public Wallet(NetworkParameters params) {
this(params, new KeyChainGroup(params)); this(Context.getOrCreate(params));
} }
/** /**

View File

@ -214,12 +214,13 @@ public abstract class AbstractFullPrunedBlockChainTest {
@Test @Test
public void testFirst100KBlocks() throws Exception { public void testFirst100KBlocks() throws Exception {
NetworkParameters params = MainNetParams.get(); NetworkParameters params = MainNetParams.get();
Context context = new Context(params);
File blockFile = new File(getClass().getResource("first-100k-blocks.dat").getFile()); File blockFile = new File(getClass().getResource("first-100k-blocks.dat").getFile());
BlockFileLoader loader = new BlockFileLoader(params, Arrays.asList(blockFile)); BlockFileLoader loader = new BlockFileLoader(params, Arrays.asList(blockFile));
store = createStore(params, 10); store = createStore(params, 10);
resetStore(store); resetStore(store);
chain = new FullPrunedBlockChain(params, store); chain = new FullPrunedBlockChain(context, store);
for (Block block : loader) for (Block block : loader)
chain.add(block); chain.add(block);
try { try {

View File

@ -396,7 +396,7 @@ public class BlockChainTest {
@Test @Test
public void estimatedBlockTime() throws Exception { public void estimatedBlockTime() throws Exception {
NetworkParameters params = MainNetParams.get(); 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); Date d = prod.estimateBlockTime(200000);
// The actual date of block 200,000 was 2012-09-22 10:47:00 // 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); assertEquals(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US).parse("2012-10-23T08:35:05.000-0700"), d);