[bisq-network/projects] Introduce interface between Bisq and BitcoinJ (#30)

dmos62 notifications at github.com
Sun May 17 18:26:13 UTC 2020


# Concrete plan

Note: below text is written in a tree-like fashion, which helps me structure my writing and navigate the text. Hopefully it doesn't look too outlandish.

- Below algorithm describes a refactoring of BitcoinJ usage in Bisq
  - the goal of the refactoring is to
    - generally speaking, improve maintenance of Bisq's Bitcoin network code
    - more specifically, lay the foundation for ongoing reduction of the BitcoinJ-Bisq coupling
      - ongoing, because the coupling is too extensive to be safely undone at once
  - the described refactoring aims to achieve that by
    - introducing a "btc.low" layer that
      - acts as a Bitcoin client API that is implementation agnostic
        - in other words, it would be the only place in Bisq with Bitcoin-client-specific (BitcoinJ-specific) logic
    - doing it in a way that allows safe incremental changes
      - what will make the process safe is the smallness of the refactoring steps
        - the small steps facilitate audits
        - further, being able to refactor in small steps will make opportunistic refactoring more common
  - the end product of this initial refactoring
    - a place where we can move BitcoinJ-specific logic
    - a place where we can see how exactly we're using BitcoinJ (in a much more centralized way)
    - a clear and simple abstraction and refactoring system for ongoing improvement of our BitcoinJ usage

## Refactoring steps

For readability, I've bolded what you'd call the main variable names if this were code:

- Make an identical **copy** of the BitcoinJ API inside Bisq
  - more specifically, of the subset of bitcoinj api that we use
  - initially this copy will just redirect all calls to BitcoinJ
     - nothing more than a fully transparent wrap
  - you call this copy in the same way that you call the original
    - and you get the same results
- Designate the **copy** as foundation for Bisq-BitcoinJ separation **layer**
  - Bisq-BitcoinJ separation layer
    - or, in other words, Bitcoin client agnostic layer
  - the ultimate goal of this abstraction is to be the only repository of BitcoinJ-specific logic in Bisq
- Make this **layer** the (only) Bitcoin client used by Bisq
  - as simple as
    - search and replace `import org.bitcoinj.PeerGroup` for `import bisq.core.btc.low.PeerGroup`
  - will now refer to this layer as **btc.low**, as in the package bisq.core.btc.low.
- Incrementally mutate the **btc.low** abstraction
  - by
    - moving BitcoinJ-specific logic into it (from the rest of Bisq)
    - generally refactoring it to better match the needs of Bisq
  - this step is what makes the refactoring ongoing

## Illustrative code sketch

Below sketch illustrates what `btc.core.btc.low.PeerGroup` could look like.

```
package bisq.core.btc.low;

import org.bitcoinj.core.BlockChain;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.net.BlockingClientManager;

import bisq.core.btc.nodes.ProxySocketFactory;
import bisq.core.btc.nodes.LocalBitcoinNode;

import java.net.Proxy;
import java.net.InetSocketAddress;

import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;

/* Below code is a sketch of what btc.low can look like.
 * To make it short and simple, it presumes that our BitcoinJ usage is only
 * what is in the bisq.core.btc.WalletConfig::createPeerGroup method.
 * This sketch tries to demonstrate how logic is moved into btc.low: you start
 * out with a lot of BitcoinJ-specific logic, and end up with a
 * BitcoinJ-agnostic endpoint and a clear view of what BitcoinJ endpoints are
 * used under the sheets.
 * The code would definitely be simplified more after moving, but that's
 * outside the scope of this sketch.
 */

public class PeerGroup {

    private final org.bitcoinj.core.PeerGroup bitcoinjPeerGroup;

    private PeerGroup(org.bitcoinj.core.PeerGroup bitcoinjPeerGroup) {
        this.bitcoinjPeerGroup = bitcoinjPeerGroup;
    }

    /* This method is a copy-paste of
     * bisq.core.btc.WalletConfig::createPeerGroup (except for the signature
     * and using locally defined constructors). It serves only demo purposes
     * and code quality inside it not representative of standards set for this
     * project.
     */
    private static PeerGroup createPeerGroup(
            Socks5Proxy socks5Proxy,
            NetworkParameters params,
            BlockChain vChain,
            LocalBitcoinNode localBitcoinNode
    ) {
        PeerGroup peerGroup;
        // no proxy case.
        if (socks5Proxy == null) {
            peerGroup = this(params, vChain);
        } else {
            // proxy case (tor).
            Proxy proxy = new Proxy(Proxy.Type.SOCKS,
                    new InetSocketAddress(
                        socks5Proxy.getInetAddress().getHostName(),
                        socks5Proxy.getPort()));

            ProxySocketFactory proxySocketFactory =
                new ProxySocketFactory(proxy);
            // We don't use tor mode if we have a local node running
            BlockingClientManager blockingClientManager =
                config.ignoreLocalBtcNode ?
                new BlockingClientManager() :
                new BlockingClientManager(proxySocketFactory);

            peerGroup = this(params, vChain, blockingClientManager);

            blockingClientManager.setConnectTimeoutMillis(TOR_SOCKET_TIMEOUT);
            peerGroup.setConnectTimeoutMillis(TOR_VERSION_EXCHANGE_TIMEOUT);
        }

        if (!localBitcoinNode.shouldBeUsed())
            peerGroup.setUseLocalhostPeerWhenPossible(false);

        return peerGroup;
    }

    /* Proxy all PeerGroup methods that Bisq uses.
     * These would probably be "protected" and be in a separate class, which
     * would be subclassed by this one, for the sake of separating the used
     * BitcoinJ endpoints and their usage.
     */

    private PeerGroup(
            NetworkParameters params,
            BlockChain vChain
    ) {
        org.bitcoinj.core.PeerGroup bitcoinjPeerGroup =
            new org.bitcoinj.core.PeerGroup(params, vChain);
        this(bitcoinjPeerGroup);
    }

    private PeerGroup(
            NetworkParameters params,
            BlockChain vChain,
            BlockingClientManager
            blockingClientManager
    ) {
        org.bitcoinj.core.PeerGroup bitcoinjPeerGroup =
            new org.bitcoinj.core.PeerGroup(
                    params, vChain, blockingClientManager);
        this(bitcoinjPeerGroup);
    }

    private void setUseLocalhostPeerWhenPossible(boolean bool) {
        this.bitcoinjPeerGroup.setUseLocalhostPeerWhenPossible(bool);
    }

    private void setConnectTimeoutMillis(int timeout) {
        this.bitcoinjPeerGroup.setConnectTimeoutMillis(timeout);
    }

}

```

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/bisq-network/projects/issues/30#issuecomment-629840234
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.bisq.network/pipermail/bisq-github/attachments/20200517/acfdeda2/attachment.html>


More information about the bisq-github mailing list