diff --git a/.gitignore b/.gitignore index 503ef2f6f6..b88fd5e996 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,6 @@ website/static/api #OSX .DS_Store + +#Docker +data/ diff --git a/app/server/src/universal/docker-application.conf b/app/server/src/universal/docker-application.conf index 52beb860f9..91b266c597 100644 --- a/app/server/src/universal/docker-application.conf +++ b/app/server/src/universal/docker-application.conf @@ -26,10 +26,15 @@ bitcoin-s.proxy.enabled = ${?BITCOIN_S_PROXY_ENABLED} bitcoin-s.bitcoind-rpc.proxy.enabled = ${?BITCOIN_S_BITCOIND_RPC_PROXY_ENABLED} bitcoin-s.node.proxy.enabled = ${?BITCOIN_S_NODE_PROXY_ENABLED} +bitcoin-s.node.proxy.socks5 = ${?BITCOIN_S_NODE_PROXY_SOCKS5} bitcoin-s.node.tor.enabled = ${?BITCOIN_S_NODE_TOR_ENABLED} +bitcoin-s.node.tor.control = ${?BITCOIN_S_NODE_TOR_CONTROL} +bitcoin-s.node.tor.password = ${?BITCOIN_S_NODE_TOR_PASSWORD} bitcoin-s.dlcnode.proxy.enabled = ${?BITCOIN_S_DLCNODE_PROXY_ENABLED} bitcoin-s.dlcnode.proxy.socks5 = ${?BITCOIN_S_DLCNODE_PROXY_SOCKS5} bitcoin-s.dlcnode.tor.enabled = ${?BITCOIN_S_DLCNODE_TOR_ENABLED} +bitcoin-s.dlcnode.tor.control = ${?BITCOIN_S_DLCNODE_TOR_CONTROL} +bitcoin-s.dlcnode.tor.password = ${?BITCOIN_S_DLCNODE_TOR_PASSWORD} bitcoin-s.dlcnode.external-ip = ${?BITCOIN_S_DLCNODE_EXTERNAL_IP} bitcoin-s.wallet.allowExternalDLCAddresses = false diff --git a/dlc-node-test/src/test/scala/org/bitcoins/dlc/node/DLCServerTorTest.scala b/dlc-node-test/src/test/scala/org/bitcoins/dlc/node/DLCServerTorTest.scala index 8ac65869ba..595dad7b39 100644 --- a/dlc-node-test/src/test/scala/org/bitcoins/dlc/node/DLCServerTorTest.scala +++ b/dlc-node-test/src/test/scala/org/bitcoins/dlc/node/DLCServerTorTest.scala @@ -5,6 +5,7 @@ import akka.testkit.{TestActorRef, TestProbe} import org.bitcoins.asyncutil.AsyncUtil import org.bitcoins.core.number.UInt16 import org.bitcoins.core.protocol.tlv.{LnMessage, PingTLV, PongTLV} +import org.bitcoins.dlc.node.DLCDataHandler.Received import org.bitcoins.dlc.node.peer.Peer import org.bitcoins.rpc.util.RpcUtil import org.bitcoins.server.BitcoinSAppConfig @@ -106,17 +107,17 @@ class DLCServerTorTest ByteVector.fromValidHex("00112233445566778899aabbccddeeff")) clientConnectionHandler = clientConnectionHandlerOpt.get _ = clientProbe.send(clientConnectionHandler, pingTLV) - _ = serverProbe.expectMsg(timeout, LnMessage(pingTLV)) + _ = serverProbe.expectMsg(timeout, Received(LnMessage(pingTLV))) pongTLV = PongTLV.forIgnored( ByteVector.fromValidHex("00112233445566778899aabbccddeeff")) serverConnectionHandler = serverConnectionHandlerOpt.get _ = serverProbe.send(serverConnectionHandler, pongTLV) - _ = clientProbe.expectMsg(timeout, LnMessage(pongTLV)) + _ = clientProbe.expectMsg(timeout, Received(LnMessage(pongTLV))) // 131063 - is a magic size for OS X when this test case starts failing (131073 overall TLV size) ignored = ByteVector.fill(65000)(0x55) bigTLV = PongTLV.forIgnored(ignored) _ = clientProbe.send(clientConnectionHandler, bigTLV) - _ = serverProbe.expectMsg(timeout, LnMessage(bigTLV)) + _ = serverProbe.expectMsg(timeout, Received(LnMessage(bigTLV))) _ = clientProbe.send(clientConnectionHandler, DLCConnectionHandler.CloseConnection) _ = clientProbe.send(clientConnectionHandler, pingTLV) diff --git a/docs/applications/server.md b/docs/applications/server.md index 5b9d71cf61..196d968a08 100644 --- a/docs/applications/server.md +++ b/docs/applications/server.md @@ -52,7 +52,7 @@ This will build a `Dockerfile` that is located in `app/server/target/docker/stag You can now build the docker image with ``` -docker build app/server/target/docker/stage/ -t bitcoin-s-server:latest +docker build app/server/target/docker/stage/ -t bitcoinscala/bitcoin-s-server:latest ``` Finally, let's run the image! It's important that you correctly configure port forwarding with the docker container so diff --git a/tor/Dockerfile b/tor/Dockerfile new file mode 100644 index 0000000000..3a2b2b482d --- /dev/null +++ b/tor/Dockerfile @@ -0,0 +1,5 @@ +FROM --platform=linux/amd64 ubuntu:22.04 + +COPY src/main/resources/linux_64 . + +CMD ./tor \ No newline at end of file diff --git a/tor/src/main/scala/org/bitcoins/tor/TorController.scala b/tor/src/main/scala/org/bitcoins/tor/TorController.scala index 07227f5d53..51408924f2 100644 --- a/tor/src/main/scala/org/bitcoins/tor/TorController.scala +++ b/tor/src/main/scala/org/bitcoins/tor/TorController.scala @@ -1,5 +1,6 @@ package org.bitcoins.tor +import akka.Done import akka.actor.{ Actor, ActorLogging, @@ -14,6 +15,7 @@ import akka.util.ByteString import grizzled.slf4j.Logging import org.bitcoins.tor.TorProtocolHandler.Authentication +import java.io.IOException import java.net.InetSocketAddress import java.nio.file.Path import scala.concurrent.{Future, Promise} @@ -24,7 +26,10 @@ import scala.concurrent.{Future, Promise} * @param protocolHandlerProps Tor protocol handler props * @param ec execution context */ -class TorController(address: InetSocketAddress, protocolHandlerProps: Props) +class TorController( + address: InetSocketAddress, + protocolHandlerProps: Props, + connectedPromiseOpt: Option[Promise[Done]]) extends Actor with ActorLogging { @@ -36,9 +41,14 @@ class TorController(address: InetSocketAddress, protocolHandlerProps: Props) override def receive: Receive = { case e @ CommandFailed(_: Connect) => + val errMessage = s"Cannot connect to Tor control address $address" e.cause match { - case Some(ex) => log.error(ex, "Cannot connect") - case _ => log.error("Cannot connect") + case Some(ex) => + log.error(ex, errMessage) + connectedPromiseOpt.foreach(_.failure(ex)) + case _ => + log.error(errMessage) + connectedPromiseOpt.foreach(_.failure(new IOException(errMessage))) } context.stop(self) case c: Connected => @@ -48,6 +58,7 @@ class TorController(address: InetSocketAddress, protocolHandlerProps: Props) connection ! Register(self) context.watch(connection) context.watch(protocolHandler) + connectedPromiseOpt.foreach(_.success(Done)) context.become { case data: ByteString => connection ! Write(data) @@ -76,8 +87,11 @@ class TorController(address: InetSocketAddress, protocolHandlerProps: Props) object TorController extends Logging { - def props(address: InetSocketAddress, protocolHandlerProps: Props) = - Props(new TorController(address, protocolHandlerProps)) + def props( + address: InetSocketAddress, + protocolHandlerProps: Props, + connectedPromiseOpt: Option[Promise[Done]]) = + Props(new TorController(address, protocolHandlerProps, connectedPromiseOpt)) case object SendFailed @@ -101,6 +115,7 @@ object TorController extends Logging { system: ActorSystem): Future[InetSocketAddress] = { import system.dispatcher val promiseTorAddress = Promise[InetSocketAddress]() + val promiseConnected = Promise[Done]() val protocolHandlerProps = TorProtocolHandler.props( version = TorProtocolHandler.V3, @@ -113,16 +128,18 @@ object TorController extends Logging { val _ = system.actorOf( TorController.props(address = controlAddress, - protocolHandlerProps = protocolHandlerProps), + protocolHandlerProps = protocolHandlerProps, + connectedPromiseOpt = Some(promiseConnected)), s"tor-${System.currentTimeMillis()}" ) - val addressF = promiseTorAddress.future - - addressF.foreach(address => - logger.info(s"Created hidden service with address=$address")) - - addressF + for { + _ <- promiseConnected.future + torAddress <- promiseTorAddress.future + } yield { + logger.info(s"Created hidden service with address=$torAddress") + torAddress + } } }