2025-02-05 10:52:15 +01:00
|
|
|
import std/net
|
2025-02-06 10:16:47 +01:00
|
|
|
import std/sequtils
|
|
|
|
|
import pkg/chronicles
|
|
|
|
|
import pkg/libp2p
|
|
|
|
|
import pkg/codexdht
|
2025-02-10 13:54:59 +01:00
|
|
|
import ./utils/version
|
2025-02-05 10:52:15 +01:00
|
|
|
|
2025-02-05 11:06:18 +01:00
|
|
|
let doc =
|
2025-08-26 15:03:11 +03:00
|
|
|
"""
|
|
|
|
|
Codex Network Crawler. Generates network metrics.
|
|
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
|
codexcrawler [--logLevel=<l>] [--publicIp=<a>] [--metricsAddress=<ip>] [--metricsPort=<p>] [--dataDir=<dir>] [--discoveryPort=<p>] [--bootNodes=<n>] [--dhtEnable=<e>] [--stepDelay=<ms>] [--revisitDelay=<m>] [--checkDelay=<m>] [--expiryDelay=<m>] [--marketplaceEnable=<e>] [--ethProvider=<a>] [--marketplaceAddress=<a>] [--requestCheckDelay=<m>]
|
|
|
|
|
|
|
|
|
|
Options:
|
|
|
|
|
--logLevel=<l> Sets log level [default: INFO]
|
|
|
|
|
--publicIp=<a> Public IP address where this instance is reachable.
|
|
|
|
|
--metricsAddress=<ip> Listen address of the metrics server [default: 0.0.0.0]
|
|
|
|
|
--metricsPort=<p> Listen HTTP port of the metrics server [default: 8008]
|
|
|
|
|
--dataDir=<dir> Directory for storing data [default: crawler_data]
|
|
|
|
|
--discoveryPort=<p> Port used for DHT [default: 8090]
|
|
|
|
|
--bootNodes=<n> Semi-colon-separated list of Codex bootstrap SPRs [default: testnet_sprs]
|
|
|
|
|
|
|
|
|
|
--dhtEnable=<e> Set to "1" to enable DHT crawler [default: 1]
|
|
|
|
|
--stepDelay=<ms> Delay in milliseconds per node visit [default: 1000]
|
|
|
|
|
--revisitDelay=<m> Delay in minutes after which a node can be revisited [default: 60]
|
|
|
|
|
--checkDelay=<m> Delay with which the 'revisitDelay' is checked for all known nodes [default: 10]
|
|
|
|
|
--expiryDelay=<m> Delay in minutes after which unresponsive nodes are discarded [default: 1440] (24h)
|
|
|
|
|
|
|
|
|
|
--marketplaceEnable=<e> Set to "1" to enable marketplace metrics [default: 1]
|
|
|
|
|
--ethProvider=<a> Address including http(s) or ws of the eth provider
|
|
|
|
|
--marketplaceAddress=<a> Eth address of Codex contracts deployment
|
|
|
|
|
--requestCheckDelay=<m> Delay in minutes after which storage contract status is (re)checked [default: 10]
|
2025-02-05 10:52:15 +01:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import strutils
|
|
|
|
|
import docopt
|
|
|
|
|
|
2025-02-10 14:49:30 +01:00
|
|
|
type Config* = ref object
|
2025-02-05 11:06:18 +01:00
|
|
|
logLevel*: string
|
2025-02-07 13:44:35 +01:00
|
|
|
publicIp*: string
|
2025-02-05 11:06:18 +01:00
|
|
|
metricsAddress*: IpAddress
|
|
|
|
|
metricsPort*: Port
|
|
|
|
|
dataDir*: string
|
|
|
|
|
discPort*: Port
|
2025-02-06 10:16:47 +01:00
|
|
|
bootNodes*: seq[SignedPeerRecord]
|
2025-03-10 13:51:51 +01:00
|
|
|
|
|
|
|
|
dhtEnable*: bool
|
2025-02-07 16:19:26 +01:00
|
|
|
stepDelayMs*: int
|
2025-02-13 14:55:45 +01:00
|
|
|
revisitDelayMins*: int
|
2025-02-13 12:35:19 +01:00
|
|
|
checkDelayMins*: int
|
2025-02-13 14:55:45 +01:00
|
|
|
expiryDelayMins*: int
|
2025-02-05 10:52:15 +01:00
|
|
|
|
2025-03-10 13:51:51 +01:00
|
|
|
marketplaceEnable*: bool
|
|
|
|
|
ethProvider*: string
|
|
|
|
|
marketplaceAddress*: string
|
2025-03-24 09:05:07 +01:00
|
|
|
requestCheckDelay*: int
|
2025-03-10 13:51:51 +01:00
|
|
|
|
2025-02-10 14:49:30 +01:00
|
|
|
proc `$`*(config: Config): string =
|
|
|
|
|
"Crawler:" & " logLevel=" & config.logLevel & " publicIp=" & config.publicIp &
|
2025-02-07 13:57:57 +01:00
|
|
|
" metricsAddress=" & $config.metricsAddress & " metricsPort=" & $config.metricsPort &
|
2025-03-10 13:51:51 +01:00
|
|
|
" dataDir=" & config.dataDir & " discPort=" & $config.discPort & " dhtEnable=" &
|
|
|
|
|
$config.dhtEnable & " bootNodes=" & config.bootNodes.mapIt($it).join(";") &
|
|
|
|
|
" stepDelay=" & $config.stepDelayMs & " revisitDelayMins=" & $config.revisitDelayMins &
|
|
|
|
|
" expiryDelayMins=" & $config.expiryDelayMins & " checkDelayMins=" &
|
|
|
|
|
$config.checkDelayMins & " marketplaceEnable=" & $config.marketplaceEnable &
|
|
|
|
|
" ethProvider=" & config.ethProvider & " marketplaceAddress=" &
|
2025-03-24 09:05:07 +01:00
|
|
|
config.marketplaceAddress & " requestCheckDelay=" & $config.requestCheckDelay
|
2025-02-05 16:43:36 +01:00
|
|
|
|
|
|
|
|
proc getDefaultTestnetBootNodes(): seq[string] =
|
|
|
|
|
@[
|
|
|
|
|
"spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P",
|
2025-03-10 17:14:56 +02:00
|
|
|
"spr:CiUIAhIhAlNJ7ary8eOK5GcwQ6q4U8brR7iWjwhMwzHb8BzzmCEDEgIDARpJCicAJQgCEiECU0ntqvLx44rkZzBDqrhTxutHuJaPCEzDMdvwHPOYIQMQsZ67vgYaCwoJBK6Kf1-RAnVEGgsKCQSuin9fkQJ1RCpGMEQCIDxd6lXDvj1PcHgQYnNpHGfgCO5a7fejg3WhSjh2wTimAiB7YHsL1WZYU_zkHcNDWhRgMbkb3C5yRuvUhjBjGOYJYQ",
|
2025-08-26 15:03:11 +03:00
|
|
|
"spr:CiUIAhIhAyUvcPkKoGE7-gh84RmKIPHJPdsX5Ugm_IHVJgF-Mmu_EgIDARo8CicAJQgCEiEDJS9w-QqgYTv6CHzhGYog8ck92xflSCb8gdUmAX4ya78QoemesAYaCwoJBES39Q2RAnVOKkYwRAIgLi3rouyaZFS_Uilx8k99ySdQCP1tsmLR21tDb9p8LcgCIG30o5YnEooQ1n6tgm9fCT7s53k6XlxyeSkD_uIO9mb3",
|
2025-02-05 16:43:36 +01:00
|
|
|
]
|
|
|
|
|
|
2025-06-27 14:13:08 +03:00
|
|
|
proc getDefaultDevnetBootNodes(): seq[string] =
|
|
|
|
|
@[
|
|
|
|
|
"spr:CiUIAhIhA-VlcoiRm02KyIzrcTP-ljFpzTljfBRRKTIvhMIwqBqWEgIDARpJCicAJQgCEiED5WVyiJGbTYrIjOtxM_6WMWnNOWN8FFEpMi-EwjCoGpYQs8n8wQYaCwoJBHTKubmRAnU6GgsKCQR0yrm5kQJ1OipHMEUCIQDwUNsfReB4ty7JFS5WVQ6n1fcko89qVAOfQEHixa03rgIgan2-uFNDT-r4s9TOkLe9YBkCbsRWYCHGGVJ25rLj0QE",
|
|
|
|
|
"spr:CiUIAhIhApIj9p6zJDRbw2NoCo-tj98Y760YbppRiEpGIE1yGaMzEgIDARpJCicAJQgCEiECkiP2nrMkNFvDY2gKj62P3xjvrRhumlGISkYgTXIZozMQvcz8wQYaCwoJBAWhF3WRAnVEGgsKCQQFoRd1kQJ1RCpGMEQCIFZB84O_nzPNuViqEGRL1vJTjHBJ-i5ZDgFL5XZxm4HAAiB8rbLHkUdFfWdiOmlencYVn0noSMRHzn4lJYoShuVzlw",
|
|
|
|
|
"spr:CiUIAhIhApqRgeWRPSXocTS9RFkQmwTZRG-Cdt7UR2N7POoz606ZEgIDARpJCicAJQgCEiECmpGB5ZE9JehxNL1EWRCbBNlEb4J23tRHY3s86jPrTpkQj8_8wQYaCwoJBAXfEfiRAnVOGgsKCQQF3xH4kQJ1TipGMEQCIGWJMsF57N1iIEQgTH7IrVOgEgv0J2P2v3jvQr5Cjy-RAiAy4aiZ8QtyDvCfl_K_w6SyZ9csFGkRNTpirq_M_QNgKw",
|
|
|
|
|
]
|
|
|
|
|
|
2025-02-06 10:16:47 +01:00
|
|
|
proc getBootNodeStrings(input: string): seq[string] =
|
2025-02-05 16:43:36 +01:00
|
|
|
if input == "testnet_sprs":
|
|
|
|
|
return getDefaultTestnetBootNodes()
|
2025-06-27 14:13:08 +03:00
|
|
|
elif input == "devnet_sprs":
|
|
|
|
|
return getDefaultDevnetBootNodes()
|
2025-02-05 16:43:36 +01:00
|
|
|
return input.split(";")
|
2025-02-05 10:52:15 +01:00
|
|
|
|
2025-02-06 10:33:11 +01:00
|
|
|
proc stringToSpr(uri: string): SignedPeerRecord =
|
2025-02-06 10:16:47 +01:00
|
|
|
var res: SignedPeerRecord
|
|
|
|
|
try:
|
|
|
|
|
if not res.fromURI(uri):
|
|
|
|
|
warn "Invalid SignedPeerRecord uri", uri = uri
|
|
|
|
|
quit QuitFailure
|
|
|
|
|
except LPError as exc:
|
|
|
|
|
warn "Invalid SignedPeerRecord uri", uri = uri, error = exc.msg
|
|
|
|
|
quit QuitFailure
|
|
|
|
|
except CatchableError as exc:
|
|
|
|
|
warn "Invalid SignedPeerRecord uri", uri = uri, error = exc.msg
|
|
|
|
|
quit QuitFailure
|
|
|
|
|
res
|
|
|
|
|
|
|
|
|
|
proc getBootNodes(input: string): seq[SignedPeerRecord] =
|
|
|
|
|
getBootNodeStrings(input).mapIt(stringToSpr(it))
|
|
|
|
|
|
2025-03-10 13:51:51 +01:00
|
|
|
proc getEnable(input: string): bool =
|
|
|
|
|
input == "1"
|
|
|
|
|
|
2025-02-10 14:49:30 +01:00
|
|
|
proc parseConfig*(): Config =
|
2025-02-05 10:52:15 +01:00
|
|
|
let args = docopt(doc, version = crawlerFullVersion)
|
|
|
|
|
|
|
|
|
|
proc get(name: string): string =
|
|
|
|
|
$args[name]
|
|
|
|
|
|
2025-02-10 14:49:30 +01:00
|
|
|
return Config(
|
2025-02-05 10:52:15 +01:00
|
|
|
logLevel: get("--logLevel"),
|
2025-02-07 13:44:35 +01:00
|
|
|
publicIp: get("--publicIp"),
|
2025-02-05 10:52:15 +01:00
|
|
|
metricsAddress: parseIpAddress(get("--metricsAddress")),
|
|
|
|
|
metricsPort: Port(parseInt(get("--metricsPort"))),
|
|
|
|
|
dataDir: get("--dataDir"),
|
|
|
|
|
discPort: Port(parseInt(get("--discoveryPort"))),
|
2025-02-05 16:43:36 +01:00
|
|
|
bootNodes: getBootNodes(get("--bootNodes")),
|
2025-03-10 13:51:51 +01:00
|
|
|
dhtEnable: getEnable(get("--dhtEnable")),
|
2025-02-07 16:19:26 +01:00
|
|
|
stepDelayMs: parseInt(get("--stepDelay")),
|
2025-02-13 14:55:45 +01:00
|
|
|
revisitDelayMins: parseInt(get("--revisitDelay")),
|
2025-02-13 12:35:19 +01:00
|
|
|
checkDelayMins: parseInt(get("--checkDelay")),
|
2025-02-13 14:55:45 +01:00
|
|
|
expiryDelayMins: parseInt(get("--expiryDelay")),
|
2025-03-10 13:51:51 +01:00
|
|
|
marketplaceEnable: getEnable(get("--marketplaceEnable")),
|
|
|
|
|
ethProvider: get("--ethProvider"),
|
|
|
|
|
marketplaceAddress: get("--marketplaceAddress"),
|
2025-03-24 09:27:52 +01:00
|
|
|
requestCheckDelay: parseInt(get("--requestCheckDelay")),
|
2025-02-05 10:52:15 +01:00
|
|
|
)
|