mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 18:47:38 +01:00
Storing peers in database (#3773)
* rebase * fix * fix * remove unwanted diffs * fix * formatting * changes from comments * Revert "changes from comments" This reverts commit eb8a795718dc590802a19c7ce4cce4501bd2de1f. * changes from comments * add PeerManager * add sha3-256 * add NetworkUtilTest * formatting
This commit is contained in:
parent
93c5121632
commit
a58ef1cd02
28 changed files with 1308 additions and 168 deletions
|
@ -25,7 +25,7 @@ import org.bitcoins.core.api.node.{
|
||||||
NodeApi,
|
NodeApi,
|
||||||
NodeType
|
NodeType
|
||||||
}
|
}
|
||||||
import org.bitcoins.core.util.{NetworkUtil, TimeUtil}
|
import org.bitcoins.core.util.TimeUtil
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
import org.bitcoins.dlc.node.DLCNode
|
import org.bitcoins.dlc.node.DLCNode
|
||||||
import org.bitcoins.dlc.node.config.DLCNodeAppConfig
|
import org.bitcoins.dlc.node.config.DLCNodeAppConfig
|
||||||
|
@ -35,7 +35,6 @@ import org.bitcoins.feeprovider.MempoolSpaceTarget.HourFeeTarget
|
||||||
import org.bitcoins.feeprovider._
|
import org.bitcoins.feeprovider._
|
||||||
import org.bitcoins.node._
|
import org.bitcoins.node._
|
||||||
import org.bitcoins.node.config.NodeAppConfig
|
import org.bitcoins.node.config.NodeAppConfig
|
||||||
import org.bitcoins.node.models.Peer
|
|
||||||
import org.bitcoins.rpc.BitcoindException.InWarmUp
|
import org.bitcoins.rpc.BitcoindException.InWarmUp
|
||||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||||
import org.bitcoins.rpc.config.{BitcoindRpcAppConfig, ZmqConfig}
|
import org.bitcoins.rpc.config.{BitcoindRpcAppConfig, ZmqConfig}
|
||||||
|
@ -112,25 +111,13 @@ class BitcoinSServerMain(override val serverArgParser: ServerArgParser)(implicit
|
||||||
def startBitcoinSBackend(): Future[Unit] = {
|
def startBitcoinSBackend(): Future[Unit] = {
|
||||||
logger.info(s"startBitcoinSBackend()")
|
logger.info(s"startBitcoinSBackend()")
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
if (nodeConf.peers.isEmpty) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"No peers specified, unable to start node")
|
|
||||||
}
|
|
||||||
|
|
||||||
val peerSockets = {
|
|
||||||
nodeConf.peers.map(
|
|
||||||
NetworkUtil.parseInetSocketAddress(_, nodeConf.network.port)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val peers = peerSockets.map(Peer.fromSocket(_, nodeConf.socks5ProxyParams))
|
|
||||||
|
|
||||||
//run chain work migration
|
//run chain work migration
|
||||||
val chainApiF = runChainWorkCalc(
|
val chainApiF = runChainWorkCalc(
|
||||||
serverArgParser.forceChainWorkRecalc || chainConf.forceRecalcChainWork)
|
serverArgParser.forceChainWorkRecalc || chainConf.forceRecalcChainWork)
|
||||||
|
|
||||||
//get a node that isn't started
|
//get a node that isn't started
|
||||||
val nodeF = nodeConf.createNode(peers)(chainConf, system)
|
val nodeF = nodeConf.createNode()(chainConf, system)
|
||||||
|
|
||||||
val feeProvider = getFeeProviderOrElse(
|
val feeProvider = getFeeProviderOrElse(
|
||||||
MempoolSpaceProvider(HourFeeTarget,
|
MempoolSpaceProvider(HourFeeTarget,
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.bitcoins.core.util
|
||||||
|
|
||||||
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
class NetworkUtilTest extends BitcoinSUtilTest {
|
||||||
|
"NetworkUtil" must "convert torV3 pubkey to correct .onion address and vice versa" in {
|
||||||
|
val pubkey = ByteVector.fromValidHex(
|
||||||
|
"98908ec971ad17171365865a249c420d04a66f103f973a62d8404ce2f4af1ee2")
|
||||||
|
val address =
|
||||||
|
"tcii5slrvulroe3fqzncjhccbuckm3yqh6ltuywyibgof5fpd3rpycyd.onion"
|
||||||
|
val addressFromKey = NetworkUtil.parseUnresolvedInetSocketAddress(pubkey)
|
||||||
|
val pubkeyFromAddress = ByteVector(NetworkUtil.torV3AddressToBytes(address))
|
||||||
|
assert(address == addressFromKey)
|
||||||
|
assert(pubkey == pubkeyFromAddress)
|
||||||
|
}
|
||||||
|
}
|
|
@ -75,7 +75,8 @@ sealed abstract class MainNet extends BitcoinNetwork {
|
||||||
"seed.btc.petertodd.org",
|
"seed.btc.petertodd.org",
|
||||||
"seed.bitcoin.jonasschnelli.ch",
|
"seed.bitcoin.jonasschnelli.ch",
|
||||||
"seed.bitcoin.sprovoost.nl",
|
"seed.bitcoin.sprovoost.nl",
|
||||||
"dnsseed.emzy.de"
|
"dnsseed.emzy.de",
|
||||||
|
"seed.bitcoin.wiz.biz"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package org.bitcoins.core.util
|
package org.bitcoins.core.util
|
||||||
|
|
||||||
|
import org.bitcoins.core.p2p.AddrV2Message
|
||||||
|
import org.bitcoins.crypto.CryptoUtil
|
||||||
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
import java.net._
|
import java.net._
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
import scala.util.{Failure, Random, Success, Try}
|
import scala.util.{Failure, Random, Success, Try}
|
||||||
|
@ -17,6 +21,58 @@ abstract class NetworkUtil {
|
||||||
InetSocketAddress.createUnresolved(uri.getHost, port)
|
InetSocketAddress.createUnresolved(uri.getHost, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Parses IPV4,IPV6 ad TorV3 address bytes to string address */
|
||||||
|
def parseInetSocketAddress(
|
||||||
|
address: ByteVector,
|
||||||
|
port: Int): InetSocketAddress = {
|
||||||
|
val uri: URI = {
|
||||||
|
address.size match {
|
||||||
|
case AddrV2Message.IPV4_ADDR_LENGTH =>
|
||||||
|
val hostAddress =
|
||||||
|
InetAddress.getByAddress(address.toArray).getHostAddress
|
||||||
|
new URI("tcp://" + hostAddress)
|
||||||
|
case AddrV2Message.IPV6_ADDR_LENGTH =>
|
||||||
|
val hostAddress =
|
||||||
|
InetAddress.getByAddress(address.toArray).getHostAddress
|
||||||
|
new URI(s"tcp://[$hostAddress]")
|
||||||
|
case AddrV2Message.TOR_V3_ADDR_LENGTH =>
|
||||||
|
val hostAddress = parseUnresolvedInetSocketAddress(address)
|
||||||
|
new URI("tcp://" + hostAddress)
|
||||||
|
case unknownSize =>
|
||||||
|
sys.error(
|
||||||
|
s"Attempted to parse InetSocketAddress with unknown size, got=${unknownSize}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
InetSocketAddress.createUnresolved(uri.getHost, port)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddrV2 messages give pubkey bytes for TorV3 addresses and in config files addresses are as strings like
|
||||||
|
// dfghj...vbnm.onion hence such conversions to and from bytes to string is needed
|
||||||
|
|
||||||
|
/** Parses TorV3 address bytes (pubkey) to string address */
|
||||||
|
def parseUnresolvedInetSocketAddress(bytes: ByteVector): String = {
|
||||||
|
val version = BigInt(0x03).toByteArray
|
||||||
|
val pubkey = bytes.toArray
|
||||||
|
val checksum = CryptoUtil
|
||||||
|
.sha3_256(ByteVector(".onion checksum".getBytes ++ pubkey ++ version))
|
||||||
|
.bytes
|
||||||
|
val address =
|
||||||
|
ByteVector(
|
||||||
|
pubkey ++ checksum.take(2).toArray ++ version).toBase32 + ".onion"
|
||||||
|
address.toLowerCase
|
||||||
|
}
|
||||||
|
|
||||||
|
/** converts a string TorV3 address to pubkey bytes */
|
||||||
|
def torV3AddressToBytes(address: String): Array[Byte] = {
|
||||||
|
val encoded = address.substring(0, address.indexOf('.')).toUpperCase
|
||||||
|
val decoded = ByteVector.fromBase32(encoded) match {
|
||||||
|
case Some(value) => value.toArray
|
||||||
|
case None =>
|
||||||
|
throw new IllegalArgumentException("Invalid TorV3 onion address")
|
||||||
|
}
|
||||||
|
decoded.slice(0, decoded.length - 3)
|
||||||
|
}
|
||||||
|
|
||||||
def isLocalhost(hostName: String): Boolean = {
|
def isLocalhost(hostName: String): Boolean = {
|
||||||
hostName == "127.0.0.0" || hostName == "localhost"
|
hostName == "127.0.0.0" || hostName == "localhost"
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,23 +5,23 @@ import scodec.bits.ByteVector
|
||||||
class HashingTest extends BitcoinSCryptoTest {
|
class HashingTest extends BitcoinSCryptoTest {
|
||||||
|
|
||||||
private lazy val lines = Vector(
|
private lazy val lines = Vector(
|
||||||
// rnd,sha1(rnd),sha256(rnd),ripeMd160(rnd),sha256Hash160(rnd),hmac(rnd,sha256)
|
// rnd,sha1(rnd),sha256(rnd),ripeMd160(rnd),sha256Hash160(rnd),hmac(rnd,sha256),sha3_256(rnd)
|
||||||
"41dc440cf30c42cb17b935d3d8451b0c1e2a8ad9a529637228df5ca31a10c0a2,b600f58e73defdbb68650078f39760ba1bcfb391,4eb2b43a30cca0aebdefec2f6a30abb56a1f6d9b0462d252184dc5209c62d5d0,ddb6092b1103067c609b35bec4177abf5dfc9f5c,304d0d0762ec66b44764a11b0d02e234b1d75721,36d248dc8a9825ac48c32fe4ebf0b4dd8ee450c226f05dc8b8cfac62dbcc11a89bc00ab3942bc5ca74a7f189bff04fe9541b749a7670e9dcf36e3bdb37cd6e01",
|
"41dc440cf30c42cb17b935d3d8451b0c1e2a8ad9a529637228df5ca31a10c0a2,b600f58e73defdbb68650078f39760ba1bcfb391,4eb2b43a30cca0aebdefec2f6a30abb56a1f6d9b0462d252184dc5209c62d5d0,ddb6092b1103067c609b35bec4177abf5dfc9f5c,304d0d0762ec66b44764a11b0d02e234b1d75721,36d248dc8a9825ac48c32fe4ebf0b4dd8ee450c226f05dc8b8cfac62dbcc11a89bc00ab3942bc5ca74a7f189bff04fe9541b749a7670e9dcf36e3bdb37cd6e01,870d8f928cc97f37b6e0845f9f8bde004f24a12ee36cc5c5408a8dc67eb9d051",
|
||||||
"a361ef0fdc98778bd5c6f6c50a6300f560a88644029a623294091d2b3d0e22d7,7cb911a6852779261cc151410691bd408b23ba1d,d63c99b1abffc915ba9e35fdc5763304839d981dc25c106bdd90a8bdc4eb6f13,6003b2e364b11f2737c7fb4cb190fdd55783f76b,a4f38c39eab8afe5f2e63d1a89d0c365c96cc7a7,87c59c1c9535043a3c3ecdec25776613f198ae4707675c129a1ed8d217aac20f7d07ce4c84e6cfa833ee7d3e52b3673730b900e6ca7075185d1ecce473110447",
|
"a361ef0fdc98778bd5c6f6c50a6300f560a88644029a623294091d2b3d0e22d7,7cb911a6852779261cc151410691bd408b23ba1d,d63c99b1abffc915ba9e35fdc5763304839d981dc25c106bdd90a8bdc4eb6f13,6003b2e364b11f2737c7fb4cb190fdd55783f76b,a4f38c39eab8afe5f2e63d1a89d0c365c96cc7a7,87c59c1c9535043a3c3ecdec25776613f198ae4707675c129a1ed8d217aac20f7d07ce4c84e6cfa833ee7d3e52b3673730b900e6ca7075185d1ecce473110447,48d322b5b8c781bd027686f503682e2efc37f621bb5fef14ddfad9329f97bbbb",
|
||||||
"35659ae4880ae74deda82a5d3b77ba8fc4adff84e1c46fa67955338bc7346977,e379fb92c9500d410818bd95796a87f662f1fd76,904a2128262e055f68896150e1b1da93849bda2054e5e6f6f8db11214a1b6855,a63e15d313afef12927f38924a97927ac3e61b8b,0c2109858080cad92ec93e883998b6048b671112,7bdd176479a379bb9447e5f7646cd0be210977b593d6a71fbdbe545a282b4fb9e22b6ec5d0afa62045fe96074b91544755f9c28ee0af368ae34165e5487d65d2",
|
"35659ae4880ae74deda82a5d3b77ba8fc4adff84e1c46fa67955338bc7346977,e379fb92c9500d410818bd95796a87f662f1fd76,904a2128262e055f68896150e1b1da93849bda2054e5e6f6f8db11214a1b6855,a63e15d313afef12927f38924a97927ac3e61b8b,0c2109858080cad92ec93e883998b6048b671112,7bdd176479a379bb9447e5f7646cd0be210977b593d6a71fbdbe545a282b4fb9e22b6ec5d0afa62045fe96074b91544755f9c28ee0af368ae34165e5487d65d2,d34318f7c0ae01caaebca717a6388cae96e3f8c506acd3f152d5619893d4defb",
|
||||||
"e3c54af8504a7f0d69f8f9c9b29c5d15fc861821547f285bb70d2850ce08efe9,a93c7e60aa08e08919c9085641ff1a7cd3400613,1325fb6c0029b128b0fdf37d014e3739aea56fc670756e335a2ce34fe08c2574,d5409d92add4c4f7fad2ae8eea100e19e2f1e66f,90dcb2f658418089a0d41abb7f012f2531f860a0,911a7b19f7f0f145921002ed3830d46045041e786cbea13c7f77066ed8a03d56ddaa2db987358f6a4c713fddd07570647fd80ea072da309a60758c305137d4a8",
|
"e3c54af8504a7f0d69f8f9c9b29c5d15fc861821547f285bb70d2850ce08efe9,a93c7e60aa08e08919c9085641ff1a7cd3400613,1325fb6c0029b128b0fdf37d014e3739aea56fc670756e335a2ce34fe08c2574,d5409d92add4c4f7fad2ae8eea100e19e2f1e66f,90dcb2f658418089a0d41abb7f012f2531f860a0,911a7b19f7f0f145921002ed3830d46045041e786cbea13c7f77066ed8a03d56ddaa2db987358f6a4c713fddd07570647fd80ea072da309a60758c305137d4a8,1b9a19ea9447d58fa980091d04e20b9f9b4999b54b415cc522089bfe664a6319",
|
||||||
"8283f8f51b5045ef414e462ebb5c9573950ec0162578df73d0f5490febac5a97,40ebb9af58651c51135641278884217f23f14993,540ed853ed97664d7ea82e663d2480076d1b81088a5ef405465871c8df3d1b9f,4c69787f663f188fbcee4b0d9a737083e018ac08,137b3fb7855dc321348e03c458ecc18daedf0f95,5172f81bbabd00b9c81654826dba9e527b5a1c553b9c2c92b7b59b420d5b8064c2fd3f9e8107ec3a07298f712de10a126d348d2bb6dac21aa397a665a1ee787d",
|
"8283f8f51b5045ef414e462ebb5c9573950ec0162578df73d0f5490febac5a97,40ebb9af58651c51135641278884217f23f14993,540ed853ed97664d7ea82e663d2480076d1b81088a5ef405465871c8df3d1b9f,4c69787f663f188fbcee4b0d9a737083e018ac08,137b3fb7855dc321348e03c458ecc18daedf0f95,5172f81bbabd00b9c81654826dba9e527b5a1c553b9c2c92b7b59b420d5b8064c2fd3f9e8107ec3a07298f712de10a126d348d2bb6dac21aa397a665a1ee787d,eb4080b54011e5cd852d20b933412a1615f1d6fce96bb00af4d47b70b95f6b64",
|
||||||
"6286477a8da8d7b6f2fc9080d5e7a4091b1d506ee2dc4f81740b0f54f438537d,aeded4ba719eb6fed787d34b8064402082db7a4d,3df54218915767977bdf2bcde8b45a711caa460c3baa2448f91bc13731e6ea3d,946d3624e583fef1b46bdb8c24155d62083c0b47,839cff76a9b045f49a0b7c44f34d8561dc442870,280245f199d155794032fb4ea90f22c38de688bfb4e43c66507994610d01676b0c05eb1d531fe4cb628fee5ff00b863feec037088e128c0d4e875816c9a4b6bd",
|
"6286477a8da8d7b6f2fc9080d5e7a4091b1d506ee2dc4f81740b0f54f438537d,aeded4ba719eb6fed787d34b8064402082db7a4d,3df54218915767977bdf2bcde8b45a711caa460c3baa2448f91bc13731e6ea3d,946d3624e583fef1b46bdb8c24155d62083c0b47,839cff76a9b045f49a0b7c44f34d8561dc442870,280245f199d155794032fb4ea90f22c38de688bfb4e43c66507994610d01676b0c05eb1d531fe4cb628fee5ff00b863feec037088e128c0d4e875816c9a4b6bd,1d50401d65343f79ef63368043a0beba4171b86ef1991ec2b0be54b0f2e3f70a",
|
||||||
"47a8bb983cfc0387769dd6b80b8674c0531545c31cef0feff5c1113326003510,025c7f81895c1cd8e92c79a61a11b4b900eaf475,da19d198af8bcb060b07a8825f6898ac821b002b0e5da574cab2753bee430f8a,22292f488c729250acf0d2f7147fd6b2e6a808db,da91c4f8751060450782a9b023f6f5f4f2a0ee9f,aaebe082b58dce13087555d9ada0ec6c965acd39a014d47ad9f43700a8f36e466c5117165b4d585cc5bc5b295d9bbd6dcc8d27cce4a1c563ed1cfe1353186b79",
|
"47a8bb983cfc0387769dd6b80b8674c0531545c31cef0feff5c1113326003510,025c7f81895c1cd8e92c79a61a11b4b900eaf475,da19d198af8bcb060b07a8825f6898ac821b002b0e5da574cab2753bee430f8a,22292f488c729250acf0d2f7147fd6b2e6a808db,da91c4f8751060450782a9b023f6f5f4f2a0ee9f,aaebe082b58dce13087555d9ada0ec6c965acd39a014d47ad9f43700a8f36e466c5117165b4d585cc5bc5b295d9bbd6dcc8d27cce4a1c563ed1cfe1353186b79,73057ed727c4b004c3f3af867c667bff8b6671271a689c8ca99dd82f098e341b",
|
||||||
"8a329193ab14c37b397d749d1c254d9c5a962248cd2ad48460fb7cf659e89f52,ff4090d399bbb8e3220bc57ed13c6a0c44c79ea5,20460d4766c94a72ddef09c83f5eea9545af7826a446539c1a07291f6cdc5af4,eaf846e713cf63704cf1d80fd415265f4b5d6586,d45c9dc61b959c3548fe5c2de3781714d1dcf9f7,e5e62e56726480551da0b88de1657676979f3f5e6a028b3a0c91a186495060ebf5e4cab2c71675f36bd4b86c6ab8a1ee850eaffd93c28828504ae023783f6005",
|
"8a329193ab14c37b397d749d1c254d9c5a962248cd2ad48460fb7cf659e89f52,ff4090d399bbb8e3220bc57ed13c6a0c44c79ea5,20460d4766c94a72ddef09c83f5eea9545af7826a446539c1a07291f6cdc5af4,eaf846e713cf63704cf1d80fd415265f4b5d6586,d45c9dc61b959c3548fe5c2de3781714d1dcf9f7,e5e62e56726480551da0b88de1657676979f3f5e6a028b3a0c91a186495060ebf5e4cab2c71675f36bd4b86c6ab8a1ee850eaffd93c28828504ae023783f6005,fcf3adea6f02d4f2bc2ef3f0d2be9f190524c80d65a1d97f1f358e5048938229",
|
||||||
"96c37689f01bd39b6f163fbf4b1025653ea196f0abdb8a5dcd8cbc76c78f8cf5,f7edf6a546b5c7023ae146ac1ef58256f0578b73,34957be30df1b91070c9b39e086b31906e295574d315eaf2e91c6b45a292bb84,84795b00f8405a6ca0fab024991f34187a1be0c1,2367689553879bbcea1ba7608eb1905fb8230565,98bc48d3da9fcb8723b5e37ae30a8aa54a411eede7a9e5220c9ae849cbd591577991922b8995ef34704618b23f1961770c9f31ebe346ca6089da391c96c6a11d",
|
"96c37689f01bd39b6f163fbf4b1025653ea196f0abdb8a5dcd8cbc76c78f8cf5,f7edf6a546b5c7023ae146ac1ef58256f0578b73,34957be30df1b91070c9b39e086b31906e295574d315eaf2e91c6b45a292bb84,84795b00f8405a6ca0fab024991f34187a1be0c1,2367689553879bbcea1ba7608eb1905fb8230565,98bc48d3da9fcb8723b5e37ae30a8aa54a411eede7a9e5220c9ae849cbd591577991922b8995ef34704618b23f1961770c9f31ebe346ca6089da391c96c6a11d,2c292189440176ae193a5326e82b67fe058603a5f12ab3382e69e2eaaf457e4f",
|
||||||
"7eff84aeca24260baa06b61394bdec8b760a0c6558dd1748d91d6f492e0779b7,1c182efc13f2468d880372f4809d5a5e7011dfbf,13d1c9c1d3ac10cc78c43a2f0724a6a2e06adf5844a4ab45ff4779af1f15029d,8ce4f2abb9775f7e3cea0fa75238ab75cf6908e3,d3e2938a69fdce888260003f6f1702e9d3392ab0,4569f2282b016fee5b583390e709dd285eb09b7510bbe092f37e5fef581a78b42729eb9f46088d1d52a00f2f57d1ffd48ab64b5c0dfc38d01bf2c793c977fcfc",
|
"7eff84aeca24260baa06b61394bdec8b760a0c6558dd1748d91d6f492e0779b7,1c182efc13f2468d880372f4809d5a5e7011dfbf,13d1c9c1d3ac10cc78c43a2f0724a6a2e06adf5844a4ab45ff4779af1f15029d,8ce4f2abb9775f7e3cea0fa75238ab75cf6908e3,d3e2938a69fdce888260003f6f1702e9d3392ab0,4569f2282b016fee5b583390e709dd285eb09b7510bbe092f37e5fef581a78b42729eb9f46088d1d52a00f2f57d1ffd48ab64b5c0dfc38d01bf2c793c977fcfc,a1804b2d4eabf9a4ac77531f5f12d1b12fa5d7042d7e526c6c59ea7d4259d338",
|
||||||
"c7acfcf801519b59c4750b06d6d55b1915f3a0317859685dd2ae337a6065d4bb,384c59c208e92c46e4fb8bcea9e286181ee4f956,4853fbb9eafeb0bfe2d717ad34973ea979413874e97d92d7a85c16a8fb61626e,e45f80b6cd0533e8b6f9a974b17c20244812e0fe,d531970c5f1ca7d0772513b32e8b75fa837c27fd,fc7946c37e09c86ce48e704f162e96c06cd227df7813dcc910fb56793a8cd5b0f205207292f6c7d34aeddeae80d3a6243409f2d4bd11e0f4eba5e6711df77586",
|
"c7acfcf801519b59c4750b06d6d55b1915f3a0317859685dd2ae337a6065d4bb,384c59c208e92c46e4fb8bcea9e286181ee4f956,4853fbb9eafeb0bfe2d717ad34973ea979413874e97d92d7a85c16a8fb61626e,e45f80b6cd0533e8b6f9a974b17c20244812e0fe,d531970c5f1ca7d0772513b32e8b75fa837c27fd,fc7946c37e09c86ce48e704f162e96c06cd227df7813dcc910fb56793a8cd5b0f205207292f6c7d34aeddeae80d3a6243409f2d4bd11e0f4eba5e6711df77586,cf385747877b360b3582331aa1473039946c57c59d7969988b103c26cd43c949",
|
||||||
"b53e7fb86d09133c5d1bfccae6a16652d26376784ec97995c9173f8d4d9151bc,69a8d04118b7f4e5c49a877ea2a1e6d9bdcc6dc5,33cb2e45fe278f822c9f8f0b0f6ca7c0aa84e588237a70e0870607756bdb18e0,f17ef3913819472407b45b9bf2bf454b4185bfe7,75cd9d71a818ccfc234c80cd89b6b52b898530bc,008892ec410fcc7197049a9967738edff5abeef1e29eb03a2b3f1939433f16ce284a9d3be887b3b1500161a38a617e8e467b4564bb6d030f617fc996d3a26dd2",
|
"b53e7fb86d09133c5d1bfccae6a16652d26376784ec97995c9173f8d4d9151bc,69a8d04118b7f4e5c49a877ea2a1e6d9bdcc6dc5,33cb2e45fe278f822c9f8f0b0f6ca7c0aa84e588237a70e0870607756bdb18e0,f17ef3913819472407b45b9bf2bf454b4185bfe7,75cd9d71a818ccfc234c80cd89b6b52b898530bc,008892ec410fcc7197049a9967738edff5abeef1e29eb03a2b3f1939433f16ce284a9d3be887b3b1500161a38a617e8e467b4564bb6d030f617fc996d3a26dd2,b8b865556a937c3c0dbed23abe2d40ed424b5fb53d22ed83db9eec00dc15e4cf",
|
||||||
"7125adb44be6dc3bea98c348fc546b92371e99b4294d753c3a2c408447057a48,06fed168e3f0a8928d56c847364caeaf63c11f34,721e34ca27da076c1e18b51ffbf1f2921a431f55e83f85c4cbe679d5e081c120,023445e83064df92dcd60478cd68ea45f032d5c0,d0e99a8e4a7ba80bcc861b6dc81c29547dfd7dae,a485d3f5f22d70dae68176b76df8f8173adae876dcae8e93c5156277204a507484a50cc25b40e967ed75c4eaf29cda8e97ab8b05f72fa30a28e11ed9a30c6f7a",
|
"7125adb44be6dc3bea98c348fc546b92371e99b4294d753c3a2c408447057a48,06fed168e3f0a8928d56c847364caeaf63c11f34,721e34ca27da076c1e18b51ffbf1f2921a431f55e83f85c4cbe679d5e081c120,023445e83064df92dcd60478cd68ea45f032d5c0,d0e99a8e4a7ba80bcc861b6dc81c29547dfd7dae,a485d3f5f22d70dae68176b76df8f8173adae876dcae8e93c5156277204a507484a50cc25b40e967ed75c4eaf29cda8e97ab8b05f72fa30a28e11ed9a30c6f7a,4e788e256ab33c5143425544bfa179e4a0a529142670dd45cda42f26a3b8d4f0",
|
||||||
"34ab9bc63b31a019e59af803cd9365500ed01e36e5d8e166d7fa22a3dd06a4b2,495804100e19df440a1026e016c3a55800064bed,203f617d00fada67c5d5f48736793d79d3b75633e8977d531a035b51df696853,4278ed1405c4d61d35bf2dbd8b0ad17cf8eb2de8,23656338b7894db5ca7c5804e91a128cf0d17acf,4ab854a2ce4f7a2ac71fb0b84b88f960cc0fd7467b9a6e298243b0117e8d38525876608fa403d43bceb2aee43abebac670db6e74a2f346cb1a254aa942cc1fbd",
|
"34ab9bc63b31a019e59af803cd9365500ed01e36e5d8e166d7fa22a3dd06a4b2,495804100e19df440a1026e016c3a55800064bed,203f617d00fada67c5d5f48736793d79d3b75633e8977d531a035b51df696853,4278ed1405c4d61d35bf2dbd8b0ad17cf8eb2de8,23656338b7894db5ca7c5804e91a128cf0d17acf,4ab854a2ce4f7a2ac71fb0b84b88f960cc0fd7467b9a6e298243b0117e8d38525876608fa403d43bceb2aee43abebac670db6e74a2f346cb1a254aa942cc1fbd,666855a84f4be9a469296f20dd660126490ecf2d7bacda3f9e2a0dd11ca20636",
|
||||||
"93dc29da56fac0a611c8c5014bc61a6c3861ae9def571818664c7e44b25a954d,ceb1b9394c434c5a1648112477c5f674ed4430ca,f3a1d0c012317a4802aa52ae17c03e6bb8f769d35c909af8c0dbab16fe238d79,31c690c105e778b5941492cdffa5a817adc14202,ac6975f571f6e961c3db6ac29cfc7e975b2aaa09,f2f758a0e28f40d2b13a590d57875295668f12725a1536b513b19f59b65f88f885229ef424f8b226ee5b53749097ca70aa8b6dbb3650779074775239c652b70c",
|
"93dc29da56fac0a611c8c5014bc61a6c3861ae9def571818664c7e44b25a954d,ceb1b9394c434c5a1648112477c5f674ed4430ca,f3a1d0c012317a4802aa52ae17c03e6bb8f769d35c909af8c0dbab16fe238d79,31c690c105e778b5941492cdffa5a817adc14202,ac6975f571f6e961c3db6ac29cfc7e975b2aaa09,f2f758a0e28f40d2b13a590d57875295668f12725a1536b513b19f59b65f88f885229ef424f8b226ee5b53749097ca70aa8b6dbb3650779074775239c652b70c,f091844b69ab5e3075255831b61ef62712adecbb9403c4b2b4f2719786bc4405",
|
||||||
"f6372c5a3c6957b655d56167a4e723fc0eefdd3abf1857b2c7d797a0be0e4b0e,960b962cea70b57c7edc4f137261f94829957a3b,70eeaa3dc29f434da194e23bb5eb1001e9012bab15bec0fb9532c63f022c19a8,80f5a9119a99ef6bc04a1944f256fc8176216ad2,d535e38f334aa06538ea644849b80972a7fe6c6f,ac08b0031b5026157997b5c4a5f60df1c8afd39c5d7691033c72d65e4fa06312b48dd0cf46dd350188563c957ddabdb4b06ed2e9b4be2babcf640825358b555e"
|
"f6372c5a3c6957b655d56167a4e723fc0eefdd3abf1857b2c7d797a0be0e4b0e,960b962cea70b57c7edc4f137261f94829957a3b,70eeaa3dc29f434da194e23bb5eb1001e9012bab15bec0fb9532c63f022c19a8,80f5a9119a99ef6bc04a1944f256fc8176216ad2,d535e38f334aa06538ea644849b80972a7fe6c6f,ac08b0031b5026157997b5c4a5f60df1c8afd39c5d7691033c72d65e4fa06312b48dd0cf46dd350188563c957ddabdb4b06ed2e9b4be2babcf640825358b555e,bf166ee74cf3c2dfcc88dd9c6d548438b9b76fa03df6589990997f44fa4b6f13"
|
||||||
)
|
)
|
||||||
|
|
||||||
private lazy val hashes = lines.map { line =>
|
private lazy val hashes = lines.map { line =>
|
||||||
|
@ -32,7 +32,8 @@ class HashingTest extends BitcoinSCryptoTest {
|
||||||
val ripeMd160 = RipeMd160Digest.fromHex(arr(3))
|
val ripeMd160 = RipeMd160Digest.fromHex(arr(3))
|
||||||
val sha256Hash160 = Sha256Hash160Digest.fromHex(arr(4))
|
val sha256Hash160 = Sha256Hash160Digest.fromHex(arr(4))
|
||||||
val hmac = ByteVector.fromValidHex(arr(5))
|
val hmac = ByteVector.fromValidHex(arr(5))
|
||||||
(data, sha1, sha256, ripeMd160, sha256Hash160, hmac)
|
val sha3_256 = Sha3_256Digest.fromHex(arr(6))
|
||||||
|
(data, sha1, sha256, ripeMd160, sha256Hash160, hmac, sha3_256)
|
||||||
}
|
}
|
||||||
|
|
||||||
it must "compute sha1" in {
|
it must "compute sha1" in {
|
||||||
|
@ -68,6 +69,12 @@ class HashingTest extends BitcoinSCryptoTest {
|
||||||
assert(actual == expected)
|
assert(actual == expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it must "compute sha3-256" in {
|
||||||
|
val expected = hashes.map(_._7)
|
||||||
|
val actual = hashes.map(_._1).map(BCryptoCryptoRuntime.sha3_256)
|
||||||
|
assert(actual == expected)
|
||||||
|
}
|
||||||
|
|
||||||
// From https://github.com/dgarage/NDLC/blob/d816c0c517611b336f09ceaa43d400ecb5ab909b/NDLC.Tests/Data/normalization_tests.json
|
// From https://github.com/dgarage/NDLC/blob/d816c0c517611b336f09ceaa43d400ecb5ab909b/NDLC.Tests/Data/normalization_tests.json
|
||||||
it must "normalize and serialize strings correctly" in {
|
it must "normalize and serialize strings correctly" in {
|
||||||
val singletons = Vector("\u00c5", "\u212b", "\u0041\u030a")
|
val singletons = Vector("\u00c5", "\u212b", "\u0041\u030a")
|
||||||
|
|
|
@ -238,4 +238,12 @@ class CryptoUtilTest extends BitcoinSCryptoTest {
|
||||||
assert(CryptoUtil.checkEntropy(bytes))
|
assert(CryptoUtil.checkEntropy(bytes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it must "perform a SHA3-256 hash" in {
|
||||||
|
val hash = CryptoUtil.sha3_256(hex"")
|
||||||
|
val expected =
|
||||||
|
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"
|
||||||
|
hash.hex must be(expected)
|
||||||
|
hash.flip.flip.hex must be(expected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ trait BCryptoCryptoRuntime extends CryptoRuntime {
|
||||||
private lazy val sha256 = SHA256Factory.create()
|
private lazy val sha256 = SHA256Factory.create()
|
||||||
private lazy val sha512 = SHA512Factory.create()
|
private lazy val sha512 = SHA512Factory.create()
|
||||||
private lazy val hmac = SHA512.hmac.apply().asInstanceOf[HMAC]
|
private lazy val hmac = SHA512.hmac.apply().asInstanceOf[HMAC]
|
||||||
|
private lazy val sha3_256 = new SHA3_256
|
||||||
|
|
||||||
private lazy val randomBytesFunc: Int => ByteVector = { int =>
|
private lazy val randomBytesFunc: Int => ByteVector = { int =>
|
||||||
try {
|
try {
|
||||||
|
@ -77,6 +78,15 @@ trait BCryptoCryptoRuntime extends CryptoRuntime {
|
||||||
Sha256Digest.fromBytes(hashByteVec)
|
Sha256Digest.fromBytes(hashByteVec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def sha3_256(bytes: ByteVector): Sha3_256Digest = {
|
||||||
|
val buffer = CryptoJsUtil.toNodeBuffer(bytes)
|
||||||
|
sha3_256.init()
|
||||||
|
sha3_256.update(buffer)
|
||||||
|
val hashBuffer = sha3_256.`final`()
|
||||||
|
val hashByteVec = CryptoJsUtil.toByteVector(hashBuffer)
|
||||||
|
Sha3_256Digest.fromBytes(hashByteVec)
|
||||||
|
}
|
||||||
|
|
||||||
def sha512(bytes: ByteVector): ByteVector = {
|
def sha512(bytes: ByteVector): ByteVector = {
|
||||||
val buffer = CryptoJsUtil.toNodeBuffer(bytes)
|
val buffer = CryptoJsUtil.toNodeBuffer(bytes)
|
||||||
sha512.init()
|
sha512.init()
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.bitcoins.crypto.facade
|
||||||
|
|
||||||
|
import org.bitcoins.crypto.Hasher
|
||||||
|
|
||||||
|
import scala.scalajs.js
|
||||||
|
import scala.scalajs.js.annotation._
|
||||||
|
|
||||||
|
@js.native
|
||||||
|
@JSImport("bcrypto/lib/sha3-256.js", JSImport.Default)
|
||||||
|
class SHA3_256 extends Hasher {
|
||||||
|
|
||||||
|
override def init(): Unit = js.native
|
||||||
|
|
||||||
|
override def update(bytes: Buffer): Unit = js.native
|
||||||
|
|
||||||
|
override def `final`(): Buffer = js.native
|
||||||
|
}
|
|
@ -114,6 +114,11 @@ trait BouncycastleCryptoRuntime extends CryptoRuntime {
|
||||||
Sha256Digest(ByteVector(hash))
|
Sha256Digest(ByteVector(hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def sha3_256(bytes: ByteVector): Sha3_256Digest = {
|
||||||
|
val hash = MessageDigest.getInstance("SHA3-256").digest(bytes.toArray)
|
||||||
|
Sha3_256Digest(ByteVector(hash))
|
||||||
|
}
|
||||||
|
|
||||||
override def sha1(bytes: ByteVector): Sha1Digest = {
|
override def sha1(bytes: ByteVector): Sha1Digest = {
|
||||||
val hash = MessageDigest.getInstance("SHA-1").digest(bytes.toArray).toList
|
val hash = MessageDigest.getInstance("SHA-1").digest(bytes.toArray).toList
|
||||||
Sha1Digest(ByteVector(hash))
|
Sha1Digest(ByteVector(hash))
|
||||||
|
|
|
@ -30,6 +30,10 @@ trait LibSecp256k1CryptoRuntime extends CryptoRuntime {
|
||||||
BouncycastleCryptoRuntime.sha256(bytes)
|
BouncycastleCryptoRuntime.sha256(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def sha3_256(bytes: ByteVector): Sha3_256Digest = {
|
||||||
|
BouncycastleCryptoRuntime.sha3_256(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
override def sha1(bytes: ByteVector): Sha1Digest = {
|
override def sha1(bytes: ByteVector): Sha1Digest = {
|
||||||
BouncycastleCryptoRuntime.sha1(bytes)
|
BouncycastleCryptoRuntime.sha1(bytes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ trait CryptoRuntime {
|
||||||
sha256(bitVector.toByteVector)
|
sha256(bitVector.toByteVector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def sha3_256(bytes: ByteVector): Sha3_256Digest
|
||||||
|
|
||||||
def taggedSha256(bytes: ByteVector, tag: String): Sha256Digest = {
|
def taggedSha256(bytes: ByteVector, tag: String): Sha256Digest = {
|
||||||
val tagHash = sha256(tag)
|
val tagHash = sha256(tag)
|
||||||
val tagBytes = tagHash.bytes ++ tagHash.bytes
|
val tagBytes = tagHash.bytes ++ tagHash.bytes
|
||||||
|
|
|
@ -50,6 +50,11 @@ trait CryptoUtil extends CryptoRuntime {
|
||||||
cryptoRuntime.taggedSha256(serializeForHash(str), tag)
|
cryptoRuntime.taggedSha256(serializeForHash(str), tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Performs SHA3-256(bytes) */
|
||||||
|
override def sha3_256(bytes: ByteVector): Sha3_256Digest = {
|
||||||
|
cryptoRuntime.sha3_256(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
/** Performs SHA1(bytes). */
|
/** Performs SHA1(bytes). */
|
||||||
override def sha1(bytes: ByteVector): Sha1Digest = {
|
override def sha1(bytes: ByteVector): Sha1Digest = {
|
||||||
cryptoRuntime.sha1(bytes)
|
cryptoRuntime.sha1(bytes)
|
||||||
|
|
|
@ -246,3 +246,56 @@ object Sha256Hash160DigestBE extends Factory[Sha256Hash160DigestBE] {
|
||||||
Sha256Hash160DigestBEImpl(bytes)
|
Sha256Hash160DigestBEImpl(bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Represents the result of SHA3-256()
|
||||||
|
*/
|
||||||
|
sealed trait Sha3_256Digest extends Any with HashDigest {
|
||||||
|
override def flip: Sha3_256DigestBE = Sha3_256DigestBE(bytes.reverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Sha3_256Digest extends Factory[Sha3_256Digest] {
|
||||||
|
|
||||||
|
private case class Sha3_256DigestImpl(bytes: ByteVector)
|
||||||
|
extends AnyVal
|
||||||
|
with Sha3_256Digest {
|
||||||
|
override def toString = s"Sha3-256DigestImpl($hex)"
|
||||||
|
// $COVERAGE-ON$
|
||||||
|
}
|
||||||
|
|
||||||
|
override def fromBytes(bytes: ByteVector): Sha3_256Digest = {
|
||||||
|
require(bytes.length == 32,
|
||||||
|
// $COVERAGE-OFF$
|
||||||
|
"Sha3-256Digest must be 32 bytes in size, got: " + bytes.length)
|
||||||
|
Sha3_256DigestImpl(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val e = ByteVector(Array.fill(32)(0.toByte))
|
||||||
|
|
||||||
|
val empty: Sha3_256Digest = Sha3_256Digest.fromBytes(e)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents the result of SHA3-256()
|
||||||
|
*/
|
||||||
|
sealed trait Sha3_256DigestBE extends Any with HashDigest {
|
||||||
|
override def flip: Sha3_256Digest = Sha3_256Digest(bytes.reverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Sha3_256DigestBE extends Factory[Sha3_256DigestBE] {
|
||||||
|
|
||||||
|
private case class Sha3_256DigestBEImpl(bytes: ByteVector)
|
||||||
|
extends AnyVal
|
||||||
|
with Sha3_256DigestBE {
|
||||||
|
override def toString = s"Sha3-256DigestBEImpl($hex)"
|
||||||
|
// $COVERAGE-ON$
|
||||||
|
}
|
||||||
|
|
||||||
|
override def fromBytes(bytes: ByteVector): Sha3_256DigestBE = {
|
||||||
|
require(bytes.length == 32,
|
||||||
|
// $COVERAGE-OFF$
|
||||||
|
"Sha3-256Digest must be 32 bytes in size, got: " + bytes.length)
|
||||||
|
Sha3_256DigestBEImpl(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy val empty: Sha256DigestBE = Sha256DigestBE(ByteVector.low(32))
|
||||||
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ val nodeF = for {
|
||||||
peer <- peerF
|
peer <- peerF
|
||||||
} yield {
|
} yield {
|
||||||
val dataMessageHandler = DataMessageHandler(chainApi)
|
val dataMessageHandler = DataMessageHandler(chainApi)
|
||||||
NeutrinoNode(nodePeer = Vector(peer),
|
NeutrinoNode(configPeersOverride = Vector(peer),
|
||||||
dataMessageHandler = dataMessageHandler,
|
dataMessageHandler = dataMessageHandler,
|
||||||
nodeConfig = nodeConfig,
|
nodeConfig = nodeConfig,
|
||||||
chainConfig = chainConfig,
|
chainConfig = chainConfig,
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package org.bitcoins.node
|
package org.bitcoins.node
|
||||||
|
|
||||||
import akka.actor.Cancellable
|
import akka.actor.Cancellable
|
||||||
|
import org.bitcoins.core.util.NetworkUtil
|
||||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||||
|
import org.bitcoins.node.models.PeerDAO
|
||||||
import org.bitcoins.server.BitcoinSAppConfig
|
import org.bitcoins.server.BitcoinSAppConfig
|
||||||
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
import org.bitcoins.testkit.BitcoinSTestAppConfig
|
||||||
import org.bitcoins.testkit.node.fixture.NeutrinoNodeConnectedWithBitcoinds
|
import org.bitcoins.testkit.node.fixture.NeutrinoNodeConnectedWithBitcoinds
|
||||||
|
@ -39,12 +41,13 @@ class NeutrinoNodeTest extends NodeTestWithCachedBitcoindPair {
|
||||||
nodeConnectedWithBitcoind: NeutrinoNodeConnectedWithBitcoinds =>
|
nodeConnectedWithBitcoind: NeutrinoNodeConnectedWithBitcoinds =>
|
||||||
//checking all peers are connected
|
//checking all peers are connected
|
||||||
val node = nodeConnectedWithBitcoind.node
|
val node = nodeConnectedWithBitcoind.node
|
||||||
val connFs = node.peers.indices.map(node.isConnected)
|
val connFs = node.peerManager.peers.indices.map(node.isConnected)
|
||||||
val connF = Future.sequence(connFs).map(_.forall(_ == true))
|
val connF = Future.sequence(connFs).map(_.forall(_ == true))
|
||||||
val connAssertion = connF.map(assert(_))
|
val connAssertion = connF.map(assert(_))
|
||||||
|
|
||||||
//checking all peers are initialized
|
//checking all peers are initialized
|
||||||
val isInitializedFs = node.peers.indices.map(node.isInitialized)
|
val isInitializedFs =
|
||||||
|
node.peerManager.peers.indices.map(node.isInitialized)
|
||||||
val isInitializedF = for {
|
val isInitializedF = for {
|
||||||
_ <- connAssertion
|
_ <- connAssertion
|
||||||
f <- Future.sequence(isInitializedFs).map(_.forall(_ == true))
|
f <- Future.sequence(isInitializedFs).map(_.forall(_ == true))
|
||||||
|
@ -60,6 +63,45 @@ class NeutrinoNodeTest extends NodeTestWithCachedBitcoindPair {
|
||||||
disconnF.map(assert(_))
|
disconnF.map(assert(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it must "store peer after successful initialization" in {
|
||||||
|
nodeConnectedWithBitcoind: NeutrinoNodeConnectedWithBitcoinds =>
|
||||||
|
val node = nodeConnectedWithBitcoind.node
|
||||||
|
|
||||||
|
val assertConnAndInit = for {
|
||||||
|
_ <- node.isConnected(0).map(assert(_))
|
||||||
|
a2 <- node.isInitialized(0).map(assert(_))
|
||||||
|
} yield a2
|
||||||
|
|
||||||
|
for {
|
||||||
|
_ <- assertConnAndInit
|
||||||
|
peerDbs <- PeerDAO()(executionContext, node.nodeAppConfig).findAll()
|
||||||
|
} yield {
|
||||||
|
val compares = for {
|
||||||
|
peer <- node.peerManager.peers
|
||||||
|
peerDb <- peerDbs
|
||||||
|
} yield {
|
||||||
|
val dbSocket =
|
||||||
|
NetworkUtil.parseInetSocketAddress(peerDb.address, peerDb.port)
|
||||||
|
|
||||||
|
val hostMatch: Boolean = {
|
||||||
|
if (dbSocket.getHostString == peer.socket.getHostString) true
|
||||||
|
else {
|
||||||
|
//checking if both are localhost
|
||||||
|
//a bit hacky way but resolution of localhost to address cannot be done so as to allow for tor
|
||||||
|
//addresses too
|
||||||
|
val localhost = Vector("localhost", "127.0.0.1")
|
||||||
|
localhost.contains(dbSocket.getHostString) && localhost.contains(
|
||||||
|
peer.socket.getHostString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hostMatch && dbSocket.getPort == peer.socket.getPort
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(compares.exists(p => p))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
it must "receive notification that a block occurred on the p2p network for neutrino" in {
|
it must "receive notification that a block occurred on the p2p network for neutrino" in {
|
||||||
nodeConnectedWithBitcoind: NeutrinoNodeConnectedWithBitcoinds =>
|
nodeConnectedWithBitcoind: NeutrinoNodeConnectedWithBitcoinds =>
|
||||||
val node = nodeConnectedWithBitcoind.node
|
val node = nodeConnectedWithBitcoind.node
|
||||||
|
@ -137,7 +179,7 @@ class NeutrinoNodeTest extends NodeTestWithCachedBitcoindPair {
|
||||||
|
|
||||||
//checking all peers can be disconnected
|
//checking all peers can be disconnected
|
||||||
private def isAllDisconnectedF(node: Node): Future[Boolean] = {
|
private def isAllDisconnectedF(node: Node): Future[Boolean] = {
|
||||||
val disconnFs = node.peers.indices.map(node.isDisconnected)
|
val disconnFs = node.peerManager.peers.indices.map(node.isDisconnected)
|
||||||
val res = Future.sequence(disconnFs).map(_.forall(_ == true))
|
val res = Future.sequence(disconnFs).map(_.forall(_ == true))
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,8 @@ class PeerMessageReceiverTest extends NodeTestWithCachedBitcoindPair {
|
||||||
verackMsgP = verackMsgP)
|
verackMsgP = verackMsgP)
|
||||||
|
|
||||||
val peerMsgReceiver =
|
val peerMsgReceiver =
|
||||||
PeerMessageReceiver(normal, node, node.peers.head)(system,
|
PeerMessageReceiver(normal, node, node.peerManager.peers.head)(
|
||||||
|
system,
|
||||||
node.nodeAppConfig)
|
node.nodeAppConfig)
|
||||||
|
|
||||||
val newMsgReceiver = peerMsgReceiver.disconnect()
|
val newMsgReceiver = peerMsgReceiver.disconnect()
|
||||||
|
@ -108,7 +109,8 @@ class PeerMessageReceiverTest extends NodeTestWithCachedBitcoindPair {
|
||||||
verackMsgP = verackMsgP)
|
verackMsgP = verackMsgP)
|
||||||
|
|
||||||
val peerMsgReceiver =
|
val peerMsgReceiver =
|
||||||
PeerMessageReceiver(normal, node, node.peers.head)(system,
|
PeerMessageReceiver(normal, node, node.peerManager.peers.head)(
|
||||||
|
system,
|
||||||
node.nodeAppConfig)
|
node.nodeAppConfig)
|
||||||
|
|
||||||
val newMsgReceiver = peerMsgReceiver.initializeDisconnect()
|
val newMsgReceiver = peerMsgReceiver.initializeDisconnect()
|
||||||
|
|
676
node/src/main/resources/hardcoded-peers.txt
Normal file
676
node/src/main/resources/hardcoded-peers.txt
Normal file
|
@ -0,0 +1,676 @@
|
||||||
|
2.39.173.126:8333
|
||||||
|
3.14.168.201:48333
|
||||||
|
4.36.112.44:8333
|
||||||
|
5.8.18.31:8333
|
||||||
|
5.14.200.167:8333
|
||||||
|
5.56.20.2:8333
|
||||||
|
5.102.146.99:8333
|
||||||
|
5.103.137.146:9333
|
||||||
|
5.128.87.126:8333
|
||||||
|
5.133.65.82:8333
|
||||||
|
5.187.55.242:8333
|
||||||
|
5.188.62.24:8333
|
||||||
|
5.188.62.33:8333
|
||||||
|
5.199.133.193:8333
|
||||||
|
8.38.89.152:8333
|
||||||
|
13.231.20.249:8333
|
||||||
|
18.27.79.17:8333
|
||||||
|
20.184.15.116:8433
|
||||||
|
23.28.205.97:8333
|
||||||
|
23.106.252.230:8333
|
||||||
|
23.175.0.202:8333
|
||||||
|
23.175.0.212:8333
|
||||||
|
23.241.250.252:8333
|
||||||
|
23.245.24.154:8333
|
||||||
|
24.86.184.66:8333
|
||||||
|
24.116.246.9:8333
|
||||||
|
24.141.34.166:8333
|
||||||
|
24.155.196.246:8333
|
||||||
|
24.157.130.222:8333
|
||||||
|
24.188.176.255:8333
|
||||||
|
24.237.70.53:8333
|
||||||
|
27.124.4.67:8333
|
||||||
|
31.17.70.80:8333
|
||||||
|
31.21.8.32:8333
|
||||||
|
31.45.118.10:8333
|
||||||
|
31.132.17.56:8333
|
||||||
|
31.134.121.223:8333
|
||||||
|
32.214.183.114:8333
|
||||||
|
35.137.236.32:8333
|
||||||
|
35.185.145.105:8333
|
||||||
|
35.209.51.212:8333
|
||||||
|
35.245.175.76:8333
|
||||||
|
37.116.95.41:8333
|
||||||
|
37.143.9.107:8333
|
||||||
|
37.143.116.43:8333
|
||||||
|
37.191.244.149:8333
|
||||||
|
37.211.78.253:8333
|
||||||
|
37.221.209.222:24333
|
||||||
|
37.228.92.110:8333
|
||||||
|
43.225.62.107:8333
|
||||||
|
43.225.157.152:8333
|
||||||
|
45.36.184.6:8333
|
||||||
|
45.48.168.16:8333
|
||||||
|
45.85.85.8:8333
|
||||||
|
45.85.85.9:8333
|
||||||
|
45.129.180.214:8333
|
||||||
|
45.149.78.128:8333
|
||||||
|
45.151.125.218:8333
|
||||||
|
45.154.255.46:8333
|
||||||
|
45.155.157.239:8333
|
||||||
|
46.28.132.34:8333
|
||||||
|
46.28.204.21:8333
|
||||||
|
46.32.50.98:8333
|
||||||
|
46.59.13.35:8333
|
||||||
|
46.128.40.173:8333
|
||||||
|
46.128.140.193:8333
|
||||||
|
46.146.248.89:8333
|
||||||
|
46.166.162.45:20001
|
||||||
|
46.188.15.6:8333
|
||||||
|
46.229.165.142:8333
|
||||||
|
46.229.238.187:8333
|
||||||
|
46.249.83.82:8333
|
||||||
|
46.254.217.169:8333
|
||||||
|
47.74.191.34:8333
|
||||||
|
47.115.53.163:8333
|
||||||
|
47.187.26.135:8333
|
||||||
|
47.222.103.234:8333
|
||||||
|
47.253.5.99:8333
|
||||||
|
49.232.82.76:8333
|
||||||
|
49.247.215.43:8333
|
||||||
|
50.2.13.166:8333
|
||||||
|
50.34.39.72:8333
|
||||||
|
50.45.232.189:8333
|
||||||
|
50.68.104.92:8333
|
||||||
|
51.68.36.57:8333
|
||||||
|
51.154.60.34:8333
|
||||||
|
52.169.238.66:8333
|
||||||
|
54.197.30.223:8333
|
||||||
|
54.227.66.57:8333
|
||||||
|
58.158.0.86:8333
|
||||||
|
58.171.135.242:8333
|
||||||
|
58.229.208.158:8333
|
||||||
|
60.244.109.19:8333
|
||||||
|
62.38.75.208:8333
|
||||||
|
62.74.143.11:8333
|
||||||
|
62.80.227.49:8333
|
||||||
|
62.152.58.16:9421
|
||||||
|
62.210.167.199:8333
|
||||||
|
62.234.188.160:8333
|
||||||
|
62.251.54.163:8333
|
||||||
|
63.227.116.162:8333
|
||||||
|
65.19.155.82:8333
|
||||||
|
65.95.49.102:8333
|
||||||
|
66.18.172.21:8333
|
||||||
|
66.240.237.155:8333
|
||||||
|
67.210.228.203:8333
|
||||||
|
69.30.215.42:8333
|
||||||
|
69.59.18.206:8333
|
||||||
|
69.64.33.71:8333
|
||||||
|
69.119.193.9:8333
|
||||||
|
69.209.23.72:8333
|
||||||
|
70.123.125.237:8333
|
||||||
|
70.185.56.136:8333
|
||||||
|
71.38.90.235:8333
|
||||||
|
72.12.73.70:8333
|
||||||
|
72.53.134.182:8333
|
||||||
|
72.225.7.80:8333
|
||||||
|
72.234.182.39:8333
|
||||||
|
72.250.184.57:8333
|
||||||
|
73.83.103.79:8333
|
||||||
|
74.118.137.119:8333
|
||||||
|
74.133.100.74:8333
|
||||||
|
74.215.219.214:8333
|
||||||
|
74.220.255.190:8333
|
||||||
|
75.158.39.231:8333
|
||||||
|
77.53.53.196:8333
|
||||||
|
77.70.16.245:8333
|
||||||
|
77.105.87.97:8333
|
||||||
|
77.120.113.69:8433
|
||||||
|
77.120.122.22:8433
|
||||||
|
77.166.83.167:8333
|
||||||
|
77.247.178.130:8333
|
||||||
|
78.27.139.13:8333
|
||||||
|
78.63.28.146:8333
|
||||||
|
78.83.103.4:8333
|
||||||
|
78.141.123.99:8333
|
||||||
|
79.77.33.131:8333
|
||||||
|
79.77.133.30:8333
|
||||||
|
79.101.1.25:8333
|
||||||
|
79.117.192.229:8333
|
||||||
|
79.133.228.55:8333
|
||||||
|
79.146.21.163:8333
|
||||||
|
80.89.203.172:8001
|
||||||
|
80.93.213.246:8333
|
||||||
|
80.192.98.110:8334
|
||||||
|
80.229.28.60:8333
|
||||||
|
80.232.247.210:8333
|
||||||
|
80.242.39.76:8333
|
||||||
|
80.253.94.252:8333
|
||||||
|
81.0.198.25:8333
|
||||||
|
81.7.13.84:8333
|
||||||
|
81.117.225.245:8333
|
||||||
|
81.135.137.225:8333
|
||||||
|
81.171.22.143:8333
|
||||||
|
81.191.233.134:8333
|
||||||
|
81.232.78.75:8333
|
||||||
|
81.242.91.23:8333
|
||||||
|
82.29.58.109:8333
|
||||||
|
82.136.99.22:8333
|
||||||
|
82.149.97.25:17567
|
||||||
|
82.165.19.48:8333
|
||||||
|
82.194.153.233:8333
|
||||||
|
82.197.215.125:8333
|
||||||
|
82.199.102.10:8333
|
||||||
|
82.200.205.30:8333
|
||||||
|
82.202.68.231:8333
|
||||||
|
82.221.128.31:8333
|
||||||
|
82.228.6.131:8333
|
||||||
|
83.85.139.94:8333
|
||||||
|
83.99.245.20:8333
|
||||||
|
83.137.41.10:8333
|
||||||
|
83.174.209.87:8333
|
||||||
|
83.217.8.31:44420
|
||||||
|
84.38.3.249:8333
|
||||||
|
84.38.185.122:8333
|
||||||
|
84.92.92.247:8333
|
||||||
|
84.192.16.234:8333
|
||||||
|
84.194.158.124:8333
|
||||||
|
84.212.145.24:8333
|
||||||
|
84.212.244.95:8333
|
||||||
|
84.216.51.36:8333
|
||||||
|
84.255.249.163:8333
|
||||||
|
85.25.255.147:8333
|
||||||
|
85.70.156.209:8333
|
||||||
|
85.145.142.46:8333
|
||||||
|
85.170.233.95:8333
|
||||||
|
85.184.138.108:8333
|
||||||
|
85.190.0.5:8333
|
||||||
|
85.191.200.51:8333
|
||||||
|
85.192.191.6:18500
|
||||||
|
85.194.238.131:8333
|
||||||
|
85.195.54.110:8333
|
||||||
|
85.214.161.252:8333
|
||||||
|
85.214.185.51:8333
|
||||||
|
85.241.106.203:8333
|
||||||
|
85.246.168.252:8333
|
||||||
|
86.56.238.247:8333
|
||||||
|
87.61.90.230:8333
|
||||||
|
87.79.68.86:8333
|
||||||
|
87.79.94.221:8333
|
||||||
|
87.120.8.5:20008
|
||||||
|
87.246.46.132:8333
|
||||||
|
87.247.111.222:8333
|
||||||
|
88.84.222.252:8333
|
||||||
|
88.86.243.241:8333
|
||||||
|
88.87.93.52:1691
|
||||||
|
88.119.197.200:8333
|
||||||
|
88.129.253.94:8333
|
||||||
|
88.147.244.250:8333
|
||||||
|
88.208.3.195:8333
|
||||||
|
88.212.44.33:8333
|
||||||
|
88.214.57.95:8333
|
||||||
|
89.106.199.38:8333
|
||||||
|
89.108.126.228:8333
|
||||||
|
89.115.120.43:8333
|
||||||
|
89.133.68.65:8333
|
||||||
|
89.190.19.162:8333
|
||||||
|
89.248.172.10:8333
|
||||||
|
90.146.153.21:8333
|
||||||
|
90.182.165.18:8333
|
||||||
|
91.106.188.229:8333
|
||||||
|
91.193.237.116:8333
|
||||||
|
91.204.99.178:8333
|
||||||
|
91.204.149.5:8333
|
||||||
|
91.214.70.63:8333
|
||||||
|
91.228.152.236:8333
|
||||||
|
92.12.154.115:8333
|
||||||
|
92.249.143.44:8333
|
||||||
|
93.12.66.98:8333
|
||||||
|
93.46.54.4:8333
|
||||||
|
93.115.20.130:8333
|
||||||
|
93.123.180.164:8333
|
||||||
|
93.189.145.169:8333
|
||||||
|
93.241.228.102:8333
|
||||||
|
94.19.7.55:8333
|
||||||
|
94.19.128.204:8333
|
||||||
|
94.52.112.227:8333
|
||||||
|
94.154.96.130:8333
|
||||||
|
94.156.174.201:8333
|
||||||
|
94.158.246.183:8333
|
||||||
|
94.177.171.73:8333
|
||||||
|
94.199.178.233:8100
|
||||||
|
94.237.125.30:8333
|
||||||
|
94.247.134.77:8333
|
||||||
|
95.48.228.45:8333
|
||||||
|
95.69.249.63:8333
|
||||||
|
95.82.146.70:8333
|
||||||
|
95.83.73.31:8333
|
||||||
|
95.84.164.43:8333
|
||||||
|
95.87.226.56:8333
|
||||||
|
95.110.234.93:8333
|
||||||
|
95.163.71.126:8333
|
||||||
|
95.164.65.194:8333
|
||||||
|
95.174.66.211:8333
|
||||||
|
95.211.174.137:8333
|
||||||
|
95.216.11.156:8433
|
||||||
|
96.47.114.108:8333
|
||||||
|
97.84.232.105:8333
|
||||||
|
97.99.205.241:8333
|
||||||
|
98.25.193.114:8333
|
||||||
|
99.115.25.13:8333
|
||||||
|
101.32.19.184:8333
|
||||||
|
101.100.174.240:8333
|
||||||
|
102.132.245.16:8333
|
||||||
|
103.14.244.190:8333
|
||||||
|
103.76.48.5:8333
|
||||||
|
103.84.84.250:8335
|
||||||
|
103.99.168.150:8333
|
||||||
|
103.109.101.216:8333
|
||||||
|
103.122.247.102:8333
|
||||||
|
103.129.13.45:8333
|
||||||
|
103.198.192.14:20008
|
||||||
|
103.224.119.99:8333
|
||||||
|
103.231.191.7:8333
|
||||||
|
103.235.230.196:8333
|
||||||
|
104.171.242.155:8333
|
||||||
|
104.238.220.199:8333
|
||||||
|
106.163.158.127:8333
|
||||||
|
107.150.41.179:8333
|
||||||
|
107.159.93.103:8333
|
||||||
|
108.183.77.12:8333
|
||||||
|
109.9.175.65:8333
|
||||||
|
109.99.63.159:8333
|
||||||
|
109.110.81.90:8333
|
||||||
|
109.123.213.130:8333
|
||||||
|
109.134.232.81:8333
|
||||||
|
109.169.20.168:8333
|
||||||
|
109.199.241.148:8333
|
||||||
|
109.229.210.6:8333
|
||||||
|
109.236.105.40:8333
|
||||||
|
109.248.206.13:8333
|
||||||
|
111.42.74.65:8333
|
||||||
|
111.90.140.179:8333
|
||||||
|
112.215.205.236:8333
|
||||||
|
113.52.135.125:8333
|
||||||
|
114.23.246.137:8333
|
||||||
|
115.47.141.250:8885
|
||||||
|
115.70.110.4:8333
|
||||||
|
116.34.189.55:8333
|
||||||
|
118.103.126.140:28333
|
||||||
|
118.189.187.219:8333
|
||||||
|
119.3.208.236:8333
|
||||||
|
119.8.47.225:8333
|
||||||
|
119.17.151.61:8333
|
||||||
|
120.25.24.30:8333
|
||||||
|
120.241.34.10:8333
|
||||||
|
121.98.205.100:8333
|
||||||
|
122.112.148.153:8339
|
||||||
|
122.116.42.140:8333
|
||||||
|
124.217.235.180:8333
|
||||||
|
125.236.215.133:8333
|
||||||
|
129.13.189.212:8333
|
||||||
|
130.185.77.105:8333
|
||||||
|
131.188.40.191:8333
|
||||||
|
131.193.220.15:8333
|
||||||
|
135.23.124.239:8333
|
||||||
|
136.33.185.32:8333
|
||||||
|
136.56.170.96:8333
|
||||||
|
137.226.34.46:8333
|
||||||
|
138.229.26.42:8333
|
||||||
|
139.9.249.234:8333
|
||||||
|
141.101.8.36:8333
|
||||||
|
143.176.224.104:8333
|
||||||
|
144.2.69.224:8333
|
||||||
|
144.34.161.65:18333
|
||||||
|
144.91.116.44:8333
|
||||||
|
144.137.29.181:8333
|
||||||
|
148.66.50.50:8335
|
||||||
|
148.72.150.231:8333
|
||||||
|
148.170.212.44:8333
|
||||||
|
149.167.99.190:8333
|
||||||
|
154.92.16.191:8333
|
||||||
|
154.221.27.21:8333
|
||||||
|
156.19.19.90:8333
|
||||||
|
156.241.5.190:8333
|
||||||
|
157.13.61.76:8333
|
||||||
|
157.13.61.80:8333
|
||||||
|
157.230.166.98:14391
|
||||||
|
158.75.203.2:8333
|
||||||
|
158.181.125.150:8333
|
||||||
|
158.181.226.33:8333
|
||||||
|
159.100.242.254:8333
|
||||||
|
159.100.248.234:8333
|
||||||
|
159.138.87.18:8333
|
||||||
|
160.16.0.30:8333
|
||||||
|
162.0.227.54:8333
|
||||||
|
162.0.227.56:8333
|
||||||
|
162.62.18.226:8333
|
||||||
|
162.209.1.233:8333
|
||||||
|
162.243.175.86:8333
|
||||||
|
162.244.80.208:8333
|
||||||
|
162.250.188.87:8333
|
||||||
|
162.250.189.53:8333
|
||||||
|
163.158.202.112:8333
|
||||||
|
163.158.243.230:8333
|
||||||
|
165.73.62.31:8333
|
||||||
|
166.62.82.103:32771
|
||||||
|
166.70.94.106:8333
|
||||||
|
167.86.90.239:8333
|
||||||
|
169.44.34.203:8333
|
||||||
|
172.93.101.73:8333
|
||||||
|
172.105.7.47:8333
|
||||||
|
173.23.103.30:8000
|
||||||
|
173.53.79.6:8333
|
||||||
|
173.70.12.86:8333
|
||||||
|
173.89.28.137:8333
|
||||||
|
173.176.184.54:8333
|
||||||
|
173.208.128.10:8333
|
||||||
|
173.254.204.69:8333
|
||||||
|
173.255.204.124:8333
|
||||||
|
174.94.155.224:8333
|
||||||
|
174.114.102.41:8333
|
||||||
|
174.114.124.12:8333
|
||||||
|
176.10.227.59:8333
|
||||||
|
176.31.224.214:8333
|
||||||
|
176.74.136.237:8333
|
||||||
|
176.99.2.207:8333
|
||||||
|
176.106.191.2:8333
|
||||||
|
176.160.228.9:8333
|
||||||
|
176.191.182.3:8333
|
||||||
|
176.212.185.153:8333
|
||||||
|
176.241.137.183:8333
|
||||||
|
177.38.215.73:8333
|
||||||
|
178.16.222.146:8333
|
||||||
|
178.132.2.246:8333
|
||||||
|
178.143.191.171:8333
|
||||||
|
178.148.172.209:8333
|
||||||
|
178.148.226.180:8333
|
||||||
|
178.150.96.46:8333
|
||||||
|
178.182.227.50:8333
|
||||||
|
178.236.137.63:8333
|
||||||
|
178.255.42.126:8333
|
||||||
|
180.150.52.37:8333
|
||||||
|
181.39.32.99:8333
|
||||||
|
181.48.77.26:8333
|
||||||
|
181.52.223.52:8333
|
||||||
|
181.238.51.152:8333
|
||||||
|
183.88.223.208:8333
|
||||||
|
183.110.220.210:30301
|
||||||
|
184.95.58.166:8336
|
||||||
|
184.164.147.82:41333
|
||||||
|
184.171.208.109:8333
|
||||||
|
185.25.48.39:8333
|
||||||
|
185.25.48.184:8333
|
||||||
|
185.64.116.15:8333
|
||||||
|
185.80.219.132:8333
|
||||||
|
185.85.3.140:8333
|
||||||
|
185.95.219.53:8333
|
||||||
|
185.108.244.41:8333
|
||||||
|
185.134.233.121:8333
|
||||||
|
185.145.128.21:8333
|
||||||
|
185.148.3.227:8333
|
||||||
|
185.153.196.240:8333
|
||||||
|
185.158.114.184:8333
|
||||||
|
185.165.168.196:8333
|
||||||
|
185.181.230.74:8333
|
||||||
|
185.185.26.141:8111
|
||||||
|
185.186.208.162:8333
|
||||||
|
185.189.132.178:57780
|
||||||
|
185.211.59.50:8333
|
||||||
|
185.233.148.146:8333
|
||||||
|
185.238.129.113:8333
|
||||||
|
185.249.199.106:8333
|
||||||
|
185.251.161.54:8333
|
||||||
|
187.189.153.136:8333
|
||||||
|
188.37.24.190:8333
|
||||||
|
188.42.40.234:18333
|
||||||
|
188.61.46.36:8333
|
||||||
|
188.68.45.143:8333
|
||||||
|
188.127.229.105:8333
|
||||||
|
188.134.6.84:8333
|
||||||
|
188.134.8.36:8333
|
||||||
|
188.214.129.65:20012
|
||||||
|
188.230.168.114:8333
|
||||||
|
189.34.14.93:8333
|
||||||
|
189.207.46.32:8333
|
||||||
|
190.211.204.68:8333
|
||||||
|
191.209.21.188:8333
|
||||||
|
192.3.11.20:8333
|
||||||
|
192.3.185.210:8333
|
||||||
|
192.65.170.15:8333
|
||||||
|
192.65.170.50:8333
|
||||||
|
192.146.137.18:8333
|
||||||
|
192.157.202.178:8333
|
||||||
|
192.227.80.83:8333
|
||||||
|
193.10.203.23:8334
|
||||||
|
193.25.6.206:8333
|
||||||
|
193.42.110.30:8333
|
||||||
|
193.58.196.212:8333
|
||||||
|
193.106.28.8:8333
|
||||||
|
193.189.190.123:8333
|
||||||
|
193.194.163.35:8333
|
||||||
|
193.194.163.53:8333
|
||||||
|
194.14.246.205:8333
|
||||||
|
194.36.91.253:8333
|
||||||
|
194.126.113.135:8333
|
||||||
|
194.135.135.69:8333
|
||||||
|
195.56.63.4:8333
|
||||||
|
195.56.63.5:8333
|
||||||
|
195.67.139.54:8333
|
||||||
|
195.135.194.8:8333
|
||||||
|
195.202.169.149:8333
|
||||||
|
195.206.105.42:8333
|
||||||
|
195.209.249.164:8333
|
||||||
|
198.1.231.6:8333
|
||||||
|
198.200.43.215:8333
|
||||||
|
199.182.184.204:8333
|
||||||
|
199.247.7.208:8333
|
||||||
|
199.247.249.188:8333
|
||||||
|
200.7.252.118:8333
|
||||||
|
200.20.186.254:8333
|
||||||
|
200.83.166.136:8333
|
||||||
|
202.55.87.45:8333
|
||||||
|
202.79.167.65:8333
|
||||||
|
202.108.211.135:8333
|
||||||
|
202.169.102.73:8333
|
||||||
|
203.130.48.117:8885
|
||||||
|
203.132.95.10:8333
|
||||||
|
203.151.166.123:8333
|
||||||
|
204.93.113.108:8333
|
||||||
|
204.111.241.195:8333
|
||||||
|
206.124.149.66:8333
|
||||||
|
207.115.102.98:8333
|
||||||
|
207.229.46.150:8333
|
||||||
|
208.76.252.198:8333
|
||||||
|
208.100.13.56:8333
|
||||||
|
208.100.178.175:8333
|
||||||
|
208.110.99.105:8333
|
||||||
|
209.6.210.179:8333
|
||||||
|
209.133.220.74:8333
|
||||||
|
209.141.57.57:8333
|
||||||
|
211.27.147.67:8333
|
||||||
|
212.34.225.118:8333
|
||||||
|
212.89.173.216:8333
|
||||||
|
212.99.226.36:9020
|
||||||
|
212.237.96.98:8333
|
||||||
|
213.89.131.53:8333
|
||||||
|
216.38.129.164:8333
|
||||||
|
216.134.165.55:8333
|
||||||
|
216.146.251.8:8333
|
||||||
|
216.189.190.95:8333
|
||||||
|
216.226.128.189:8333
|
||||||
|
216.236.164.82:8333
|
||||||
|
217.19.216.210:8333
|
||||||
|
217.26.32.10:8333
|
||||||
|
217.64.47.138:8333
|
||||||
|
217.64.133.220:8333
|
||||||
|
217.92.55.246:8333
|
||||||
|
218.31.113.245:8333
|
||||||
|
218.255.242.114:8333
|
||||||
|
220.133.39.61:8333
|
||||||
|
223.16.30.175:8333
|
||||||
|
[2001:19f0:6001:306f:ec4:7aff:fe8f:66ec]:8333
|
||||||
|
[2001:1bc0:cc::a001]:8333
|
||||||
|
[2001:1c02:2f18:d00:b62e:99ff:fe49:d492]:8333
|
||||||
|
[2001:4100:0:64::93]:8333
|
||||||
|
[2001:4100:0:64:dcaf:afff:fe00:6707]:8333
|
||||||
|
[2001:470:a:c13::2]:8333
|
||||||
|
[2001:4801:7819:74:b745:b9d5:ff10:a61a]:8333
|
||||||
|
[2001:4ba0:fffa:5d::93]:8333
|
||||||
|
[2001:610:1908:ff01:f816:3eff:fe33:2e32]:8333
|
||||||
|
[2001:638:a000:4140::ffff:191]:8333
|
||||||
|
[2001:648:2800:131:4b1f:f6fc:20f7:f99f]:8333
|
||||||
|
[2001:678:7dc:8::2]:8333
|
||||||
|
[2001:678:cc8::1:10:88]:20008
|
||||||
|
[2001:67c:1220:80c::93e5:dd2]:8333
|
||||||
|
[2001:67c:1220:80c:e5dc:ad0c:9289:c28f]:8333
|
||||||
|
[2001:67c:16dc:1201:5054:ff:fe17:4dac]:8333
|
||||||
|
[2001:67c:2354:2::22]:8333
|
||||||
|
[2001:67c:26b4:12:7ae3:b5ff:fe04:6f9c]:8333
|
||||||
|
[2001:67c:2f0::20:fa]:8333
|
||||||
|
[2001:718:801:311:5054:ff:fe19:c483]:8333
|
||||||
|
[2001:8d8:87c:7c00::99:3c1]:8333
|
||||||
|
[2001:8f1:1404:3700:8e49:715a:2e09:b634]:9444
|
||||||
|
[2001:b07:5d29:99a5:194b:3874:d65e:a90d]:8333
|
||||||
|
[2001:ba8:1f1:f0fe::2]:8333
|
||||||
|
[2001:bc8:1200:0:dac4:97ff:fe2a:3554]:20008
|
||||||
|
[2001:da8:100d:22:10fa:d85f:10f2:21fd]:8333
|
||||||
|
[2001:da8:8001:7a39:f035:7d:b99f:eb79]:8333
|
||||||
|
[2001:e42:103:100::30]:8333
|
||||||
|
[2400:2412:103:c900:825:8f20:eaff:65c2]:8333
|
||||||
|
[2400:4052:e20:4f00:69fe:bb33:7b1c:a1ca]:8333
|
||||||
|
[2401:1800:7800:105:be76:4eff:fe1c:b35]:8333
|
||||||
|
[2401:3900:2:1::2]:8333
|
||||||
|
[2401:b140::44:150]:8333
|
||||||
|
[2401:d002:4402:0:8f28:591a:6ea0:c683]:8333
|
||||||
|
[2403:6200:8821:3d68:195b:87e9:6819:d5c8]:8333
|
||||||
|
[2405:6580:2140:3a00:c28c:983:364b:5d70]:8333
|
||||||
|
[2405:9800:b911:a18a:58eb:cd3c:9d82:ea4a]:8333
|
||||||
|
[2405:aa00:2::40]:8333
|
||||||
|
[2409:10:ca20:1df0:224:e8ff:fe1f:60d9]:8333
|
||||||
|
[2409:8a1e:a9af:3660:1c5a:5b6b:8a2d:9848]:8333
|
||||||
|
[2409:8a1e:a9af:3660:404:39ba:88f2:e8df]:8333
|
||||||
|
[240b:10:9141:400:49b4:3a2e:1e5:84c]:8333
|
||||||
|
[240d:1a:759:6000:a7b1:451a:8874:e1ac]:8333
|
||||||
|
[240d:1a:759:6000:ddab:3141:4da0:8878]:8333
|
||||||
|
[2600:8805:2400:14e:12dd:b1ff:fef2:3013]:8333
|
||||||
|
[2601:602:8d80:b63:dc3e:24ff:fe92:5eb]:8333
|
||||||
|
[2602:ffb6:4:2798:f816:3eff:fe2f:5441]:8333
|
||||||
|
[2602:ffb6:4:739e:f816:3eff:fe00:c2b3]:8333
|
||||||
|
[2602:ffb8::208:72:57:200]:8333
|
||||||
|
[2604:1380:4111:9300::1]:8333
|
||||||
|
[2604:4300:a:2e:21b:21ff:fe11:392]:8333
|
||||||
|
[2604:4500::2e06]:8112
|
||||||
|
[2604:5500:706a:4000:fc79:b9bb:1d7:c325]:8333
|
||||||
|
[2604:5500:c134:4000::3fc]:32797
|
||||||
|
[2604:6800:5e11:162:5c8f:d2ff:fe26:146f]:8333
|
||||||
|
[2605:4d00::50]:8333
|
||||||
|
[2605:6400:20:13bf:df1d:181c:83bb:22e8]:8333
|
||||||
|
[2605:ae00:203::203]:8333
|
||||||
|
[2605:c000:2a0a:1::102]:8333
|
||||||
|
[2607:f2c0:f00e:300::54]:8333
|
||||||
|
[2607:f2f8:ad40:bc1::1]:8333
|
||||||
|
[2607:f470:8:1048:ae1f:6bff:fe70:7240]:8333
|
||||||
|
[2607:ff28:800f:97:225:90ff:fe75:1110]:8333
|
||||||
|
[2620:11c:5001:1118:d267:e5ff:fee9:e673]:8333
|
||||||
|
[2620:6e:a000:2001::6]:8333
|
||||||
|
[2804:14d:4c93:9809:9769:da80:1832:3480]:8333
|
||||||
|
[2a00:1328:e101:c00::163]:8333
|
||||||
|
[2a00:1398:4:2a03:215:5dff:fed6:1033]:8333
|
||||||
|
[2a00:13a0:3015:1:85:14:79:26]:8333
|
||||||
|
[2a00:1630:14::101]:8333
|
||||||
|
[2a00:1768:2001:27::ef6a]:8333
|
||||||
|
[2a00:1828:a004:2::666]:8333
|
||||||
|
[2a00:1838:36:17::38cb]:8333
|
||||||
|
[2a00:1838:36:7d::d3c6]:8333
|
||||||
|
[2a00:1c10:2:709:58f7:e0ff:fe24:a0ba]:22220
|
||||||
|
[2a00:1c10:2:709::217]:22220
|
||||||
|
[2a00:1f40:5001:100::31]:8333
|
||||||
|
[2a00:6020:1395:1400:baf7:2d43:60b3:198b]:8333
|
||||||
|
[2a00:7c80:0:10b::3faf]:8333
|
||||||
|
[2a00:8a60:e012:a00::21]:8333
|
||||||
|
[2a00:ab00:603:84::3]:8333
|
||||||
|
[2a00:bbe0:cc:0:62a4:4cff:fe23:7510]:8333
|
||||||
|
[2a00:ca8:a1f:3025:f949:e442:c940:13e8]:8333
|
||||||
|
[2a00:d2a0:a:3d00:1cdf:38bb:a7d6:c251]:8333
|
||||||
|
[2a00:d880:11::20e]:8333
|
||||||
|
[2a00:ec0:7207:9100:5f8f:25dd:2574:3982]:8333
|
||||||
|
[2a00:f820:433::36]:8333
|
||||||
|
[2a01:138:a017:b018::42]:8333
|
||||||
|
[2a01:430:17:1::ffff:1153]:8333
|
||||||
|
[2a01:490:16:301::2]:8333
|
||||||
|
[2a01:4b00:807c:1b00:cda1:c6a:2bad:2418]:8333
|
||||||
|
[2a01:4b00:80e7:5405::1]:8333
|
||||||
|
[2a01:4f8:192:4212::2]:8433
|
||||||
|
[2a01:7a0:2:137c::3]:8333
|
||||||
|
[2a01:7a7:2:1467:ec4:7aff:fee2:5690]:8333
|
||||||
|
[2a01:7c8:d002:10f:5054:ff:fe5c:dac7]:8333
|
||||||
|
[2a01:7c8:d002:318:5054:ff:febe:cbb1]:8333
|
||||||
|
[2a01:8740:1:ffc5::8c6a]:8333
|
||||||
|
[2a01:cb00:f98:ca00:5054:ff:fed4:763d]:8333
|
||||||
|
[2a01:cb14:cf6:bc00:21e5:f12e:32c8:145]:8333
|
||||||
|
[2a01:d0:0:1c::245]:8333
|
||||||
|
[2a01:d0:bef2::12]:8333
|
||||||
|
[2a01:e35:2e40:6830:211:32ff:fea6:de3d]:8333
|
||||||
|
[2a02:1205:c6aa:60c0:70d8:aaee:a82d:993c]:8333
|
||||||
|
[2a02:169:502::614]:8333
|
||||||
|
[2a02:180:1:1::5b8f:538c]:8333
|
||||||
|
[2a02:348:62:5ef7::1]:8333
|
||||||
|
[2a02:390:9000:0:218:7dff:fe10:be33]:8333
|
||||||
|
[2a02:7aa0:1619::adc:8de0]:8333
|
||||||
|
[2a02:7b40:b0df:8925::1]:8333
|
||||||
|
[2a02:7b40:b905:37db::1]:8333
|
||||||
|
[2a02:810d:8cbf:f3a8:96c6:91ff:fe17:ae1d]:8333
|
||||||
|
[2a02:8389:1c0:9680:201:2eff:fe82:b3cc]:8333
|
||||||
|
[2a02:a454:a516:1:517:928:7e0d:957c]:8333
|
||||||
|
[2a02:af8:fab0:804:151:236:34:161]:8333
|
||||||
|
[2a02:af8:fab0:808:85:234:145:132]:8333
|
||||||
|
[2a02:e00:fff0:1e2::a]:8333
|
||||||
|
[2a03:2260:3006:d:d307:5d1d:32ca:1fe8]:8333
|
||||||
|
[2a03:6000:870:0:46:23:87:218]:8333
|
||||||
|
[2a03:9da0:f6:1::2]:8333
|
||||||
|
[2a03:c980:db:47::]:8333
|
||||||
|
[2a03:e2c0:1ce::2]:8333
|
||||||
|
[2a04:3544:1000:1510:706c:abff:fe6c:501c]:8333
|
||||||
|
[2a04:52c0:101:383::2a87]:8333
|
||||||
|
[2a04:52c0:101:3fb::4c27]:8333
|
||||||
|
[2a04:ee41:83:50df:d908:f71d:2a86:b337]:8333
|
||||||
|
[2a05:6d40:b94e:d100:225:90ff:fe0d:cfc2]:8333
|
||||||
|
[2a05:e5c0:0:100:250:56ff:feb9:d6cb]:8333
|
||||||
|
[2a05:fc87:1:6::2]:8333
|
||||||
|
[2a05:fc87:4::8]:8333
|
||||||
|
[2a07:5741:0:115d::1]:8333
|
||||||
|
[2a07:a880:4601:1062:b4b4:bd2a:39d4:7acf]:51401
|
||||||
|
[2a07:abc4::1:946]:8333
|
||||||
|
[2a07:b400:1:34c::2:1002]:8333
|
||||||
|
[2a0a:8c41::b4]:8333
|
||||||
|
[2a0a:c801:1:7::183]:8333
|
||||||
|
[2a0b:ae40:3:4a0a::15]:8333
|
||||||
|
[2a0f:df00:0:254::46]:8333
|
||||||
|
[2c0f:f598:5:1:1001::1]:8333
|
||||||
|
[2c0f:fce8:0:400:b7c::1]:8333
|
||||||
|
2g5qfdkn2vvcbqhzcyvyiitg4ceukybxklraxjnu7atlhd22gdwywaid.onion:8333
|
||||||
|
2jmtxvyup3ijr7u6uvu7ijtnojx4g5wodvaedivbv74w4vzntxbrhvad.onion:8333
|
||||||
|
37m62wn7dz3uqpathpc4qfmgrbupachj52nt3jbtbjugpbu54kbud7yd.onion:8333
|
||||||
|
5g72ppm3krkorsfopcm2bi7wlv4ohhs4u4mlseymasn7g7zhdcyjpfid.onion:8333
|
||||||
|
7cgwjuwi5ehvcay4tazy7ya6463bndjk6xzrttw5t3xbpq4p22q6fyid.onion:8333
|
||||||
|
7pyrpvqdhmayxggpcyqn5l3m5vqkw3qubnmgwlpya2mdo6x7pih7r7id.onion:8333
|
||||||
|
b64xcbleqmwgq2u46bh4hegnlrzzvxntyzbmucn3zt7cssm7y4ubv3id.onion:8333
|
||||||
|
ejxefzf5fpst4mg2rib7grksvscl7p6fvjp6agzgfc2yglxnjtxc3aid.onion:8333
|
||||||
|
fjdyxicpm4o42xmedlwl3uvk5gmqdfs5j37wir52327vncjzvtpfv7yd.onion:8333
|
||||||
|
fpz6r5ppsakkwypjcglz6gcnwt7ytfhxskkfhzu62tnylcknh3eq6pad.onion:8333
|
||||||
|
fzhn4uoxfbfss7h7d6ffbn266ca432ekbbzvqtsdd55ylgxn4jucm5qd.onion:8333
|
||||||
|
gxo5anvfnffnftfy5frkgvplq3rpga2ie3tcblo2vl754fvnhgorn5yd.onion:8333
|
||||||
|
ifdu5qvbofrt4ekui2iyb3kbcyzcsglazhx2hn4wfskkrx2v24qxriid.onion:8333
|
||||||
|
itz3oxsihs62muvknc237xabl5f6w6rfznfhbpayrslv2j2ubels47yd.onion:8333
|
||||||
|
lrjh6fywjqttmlifuemq3puhvmshxzzyhoqx7uoufali57eypuenzzid.onion:8333
|
||||||
|
m7cbpjolo662uel7rpaid46as2otcj44vvwg3gccodnvaeuwbm3anbyd.onion:8333
|
||||||
|
opnyfyeiibe5qo5a3wbxzbb4xdiagc32bbce46owmertdknta5mi7uyd.onion:8333
|
||||||
|
owjsdxmzla6d7lrwkbmetywqym5cyswpihciesfl5qdv2vrmwsgy4uqd.onion:8333
|
||||||
|
q7kgmd7n7h27ds4fg7wocgniuqb3oe2zxp4nfe4skd5da6wyipibqzqd.onion:8333
|
||||||
|
rp7k2go3s5lyj3fnj6zn62ktarlrsft2ohlsxkyd7v3e3idqyptvread.onion:8333
|
||||||
|
sys54sv4xv3hn3sdiv3oadmzqpgyhd4u4xphv4xqk64ckvaxzm57a7yd.onion:8333
|
||||||
|
tddeij4qigtjr6jfnrmq6btnirmq5msgwcsdpcdjr7atftm7cxlqztid.onion:8333
|
||||||
|
vi5bnbxkleeqi6hfccjochnn65lcxlfqs4uwgmhudph554zibiusqnad.onion:8333
|
||||||
|
xqt25cobm5zqucac3634zfght72he6u3eagfyej5ellbhcdgos7t2had.onion:8333
|
|
@ -22,11 +22,11 @@ import org.bitcoins.node.networking.peer.{
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
|
|
||||||
case class NeutrinoNode(
|
case class NeutrinoNode(
|
||||||
nodePeer: Vector[Peer],
|
|
||||||
private var dataMessageHandler: DataMessageHandler,
|
private var dataMessageHandler: DataMessageHandler,
|
||||||
nodeConfig: NodeAppConfig,
|
nodeConfig: NodeAppConfig,
|
||||||
chainConfig: ChainAppConfig,
|
chainConfig: ChainAppConfig,
|
||||||
actorSystem: ActorSystem)
|
actorSystem: ActorSystem,
|
||||||
|
configPeersOverride: Vector[Peer] = Vector.empty)
|
||||||
extends Node {
|
extends Node {
|
||||||
require(
|
require(
|
||||||
nodeConfig.nodeType == NodeType.NeutrinoNode,
|
nodeConfig.nodeType == NodeType.NeutrinoNode,
|
||||||
|
@ -38,10 +38,10 @@ case class NeutrinoNode(
|
||||||
|
|
||||||
override def chainAppConfig: ChainAppConfig = chainConfig
|
override def chainAppConfig: ChainAppConfig = chainConfig
|
||||||
|
|
||||||
override val peers: Vector[Peer] = nodePeer
|
|
||||||
|
|
||||||
val controlMessageHandler: ControlMessageHandler = ControlMessageHandler(this)
|
val controlMessageHandler: ControlMessageHandler = ControlMessageHandler(this)
|
||||||
|
|
||||||
|
override val peerManager: PeerManager = PeerManager(this, configPeersOverride)
|
||||||
|
|
||||||
override def getDataMessageHandler: DataMessageHandler = dataMessageHandler
|
override def getDataMessageHandler: DataMessageHandler = dataMessageHandler
|
||||||
|
|
||||||
override def updateDataMessageHandler(
|
override def updateDataMessageHandler(
|
||||||
|
@ -55,7 +55,7 @@ case class NeutrinoNode(
|
||||||
node <- super.start()
|
node <- super.start()
|
||||||
chainApi <- chainApiFromDb()
|
chainApi <- chainApiFromDb()
|
||||||
bestHash <- chainApi.getBestBlockHash()
|
bestHash <- chainApi.getBestBlockHash()
|
||||||
_ <- randomPeerMsgSenderWithCompactFilters
|
_ <- peerManager.randomPeerMsgSenderWithCompactFilters
|
||||||
.sendGetCompactFilterCheckPointMessage(stopHash = bestHash.flip)
|
.sendGetCompactFilterCheckPointMessage(stopHash = bestHash.flip)
|
||||||
} yield {
|
} yield {
|
||||||
node.asInstanceOf[NeutrinoNode]
|
node.asInstanceOf[NeutrinoNode]
|
||||||
|
@ -84,7 +84,7 @@ case class NeutrinoNode(
|
||||||
blockchains <- blockchainsF
|
blockchains <- blockchainsF
|
||||||
// Get all of our cached headers in case of a reorg
|
// Get all of our cached headers in case of a reorg
|
||||||
cachedHeaders = blockchains.flatMap(_.headers).map(_.hashBE.flip)
|
cachedHeaders = blockchains.flatMap(_.headers).map(_.hashBE.flip)
|
||||||
_ <- randomPeerMsgSender.sendGetHeadersMessage(cachedHeaders)
|
_ <- peerManager.randomPeerMsgSender.sendGetHeadersMessage(cachedHeaders)
|
||||||
_ <- syncFilters(bestFilterHeaderOpt = bestFilterHeaderOpt,
|
_ <- syncFilters(bestFilterHeaderOpt = bestFilterHeaderOpt,
|
||||||
bestFilterOpt = bestFilterOpt,
|
bestFilterOpt = bestFilterOpt,
|
||||||
bestBlockHeader = header,
|
bestBlockHeader = header,
|
||||||
|
@ -137,7 +137,7 @@ case class NeutrinoNode(
|
||||||
chainApi: ChainApi,
|
chainApi: ChainApi,
|
||||||
bestFilterOpt: Option[CompactFilterDb]): Future[Unit] = {
|
bestFilterOpt: Option[CompactFilterDb]): Future[Unit] = {
|
||||||
val sendCompactFilterHeaderMsgF = {
|
val sendCompactFilterHeaderMsgF = {
|
||||||
randomPeerMsgSenderWithCompactFilters
|
peerManager.randomPeerMsgSenderWithCompactFilters
|
||||||
.sendNextGetCompactFilterHeadersCommand(
|
.sendNextGetCompactFilterHeadersCommand(
|
||||||
chainApi = chainApi,
|
chainApi = chainApi,
|
||||||
filterHeaderBatchSize = chainConfig.filterHeaderBatchSize,
|
filterHeaderBatchSize = chainConfig.filterHeaderBatchSize,
|
||||||
|
@ -153,7 +153,7 @@ case class NeutrinoNode(
|
||||||
//means we are not syncing filter headers, and our filters are NOT
|
//means we are not syncing filter headers, and our filters are NOT
|
||||||
//in sync with our compact filter headers
|
//in sync with our compact filter headers
|
||||||
logger.info(s"Starting sync filters in NeutrinoNode.sync()")
|
logger.info(s"Starting sync filters in NeutrinoNode.sync()")
|
||||||
randomPeerMsgSenderWithCompactFilters
|
peerManager.randomPeerMsgSenderWithCompactFilters
|
||||||
.sendNextGetCompactFilterCommand(
|
.sendNextGetCompactFilterCommand(
|
||||||
chainApi = chainApi,
|
chainApi = chainApi,
|
||||||
filterBatchSize = chainConfig.filterBatchSize,
|
filterBatchSize = chainConfig.filterBatchSize,
|
||||||
|
|
|
@ -10,28 +10,22 @@ import org.bitcoins.chain.models.{
|
||||||
CompactFilterHeaderDAO
|
CompactFilterHeaderDAO
|
||||||
}
|
}
|
||||||
import org.bitcoins.core.api.chain._
|
import org.bitcoins.core.api.chain._
|
||||||
import org.bitcoins.core.api.node.{NodeApi, NodeType}
|
import org.bitcoins.core.api.node.NodeApi
|
||||||
import org.bitcoins.core.p2p.{NetworkPayload, ServiceIdentifier, TypeIdentifier}
|
import org.bitcoins.core.p2p._
|
||||||
import org.bitcoins.core.protocol.transaction.Transaction
|
import org.bitcoins.core.protocol.transaction.Transaction
|
||||||
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
|
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
|
||||||
import org.bitcoins.node.config.NodeAppConfig
|
import org.bitcoins.node.config.NodeAppConfig
|
||||||
import org.bitcoins.node.models.{
|
import org.bitcoins.node.models._
|
||||||
BroadcastAbleTransaction,
|
|
||||||
BroadcastAbleTransactionDAO,
|
|
||||||
Peer
|
|
||||||
}
|
|
||||||
import org.bitcoins.node.networking.P2PClient
|
import org.bitcoins.node.networking.P2PClient
|
||||||
import org.bitcoins.node.networking.peer.{
|
import org.bitcoins.node.networking.peer.{
|
||||||
ControlMessageHandler,
|
ControlMessageHandler,
|
||||||
DataMessageHandler,
|
DataMessageHandler,
|
||||||
PeerMessageReceiver,
|
|
||||||
PeerMessageSender
|
PeerMessageSender
|
||||||
}
|
}
|
||||||
|
|
||||||
import scala.collection.mutable
|
|
||||||
import scala.concurrent.duration.DurationInt
|
import scala.concurrent.duration.DurationInt
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
import scala.util.{Failure, Random, Success}
|
import scala.util.{Failure, Success}
|
||||||
|
|
||||||
/** This a base trait for various kinds of nodes. It contains house keeping methods required for all nodes.
|
/** This a base trait for various kinds of nodes. It contains house keeping methods required for all nodes.
|
||||||
*/
|
*/
|
||||||
|
@ -45,39 +39,7 @@ trait Node extends NodeApi with ChainQueryApi with P2PLogger {
|
||||||
|
|
||||||
implicit def executionContext: ExecutionContext = system.dispatcher
|
implicit def executionContext: ExecutionContext = system.dispatcher
|
||||||
|
|
||||||
val peers: Vector[Peer]
|
val peerManager: PeerManager
|
||||||
|
|
||||||
private val _peerServices: mutable.Map[Peer, ServiceIdentifier] =
|
|
||||||
mutable.Map.empty
|
|
||||||
|
|
||||||
def peerServices: Map[Peer, ServiceIdentifier] = _peerServices.toMap
|
|
||||||
|
|
||||||
def setPeerServices(
|
|
||||||
peer: Peer,
|
|
||||||
serviceIdentifier: ServiceIdentifier): Unit = {
|
|
||||||
_peerServices.put(peer, serviceIdentifier)
|
|
||||||
()
|
|
||||||
}
|
|
||||||
|
|
||||||
def randomPeerMsgSenderWithService(
|
|
||||||
f: ServiceIdentifier => Boolean): PeerMessageSender = {
|
|
||||||
val filteredPeers =
|
|
||||||
peerServices.filter(p => f(p._2)).keys.toVector
|
|
||||||
if (filteredPeers.isEmpty)
|
|
||||||
throw new RuntimeException("No peers supporting compact filters!")
|
|
||||||
val peer = filteredPeers(Random.nextInt(filteredPeers.length))
|
|
||||||
peerMsgSenders
|
|
||||||
.find(_.client.peer == peer)
|
|
||||||
.getOrElse(throw new RuntimeException("This should not happen."))
|
|
||||||
}
|
|
||||||
|
|
||||||
def randomPeerMsgSenderWithCompactFilters: PeerMessageSender = {
|
|
||||||
randomPeerMsgSenderWithService(_.nodeCompactFilters)
|
|
||||||
}
|
|
||||||
|
|
||||||
def randomPeerMsgSender: PeerMessageSender = {
|
|
||||||
peerMsgSenders(Random.nextInt(peerMsgSenders.length))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The current data message handler.
|
/** The current data message handler.
|
||||||
* It should be noted that the dataMessageHandler contains
|
* It should be noted that the dataMessageHandler contains
|
||||||
|
@ -110,22 +72,9 @@ trait Node extends NodeApi with ChainQueryApi with P2PLogger {
|
||||||
* object. Internally in [[org.bitcoins.node.networking.P2PClient p2p client]] you will see that
|
* object. Internally in [[org.bitcoins.node.networking.P2PClient p2p client]] you will see that
|
||||||
* the [[ChainApi chain api]] is updated inside of the p2p client
|
* the [[ChainApi chain api]] is updated inside of the p2p client
|
||||||
*/
|
*/
|
||||||
lazy val clients: Vector[P2PClient] = {
|
def clients: Vector[P2PClient] = peerManager.clients
|
||||||
val peerMsgRecvs: Vector[PeerMessageReceiver] =
|
|
||||||
peers.map(x => PeerMessageReceiver.newReceiver(node = this, peer = x))
|
|
||||||
val zipped = peers.zip(peerMsgRecvs)
|
|
||||||
val p2p = zipped.map { case (peer, peerMsgRecv) =>
|
|
||||||
P2PClient(context = system,
|
|
||||||
peer = peer,
|
|
||||||
peerMessageReceiver = peerMsgRecv,
|
|
||||||
onReconnect = sync)
|
|
||||||
}
|
|
||||||
p2p
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val peerMsgSenders: Vector[PeerMessageSender] = {
|
def peerMsgSenders: Vector[PeerMessageSender] = peerManager.peerMsgSenders
|
||||||
clients.map(PeerMessageSender(_))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sends the given P2P to our peer.
|
/** Sends the given P2P to our peer.
|
||||||
* This method is useful for playing around
|
* This method is useful for playing around
|
||||||
|
@ -150,6 +99,20 @@ trait Node extends NodeApi with ChainQueryApi with P2PLogger {
|
||||||
def isDisconnected(idx: Int): Future[Boolean] =
|
def isDisconnected(idx: Int): Future[Boolean] =
|
||||||
peerMsgSenders(idx).isDisconnected()
|
peerMsgSenders(idx).isDisconnected()
|
||||||
|
|
||||||
|
def initializePeer(peer: Peer): Future[Unit] = {
|
||||||
|
peerManager.peerDataOf(peer).peerMessageSender.connect()
|
||||||
|
val isInitializedF = AsyncUtil
|
||||||
|
.retryUntilSatisfiedF(
|
||||||
|
() => peerManager.peerDataOf(peer).peerMessageSender.isInitialized(),
|
||||||
|
maxTries = 50,
|
||||||
|
interval = 250.millis)
|
||||||
|
isInitializedF.failed
|
||||||
|
.foreach { err =>
|
||||||
|
logger.error(s"Failed to initialize with peer=$peer with err=$err")
|
||||||
|
}
|
||||||
|
isInitializedF
|
||||||
|
}
|
||||||
|
|
||||||
/** Starts our node */
|
/** Starts our node */
|
||||||
def start(): Future[Node] = {
|
def start(): Future[Node] = {
|
||||||
logger.info("Starting node")
|
logger.info("Starting node")
|
||||||
|
@ -162,42 +125,15 @@ trait Node extends NodeApi with ChainQueryApi with P2PLogger {
|
||||||
|
|
||||||
val chainApiF = startConfsF.flatMap(_ => chainApiFromDb())
|
val chainApiF = startConfsF.flatMap(_ => chainApiFromDb())
|
||||||
|
|
||||||
val startNodeF = {
|
val startNodeF = for {
|
||||||
val isInitializedFs = peerMsgSenders.indices.map { idx =>
|
peers <- peerManager.getPeers
|
||||||
peerMsgSenders(idx).connect()
|
_ = peers.foreach(peerManager.addPeer)
|
||||||
val isInitializedF = for {
|
_ <- Future.sequence(peers.map(initializePeer))
|
||||||
_ <- AsyncUtil.retryUntilSatisfiedF(() => isInitialized(idx),
|
} yield {
|
||||||
maxTries = 1024,
|
|
||||||
interval = 250.millis)
|
|
||||||
} yield ()
|
|
||||||
isInitializedF.failed.foreach { err =>
|
|
||||||
logger.error(
|
|
||||||
s"Failed to connect with peer=${peers(idx)} with err=$err")
|
|
||||||
}
|
|
||||||
isInitializedF.map { _ =>
|
|
||||||
nodeAppConfig.nodeType match {
|
|
||||||
case NodeType.NeutrinoNode => {
|
|
||||||
if (peerServices(peers(idx)).nodeCompactFilters) {
|
|
||||||
logger.info(s"Our peer=${peers(idx)} has been initialized")
|
|
||||||
} else {
|
|
||||||
logger.info(
|
|
||||||
s"Our peer=${peers(idx)} does not support compact filters. Disconnecting.")
|
|
||||||
peerMsgSenders(idx).disconnect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case NodeType.SpvNode =>
|
|
||||||
case NodeType.BitcoindBackend =>
|
|
||||||
case NodeType.FullNode =>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future.sequence(isInitializedFs).map { _ =>
|
|
||||||
logger.info(s"Our node has been full started. It took=${System
|
logger.info(s"Our node has been full started. It took=${System
|
||||||
.currentTimeMillis() - start}ms")
|
.currentTimeMillis() - start}ms")
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val bestHashF = chainApiF.flatMap(_.getBestBlockHash())
|
val bestHashF = chainApiF.flatMap(_.getBestBlockHash())
|
||||||
val bestHeightF = chainApiF.flatMap(_.getBestHashBlockHeight())
|
val bestHeightF = chainApiF.flatMap(_.getBestHashBlockHeight())
|
||||||
|
@ -272,7 +208,7 @@ trait Node extends NodeApi with ChainQueryApi with P2PLogger {
|
||||||
|
|
||||||
// Get all of our cached headers in case of a reorg
|
// Get all of our cached headers in case of a reorg
|
||||||
cachedHeaders = blockchains.flatMap(_.headers).map(_.hashBE.flip)
|
cachedHeaders = blockchains.flatMap(_.headers).map(_.hashBE.flip)
|
||||||
_ <- randomPeerMsgSender.sendGetHeadersMessage(cachedHeaders)
|
_ <- peerManager.randomPeerMsgSender.sendGetHeadersMessage(cachedHeaders)
|
||||||
} yield {
|
} yield {
|
||||||
logger.info(
|
logger.info(
|
||||||
s"Starting sync node, height=${header.height} hash=${header.hashBE}")
|
s"Starting sync node, height=${header.height} hash=${header.hashBE}")
|
||||||
|
@ -306,8 +242,10 @@ trait Node extends NodeApi with ChainQueryApi with P2PLogger {
|
||||||
logger.info(s"Sending out tx message for tx=$txIds")
|
logger.info(s"Sending out tx message for tx=$txIds")
|
||||||
peerMsgSenders(0).sendInventoryMessage(transactions: _*)
|
peerMsgSenders(0).sendInventoryMessage(transactions: _*)
|
||||||
} else {
|
} else {
|
||||||
Future.failed(new RuntimeException(
|
Future.failed(
|
||||||
s"Error broadcasting transaction $txIds, peer is disconnected ${peers(0)}"))
|
new RuntimeException(
|
||||||
|
s"Error broadcasting transaction $txIds, peer is disconnected ${peerManager
|
||||||
|
.peers(0)}"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} yield res
|
} yield res
|
||||||
|
|
44
node/src/main/scala/org/bitcoins/node/PeerData.scala
Normal file
44
node/src/main/scala/org/bitcoins/node/PeerData.scala
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package org.bitcoins.node
|
||||||
|
|
||||||
|
import akka.actor.ActorSystem
|
||||||
|
import org.bitcoins.core.p2p.ServiceIdentifier
|
||||||
|
import org.bitcoins.node.config.NodeAppConfig
|
||||||
|
import org.bitcoins.node.models.Peer
|
||||||
|
import org.bitcoins.node.networking.P2PClient
|
||||||
|
import org.bitcoins.node.networking.peer.{
|
||||||
|
PeerMessageReceiver,
|
||||||
|
PeerMessageSender
|
||||||
|
}
|
||||||
|
|
||||||
|
/** PeerData contains objects specific to a peer associated together
|
||||||
|
*/
|
||||||
|
case class PeerData(
|
||||||
|
peer: Peer,
|
||||||
|
node: Node
|
||||||
|
)(implicit system: ActorSystem, nodeAppConfig: NodeAppConfig) {
|
||||||
|
|
||||||
|
lazy val peerMessageSender: PeerMessageSender = PeerMessageSender(client)
|
||||||
|
|
||||||
|
lazy val client: P2PClient = {
|
||||||
|
val peerMessageReceiver =
|
||||||
|
PeerMessageReceiver.newReceiver(node = node, peer = peer)
|
||||||
|
P2PClient(
|
||||||
|
context = system,
|
||||||
|
peer = peer,
|
||||||
|
peerMessageReceiver = peerMessageReceiver,
|
||||||
|
onReconnect = node.sync
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _serviceIdentifier: Option[ServiceIdentifier] = None
|
||||||
|
|
||||||
|
def serviceIdentifier: ServiceIdentifier = {
|
||||||
|
_serviceIdentifier.getOrElse(
|
||||||
|
throw new RuntimeException(
|
||||||
|
s"Tried using ServiceIdentifier for uninitialized peer $peer"))
|
||||||
|
}
|
||||||
|
|
||||||
|
def setServiceIdentifier(serviceIdentifier: ServiceIdentifier): Unit = {
|
||||||
|
_serviceIdentifier = Some(serviceIdentifier)
|
||||||
|
}
|
||||||
|
}
|
199
node/src/main/scala/org/bitcoins/node/PeerManager.scala
Normal file
199
node/src/main/scala/org/bitcoins/node/PeerManager.scala
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
package org.bitcoins.node
|
||||||
|
|
||||||
|
import akka.actor.ActorSystem
|
||||||
|
import org.bitcoins.core.p2p.{AddrV2Message, ServiceIdentifier}
|
||||||
|
import org.bitcoins.core.util.NetworkUtil
|
||||||
|
import org.bitcoins.node.config.NodeAppConfig
|
||||||
|
import org.bitcoins.node.models.{Peer, PeerDAO, PeerDb}
|
||||||
|
import org.bitcoins.node.networking.P2PClient
|
||||||
|
import org.bitcoins.node.networking.peer.PeerMessageSender
|
||||||
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
import java.net.{InetAddress, UnknownHostException}
|
||||||
|
import scala.collection.mutable
|
||||||
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
|
import scala.io.Source
|
||||||
|
import scala.util.Random
|
||||||
|
|
||||||
|
case class PeerManager(node: Node, configPeers: Vector[Peer] = Vector.empty)(
|
||||||
|
implicit
|
||||||
|
ec: ExecutionContext,
|
||||||
|
system: ActorSystem,
|
||||||
|
nodeAppConfig: NodeAppConfig)
|
||||||
|
extends P2PLogger {
|
||||||
|
|
||||||
|
private val _peerData: mutable.Map[Peer, PeerData] =
|
||||||
|
mutable.Map.empty
|
||||||
|
|
||||||
|
def peerData: Map[Peer, PeerData] = _peerData.toMap
|
||||||
|
|
||||||
|
def peers: Vector[Peer] = peerData.keys.toVector
|
||||||
|
|
||||||
|
def peerMsgSenders: Vector[PeerMessageSender] =
|
||||||
|
peerData.values
|
||||||
|
.map(_.peerMessageSender)
|
||||||
|
.toVector
|
||||||
|
|
||||||
|
def clients: Vector[P2PClient] = peerData.values.map(_.client).toVector
|
||||||
|
|
||||||
|
/** Returns peers by querying each dns seed once. These will be IPv4 addresses. */
|
||||||
|
private def getPeersFromDnsSeeds: Vector[Peer] = {
|
||||||
|
val dnsSeeds = nodeAppConfig.network.dnsSeeds
|
||||||
|
val addresses = dnsSeeds
|
||||||
|
.flatMap(seed => {
|
||||||
|
try {
|
||||||
|
InetAddress
|
||||||
|
.getAllByName(seed)
|
||||||
|
} catch {
|
||||||
|
case _: UnknownHostException =>
|
||||||
|
logger.debug(s"DNS seed $seed is unavailable")
|
||||||
|
Vector()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.distinct
|
||||||
|
.filter(_.isReachable(500))
|
||||||
|
.map(_.getHostAddress)
|
||||||
|
val inetSockets = addresses.map(
|
||||||
|
NetworkUtil.parseInetSocketAddress(_, nodeAppConfig.network.port))
|
||||||
|
val peers =
|
||||||
|
inetSockets.map(Peer.fromSocket(_, nodeAppConfig.socks5ProxyParams))
|
||||||
|
peers.toVector
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns peers from hardcoded addresses taken from https://github.com/bitcoin/bitcoin/blob/master/contrib/seeds/nodes_main.txt */
|
||||||
|
private def getPeersFromResources: Vector[Peer] = {
|
||||||
|
val source = Source.fromURL(getClass.getResource("/hardcoded-peers.txt"))
|
||||||
|
val addresses = source
|
||||||
|
.getLines()
|
||||||
|
.toVector
|
||||||
|
.filter(nodeAppConfig.torConf.enabled || !_.contains(".onion"))
|
||||||
|
val inetSockets = addresses.map(
|
||||||
|
NetworkUtil.parseInetSocketAddress(_, nodeAppConfig.network.port))
|
||||||
|
val peers =
|
||||||
|
inetSockets.map(Peer.fromSocket(_, nodeAppConfig.socks5ProxyParams))
|
||||||
|
peers
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns all peers stored in database */
|
||||||
|
private def getPeersFromDb: Future[Vector[Peer]] = {
|
||||||
|
val addressesF: Future[Vector[PeerDb]] =
|
||||||
|
PeerDAO().findAllWithTorFilter(nodeAppConfig.torConf.enabled)
|
||||||
|
val peersF = addressesF.map { addresses =>
|
||||||
|
val inetSockets = addresses.map(a => {
|
||||||
|
NetworkUtil.parseInetSocketAddress(a.address, a.port)
|
||||||
|
})
|
||||||
|
val peers =
|
||||||
|
inetSockets.map(Peer.fromSocket(_, nodeAppConfig.socks5ProxyParams))
|
||||||
|
peers
|
||||||
|
}
|
||||||
|
peersF
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns peers from bitcoin-s.config file unless peers are supplied as an argument to [[PeerManager]] in which
|
||||||
|
* case it returns those.
|
||||||
|
*/
|
||||||
|
private def getPeersFromConfig: Vector[Peer] = {
|
||||||
|
if (configPeers.nonEmpty) {
|
||||||
|
configPeers
|
||||||
|
} else {
|
||||||
|
val addresses = nodeAppConfig.peers.filter(
|
||||||
|
nodeAppConfig.torConf.enabled || !_.contains(".onion"))
|
||||||
|
val inetSockets = addresses.map(
|
||||||
|
NetworkUtil.parseInetSocketAddress(_, nodeAppConfig.network.port))
|
||||||
|
val peers =
|
||||||
|
inetSockets.map(Peer.fromSocket(_, nodeAppConfig.socks5ProxyParams))
|
||||||
|
peers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns peers randomly taken from config, database, hardcoded peers, dns seeds in that order */
|
||||||
|
def getPeers: Future[Vector[Peer]] = {
|
||||||
|
//currently this would only give the first peer from config
|
||||||
|
val peersFromConfig = getPeersFromConfig
|
||||||
|
val peersFromDbF = getPeersFromDb
|
||||||
|
val peersFromResources = getPeersFromResources
|
||||||
|
val maxConnectedPeers = nodeAppConfig.maxConnectedPeers
|
||||||
|
|
||||||
|
val allF = for {
|
||||||
|
peersFromDb <- peersFromDbF
|
||||||
|
} yield {
|
||||||
|
val shuffledPeers = (Random.shuffle(peersFromConfig) ++ Random.shuffle(
|
||||||
|
peersFromDb) ++ Random.shuffle(peersFromResources)).distinct
|
||||||
|
|
||||||
|
//getting peers from dns seeds takes a noticeable 5-8 sec so treating this separately
|
||||||
|
if (maxConnectedPeers > shuffledPeers.size) {
|
||||||
|
shuffledPeers.take(maxConnectedPeers) ++ getPeersFromDnsSeeds.take(
|
||||||
|
maxConnectedPeers - shuffledPeers.size)
|
||||||
|
} else {
|
||||||
|
shuffledPeers.take(maxConnectedPeers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allF
|
||||||
|
}
|
||||||
|
|
||||||
|
def addPeer(peer: Peer): Unit = {
|
||||||
|
if (!_peerData.contains(peer))
|
||||||
|
_peerData.put(peer, PeerData(peer, node))
|
||||||
|
else logger.debug(s"Peer $peer already added.")
|
||||||
|
()
|
||||||
|
}
|
||||||
|
|
||||||
|
def removePeer(peer: Peer): Future[Unit] = {
|
||||||
|
if (_peerData.contains(peer)) {
|
||||||
|
val connF = peerData(peer).peerMessageSender.isConnected()
|
||||||
|
val disconnectF = connF.map { conn =>
|
||||||
|
if (conn) peerData(peer).peerMessageSender.disconnect()
|
||||||
|
else Future.unit
|
||||||
|
}
|
||||||
|
for {
|
||||||
|
_ <- disconnectF
|
||||||
|
_ <- removePeer(peer)
|
||||||
|
} yield ()
|
||||||
|
} else {
|
||||||
|
logger.debug(s"Key $peer not found in peerData")
|
||||||
|
Future.unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def randomPeerMsgSenderWithService(
|
||||||
|
f: ServiceIdentifier => Boolean): PeerMessageSender = {
|
||||||
|
val filteredPeers =
|
||||||
|
peerData.values.filter(p => f(p.serviceIdentifier)).toVector
|
||||||
|
if (filteredPeers.isEmpty)
|
||||||
|
throw new RuntimeException("No peers supporting compact filters!")
|
||||||
|
val randomPeerData = filteredPeers(Random.nextInt(filteredPeers.length))
|
||||||
|
randomPeerData.peerMessageSender
|
||||||
|
}
|
||||||
|
|
||||||
|
def randomPeerMsgSenderWithCompactFilters: PeerMessageSender = {
|
||||||
|
randomPeerMsgSenderWithService(_.nodeCompactFilters)
|
||||||
|
}
|
||||||
|
|
||||||
|
def randomPeerMsgSender: PeerMessageSender = {
|
||||||
|
peerMsgSenders(Random.nextInt(peerMsgSenders.length))
|
||||||
|
}
|
||||||
|
|
||||||
|
def createInDb(peer: Peer): Future[PeerDb] = {
|
||||||
|
logger.debug(s"Adding peer to db $peer")
|
||||||
|
val addrBytes =
|
||||||
|
if (peer.socket.getHostString.contains(".onion"))
|
||||||
|
NetworkUtil.torV3AddressToBytes(peer.socket.getHostString)
|
||||||
|
else
|
||||||
|
InetAddress.getByName(peer.socket.getHostString).getAddress
|
||||||
|
val networkByte = addrBytes.length match {
|
||||||
|
case AddrV2Message.IPV4_ADDR_LENGTH => AddrV2Message.IPV4_NETWORK_BYTE
|
||||||
|
case AddrV2Message.IPV6_ADDR_LENGTH => AddrV2Message.IPV6_NETWORK_BYTE
|
||||||
|
case AddrV2Message.TOR_V3_ADDR_LENGTH => AddrV2Message.TOR_V3_NETWORK_BYTE
|
||||||
|
case unknownSize =>
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
s"Unsupported address type of size $unknownSize bytes")
|
||||||
|
}
|
||||||
|
PeerDAO()
|
||||||
|
.upsertPeer(ByteVector(addrBytes), peer.socket.getPort, networkByte)
|
||||||
|
}
|
||||||
|
|
||||||
|
//makes it more readable, compare peerManager.peerData(peer) vs peerManager.peerDataOf(peer) as peer is used thrice
|
||||||
|
//in a simple statement
|
||||||
|
/** get [[PeerData]] for a [[Peer]] */
|
||||||
|
def peerDataOf(peer: Peer): PeerData = peerData(peer)
|
||||||
|
}
|
|
@ -19,11 +19,11 @@ import org.bitcoins.node.networking.peer.{
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
|
|
||||||
case class SpvNode(
|
case class SpvNode(
|
||||||
nodePeer: Vector[Peer],
|
|
||||||
dataMessageHandler: DataMessageHandler,
|
dataMessageHandler: DataMessageHandler,
|
||||||
nodeConfig: NodeAppConfig,
|
nodeConfig: NodeAppConfig,
|
||||||
chainConfig: ChainAppConfig,
|
chainConfig: ChainAppConfig,
|
||||||
actorSystem: ActorSystem)
|
actorSystem: ActorSystem,
|
||||||
|
configPeersOverride: Vector[Peer] = Vector.empty)
|
||||||
extends Node {
|
extends Node {
|
||||||
require(nodeConfig.nodeType == NodeType.SpvNode,
|
require(nodeConfig.nodeType == NodeType.SpvNode,
|
||||||
s"We need our SPV mode enabled to be able to construct a SPV node!")
|
s"We need our SPV mode enabled to be able to construct a SPV node!")
|
||||||
|
@ -34,8 +34,6 @@ case class SpvNode(
|
||||||
|
|
||||||
override def chainAppConfig: ChainAppConfig = chainConfig
|
override def chainAppConfig: ChainAppConfig = chainConfig
|
||||||
|
|
||||||
override val peers: Vector[Peer] = nodePeer
|
|
||||||
|
|
||||||
private val _bloomFilter = new Mutable(BloomFilter.empty)
|
private val _bloomFilter = new Mutable(BloomFilter.empty)
|
||||||
|
|
||||||
def bloomFilter: BloomFilter = _bloomFilter.atomicGet
|
def bloomFilter: BloomFilter = _bloomFilter.atomicGet
|
||||||
|
@ -44,6 +42,8 @@ case class SpvNode(
|
||||||
|
|
||||||
override def getDataMessageHandler: DataMessageHandler = dataMessageHandler
|
override def getDataMessageHandler: DataMessageHandler = dataMessageHandler
|
||||||
|
|
||||||
|
override val peerManager: PeerManager = PeerManager(this, configPeersOverride)
|
||||||
|
|
||||||
def setBloomFilter(bloom: BloomFilter): SpvNode = {
|
def setBloomFilter(bloom: BloomFilter): SpvNode = {
|
||||||
_bloomFilter.atomicSet(bloom)
|
_bloomFilter.atomicSet(bloom)
|
||||||
this
|
this
|
||||||
|
@ -92,7 +92,8 @@ case class SpvNode(
|
||||||
_ <- AsyncUtil.retryUntilSatisfiedF(() => isConnected(0))
|
_ <- AsyncUtil.retryUntilSatisfiedF(() => isConnected(0))
|
||||||
_ <- peerMsgSenders(0).sendFilterLoadMessage(bloomFilter)
|
_ <- peerMsgSenders(0).sendFilterLoadMessage(bloomFilter)
|
||||||
} yield {
|
} yield {
|
||||||
logger.info(s"Sending bloomfilter=${bloomFilter.hex} to ${peers(0)}")
|
logger.info(
|
||||||
|
s"Sending bloomfilter=${bloomFilter.hex} to ${peerManager.peers(0)}")
|
||||||
node.asInstanceOf[SpvNode]
|
node.asInstanceOf[SpvNode]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,14 @@ case class NodeAppConfig(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy val maxConnectedPeers: Int = {
|
||||||
|
if (config.hasPath("bitcoin-s.node.maxConnectedPeers"))
|
||||||
|
config.getInt("bitcoin-s.node.maxConnectedPeers")
|
||||||
|
else 1
|
||||||
|
}
|
||||||
|
|
||||||
/** Creates either a neutrino node or a spv node based on the [[NodeAppConfig]] given */
|
/** Creates either a neutrino node or a spv node based on the [[NodeAppConfig]] given */
|
||||||
def createNode(peers: Vector[Peer])(
|
def createNode(peers: Vector[Peer] = Vector.empty[Peer])(
|
||||||
chainConf: ChainAppConfig,
|
chainConf: ChainAppConfig,
|
||||||
system: ActorSystem): Future[Node] = {
|
system: ActorSystem): Future[Node] = {
|
||||||
NodeAppConfig.createNode(peers)(this, chainConf, system)
|
NodeAppConfig.createNode(peers)(this, chainConf, system)
|
||||||
|
@ -163,9 +169,19 @@ object NodeAppConfig extends AppConfigFactoryActorSystem[NodeAppConfig] {
|
||||||
|
|
||||||
nodeConf.nodeType match {
|
nodeConf.nodeType match {
|
||||||
case NodeType.SpvNode =>
|
case NodeType.SpvNode =>
|
||||||
dmhF.map(dmh => SpvNode(peers, dmh, nodeConf, chainConf, system))
|
dmhF.map(dmh =>
|
||||||
|
SpvNode(dmh,
|
||||||
|
nodeConf,
|
||||||
|
chainConf,
|
||||||
|
system,
|
||||||
|
configPeersOverride = peers))
|
||||||
case NodeType.NeutrinoNode =>
|
case NodeType.NeutrinoNode =>
|
||||||
dmhF.map(dmh => NeutrinoNode(peers, dmh, nodeConf, chainConf, system))
|
dmhF.map(dmh =>
|
||||||
|
NeutrinoNode(dmh,
|
||||||
|
nodeConf,
|
||||||
|
chainConf,
|
||||||
|
system,
|
||||||
|
configPeersOverride = peers))
|
||||||
case NodeType.FullNode =>
|
case NodeType.FullNode =>
|
||||||
Future.failed(new RuntimeException("Not implemented"))
|
Future.failed(new RuntimeException("Not implemented"))
|
||||||
case NodeType.BitcoindBackend =>
|
case NodeType.BitcoindBackend =>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.bitcoins.node.models
|
package org.bitcoins.node.models
|
||||||
|
|
||||||
|
import org.bitcoins.core.p2p.AddrV2Message
|
||||||
import org.bitcoins.db.{CRUD, SlickUtil}
|
import org.bitcoins.db.{CRUD, SlickUtil}
|
||||||
import org.bitcoins.node.config.NodeAppConfig
|
import org.bitcoins.node.config.NodeAppConfig
|
||||||
import scodec.bits.ByteVector
|
import scodec.bits.ByteVector
|
||||||
|
@ -45,6 +46,13 @@ case class PeerDAO()(implicit ec: ExecutionContext, appConfig: NodeAppConfig)
|
||||||
safeDatabase.run(q.delete)
|
safeDatabase.run(q.delete)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** returns only non onion addresses if tor is disabled, all otherwise */
|
||||||
|
def findAllWithTorFilter(torEnabled: Boolean): Future[Vector[PeerDb]] = {
|
||||||
|
val q = table.filterIf(!torEnabled)(
|
||||||
|
_.networkId =!= AddrV2Message.TOR_V3_NETWORK_BYTE)
|
||||||
|
safeDatabase.run(q.result).map(_.toVector)
|
||||||
|
}
|
||||||
|
|
||||||
def upsertPeer(
|
def upsertPeer(
|
||||||
address: ByteVector,
|
address: ByteVector,
|
||||||
port: Int,
|
port: Int,
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
package org.bitcoins.node.networking.peer
|
package org.bitcoins.node.networking.peer
|
||||||
|
|
||||||
|
import org.bitcoins.core.api.node.{
|
||||||
|
ExternalImplementationNodeType,
|
||||||
|
InternalImplementationNodeType,
|
||||||
|
NodeType
|
||||||
|
}
|
||||||
import org.bitcoins.core.p2p._
|
import org.bitcoins.core.p2p._
|
||||||
import org.bitcoins.node.models.Peer
|
import org.bitcoins.node.models.Peer
|
||||||
import org.bitcoins.node.networking.peer.PeerMessageReceiverState._
|
import org.bitcoins.node.networking.peer.PeerMessageReceiverState._
|
||||||
|
@ -31,13 +36,16 @@ case class ControlMessageHandler(node: Node)(implicit ec: ExecutionContext)
|
||||||
case good: Initializing =>
|
case good: Initializing =>
|
||||||
val newState = good.withVersionMsg(versionMsg)
|
val newState = good.withVersionMsg(versionMsg)
|
||||||
|
|
||||||
sender.sendVerackMessage()
|
node.peerManager
|
||||||
node.setPeerServices(peer, versionMsg.services)
|
.peerData(peer)
|
||||||
|
.setServiceIdentifier(versionMsg.services)
|
||||||
|
|
||||||
val newRecv = peerMessageReceiver.toState(newState)
|
val newRecv = peerMessageReceiver.toState(newState)
|
||||||
|
|
||||||
Future.successful(newRecv)
|
for {
|
||||||
|
_ <- sender.sendVerackMessage()
|
||||||
|
_ <- onPeerInitialization(peer)
|
||||||
|
} yield newRecv
|
||||||
}
|
}
|
||||||
|
|
||||||
case VerAckMessage =>
|
case VerAckMessage =>
|
||||||
|
@ -75,4 +83,23 @@ case class ControlMessageHandler(node: Node)(implicit ec: ExecutionContext)
|
||||||
Future.successful(peerMessageReceiver)
|
Future.successful(peerMessageReceiver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def onPeerInitialization(peer: Peer): Future[Unit] = {
|
||||||
|
node.nodeAppConfig.nodeType match {
|
||||||
|
case nodeType: InternalImplementationNodeType =>
|
||||||
|
nodeType match {
|
||||||
|
case NodeType.FullNode =>
|
||||||
|
throw new Exception("Node cannot be FullNode")
|
||||||
|
case NodeType.NeutrinoNode =>
|
||||||
|
node.peerManager.createInDb(peer).map(_ => ())
|
||||||
|
case NodeType.SpvNode =>
|
||||||
|
node.peerManager.createInDb(peer).map(_ => ())
|
||||||
|
}
|
||||||
|
case nodeType: ExternalImplementationNodeType =>
|
||||||
|
nodeType match {
|
||||||
|
case NodeType.BitcoindBackend =>
|
||||||
|
throw new Exception("Node cannot be BitcoindBackend")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,8 +50,9 @@ case class DataMessageHandler(
|
||||||
peerMsgSender: PeerMessageSender,
|
peerMsgSender: PeerMessageSender,
|
||||||
node: Node): Future[DataMessageHandler] = {
|
node: Node): Future[DataMessageHandler] = {
|
||||||
|
|
||||||
lazy val peerWithCompactFilters = node.randomPeerMsgSenderWithCompactFilters
|
lazy val peerWithCompactFilters =
|
||||||
lazy val randomPeer = node.randomPeerMsgSender
|
node.peerManager.randomPeerMsgSenderWithCompactFilters
|
||||||
|
lazy val randomPeer = node.peerManager.randomPeerMsgSender
|
||||||
|
|
||||||
val resultF = payload match {
|
val resultF = payload match {
|
||||||
case checkpoint: CompactFilterCheckPointMessage =>
|
case checkpoint: CompactFilterCheckPointMessage =>
|
||||||
|
|
|
@ -114,7 +114,6 @@ trait NodeTestWithCachedBitcoind extends BaseNodeTest with CachedTor {
|
||||||
appConfig.chainConf,
|
appConfig.chainConf,
|
||||||
appConfig.nodeConf)
|
appConfig.nodeConf)
|
||||||
startedNode <- node.start()
|
startedNode <- node.start()
|
||||||
//is it enough to just sync with one bitcoind client for a test?
|
|
||||||
syncedNode <- syncNeutrinoNode(startedNode, bitcoinds(0))
|
syncedNode <- syncNeutrinoNode(startedNode, bitcoinds(0))
|
||||||
} yield NeutrinoNodeConnectedWithBitcoinds(syncedNode, bitcoinds)
|
} yield NeutrinoNodeConnectedWithBitcoinds(syncedNode, bitcoinds)
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,15 @@ object NodeUnitTest extends P2PLogger {
|
||||||
val chainApiF = ChainHandlerCached
|
val chainApiF = ChainHandlerCached
|
||||||
.fromDatabase(blockHeaderDAO, filterHeaderDAO, filterDAO)
|
.fromDatabase(blockHeaderDAO, filterHeaderDAO, filterDAO)
|
||||||
|
|
||||||
chainApiF.map(buildNode(peer, _))
|
val nodeF = chainApiF.map(buildNode(peer, _))
|
||||||
|
for {
|
||||||
|
node <- nodeF
|
||||||
|
_ <- node.nodeConfig.start()
|
||||||
|
peers <- node.peerManager.getPeers
|
||||||
|
} yield {
|
||||||
|
peers.foreach(node.peerManager.addPeer)
|
||||||
|
node
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildNode(peer: Peer, chainApi: ChainApi)(implicit
|
def buildNode(peer: Peer, chainApi: ChainApi)(implicit
|
||||||
|
@ -233,7 +241,11 @@ object NodeUnitTest extends P2PLogger {
|
||||||
|
|
||||||
val dmh = DataMessageHandler(chainApi)
|
val dmh = DataMessageHandler(chainApi)
|
||||||
|
|
||||||
NeutrinoNode(Vector(peer), dmh, nodeConf, chainConf, system)
|
NeutrinoNode(dmh,
|
||||||
|
nodeConf,
|
||||||
|
chainConf,
|
||||||
|
system,
|
||||||
|
configPeersOverride = Vector(peer))
|
||||||
}
|
}
|
||||||
|
|
||||||
def buildPeerMessageReceiver(chainApi: ChainApi, peer: Peer)(implicit
|
def buildPeerMessageReceiver(chainApi: ChainApi, peer: Peer)(implicit
|
||||||
|
@ -272,6 +284,7 @@ object NodeUnitTest extends P2PLogger {
|
||||||
def destroyNode(node: Node)(implicit ec: ExecutionContext): Future[Unit] = {
|
def destroyNode(node: Node)(implicit ec: ExecutionContext): Future[Unit] = {
|
||||||
for {
|
for {
|
||||||
_ <- node.stop()
|
_ <- node.stop()
|
||||||
|
_ <- node.nodeAppConfig.stop()
|
||||||
_ <- node.chainAppConfig.stop()
|
_ <- node.chainAppConfig.stop()
|
||||||
} yield {
|
} yield {
|
||||||
()
|
()
|
||||||
|
@ -486,11 +499,12 @@ object NodeUnitTest extends P2PLogger {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_ <- checkConfigF
|
_ <- checkConfigF
|
||||||
|
_ <- nodeAppConfig.start()
|
||||||
chainHandler <- ChainUnitTest.createChainHandler()
|
chainHandler <- ChainUnitTest.createChainHandler()
|
||||||
} yield {
|
} yield {
|
||||||
val dmh = DataMessageHandler(chainHandler)
|
val dmh = DataMessageHandler(chainHandler)
|
||||||
SpvNode(
|
SpvNode(
|
||||||
nodePeer = Vector(peer),
|
configPeersOverride = Vector(peer),
|
||||||
dataMessageHandler = dmh,
|
dataMessageHandler = dmh,
|
||||||
nodeConfig = nodeAppConfig,
|
nodeConfig = nodeAppConfig,
|
||||||
chainConfig = chainAppConfig,
|
chainConfig = chainAppConfig,
|
||||||
|
@ -516,11 +530,12 @@ object NodeUnitTest extends P2PLogger {
|
||||||
chainHandler <- ChainUnitTest.createChainHandler()
|
chainHandler <- ChainUnitTest.createChainHandler()
|
||||||
} yield chainHandler
|
} yield chainHandler
|
||||||
val nodeF = for {
|
val nodeF = for {
|
||||||
|
_ <- nodeAppConfig.start()
|
||||||
peer <- createPeer(bitcoind)
|
peer <- createPeer(bitcoind)
|
||||||
chainApi <- chainApiF
|
chainApi <- chainApiF
|
||||||
} yield {
|
} yield {
|
||||||
val dmh = DataMessageHandler(chainApi)
|
val dmh = DataMessageHandler(chainApi)
|
||||||
NeutrinoNode(nodePeer = Vector(peer),
|
NeutrinoNode(configPeersOverride = Vector(peer),
|
||||||
dataMessageHandler = dmh,
|
dataMessageHandler = dmh,
|
||||||
nodeConfig = nodeAppConfig,
|
nodeConfig = nodeAppConfig,
|
||||||
chainConfig = chainAppConfig,
|
chainConfig = chainAppConfig,
|
||||||
|
@ -548,11 +563,12 @@ object NodeUnitTest extends P2PLogger {
|
||||||
} yield chainHandler
|
} yield chainHandler
|
||||||
val peersF = bitcoinds.map(createPeer(_))
|
val peersF = bitcoinds.map(createPeer(_))
|
||||||
val nodeF = for {
|
val nodeF = for {
|
||||||
|
_ <- nodeAppConfig.start()
|
||||||
chainApi <- chainApiF
|
chainApi <- chainApiF
|
||||||
peers <- Future.sequence(peersF)
|
peers <- Future.sequence(peersF)
|
||||||
} yield {
|
} yield {
|
||||||
val dmh = DataMessageHandler(chainApi)
|
val dmh = DataMessageHandler(chainApi)
|
||||||
NeutrinoNode(nodePeer = peers,
|
NeutrinoNode(configPeersOverride = peers,
|
||||||
dataMessageHandler = dmh,
|
dataMessageHandler = dmh,
|
||||||
nodeConfig = nodeAppConfig,
|
nodeConfig = nodeAppConfig,
|
||||||
chainConfig = chainAppConfig,
|
chainConfig = chainAppConfig,
|
||||||
|
|
Loading…
Add table
Reference in a new issue