2023-12-12 20:08:58 +00:00
|
|
|
# Fluffy
|
2024-01-25 10:04:09 +00:00
|
|
|
# Copyright (c) 2023-2024 Status Research & Development GmbH
|
2023-09-15 14:21:00 +00:00
|
|
|
# Licensed and distributed under either of
|
|
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
|
|
|
{.push raises: [].}
|
|
|
|
|
2024-03-22 18:01:22 +00:00
|
|
|
import
|
2024-07-18 09:01:40 +00:00
|
|
|
std/[strutils, os, uri],
|
|
|
|
confutils,
|
|
|
|
confutils/std/net,
|
|
|
|
nimcrypto/hash,
|
|
|
|
../../[conf, logging]
|
2023-09-15 14:21:00 +00:00
|
|
|
|
|
|
|
export net
|
|
|
|
|
2024-03-15 09:41:41 +00:00
|
|
|
proc defaultEthDataDir*(): string =
|
|
|
|
let dataDir =
|
|
|
|
when defined(windows):
|
|
|
|
"AppData" / "Roaming" / "EthData"
|
|
|
|
elif defined(macosx):
|
|
|
|
"Library" / "Application Support" / "EthData"
|
|
|
|
else:
|
|
|
|
".cache" / "eth-data"
|
|
|
|
|
|
|
|
getHomeDir() / dataDir
|
|
|
|
|
|
|
|
proc defaultEra1DataDir*(): string =
|
|
|
|
defaultEthDataDir() / "era1"
|
|
|
|
|
2024-07-18 09:01:40 +00:00
|
|
|
proc defaultPortalBridgeStateDir*(): string =
|
|
|
|
when defined(windows) or defined(macosx):
|
|
|
|
defaultDataDir() / "Bridge" / "State"
|
|
|
|
else:
|
|
|
|
defaultDataDir() / "bridge" / "state"
|
|
|
|
|
2023-09-15 14:21:00 +00:00
|
|
|
type
|
|
|
|
TrustedDigest* = MDigest[32 * 8]
|
|
|
|
|
2024-07-02 09:24:41 +00:00
|
|
|
JsonRpcUrlKind* = enum
|
2024-03-11 17:20:29 +00:00
|
|
|
HttpUrl
|
|
|
|
WsUrl
|
|
|
|
|
2024-07-02 09:24:41 +00:00
|
|
|
JsonRpcUrl* = object
|
|
|
|
kind*: JsonRpcUrlKind
|
|
|
|
value*: string
|
2024-03-11 17:20:29 +00:00
|
|
|
|
2023-12-12 20:08:58 +00:00
|
|
|
PortalBridgeCmd* = enum
|
|
|
|
beacon = "Run a Portal bridge for the beacon network"
|
|
|
|
history = "Run a Portal bridge for the history network"
|
|
|
|
state = "Run a Portal bridge for the state network"
|
2023-09-15 14:21:00 +00:00
|
|
|
|
2024-02-28 17:31:45 +00:00
|
|
|
PortalBridgeConf* = object # Logging
|
|
|
|
logLevel* {.desc: "Sets the log level", defaultValue: "INFO", name: "log-level".}:
|
|
|
|
string
|
2023-09-15 14:21:00 +00:00
|
|
|
|
|
|
|
logStdout* {.
|
2024-02-28 17:31:45 +00:00
|
|
|
hidden,
|
|
|
|
desc:
|
|
|
|
"Specifies what kind of logs should be written to stdout (auto, colors, nocolors, json)",
|
|
|
|
defaultValueDesc: "auto",
|
|
|
|
defaultValue: StdoutLogKind.Auto,
|
|
|
|
name: "log-format"
|
|
|
|
.}: StdoutLogKind
|
2023-09-15 14:21:00 +00:00
|
|
|
|
2024-07-23 10:46:53 +00:00
|
|
|
portalRpcUrl* {.
|
|
|
|
desc: "Portal node JSON-RPC API URL",
|
|
|
|
defaultValue: JsonRpcUrl(kind: HttpUrl, value: "http://127.0.0.1:8545"),
|
|
|
|
name: "portal-rpc-url"
|
|
|
|
.}: JsonRpcUrl
|
2023-09-15 14:21:00 +00:00
|
|
|
|
2024-02-28 17:31:45 +00:00
|
|
|
case cmd* {.command, desc: "".}: PortalBridgeCmd
|
2023-12-12 20:08:58 +00:00
|
|
|
of PortalBridgeCmd.beacon:
|
|
|
|
# Beacon node REST API URL
|
|
|
|
restUrl* {.
|
2024-02-28 17:31:45 +00:00
|
|
|
desc: "URL of the beacon node REST service",
|
|
|
|
defaultValue: "http://127.0.0.1:5052",
|
|
|
|
name: "rest-url"
|
|
|
|
.}: string
|
2023-09-15 14:21:00 +00:00
|
|
|
|
2023-12-12 20:08:58 +00:00
|
|
|
# Backfill options
|
2024-01-25 10:04:09 +00:00
|
|
|
backfillAmount* {.
|
2024-02-28 17:31:45 +00:00
|
|
|
desc: "Amount of beacon LC updates to backfill gossip into the network",
|
|
|
|
defaultValue: 64,
|
|
|
|
name: "backfill-amount"
|
|
|
|
.}: uint64
|
2023-09-15 14:21:00 +00:00
|
|
|
|
2023-12-12 20:08:58 +00:00
|
|
|
trustedBlockRoot* {.
|
2024-02-28 17:31:45 +00:00
|
|
|
desc:
|
|
|
|
"Trusted finalized block root for which to gossip a LC bootstrap into the network",
|
|
|
|
defaultValue: none(TrustedDigest),
|
|
|
|
name: "trusted-block-root"
|
|
|
|
.}: Option[TrustedDigest]
|
2023-12-12 20:08:58 +00:00
|
|
|
of PortalBridgeCmd.history:
|
2024-07-02 09:24:41 +00:00
|
|
|
web3Url* {.desc: "Execution layer JSON-RPC API URL", name: "web3-url".}:
|
|
|
|
JsonRpcUrl
|
2024-03-11 17:20:29 +00:00
|
|
|
|
|
|
|
blockVerify* {.
|
|
|
|
desc: "Verify the block header, body and receipts",
|
|
|
|
defaultValue: false,
|
|
|
|
name: "block-verify"
|
|
|
|
.}: bool
|
2024-03-15 09:41:41 +00:00
|
|
|
|
|
|
|
latest* {.
|
|
|
|
desc:
|
|
|
|
"Follow the head of the chain and gossip latest block header, body and receipts into the network",
|
|
|
|
defaultValue: true,
|
|
|
|
name: "latest"
|
|
|
|
.}: bool
|
|
|
|
|
|
|
|
backfill* {.
|
|
|
|
desc:
|
2024-03-26 21:27:31 +00:00
|
|
|
"Randomly backfill pre-merge block headers, bodies and receipts into the network from the era1 files",
|
2024-03-15 09:41:41 +00:00
|
|
|
defaultValue: false,
|
|
|
|
name: "backfill"
|
|
|
|
.}: bool
|
|
|
|
|
2024-03-26 21:27:31 +00:00
|
|
|
audit* {.
|
|
|
|
desc:
|
|
|
|
"Run pre-merge backfill in audit mode, which will only gossip content that if failed to fetch from the network",
|
2024-03-27 18:16:24 +00:00
|
|
|
defaultValue: true,
|
2024-03-26 21:27:31 +00:00
|
|
|
name: "audit"
|
|
|
|
.}: bool
|
|
|
|
|
2024-03-15 09:41:41 +00:00
|
|
|
era1Dir* {.
|
|
|
|
desc: "The directory where all era1 files are stored",
|
|
|
|
defaultValue: defaultEra1DataDir(),
|
|
|
|
defaultValueDesc: defaultEra1DataDir(),
|
|
|
|
name: "era1-dir"
|
|
|
|
.}: InputDir
|
2023-12-12 20:08:58 +00:00
|
|
|
of PortalBridgeCmd.state:
|
2024-03-22 18:01:22 +00:00
|
|
|
web3UrlState* {.desc: "Execution layer JSON-RPC API URL", name: "web3-url".}:
|
2024-07-02 09:24:41 +00:00
|
|
|
JsonRpcUrl
|
2023-09-15 14:21:00 +00:00
|
|
|
|
2024-07-18 09:01:40 +00:00
|
|
|
stateDir* {.
|
|
|
|
desc: "The directory where the state data is stored",
|
|
|
|
defaultValue: defaultPortalBridgeStateDir(),
|
|
|
|
defaultValueDesc: defaultPortalBridgeStateDir(),
|
|
|
|
name: "state-dir"
|
|
|
|
.}: InputDir
|
|
|
|
|
2024-07-30 14:56:21 +00:00
|
|
|
startBlockNumber* {.
|
|
|
|
desc: "The block number to start from", defaultValue: 1, name: "start-block"
|
|
|
|
.}: uint64
|
|
|
|
|
2024-08-06 07:38:38 +00:00
|
|
|
verifyStateProofs* {.
|
2024-10-03 02:57:19 +00:00
|
|
|
desc:
|
|
|
|
"Verify state proofs before gossiping them into the portal network (Slow: Only used for testing).",
|
2024-08-06 07:38:38 +00:00
|
|
|
defaultValue: false,
|
|
|
|
name: "verify-state-proofs"
|
2024-07-18 09:01:40 +00:00
|
|
|
.}: bool
|
|
|
|
|
2024-10-03 02:57:19 +00:00
|
|
|
enableGossip* {.
|
|
|
|
desc:
|
|
|
|
"Enable gossipping the state into the portal network. Disable to only build the state without gossiping it.",
|
|
|
|
defaultValue: true,
|
|
|
|
name: "enable-gossip"
|
|
|
|
.}: bool
|
|
|
|
|
2024-08-06 07:38:38 +00:00
|
|
|
gossipGenesis* {.
|
2024-08-07 16:01:30 +00:00
|
|
|
desc:
|
|
|
|
"Enable gossip of the genesis state into the portal network when starting from block 1",
|
2024-07-18 09:01:40 +00:00
|
|
|
defaultValue: true,
|
2024-08-06 07:38:38 +00:00
|
|
|
name: "gossip-genesis"
|
2024-07-18 09:01:40 +00:00
|
|
|
.}: bool
|
|
|
|
|
2024-08-06 07:38:38 +00:00
|
|
|
verifyGossip* {.
|
|
|
|
desc:
|
|
|
|
"Enable verifying that the state was successfully gossipped by fetching it from the network",
|
|
|
|
defaultValue: false,
|
|
|
|
name: "verify-gossip"
|
|
|
|
.}: bool
|
|
|
|
|
|
|
|
gossipWorkersCount* {.
|
|
|
|
desc:
|
|
|
|
"The number of workers to use for gossiping the state into the portal network",
|
|
|
|
defaultValue: 2,
|
|
|
|
name: "gossip-workers"
|
|
|
|
.}: uint
|
|
|
|
|
2024-02-28 17:31:45 +00:00
|
|
|
func parseCmdArg*(T: type TrustedDigest, input: string): T {.raises: [ValueError].} =
|
2023-09-15 14:21:00 +00:00
|
|
|
TrustedDigest.fromHex(input)
|
|
|
|
|
|
|
|
func completeCmdArg*(T: type TrustedDigest, input: string): seq[string] =
|
|
|
|
return @[]
|
2024-03-11 17:20:29 +00:00
|
|
|
|
2024-07-02 09:24:41 +00:00
|
|
|
proc parseCmdArg*(T: type JsonRpcUrl, p: string): T {.raises: [ValueError].} =
|
2024-03-11 17:20:29 +00:00
|
|
|
let
|
|
|
|
url = parseUri(p)
|
|
|
|
normalizedScheme = url.scheme.toLowerAscii()
|
|
|
|
|
|
|
|
if (normalizedScheme == "http" or normalizedScheme == "https"):
|
2024-07-02 09:24:41 +00:00
|
|
|
JsonRpcUrl(kind: HttpUrl, value: p)
|
2024-03-11 17:20:29 +00:00
|
|
|
elif (normalizedScheme == "ws" or normalizedScheme == "wss"):
|
2024-07-02 09:24:41 +00:00
|
|
|
JsonRpcUrl(kind: WsUrl, value: p)
|
2024-03-11 17:20:29 +00:00
|
|
|
else:
|
|
|
|
raise newException(
|
|
|
|
ValueError,
|
|
|
|
"The Web3 URL must specify one of following protocols: http/https/ws/wss",
|
|
|
|
)
|
|
|
|
|
2024-07-02 09:24:41 +00:00
|
|
|
proc completeCmdArg*(T: type JsonRpcUrl, val: string): seq[string] =
|
2024-03-11 17:20:29 +00:00
|
|
|
return @[]
|