|
| 1 | +# beacon_chain |
| 2 | +# Copyright (c) 2021-2023 Status Research & Development GmbH |
| 3 | +# Licensed and distributed under either of |
| 4 | +# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT). |
| 5 | +# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0). |
| 6 | +# at your option. This file may not be copied, modified, or distributed except according to those terms. |
| 7 | + |
| 8 | +{.used.} |
| 9 | + |
| 10 | +import |
| 11 | + unittest2, confutils, |
| 12 | + stew/byteutils, |
| 13 | + ../beacon_chain/eth1/el_conf, |
| 14 | + ../beacon_chain/spec/engine_authentication |
| 15 | + |
| 16 | +type |
| 17 | + ExampleConfigFile = object |
| 18 | + dataDir* {.name: "data-dir".}: string |
| 19 | + el* {.name: "el".}: seq[EngineApiUrlConfigValue] |
| 20 | + |
| 21 | +proc loadExampleConfig(content: string, cmdLine = newSeq[string]()): ExampleConfigFile = |
| 22 | + ExampleConfigFile.load( |
| 23 | + cmdLine = cmdLine, |
| 24 | + secondarySources = proc (config: ExampleConfigFile, sources: auto) = |
| 25 | + sources.addConfigFileContent(Toml, content)) |
| 26 | + |
| 27 | +const |
| 28 | + validJwtToken = parseJwtTokenValue( |
| 29 | + "aa95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098cc").get |
| 30 | + |
| 31 | +suite "EL Configuration": |
| 32 | + test "URL parsing": |
| 33 | + let url1 = EngineApiUrlConfigValue.parseCmdArg("localhost:8484") |
| 34 | + check: |
| 35 | + url1.url == "localhost:8484" |
| 36 | + url1.roles.isNone |
| 37 | + url1.jwtSecret.isNone |
| 38 | + url1.jwtSecretFile.isNone |
| 39 | + |
| 40 | + let |
| 41 | + url1Final1 = url1.toFinalUrl(some validJwtToken) |
| 42 | + url1Final2 = url1.toFinalUrl(none seq[byte]) |
| 43 | + |
| 44 | + check: |
| 45 | + url1Final1.isOk |
| 46 | + url1Final1.get.url == "ws://localhost:8484" |
| 47 | + url1Final1.get.jwtSecret.get == validJwtToken |
| 48 | + url1Final1.get.roles == defaultEngineApiRoles |
| 49 | + |
| 50 | + url1Final2.isOk |
| 51 | + url1Final2.get.url == "ws://localhost:8484" |
| 52 | + url1Final2.get.jwtSecret.isNone |
| 53 | + url1Final2.get.roles == defaultEngineApiRoles |
| 54 | + |
| 55 | + let url2 = EngineApiUrlConfigValue.parseCmdArg( |
| 56 | + "https://eth-node.io:2020#jwt-secret-file=jwt.hex") |
| 57 | + check: |
| 58 | + url2.url == "https://eth-node.io:2020" |
| 59 | + url2.roles.isNone |
| 60 | + url2.jwtSecret.isNone |
| 61 | + url2.jwtSecretFile.get.string == "jwt.hex" |
| 62 | + |
| 63 | + let url3 = EngineApiUrlConfigValue.parseCmdArg( |
| 64 | + "http://localhost/#roles=sync-deposits&jwt-secret=ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba") |
| 65 | + check: |
| 66 | + url3.url == "http://localhost/" |
| 67 | + url3.roles == some({DepositSyncing}) |
| 68 | + url3.jwtSecret == some("ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba") |
| 69 | + url3.jwtSecretFile.isNone |
| 70 | + |
| 71 | + let url3Final = url3.toFinalUrl(some validJwtToken) |
| 72 | + check: |
| 73 | + url3Final.isOk |
| 74 | + url3Final.get.jwtSecret.get.toHex == "ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba" |
| 75 | + url3Final.get.roles == {DepositSyncing} |
| 76 | + |
| 77 | + let url4 = EngineApiUrlConfigValue.parseCmdArg( |
| 78 | + "localhost#roles=sync-deposits,validate-blocks&jwt-secret=ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba23") |
| 79 | + check: |
| 80 | + url4.url == "localhost" |
| 81 | + url4.roles == some({DepositSyncing, BlockValidation}) |
| 82 | + url4.jwtSecret == some("ee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba23") |
| 83 | + url4.jwtSecretFile.isNone |
| 84 | + |
| 85 | + let url4Final = url4.toFinalUrl(some validJwtToken) |
| 86 | + check: |
| 87 | + not url4Final.isOk # the JWT secret is invalid |
| 88 | + |
| 89 | + let url5 = EngineApiUrlConfigValue.parseCmdArg( |
| 90 | + "http://127.0.0.1:9090/#roles=sync-deposits,validate-blocks,produce-blocks,sync-deposits") |
| 91 | + check: |
| 92 | + url5.url == "http://127.0.0.1:9090/" |
| 93 | + url5.roles == some({DepositSyncing, BlockValidation, BlockProduction}) |
| 94 | + url5.jwtSecret.isNone |
| 95 | + url5.jwtSecretFile.isNone |
| 96 | + |
| 97 | + test "Invalid URls": |
| 98 | + template testInvalidUrl(url: string) = |
| 99 | + expect ValueError: |
| 100 | + echo "This URL should be invalid: ", EngineApiUrlConfigValue.parseCmdArg(url) |
| 101 | + |
| 102 | + testInvalidUrl "http://127.0.0.1:9090/#roles=" |
| 103 | + testInvalidUrl "http://127.0.0.1:9090/#roles=sy" |
| 104 | + testInvalidUrl "http://127.0.0.1:9090/#roles=sync-deposits," |
| 105 | + testInvalidUrl "http://127.0.0.1:9090/#roles=sync-deposits;validate-blocks" |
| 106 | + testInvalidUrl "http://127.0.0.1:9090/#roles=validate-blocks,sync-deps" |
| 107 | + |
| 108 | + test "Old style config files": |
| 109 | + let cfg = loadExampleConfig """ |
| 110 | + data-dir = "/foo" |
| 111 | + el = ["http://localhost:8585", "eth-data.io#roles=sync-deposits", "wss://eth-nodes.io/21312432"] |
| 112 | + """ |
| 113 | + |
| 114 | + check: |
| 115 | + cfg.dataDir == "/foo" |
| 116 | + cfg.el.len == 3 |
| 117 | + cfg.el[0].url == "http://localhost:8585" |
| 118 | + cfg.el[1].url == "eth-data.io" |
| 119 | + cfg.el[1].roles == some({DepositSyncing}) |
| 120 | + cfg.el[2].url == "wss://eth-nodes.io/21312432" |
| 121 | + |
| 122 | + test "New style config files": |
| 123 | + let cfg = loadExampleConfig """ |
| 124 | + data-dir = "my-data-dir" |
| 125 | +
|
| 126 | + [[el]] |
| 127 | + url = "http://localhost:8585" |
| 128 | + jwt-secret-file = "jwt.hex" |
| 129 | +
|
| 130 | + [[el]] |
| 131 | + url = "eth-data.io" |
| 132 | + roles = ["sync-deposits", "produce-blocks"] |
| 133 | +
|
| 134 | + [[el]] |
| 135 | + url = "wss://eth-nodes.io/21312432" |
| 136 | + jwt-secret = "0xee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba" |
| 137 | + """ |
| 138 | + |
| 139 | + check: |
| 140 | + cfg.dataDir == "my-data-dir" |
| 141 | + |
| 142 | + cfg.el.len == 3 |
| 143 | + cfg.el[0].url == "http://localhost:8585" |
| 144 | + cfg.el[0].roles.isNone |
| 145 | + cfg.el[0].jwtSecret.isNone |
| 146 | + cfg.el[0].jwtSecretFile.get.string == "jwt.hex" |
| 147 | + |
| 148 | + cfg.el[1].url == "eth-data.io" |
| 149 | + cfg.el[1].roles == some({DepositSyncing, BlockProduction}) |
| 150 | + cfg.el[1].jwtSecret.isNone |
| 151 | + cfg.el[1].jwtSecretFile.isNone |
| 152 | + |
| 153 | + cfg.el[2].url == "wss://eth-nodes.io/21312432" |
| 154 | + cfg.el[2].roles.isNone |
| 155 | + cfg.el[2].jwtSecret.get == "0xee95565a2cc95553d4bf2185f58658939ba3074ce5695cbabfab4a1eaf7098ba" |
| 156 | + cfg.el[2].jwtSecretFile.isNone |
| 157 | + |
| 158 | + test "Empty config file": |
| 159 | + let cfg = loadExampleConfig("", cmdLine = @["--data-dir=foo"]) |
| 160 | + |
| 161 | + check: |
| 162 | + cfg.dataDir == "foo" |
| 163 | + cfg.el.len == 0 |
0 commit comments