com.google.bitcoin.core
Class PeerGroup

java.lang.Object
  extended by com.google.common.util.concurrent.AbstractExecutionThreadService
      extended by com.google.bitcoin.core.PeerGroup
All Implemented Interfaces:
TransactionBroadcaster, com.google.common.util.concurrent.Service

public class PeerGroup
extends com.google.common.util.concurrent.AbstractExecutionThreadService
implements TransactionBroadcaster

Runs a set of connections to the P2P network, brings up connections to replace disconnected nodes and manages the interaction between them all. Most applications will want to use one of these.

PeerGroup tries to maintain a constant number of connections to a set of distinct peers. Each peer runs a network listener in its own thread. When a connection is lost, a new peer will be tried after a delay as long as the number of connections less than the maximum.

Connections are made to addresses from a provided list. When that list is exhausted, we start again from the head of the list.

The PeerGroup can broadcast a transaction to the currently connected set of peers. It can also handle download of the blockchain from peers, restarting the process when peers die.

PeerGroup implements the Service interface. This means before it will do anything, you must call the Service.start() method (which returns a future) or Service.startAndWait() method, which will block until peer discovery is completed and some outbound connections have been initiated (it will return before handshaking is done, however). You should call Service.stop() when finished. Note that not all methods of PeerGroup are safe to call from a UI thread as some may do network IO, but starting and stopping the service should be fine.


Nested Class Summary
static class PeerGroup.FilterRecalculateMode
           
 
Nested classes/interfaces inherited from interface com.google.common.util.concurrent.Service
com.google.common.util.concurrent.Service.Listener, com.google.common.util.concurrent.Service.State
 
Field Summary
static double DEFAULT_BLOOM_FILTER_FP_RATE
          A reasonable default for the bloom filter false positive rate on mainnet.
static int DEFAULT_CONNECT_TIMEOUT_MILLIS
          The default timeout between when a connection attempt begins and version message exchange completes
static long DEFAULT_PING_INTERVAL_MSEC
          How many milliseconds to wait after receiving a pong before sending another ping.
protected  ReentrantLock lock
           
static double MAX_FP_RATE_INCREASE
          Maximum increase in FP rate before forced refresh of the bloom filter
 
Constructor Summary
PeerGroup(NetworkParameters params)
          Creates a PeerGroup with the given parameters.
PeerGroup(NetworkParameters params, AbstractBlockChain chain)
          Creates a PeerGroup for the given network and chain.
PeerGroup(NetworkParameters params, AbstractBlockChain chain, ClientConnectionManager connectionManager)
          Creates a new PeerGroup allowing you to specify the ClientConnectionManager which is used to create new connections and keep track of existing ones.
 
Method Summary
 void addAddress(InetAddress address)
          Convenience method for addAddress(new PeerAddress(address, params.port));
 void addAddress(PeerAddress peerAddress)
          Add an address to the list of potential peers to connect to.
 void addEventListener(PeerEventListener listener)
          Same as addEventListener(PeerEventListener, java.util.concurrent.Executor) but defaults to running on the user thread.
 void addEventListener(PeerEventListener listener, Executor executor)
          Adds a listener that will be notified on the given executor when:
 void addPeerDiscovery(PeerDiscovery peerDiscovery)
          Add addresses from a discovery source to the list of potential peers to connect to.
 void addPeerFilterProvider(PeerFilterProvider provider)
          Link the given PeerFilterProvider to this PeerGroup.
 void addWallet(Wallet wallet)
          Link the given wallet to this PeerGroup.
 com.google.common.util.concurrent.ListenableFuture<Transaction> broadcastTransaction(Transaction tx)
          Calls broadcastTransaction(Transaction,int) with getMinBroadcastConnections() as the number of connections to wait for before commencing broadcast.
 com.google.common.util.concurrent.ListenableFuture<Transaction> broadcastTransaction(Transaction tx, int minConnections)
          Given a transaction, sends it un-announced to one peer and then waits for it to be received back from other peers.
 void clearEventListeners()
          Removes all event listeners simultaneously.
 Peer connectTo(InetSocketAddress address)
          Connect to a peer by creating a channel to the destination address.
protected  Peer connectTo(PeerAddress address, boolean incrementMaxConnections)
           
protected  void connectToAnyPeer()
          Picks a peer from discovery and connects to it.
protected  void discoverPeers()
           
 void downloadBlockChain()
          Download the blockchain from peers.
 List<Peer> getConnectedPeers()
          Returns a newly allocated list containing the currently connected peers.
 Peer getDownloadPeer()
          Returns the currently selected download peer.
 long getFastCatchupTimeSecs()
          Returns the current fast catchup time.
 int getMaxConnections()
          The maximum number of connections that we will create to peers.
 MemoryPool getMemoryPool()
          Returns the MemoryPool created by this peer group to synchronize its peers.
 int getMinBroadcastConnections()
          Returns the number of connections that are required before transactions will be broadcast.
 int getMinRequiredProtocolVersion()
          The minimum protocol version required: defaults to the version required for Bloom filtering.
 int getMostCommonChainHeight()
          Returns our peers most commonly reported chain height.
static int getMostCommonChainHeight(List<Peer> peers)
          Returns most commonly reported chain height from the given list of Peers.
 List<Peer> getPendingPeers()
          Returns a list containing Peers that did not complete connection yet.
 long getPingIntervalMsec()
          Returns the period between pings for an individual peer.
 VersionMessage getVersionMessage()
          Returns the version message provided by setVersionMessage or a default if none was given.
protected  void handleNewPeer(Peer peer)
           
protected  void handlePeerDeath(Peer peer)
           
 int numConnectedPeers()
          Returns the number of currently connected peers.
 void recalculateFastCatchupAndFilter(PeerGroup.FilterRecalculateMode mode)
          Recalculates the bloom filter given to peers as well as the timestamp after which full blocks are downloaded (instead of only headers).
 boolean removeEventListener(PeerEventListener listener)
          The given event listener will no longer be called with events.
 void removeWallet(Wallet wallet)
          Unlinks the given wallet so it no longer receives broadcast transactions or has its transactions announced.
protected  void run()
           
protected  Peer selectDownloadPeer(List<Peer> peers)
          Given a list of Peers, return a Peer to be used as the download peer.
 void setBloomFilterFalsePositiveRate(double bloomFilterFPRate)
          Sets the false positive rate of bloom filters given to peers.
 void setConnectTimeoutMillis(int connectTimeoutMillis)
          Sets the timeout between when a connection attempt to a peer begins and when the version message exchange completes.
 void setFastCatchupTimeSecs(long secondsSinceEpoch)
          Tells the PeerGroup to download only block headers before a certain time and bodies after that.
 void setMaxConnections(int maxConnections)
          Adjusts the desired number of connections that we will create to peers.
 void setMinBroadcastConnections(int value)
          See getMinBroadcastConnections().
 void setMinRequiredProtocolVersion(int minRequiredProtocolVersion)
          If a peer is connected to that claims to speak a protocol version lower than the given version, it will be disconnected and another one will be tried instead.
 void setPingIntervalMsec(long pingIntervalMsec)
          Sets the period between pings for an individual peer.
 void setUserAgent(String name, String version)
          Sets information that identifies this software to remote nodes.
 void setUserAgent(String name, String version, String comments)
          Sets information that identifies this software to remote nodes.
 void setVersionMessage(VersionMessage ver)
          Sets the VersionMessage that will be announced on newly created connections.
protected  void shutDown()
           
 void startBlockChainDownload(PeerEventListener listener)
          Start downloading the blockchain from the first available peer.
protected  void startUp()
           
protected  void triggerShutdown()
           
 com.google.common.util.concurrent.ListenableFuture<PeerGroup> waitForPeers(int numPeers)
          Returns a future that is triggered when the number of connected peers is equal to the given number of connected peers.
 
Methods inherited from class com.google.common.util.concurrent.AbstractExecutionThreadService
addListener, executor, getServiceName, isRunning, start, startAndWait, state, stop, stopAndWait, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

lock

protected final ReentrantLock lock

DEFAULT_PING_INTERVAL_MSEC

public static final long DEFAULT_PING_INTERVAL_MSEC
How many milliseconds to wait after receiving a pong before sending another ping.

See Also:
Constant Field Values

DEFAULT_BLOOM_FILTER_FP_RATE

public static final double DEFAULT_BLOOM_FILTER_FP_RATE

A reasonable default for the bloom filter false positive rate on mainnet. FP rates are values between 0.0 and 1.0 where 1.0 is "all transactions" i.e. 100%.

Users for which low data usage is of utmost concern, 0.0001 may be better, for users to whom anonymity is of utmost concern, 0.001 (0.1%) should provide very good privacy.

See Also:
Constant Field Values

MAX_FP_RATE_INCREASE

public static final double MAX_FP_RATE_INCREASE
Maximum increase in FP rate before forced refresh of the bloom filter

See Also:
Constant Field Values

DEFAULT_CONNECT_TIMEOUT_MILLIS

public static final int DEFAULT_CONNECT_TIMEOUT_MILLIS
The default timeout between when a connection attempt begins and version message exchange completes

See Also:
Constant Field Values
Constructor Detail

PeerGroup

public PeerGroup(NetworkParameters params)
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.

Parameters:
params - Network parameters

PeerGroup

public PeerGroup(NetworkParameters params,
                 @Nullable
                 AbstractBlockChain chain)
Creates a PeerGroup for the given network and chain. Blocks will be passed to the chain as they are broadcast and downloaded. This is probably the constructor you want to use.


PeerGroup

public PeerGroup(NetworkParameters params,
                 @Nullable
                 AbstractBlockChain chain,
                 ClientConnectionManager connectionManager)
Creates a new PeerGroup allowing you to specify the ClientConnectionManager which is used to create new connections and keep track of existing ones.

Method Detail

setMaxConnections

public void setMaxConnections(int maxConnections)
Adjusts the desired number of connections that we will create to peers. Note that if there are already peers open and the new value is lower than the current number of peers, those connections will be terminated. Likewise if there aren't enough current connections to meet the new requested max size, some will be added.


getMaxConnections

public int getMaxConnections()
The maximum number of connections that we will create to peers.


setVersionMessage

public void setVersionMessage(VersionMessage ver)
Sets the VersionMessage that will be announced on newly created connections. A version message is primarily interesting because it lets you customize the "subVer" field which is used a bit like the User-Agent field from HTTP. It means your client tells the other side what it is, see BIP 14. The VersionMessage you provide is copied and the best chain height/time filled in for each new connection, therefore you don't have to worry about setting that. The provided object is really more of a template.


getVersionMessage

public VersionMessage getVersionMessage()
Returns the version message provided by setVersionMessage or a default if none was given.


setUserAgent

public void setUserAgent(String name,
                         String version,
                         @Nullable
                         String comments)
Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating a new VersionMessage, calling VersionMessage.appendToSubVer(String, String, String) on it, and then calling setVersionMessage(VersionMessage) on the result of that. See the docs for VersionMessage.appendToSubVer(String, String, String) for information on what the fields should contain.


setUserAgent

public void setUserAgent(String name,
                         String version)
Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating a new VersionMessage, calling VersionMessage.appendToSubVer(String, String, String) on it, and then calling setVersionMessage(VersionMessage) on the result of that. See the docs for VersionMessage.appendToSubVer(String, String, String) for information on what the fields should contain.


addEventListener

public void addEventListener(PeerEventListener listener,
                             Executor executor)

Adds a listener that will be notified on the given executor when:

  1. New peers are connected to.
  2. Peers are disconnected from.
  3. A message is received by the download peer (there is always one peer which is elected as a peer which will be used to retrieve data).
  4. Blocks are downloaded by the download peer.


addEventListener

public void addEventListener(PeerEventListener listener)
Same as addEventListener(PeerEventListener, java.util.concurrent.Executor) but defaults to running on the user thread.


removeEventListener

public boolean removeEventListener(PeerEventListener listener)
The given event listener will no longer be called with events.


clearEventListeners

public void clearEventListeners()
Removes all event listeners simultaneously. Note that this includes listeners added internally by the framework so it's generally not advised to use this - it exists for special purposes only.


getConnectedPeers

public List<Peer> getConnectedPeers()
Returns a newly allocated list containing the currently connected peers. If all you care about is the count, use numConnectedPeers().


getPendingPeers

public List<Peer> getPendingPeers()
Returns a list containing Peers that did not complete connection yet.


addAddress

public void addAddress(PeerAddress peerAddress)
Add an address to the list of potential peers to connect to. It won't necessarily be used unless there's a need to build new connections to reach the max connection count.

Parameters:
peerAddress - IP/port to use.

addAddress

public void addAddress(InetAddress address)
Convenience method for addAddress(new PeerAddress(address, params.port));


addPeerDiscovery

public void addPeerDiscovery(PeerDiscovery peerDiscovery)
Add addresses from a discovery source to the list of potential peers to connect to. If max connections has not been configured, or set to zero, then it's set to the default at this point.


discoverPeers

protected void discoverPeers()
                      throws PeerDiscoveryException
Throws:
PeerDiscoveryException

run

protected void run()
            throws Exception
Specified by:
run in class com.google.common.util.concurrent.AbstractExecutionThreadService
Throws:
Exception

connectToAnyPeer

protected void connectToAnyPeer()
                         throws PeerDiscoveryException
Picks a peer from discovery and connects to it. If connection fails, picks another and tries again.

Throws:
PeerDiscoveryException

startUp

protected void startUp()
                throws Exception
Overrides:
startUp in class com.google.common.util.concurrent.AbstractExecutionThreadService
Throws:
Exception

shutDown

protected void shutDown()
                 throws Exception
Overrides:
shutDown in class com.google.common.util.concurrent.AbstractExecutionThreadService
Throws:
Exception

triggerShutdown

protected void triggerShutdown()
Overrides:
triggerShutdown in class com.google.common.util.concurrent.AbstractExecutionThreadService

addWallet

public void addWallet(Wallet wallet)

Link the given wallet to this PeerGroup. This is used for three purposes:

  1. So the wallet receives broadcast transactions.
  2. Announcing pending transactions that didn't get into the chain yet to our peers.
  3. Set the fast catchup time using setFastCatchupTimeSecs(long), to optimize chain download.

Note that this should be done before chain download commences because if you add a wallet with keys earlier than the current chain head, the relevant parts of the chain won't be redownloaded for you.

The Wallet will have an event listener registered on it, so to avoid leaks remember to use removeWallet(Wallet) on it if you wish to keep the Wallet but lose the PeerGroup.


addPeerFilterProvider

public void addPeerFilterProvider(PeerFilterProvider provider)

Link the given PeerFilterProvider to this PeerGroup. DO NOT use this for Wallets, use addWallet(Wallet) instead.

Note that this should be done before chain download commences because if you add a listener with keys earlier than the current chain head, the relevant parts of the chain won't be redownloaded for you.


removeWallet

public void removeWallet(Wallet wallet)
Unlinks the given wallet so it no longer receives broadcast transactions or has its transactions announced.


recalculateFastCatchupAndFilter

public void recalculateFastCatchupAndFilter(PeerGroup.FilterRecalculateMode mode)
Recalculates the bloom filter given to peers as well as the timestamp after which full blocks are downloaded (instead of only headers).

Parameters:
mode - In what situations to send the filter to connected peers.

setBloomFilterFalsePositiveRate

public void setBloomFilterFalsePositiveRate(double bloomFilterFPRate)

Sets the false positive rate of bloom filters given to peers. The default is DEFAULT_BLOOM_FILTER_FP_RATE.

Be careful regenerating the bloom filter too often, as it decreases anonymity because remote nodes can compare transactions against both the new and old filters to significantly decrease the false positive rate.

See the docs for BloomFilter.BloomFilter(int, double, long, BloomFilter.BloomUpdate) for a brief explanation of anonymity when using bloom filters.


numConnectedPeers

public int numConnectedPeers()
Returns the number of currently connected peers. To be informed when this count changes, register a PeerEventListener and use the onPeerConnected/onPeerDisconnected methods.


connectTo

@Nullable
public Peer connectTo(InetSocketAddress address)
Connect to a peer by creating a channel to the destination address. This should not be used normally - let the PeerGroup manage connections through AbstractExecutionThreadService.start()

Parameters:
address - destination IP and port.
Returns:
The newly created Peer object or null if the peer could not be connected. Use Peer.getConnectionOpenFuture() if you want a future which completes when the connection is open.

connectTo

@Nullable
protected Peer connectTo(PeerAddress address,
                                  boolean incrementMaxConnections)

setConnectTimeoutMillis

public void setConnectTimeoutMillis(int connectTimeoutMillis)
Sets the timeout between when a connection attempt to a peer begins and when the version message exchange completes. This does not apply to currently pending peers.


startBlockChainDownload

public void startBlockChainDownload(PeerEventListener listener)

Start downloading the blockchain from the first available peer.

If no peers are currently connected, the download will be started once a peer starts. If the peer dies, the download will resume with another peer.

Parameters:
listener - a listener for chain download events, may not be null

downloadBlockChain

public void downloadBlockChain()
Download the blockchain from peers. Convenience that uses a DownloadListener for you.

This method waits until the download is complete. "Complete" is defined as downloading from at least one peer all the blocks that are in that peer's inventory.


handleNewPeer

protected void handleNewPeer(Peer peer)

getMemoryPool

public MemoryPool getMemoryPool()
Returns the MemoryPool created by this peer group to synchronize its peers. The pool tracks advertised and downloaded transactions so their confidence can be measured as a proportion of how many peers announced it. With an un-tampered with internet connection, the more peers announce a transaction the more confidence you can have that it's really valid.


setFastCatchupTimeSecs

public void setFastCatchupTimeSecs(long secondsSinceEpoch)
Tells the PeerGroup to download only block headers before a certain time and bodies after that. Call this before starting block chain download. Do not use a time > NOW - 1 block, as it will break some block download logic.


getFastCatchupTimeSecs

public long getFastCatchupTimeSecs()
Returns the current fast catchup time. The contents of blocks before this time won't be downloaded as they cannot contain any interesting transactions. If you use addWallet(Wallet) this just returns the min of the wallets earliest key times.

Returns:
a time in seconds since the epoch

handlePeerDeath

protected void handlePeerDeath(Peer peer)

waitForPeers

public com.google.common.util.concurrent.ListenableFuture<PeerGroup> waitForPeers(int numPeers)
Returns a future that is triggered when the number of connected peers is equal to the given number of connected peers. By using this with getMaxConnections() you can wait until the network is fully online. To block immediately, just call get() on the result.

Parameters:
numPeers - How many peers to wait for.
Returns:
a future that will be triggered when the number of connected peers >= numPeers

getMinBroadcastConnections

public int getMinBroadcastConnections()
Returns the number of connections that are required before transactions will be broadcast. If there aren't enough, broadcastTransaction(Transaction) will wait until the minimum number is reached so propagation across the network can be observed. If no value has been set using setMinBroadcastConnections(int) a default of half of whatever getMaxConnections() returns is used.


setMinBroadcastConnections

public void setMinBroadcastConnections(int value)
See getMinBroadcastConnections().


broadcastTransaction

public com.google.common.util.concurrent.ListenableFuture<Transaction> broadcastTransaction(Transaction tx)
Calls broadcastTransaction(Transaction,int) with getMinBroadcastConnections() as the number of connections to wait for before commencing broadcast.

Specified by:
broadcastTransaction in interface TransactionBroadcaster

broadcastTransaction

public com.google.common.util.concurrent.ListenableFuture<Transaction> broadcastTransaction(Transaction tx,
                                                                                            int minConnections)

Given a transaction, sends it un-announced to one peer and then waits for it to be received back from other peers. Once all connected peers have announced the transaction, the future will be completed. If anything goes wrong the exception will be thrown when get() is called, or you can receive it via a callback on the ListenableFuture. This method returns immediately, so if you want it to block just call get() on the result.

Note that if the PeerGroup is limited to only one connection (discovery is not activated) then the future will complete as soon as the transaction was successfully written to that peer.

Other than for sending your own transactions, this method is useful if you have received a transaction from someone and want to know that it's valid. It's a bit of a weird hack because the current version of the Bitcoin protocol does not inform you if you send an invalid transaction. Because sending bad transactions counts towards your DoS limit, be careful with relaying lots of unknown transactions. Otherwise you might get kicked off the network.

The transaction won't be sent until there are at least minConnections active connections available. A good choice for proportion would be between 0.5 and 0.8 but if you want faster transmission during initial bringup of the peer group you can lower it.


getPingIntervalMsec

public long getPingIntervalMsec()
Returns the period between pings for an individual peer. Setting this lower means more accurate and timely ping times are available via Peer.getLastPingTime() but it increases load on the remote node. It defaults to 5000.


setPingIntervalMsec

public void setPingIntervalMsec(long pingIntervalMsec)
Sets the period between pings for an individual peer. Setting this lower means more accurate and timely ping times are available via Peer.getLastPingTime() but it increases load on the remote node. It defaults to DEFAULT_PING_INTERVAL_MSEC. Setting the value to be <= 0 disables pinging entirely, although you can still request one yourself using Peer.ping().


setMinRequiredProtocolVersion

public void setMinRequiredProtocolVersion(int minRequiredProtocolVersion)
If a peer is connected to that claims to speak a protocol version lower than the given version, it will be disconnected and another one will be tried instead.


getMinRequiredProtocolVersion

public int getMinRequiredProtocolVersion()
The minimum protocol version required: defaults to the version required for Bloom filtering.


getMostCommonChainHeight

public int getMostCommonChainHeight()
Returns our peers most commonly reported chain height. If multiple heights are tied, the highest is returned. If no peers are connected, returns zero.


getMostCommonChainHeight

public static int getMostCommonChainHeight(List<Peer> peers)
Returns most commonly reported chain height from the given list of Peers. If multiple heights are tied, the highest is returned. If no peers are connected, returns zero.


selectDownloadPeer

@Nullable
protected Peer selectDownloadPeer(List<Peer> peers)
Given a list of Peers, return a Peer to be used as the download peer. If you don't want PeerGroup to manage download peer statuses for you, just override this and always return null.


getDownloadPeer

public Peer getDownloadPeer()
Returns the currently selected download peer. Bear in mind that it may have changed as soon as this method returns. Can return null if no peer was selected.



Copyright © 2014. All rights reserved.