Skip to content

Commit

Permalink
Create ADT for NodeType instead of booleans (#1901)
Browse files Browse the repository at this point in the history
  • Loading branch information
benthecarman committed Aug 26, 2020
1 parent a9ad927 commit c9c18fa
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 67 deletions.
41 changes: 14 additions & 27 deletions app/server/src/main/scala/org/bitcoins/server/Main.scala
Expand Up @@ -109,8 +109,6 @@ object Main extends App with BitcoinSLogger {

implicit val walletConf: WalletAppConfig = conf.walletConf
implicit val nodeConf: NodeAppConfig = conf.nodeConf
require(nodeConf.isNeutrinoEnabled != nodeConf.isSPVEnabled,
"Either Neutrino or SPV mode should be enabled")
implicit val chainConf: ChainAppConfig = conf.chainConf

if (nodeConf.peers.isEmpty) {
Expand Down Expand Up @@ -172,13 +170,7 @@ object Main extends App with BitcoinSLogger {
_ <- wallet.start()
binding <- startHttpServer(node, wallet, rpcPortOpt)
_ = {
if (nodeConf.isSPVEnabled) {
logger.info(s"Starting SPV node sync")
} else if (nodeConf.isNeutrinoEnabled) {
logger.info(s"Starting neutrino node sync")
} else {
logger.info(s"Starting unknown type of node sync")
}
logger.info(s"Starting ${nodeConf.nodeType.shortName} node sync")
}
_ = BitcoinSServer.startedFP.success(Future.successful(binding))

Expand All @@ -193,13 +185,7 @@ object Main extends App with BitcoinSLogger {
node
.stop()
.foreach(_ =>
if (nodeConf.isSPVEnabled) {
logger.info(s"Stopped SPV node")
} else if (nodeConf.isNeutrinoEnabled) {
logger.info(s"Stopped neutrino node")
} else {
logger.info(s"Stopped unknown type of node")
})
logger.info(s"Stopped ${nodeConf.nodeType.shortName} node"))
system.terminate().foreach(_ => logger.info(s"Actor system terminated"))
}

Expand Down Expand Up @@ -234,17 +220,18 @@ object Main extends App with BitcoinSLogger {
wallet.updateUtxoPendingStates().map(_ => ())
}
}
if (nodeConf.isSPVEnabled) {
Future.successful(
NodeCallbacks(onTxReceived = Vector(onTx),
onBlockHeadersReceived = Vector(onHeaders)))
} else if (nodeConf.isNeutrinoEnabled) {
Future.successful(
NodeCallbacks(onBlockReceived = Vector(onBlock),
onCompactFiltersReceived = Vector(onCompactFilters),
onBlockHeadersReceived = Vector(onHeaders)))
} else {
Future.failed(new RuntimeException("Unexpected node type"))
nodeConf.nodeType match {
case NodeType.SpvNode =>
Future.successful(
NodeCallbacks(onTxReceived = Vector(onTx),
onBlockHeadersReceived = Vector(onHeaders)))
case NodeType.NeutrinoNode =>
Future.successful(
NodeCallbacks(onBlockReceived = Vector(onBlock),
onCompactFiltersReceived = Vector(onCompactFilters),
onBlockHeadersReceived = Vector(onHeaders)))
case NodeType.FullNode =>
Future.failed(new RuntimeException("Not yet implemented"))
}
}

Expand Down
2 changes: 1 addition & 1 deletion node/src/main/scala/org/bitcoins/node/NeutrinoNode.scala
Expand Up @@ -16,7 +16,7 @@ case class NeutrinoNode(
actorSystem: ActorSystem)
extends Node {
require(
nodeConfig.isNeutrinoEnabled,
nodeConfig.nodeType == NodeType.NeutrinoNode,
s"We need our Neutrino mode enabled to be able to construct a Neutrino node!")

implicit override def system: ActorSystem = actorSystem
Expand Down
40 changes: 40 additions & 0 deletions node/src/main/scala/org/bitcoins/node/NodeType.scala
@@ -0,0 +1,40 @@
package org.bitcoins.node

import org.bitcoins.crypto.StringFactory

sealed abstract class NodeType {
def shortName: String
}

object NodeType extends StringFactory[NodeType] {

final case object FullNode extends NodeType {
override def shortName: String = "full"
}

final case object NeutrinoNode extends NodeType {
override def shortName: String = "neutrino"
}

final case object SpvNode extends NodeType {
override def shortName: String = "spv"
}

val all: Vector[NodeType] = Vector(FullNode, NeutrinoNode, SpvNode)

override def fromStringOpt(str: String): Option[NodeType] = {
all.find(state => str.toLowerCase() == state.toString.toLowerCase) match {
case Some(value) => Some(value)
case None =>
all.find(state => str.toLowerCase() == state.shortName.toLowerCase)
}
}

override def fromString(string: String): NodeType = {
fromStringOpt(string) match {
case Some(state) => state
case None =>
sys.error(s"Could not find a NodeType for string=$string")
}
}
}
2 changes: 1 addition & 1 deletion node/src/main/scala/org/bitcoins/node/SpvNode.scala
Expand Up @@ -18,7 +18,7 @@ case class SpvNode(
chainConfig: ChainAppConfig,
actorSystem: ActorSystem)
extends Node {
require(nodeConfig.isSPVEnabled,
require(nodeConfig.nodeType == NodeType.SpvNode,
s"We need our SPV mode enabled to be able to construct a SPV node!")

implicit override def system: ActorSystem = actorSystem
Expand Down
33 changes: 10 additions & 23 deletions node/src/main/scala/org/bitcoins/node/config/NodeAppConfig.scala
Expand Up @@ -7,9 +7,9 @@ import com.typesafe.config.Config
import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.core.util.{FutureUtil, Mutable}
import org.bitcoins.db.{AppConfig, AppConfigFactory, JdbcProfileComponent}
import org.bitcoins.node._
import org.bitcoins.node.db.NodeDbManagement
import org.bitcoins.node.models.Peer
import org.bitcoins.node.{NeutrinoNode, Node, NodeCallbacks, SpvNode}

import scala.concurrent.{ExecutionContext, Future}

Expand Down Expand Up @@ -56,21 +56,8 @@ case class NodeAppConfig(
FutureUtil.unit
}

/**
* Whether or not SPV (simplified payment verification)
* mode is enabled.
*/
lazy val isSPVEnabled: Boolean = config
.getString("node.mode")
.toLowerCase == "spv"

/**
* Whether or not Neutrino (compact block filters) mode
* is enabled
*/
lazy val isNeutrinoEnabled: Boolean = config
.getString("node.mode")
.toLowerCase == "neutrino"
lazy val nodeType: NodeType =
NodeType.fromString(config.getString("node.mode"))

/**
* List of peers
Expand Down Expand Up @@ -108,13 +95,13 @@ object NodeAppConfig extends AppConfigFactory[NodeAppConfig] {
nodeConf: NodeAppConfig,
chainConf: ChainAppConfig,
system: ActorSystem): Future[Node] = {
if (nodeConf.isSPVEnabled) {
Future.successful(SpvNode(peer, nodeConf, chainConf, system))
} else if (nodeConf.isNeutrinoEnabled) {
Future.successful(NeutrinoNode(peer, nodeConf, chainConf, system))
} else {
Future.failed(
new RuntimeException("Neither Neutrino nor SPV mode is enabled."))
nodeConf.nodeType match {
case NodeType.SpvNode =>
Future.successful(SpvNode(peer, nodeConf, chainConf, system))
case NodeType.NeutrinoNode =>
Future.successful(NeutrinoNode(peer, nodeConf, chainConf, system))
case NodeType.FullNode =>
Future.failed(new RuntimeException("Not implemented"))
}
}
}
Expand Up @@ -7,7 +7,7 @@ import org.bitcoins.core.p2p._
import org.bitcoins.crypto.DoubleSha256DigestBE
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.models.BroadcastAbleTransactionDAO
import org.bitcoins.node.{NodeCallbacks, P2PLogger}
import org.bitcoins.node.{NodeCallbacks, NodeType, P2PLogger}

import scala.concurrent.{ExecutionContext, Future}

Expand Down Expand Up @@ -180,7 +180,7 @@ case class DataMessageHandler(
s"Received headers=${headers.map(_.hashBE.hex).mkString("[", ",", "]")}")
val chainApiF = chainApi.processHeaders(headers)

if (appConfig.isSPVEnabled) {
if (appConfig.nodeType == NodeType.SpvNode) {
logger.trace(s"Requesting data for headers=${headers.length}")
peerMsgSender.sendGetDataMessage(TypeIdentifier.MsgFilteredBlock,
headers.map(_.hash): _*)
Expand Down Expand Up @@ -209,7 +209,7 @@ case class DataMessageHandler(
"which is less than max. This means we are synced,",
"not requesting more.")
.mkString(" "))
if (appConfig.isNeutrinoEnabled && !syncing)
if (appConfig.nodeType == NodeType.NeutrinoNode && !syncing)
sendFirstGetCompactFilterHeadersCommand(peerMsgSender)
else
Future.successful(syncing)
Expand Down Expand Up @@ -335,9 +335,12 @@ case class DataMessageHandler(
val getData = GetDataMessage(invMsg.inventories.map {
case Inventory(TypeIdentifier.MsgBlock, hash) =>
// only request the merkle block if we are spv enabled
if (appConfig.isSPVEnabled) {
Inventory(TypeIdentifier.MsgFilteredBlock, hash)
} else Inventory(TypeIdentifier.MsgBlock, hash)
appConfig.nodeType match {
case NodeType.SpvNode =>
Inventory(TypeIdentifier.MsgFilteredBlock, hash)
case NodeType.NeutrinoNode | NodeType.FullNode =>
Inventory(TypeIdentifier.MsgBlock, hash)
}
case other: Inventory => other
})
peerMsgSender.sendMsg(getData)
Expand Down
Expand Up @@ -180,7 +180,7 @@ trait NodeUnitTest extends BitcoinSFixture with EmbeddedPg {
appConfig: BitcoinSAppConfig): FutureOutcome = {
val nodeWithBitcoindBuilder: () => Future[SpvNodeConnectedWithBitcoind] = {
() =>
require(appConfig.isSPVEnabled && !appConfig.isNeutrinoEnabled)
require(appConfig.nodeType == NodeType.SpvNode)
for {
bitcoind <- BitcoinSFixture.createBitcoind(versionOpt)
node <- NodeUnitTest.createSpvNode(bitcoind, NodeCallbacks.empty)(
Expand All @@ -202,7 +202,7 @@ trait NodeUnitTest extends BitcoinSFixture with EmbeddedPg {
appConfig: BitcoinSAppConfig): FutureOutcome = {
val nodeWithBitcoindBuilder: () => Future[
SpvNodeConnectedWithBitcoindV19] = { () =>
require(appConfig.isSPVEnabled && !appConfig.isNeutrinoEnabled)
require(appConfig.nodeType == NodeType.SpvNode)
for {
bitcoind <-
BitcoinSFixture
Expand All @@ -229,7 +229,7 @@ trait NodeUnitTest extends BitcoinSFixture with EmbeddedPg {
appConfig: BitcoinSAppConfig): FutureOutcome = {
val nodeWithBitcoindBuilder: () => Future[
NeutrinoNodeConnectedWithBitcoind] = { () =>
require(appConfig.isNeutrinoEnabled && !appConfig.isSPVEnabled)
require(appConfig.nodeType == NodeType.NeutrinoNode)
for {
bitcoind <- BitcoinSFixture.createBitcoind(versionOpt)
node <- NodeUnitTest.createNeutrinoNode(bitcoind, NodeCallbacks.empty)(
Expand Down Expand Up @@ -389,7 +389,7 @@ object NodeUnitTest extends P2PLogger {
system: ActorSystem,
appConfig: BitcoinSAppConfig): Future[SpvNodeFundedWalletBitcoind] = {
import system.dispatcher
require(appConfig.isSPVEnabled && !appConfig.isNeutrinoEnabled)
require(appConfig.nodeType == NodeType.SpvNode)
for {
bitcoind <- BitcoinSFixture.createBitcoindWithFunds(versionOpt)
node <- createSpvNode(bitcoind, nodeCallbacks)
Expand Down Expand Up @@ -417,7 +417,7 @@ object NodeUnitTest extends P2PLogger {
appConfig: BitcoinSAppConfig): Future[
NeutrinoNodeFundedWalletBitcoind] = {
import system.dispatcher
require(appConfig.isNeutrinoEnabled && !appConfig.isSPVEnabled)
require(appConfig.nodeType == NodeType.NeutrinoNode)
for {
bitcoind <- BitcoinSFixture.createBitcoindWithFunds(versionOpt)
node <- createNeutrinoNode(bitcoind, nodeCallbacks)
Expand Down Expand Up @@ -492,8 +492,7 @@ object NodeUnitTest extends P2PLogger {
nodeAppConfig.addCallbacks(callbacks)

val checkConfigF = Future {
assert(nodeAppConfig.isSPVEnabled)
assert(!nodeAppConfig.isNeutrinoEnabled)
assert(nodeAppConfig.nodeType == NodeType.SpvNode)
}
val chainApiF = for {
_ <- checkConfigF
Expand Down Expand Up @@ -527,8 +526,7 @@ object NodeUnitTest extends P2PLogger {
nodeAppConfig.addCallbacks(callbacks)

val checkConfigF = Future {
assert(!nodeAppConfig.isSPVEnabled)
assert(nodeAppConfig.isNeutrinoEnabled)
assert(nodeAppConfig.nodeType == NodeType.NeutrinoNode)
}
val chainApiF = for {
_ <- checkConfigF
Expand Down

0 comments on commit c9c18fa

Please sign in to comment.