Class PeerGroup

  • All Implemented Interfaces:
    TransactionBroadcaster

    public class PeerGroup
    extends java.lang.Object
    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.

    A PeerGroup won't do anything until you call the start() 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 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.

    • Field Detail

      • lock

        protected final java.util.concurrent.locks.ReentrantLock lock
      • DEFAULT_CONNECTIONS

        public static final int DEFAULT_CONNECTIONS
        The default number of connections to the p2p network the library will try to build. This is set to 12 empirically. It used to be 4, but because we divide the connection pool in two for broadcasting transactions, that meant we were only sending transactions to two peers and sometimes this wasn't reliable enough: transactions wouldn't get through.
        See Also:
        Constant Field Values
      • executor

        protected final java.util.concurrent.ScheduledExecutorService executor
      • 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
      • MAX_ADDRESSES_PER_ADDR_MESSAGE

        public static final int MAX_ADDRESSES_PER_ADDR_MESSAGE
        See Also:
        Constant Field Values
      • DEFAULT_BLOOM_FILTER_FP_RATE

        public static final double DEFAULT_BLOOM_FILTER_FP_RATE
        The default Bloom filter false positive rate, which is selected to be extremely low such that you hardly ever download false positives. This provides maximum performance. Although this default can be overridden to push the FP rate higher, due to various complexities there are still ways a remote peer can deanonymize the users wallet. This is why the FP rate is chosen for performance rather than privacy. If a future version of bitcoinj fixes the known de-anonymization attacks this FP rate may rise again (or more likely, become expressed as a bandwidth allowance).
        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

        public static final java.time.Duration DEFAULT_CONNECT_TIMEOUT
        The default timeout between when a connection attempt begins and version message exchange completes
    • Constructor Detail

      • PeerGroup

        public PeerGroup​(Network network)
        Creates a PeerGroup for the given network. 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:
        network - the P2P network to connect to
      • PeerGroup

        @Deprecated
        public PeerGroup​(NetworkParameters params)
        Deprecated.
        Creates a PeerGroup with the given network. 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.
      • PeerGroup

        public PeerGroup​(Network network,
                         @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.
        Parameters:
        network - the P2P network to connect to
        chain - used to process blocks
      • PeerGroup

        protected PeerGroup​(Network network,
                            @Nullable
                            AbstractBlockChain chain,
                            ClientConnectionManager connectionManager)
        Create a PeerGroup for the given network, chain and connection manager.
        Parameters:
        network - the P2P network to connect to
        chain - used to process blocks
        connectionManager - used to create new connections and keep track of existing ones.
      • PeerGroup

        protected PeerGroup​(NetworkParameters params,
                            @Nullable
                            AbstractBlockChain chain,
                            ClientConnectionManager connectionManager)
        Create a PeerGroup for the given network, chain and connection manager.
        Parameters:
        params - the P2P network to connect to
        chain - used to process blocks
        connectionManager - used to create new connections and keep track of existing ones.
    • Method Detail

      • createPrivateExecutor

        protected java.util.concurrent.ScheduledExecutorService createPrivateExecutor()
      • setPeerDiscoveryTimeout

        public void setPeerDiscoveryTimeout​(java.time.Duration peerDiscoveryTimeout)
        This is how long we wait for peer discoveries to return their results.
      • setPeerDiscoveryTimeoutMillis

        @Deprecated
        public void setPeerDiscoveryTimeoutMillis​(long peerDiscoveryTimeoutMillis)
        This is how many milliseconds we wait for peer discoveries to return their results.
      • 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.
      • setDownloadTxDependencies

        public void setDownloadTxDependencies​(int depth)
        Configure download of pending transaction dependencies. A change of values only takes effect for newly connected peers.
      • 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.
      • addChainDownloadStartedEventListener

        public void addChainDownloadStartedEventListener​(java.util.concurrent.Executor executor,
                                                         ChainDownloadStartedEventListener listener)

        Adds a listener that will be notified on the given executor when chain download starts.

      • addConnectedEventListener

        public void addConnectedEventListener​(java.util.concurrent.Executor executor,
                                              PeerConnectedEventListener listener)

        Adds a listener that will be notified on the given executor when new peers are connected to.

      • addDisconnectedEventListener

        public void addDisconnectedEventListener​(java.util.concurrent.Executor executor,
                                                 PeerDisconnectedEventListener listener)

        Adds a listener that will be notified on the given executor when peers are disconnected from.

      • addDiscoveredEventListener

        public void addDiscoveredEventListener​(java.util.concurrent.Executor executor,
                                               PeerDiscoveredEventListener listener)

        Adds a listener that will be notified on the given executor when new peers are discovered.

      • removeConnectedEventListener

        public boolean removeConnectedEventListener​(PeerConnectedEventListener listener)
        The given event listener will no longer be called with events.
      • removeDisconnectedEventListener

        public boolean removeDisconnectedEventListener​(PeerDisconnectedEventListener listener)
        The given event listener will no longer be called with events.
      • removeDiscoveredEventListener

        public boolean removeDiscoveredEventListener​(PeerDiscoveredEventListener listener)
        The given event listener will no longer be called with events.
      • removeGetDataEventListener

        public boolean removeGetDataEventListener​(GetDataEventListener listener)
        The given event listener will no longer be called with events.
      • removeOnTransactionBroadcastListener

        public boolean removeOnTransactionBroadcastListener​(OnTransactionBroadcastListener listener)
        The given event listener will no longer be called with events.
      • getConnectedPeers

        public java.util.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 java.util.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​(PeerAddress peerAddress,
                               int priority)
        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.
        priority - for connecting and being picked as a download peer
      • setRequiredServices

        public void setRequiredServices​(long requiredServices)
        Convenience for connecting only to peers that can serve specific services. It will configure suitable peer discoveries.
        Parameters:
        requiredServices - Required services as a bitmask, e.g. VersionMessage.NODE_NETWORK.
      • addAddress

        public void addAddress​(java.net.InetAddress address)
        Convenience method for addAddress(PeerAddress).
      • setDiscoverPeersViaP2P

        public void setDiscoverPeersViaP2P​(boolean discoverPeersViaP2P)
        Setting this to true will add addresses discovered via P2P addr and addrv2 messages to the list of potential peers to connect to. This will automatically be set to true if at least one peer discovery is added via addPeerDiscovery(PeerDiscovery).
        Parameters:
        discoverPeersViaP2P - true if peers should be discovered from the P2P network
      • 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 int discoverPeers()
        Returns number of discovered peers.
      • startAsync

        public ListenableCompletableFuture<java.lang.Void> startAsync()
        Starts the PeerGroup and begins network activity.
        Returns:
        A future that completes when first connection activity has been triggered (note: not first connection made).
      • start

        public void start()
        Does a blocking startup.
      • stop

        public void stop()
        Does a blocking stop
      • dropAllPeers

        public void dropAllPeers()
        Gracefully drops all connected peers.
      • 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 ListenableCompletableFuture<BloomFilter> 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.

        This method invokes recalculateFastCatchupAndFilter(FilterRecalculateMode). The return value of this method is the ListenableCompletableFuture returned by that invocation.

        Returns:
        a future that completes once each Peer in this group has had its BloomFilter (re)set.
      • removeWallet

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

        public ListenableCompletableFuture<BloomFilter> 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). Note that calls made one after another may return the same future, if the request wasn't processed yet (i.e. calls are deduplicated).
        Parameters:
        mode - In what situations to send the filter to connected peers.
        Returns:
        a future that completes once the filter has been calculated (note: this does not mean acknowledged by remote 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(int, double, int, BloomFilter.BloomUpdate) for a brief explanation of anonymity when using bloom filters.

      • connectTo

        @Nullable
        public Peer connectTo​(java.net.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 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.
      • connectToLocalHost

        @Nullable
        public Peer connectToLocalHost()
        Helper for forcing a connection to localhost. Useful when using regtest mode. Returns the peer object.
      • connectTo

        @Nullable
        protected Peer connectTo​(PeerAddress address,
                                 boolean incrementMaxConnections,
                                 java.time.Duration connectTimeout)
        Creates a version message to send, constructs a Peer object and attempts to connect it. Returns the peer on success or null on failure.
        Parameters:
        address - Remote network address
        incrementMaxConnections - Whether to consider this connection an attempt to fill our quota, or something explicitly requested.
        connectTimeout - timeout for establishing the connection to peers
        Returns:
        Peer or null.
      • setConnectTimeout

        public void setConnectTimeout​(java.time.Duration connectTimeout)
        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.
        Parameters:
        connectTimeout - timeout for estiablishing the connection to peers
      • setConnectTimeoutMillis

        @Deprecated
        public void setConnectTimeoutMillis​(int connectTimeoutMillis)
      • startBlockChainDownload

        public void startBlockChainDownload​(BlockchainDownloadEventListener listener)

        Start downloading the blockchain.

        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 DownloadProgressTracker 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

        @Deprecated
        @Nullable
        public TxConfidenceTable getMemoryPool()
        Deprecated.
        Use "Context.get().getConfidenceTable()" instead
      • setFastCatchupTime

        public void setFastCatchupTime​(java.time.Instant fastCatchupTime)
        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.
      • setFastCatchupTimeSecs

        @Deprecated
        public void setFastCatchupTimeSecs​(long fastCatchupTimeSecs)
      • fastCatchupTime

        public java.time.Instant fastCatchupTime()
        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
      • getFastCatchupTimeSecs

        @Deprecated
        public long getFastCatchupTimeSecs()
        Deprecated.
      • handlePeerDeath

        protected void handlePeerDeath​(Peer peer,
                                       @Nullable
                                       java.lang.Throwable exception)
      • setStallThreshold

        public void setStallThreshold​(int periodSecs,
                                      int bytesPerSecond)
        Configures the stall speed: the speed at which a peer is considered to be serving us the block chain unacceptably slowly. Once a peer has served us data slower than the given data rate for the given number of seconds, it is considered stalled and will be disconnected, forcing the chain download to continue from a different peer. The defaults are chosen conservatively, but if you are running on a platform that is CPU constrained or on a very slow network e.g. EDGE, the default settings may need adjustment to avoid false stalls.
        Parameters:
        periodSecs - How many seconds the download speed must be below blocksPerSec, defaults to 10.
        bytesPerSecond - Download speed (only blocks/txns count) must be consistently below this for a stall, defaults to the bandwidth required for 10 block headers per second.
      • waitForPeers

        public ListenableCompletableFuture<java.util.List<Peer>> waitForPeers​(int numPeers)
        Returns a future that is triggered when the number of connected peers is equal to the given number of peers. By using this with getMaxConnections() you can wait until the network is fully online. To block immediately, just call get() on the result. Just calls waitForPeersOfVersion(int, long) with zero as the protocol version.
        Parameters:
        numPeers - How many peers to wait for.
        Returns:
        a future that will be triggered when the number of connected peers is greater than or equals numPeers
      • waitForPeersOfVersion

        public ListenableCompletableFuture<java.util.List<Peer>> waitForPeersOfVersion​(int numPeers,
                                                                                       long protocolVersion)
        Returns a future that is triggered when there are at least the requested number of connected peers that support the given protocol version or higher. To block immediately, just call get() on the result.
        Parameters:
        numPeers - How many peers to wait for.
        protocolVersion - The protocol version the awaited peers must implement (or better).
        Returns:
        a future that will be triggered when the number of connected peers implementing protocolVersion or higher is greater than or equals numPeers
      • findPeersOfAtLeastVersion

        public java.util.List<Peer> findPeersOfAtLeastVersion​(long protocolVersion)
        Returns an array list of peers that implement the given protocol version or better.
      • waitForPeersWithServiceMask

        public ListenableCompletableFuture<java.util.List<Peer>> waitForPeersWithServiceMask​(int numPeers,
                                                                                             int mask)
        Returns a future that is triggered when there are at least the requested number of connected peers that support the given protocol version or higher. To block immediately, just call get() on the result.
        Parameters:
        numPeers - How many peers to wait for.
        mask - An integer representing a bit mask that will be ANDed with the peers advertised service masks.
        Returns:
        a future that will be triggered when the number of connected peers implementing protocolVersion or higher is greater than or equals numPeers
      • findPeersWithServiceMask

        public java.util.List<Peer> findPeersWithServiceMask​(int mask)
        Returns an array list of peers that match the requested service bit mask.
      • 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 80% of whatever getMaxConnections() returns is used.
      • broadcastTransaction

        public TransactionBroadcast broadcastTransaction​(Transaction tx,
                                                         int minConnections,
                                                         boolean dropPeersAfterBroadcast)

        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 available via the TransactionBroadcast.awaitRelayed() ()} method 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 ListenableCompletableFuture. This method returns immediately, so if you want it to block just call get() on the result.

        Optionally, peers will be dropped after they have been used for broadcasting the transaction and they have no broadcast confirmations yet.

        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.

        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.

        The returned TransactionBroadcast object can be used to get progress feedback, which is calculated by watching the transaction propagate across the network and be announced by peers.

      • 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.lastPingInterval() but it increases load on the remote node. It defaults to DEFAULT_PING_INTERVAL_MSEC.
      • 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.lastPingInterval() but it increases load on the remote node. It defaults to DEFAULT_PING_INTERVAL_MSEC. Setting the value to be smaller or equals 0 disables pinging entirely, although you can still request one yourself using Peer.sendPing().
      • 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 the most common heights are tied, or no peers are connected, returns 0.
      • getMostCommonChainHeight

        public static int getMostCommonChainHeight​(java.util.List<Peer> peers)
        Returns most commonly reported chain height from the given list of Peers. If the most common heights are tied, or no peers are connected, returns 0.
      • selectDownloadPeer

        @Nullable
        protected Peer selectDownloadPeer​(java.util.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.
      • getMaxPeersToDiscoverCount

        public int getMaxPeersToDiscoverCount()
        Returns the maximum number of Peers to discover. This maximum is checked after each PeerDiscovery so this max number can be surpassed.
        Returns:
        the maximum number of peers to discover
      • setMaxPeersToDiscoverCount

        public void setMaxPeersToDiscoverCount​(int maxPeersToDiscoverCount)
        Sets the maximum number of Peers to discover. This maximum is checked after each PeerDiscovery so this max number can be surpassed.
        Parameters:
        maxPeersToDiscoverCount - the maximum number of peers to discover
      • setUseLocalhostPeerWhenPossible

        public void setUseLocalhostPeerWhenPossible​(boolean useLocalhostPeerWhenPossible)
        When true (the default), PeerGroup will attempt to connect to a Bitcoin node running on localhost before attempting to use the P2P network. If successful, only localhost will be used. This makes for a simple and easy way for a user to upgrade a bitcoinj based app running in SPV mode to fully validating security.
      • isRunning

        public boolean isRunning()
      • setBloomFilteringEnabled

        public void setBloomFilteringEnabled​(boolean bloomFilteringEnabled)
        Can be used to disable Bloom filtering entirely, even in SPV mode. You are very unlikely to need this, it is an optimisation for rare cases when full validation is not required but it's still more efficient to download full blocks than filtered blocks.
      • isBloomFilteringEnabled

        public boolean isBloomFilteringEnabled()
        Returns whether the Bloom filtering protocol optimisation is in use: defaults to true.