<p></p>
<h1>Concrete plan</h1>
<p>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.</p>
<ul>
<li>Below algorithm describes a refactoring of BitcoinJ usage in Bisq
<ul>
<li>the goal of the refactoring is to
<ul>
<li>generally speaking, improve maintenance of Bisq's Bitcoin network code</li>
<li>more specifically, lay the foundation for ongoing reduction of the BitcoinJ-Bisq coupling
<ul>
<li>ongoing, because the coupling is too extensive to be safely undone at once</li>
</ul>
</li>
</ul>
</li>
<li>the described refactoring aims to achieve that by
<ul>
<li>introducing a "btc.low" layer that
<ul>
<li>acts as a Bitcoin client API that is implementation agnostic
<ul>
<li>in other words, it would be the only place in Bisq with Bitcoin-client-specific (BitcoinJ-specific) logic</li>
</ul>
</li>
</ul>
</li>
<li>doing it in a way that allows safe incremental changes
<ul>
<li>what will make the process safe is the smallness of the refactoring steps
<ul>
<li>the small steps facilitate audits</li>
<li>further, being able to refactor in small steps will make opportunistic refactoring more common</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>the end product of this initial refactoring
<ul>
<li>a place where we can move BitcoinJ-specific logic</li>
<li>a place where we can see how exactly we're using BitcoinJ (in a much more centralized way)</li>
<li>a clear and simple abstraction and refactoring system for ongoing improvement of our BitcoinJ usage</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>Refactoring steps</h2>
<p>For readability, I've bolded what you'd call the main variable names if this were code:</p>
<ul>
<li>Make an identical <strong>copy</strong> of the BitcoinJ API inside Bisq
<ul>
<li>more specifically, of the subset of bitcoinj api that we use</li>
<li>initially this copy will just redirect all calls to BitcoinJ
<ul>
<li>nothing more than a fully transparent wrap</li>
</ul>
</li>
<li>you call this copy in the same way that you call the original
<ul>
<li>and you get the same results</li>
</ul>
</li>
</ul>
</li>
<li>Designate the <strong>copy</strong> as foundation for Bisq-BitcoinJ separation <strong>layer</strong>
<ul>
<li>Bisq-BitcoinJ separation layer
<ul>
<li>or, in other words, Bitcoin client agnostic layer</li>
</ul>
</li>
<li>the ultimate goal of this abstraction is to be the only repository of BitcoinJ-specific logic in Bisq</li>
</ul>
</li>
<li>Make this <strong>layer</strong> the (only) Bitcoin client used by Bisq
<ul>
<li>as simple as
<ul>
<li>search and replace <code>import org.bitcoinj.PeerGroup</code> for <code>import bisq.core.btc.low.PeerGroup</code></li>
</ul>
</li>
<li>will now refer to this layer as <strong>btc.low</strong>, as in the package bisq.core.btc.low.</li>
</ul>
</li>
<li>Incrementally mutate the <strong>btc.low</strong> abstraction
<ul>
<li>by
<ul>
<li>moving BitcoinJ-specific logic into it (from the rest of Bisq)</li>
<li>generally refactoring it to better match the needs of Bisq</li>
</ul>
</li>
<li>this step is what makes the refactoring ongoing</li>
</ul>
</li>
</ul>
<h2>Illustrative code sketch</h2>
<p>Below sketch illustrates what <code>btc.core.btc.low.PeerGroup</code> could look like.</p>
<pre><code>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);
}
}
</code></pre>
<p style="font-size:small;-webkit-text-size-adjust:none;color:#666;">—<br />You are receiving this because you are subscribed to this thread.<br />Reply to this email directly, <a href="https://github.com/bisq-network/projects/issues/30#issuecomment-629840234">view it on GitHub</a>, or <a href="https://github.com/notifications/unsubscribe-auth/AJFFTNQLNXZD2FK5FM6FPMLRSAT4LANCNFSM4MPSVBDA">unsubscribe</a>.<img src="https://github.com/notifications/beacon/AJFFTNRNCN4A5J4D2SEUTBTRSAT4LA5CNFSM4MPSVBDKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEWFJS2Q.gif" height="1" width="1" alt="" /></p>
<script type="application/ld+json">[
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"potentialAction": {
"@type": "ViewAction",
"target": "https://github.com/bisq-network/projects/issues/30#issuecomment-629840234",
"url": "https://github.com/bisq-network/projects/issues/30#issuecomment-629840234",
"name": "View Issue"
},
"description": "View this Issue on GitHub",
"publisher": {
"@type": "Organization",
"name": "GitHub",
"url": "https://github.com"
}
}
]</script>