# beacon_chain # Copyright (c) 2021-2024 Status Research & Development GmbH # 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: [].} {.used.} import unittest2, confutils, stew/byteutils, ../beacon_chain/el/el_conf, ../beacon_chain/spec/engine_authentication type ExampleConfigFile = object dataDir* {.name: "data-dir".}: string el* {.name: "el".}: seq[EngineApiUrlConfigValue] proc loadExampleConfig( content: string, cmdLine = newSeq[string]() ): ExampleConfigFile {.raises: [ConfigurationError, OSError].} = ExampleConfigFile.load( cmdLine = cmdLine, secondarySources = proc ( config: ExampleConfigFile, sources: ref SecondarySources) {.raises: [ConfigurationError].} = sources.addConfigFileContent(Toml, content)) const validJwtToken = parseJwtTokenValue( "aa95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098cc").get suite "EL Configuration": test "URL parsing": let url1 = EngineApiUrlConfigValue.parseCmdArg("localhost:8484") check: url1.url == "localhost:8484" url1.roles.isNone url1.jwtSecret.isNone url1.jwtSecretFile.isNone let url1Final1 = url1.toFinalUrl(Opt.some validJwtToken) url1Final2 = url1.toFinalUrl(Opt.none seq[byte]) check: url1Final1.isOk url1Final1.get.url == "ws://localhost:8484" url1Final1.get.jwtSecret.get == validJwtToken url1Final1.get.roles == defaultEngineApiRoles url1Final2.isOk url1Final2.get.url == "ws://localhost:8484" url1Final2.get.jwtSecret.isNone url1Final2.get.roles == defaultEngineApiRoles let url2 = EngineApiUrlConfigValue.parseCmdArg( "https://eth-node.io:2020#jwt-secret-file=tests/media/jwt.hex") check: url2.url == "https://eth-node.io:2020" url2.roles.isNone url2.jwtSecret.isNone url2.jwtSecretFile.get.string == "tests/media/jwt.hex" let url3 = EngineApiUrlConfigValue.parseCmdArg( "http://localhost/#roles=sync-deposits&jwt-secret=ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba") check: url3.url == "http://localhost/" url3.roles == some({DepositSyncing}) url3.jwtSecret == some("ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba") url3.jwtSecretFile.isNone let url3Final = url3.toFinalUrl(Opt.some validJwtToken) check: url3Final.isOk url3Final.get.jwtSecret.get.toHex == "ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba" url3Final.get.roles == {DepositSyncing} let url4 = EngineApiUrlConfigValue.parseCmdArg( "localhost#roles=sync-deposits,validate-blocks&jwt-secret=ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba23") check: url4.url == "localhost" url4.roles == some({DepositSyncing, BlockValidation}) url4.jwtSecret == some("ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba23") url4.jwtSecretFile.isNone let url4Final = url4.toFinalUrl(Opt.some validJwtToken) check: not url4Final.isOk # the JWT secret is invalid let url5 = EngineApiUrlConfigValue.parseCmdArg( "http://127.0.0.1:9090/#roles=sync-deposits,validate-blocks,produce-blocks,sync-deposits") check: url5.url == "http://127.0.0.1:9090/" url5.roles == some({DepositSyncing, BlockValidation, BlockProduction}) url5.jwtSecret.isNone url5.jwtSecretFile.isNone test "Invalid URls": template testInvalidUrl(url: string) = expect ValueError: echo "This URL should be invalid: ", EngineApiUrlConfigValue.parseCmdArg(url) testInvalidUrl "http://127.0.0.1:9090/#roles=" testInvalidUrl "http://127.0.0.1:9090/#roles=sy" testInvalidUrl "http://127.0.0.1:9090/#roles=sync-deposits," testInvalidUrl "http://127.0.0.1:9090/#roles=sync-deposits;validate-blocks" testInvalidUrl "http://127.0.0.1:9090/#roles=validate-blocks,sync-deps" test "Old style config files": let cfg = loadExampleConfig """ data-dir = "/foo" el = ["http://localhost:8585", "eth-data.io#roles=sync-deposits", "wss://eth-nodes.io/21312432"] """ check: cfg.dataDir == "/foo" cfg.el.len == 3 cfg.el[0].url == "http://localhost:8585" cfg.el[1].url == "eth-data.io" cfg.el[1].roles == some({DepositSyncing}) cfg.el[2].url == "wss://eth-nodes.io/21312432" test "New style config files": let cfg = loadExampleConfig """ data-dir = "my-data-dir" [[el]] url = "http://localhost:8585" jwt-secret-file = "tests/media/jwt.hex" [[el]] url = "eth-data.io" roles = ["sync-deposits", "produce-blocks"] [[el]] url = "wss://eth-nodes.io/21312432" jwt-secret = "0xee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba" """ check: cfg.dataDir == "my-data-dir" cfg.el.len == 3 cfg.el[0].url == "http://localhost:8585" cfg.el[0].roles.isNone cfg.el[0].jwtSecret.isNone cfg.el[0].jwtSecretFile.get.string == "tests/media/jwt.hex" cfg.el[1].url == "eth-data.io" cfg.el[1].roles == some({DepositSyncing, BlockProduction}) cfg.el[1].jwtSecret.isNone cfg.el[1].jwtSecretFile.isNone cfg.el[2].url == "wss://eth-nodes.io/21312432" cfg.el[2].roles.isNone cfg.el[2].jwtSecret.get == "0xee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba" cfg.el[2].jwtSecretFile.isNone test "Empty config file": let cfg = loadExampleConfig("", cmdLine = @["--data-dir=foo"]) check: cfg.dataDir == "foo" cfg.el.len == 0