From 2a0361cd189cfbf68f1cd815e6c3c42594a7d774 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 12 Oct 2022 17:58:36 -0500 Subject: [PATCH 1/5] make deployment phase configurable (#4231) Allow config of deployment phase via config instead of attempting to derive from genesis content (when running relevant testnets), so that we don't have to keep maintaining the list inside the binary. --- beacon_chain/conf.nim | 13 +++++++++++++ beacon_chain/networking/network_metadata.nim | 9 --------- beacon_chain/nimbus_beacon_node.nim | 2 +- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index 294ea8493..aab2ad700 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -113,6 +113,12 @@ type # migrateAll = "Export and remove the whole validator slashing protection DB." # migrate = "Export and remove specified validators from Nimbus." + DeploymentPhase* {.pure.} = enum + Devnet = "devnet" + Testnet = "testnet" + Mainnet = "mainnet" + None = "none" + BeaconNodeConf* = object configFile* {. desc: "Loads the configuration from a TOML file" @@ -515,6 +521,13 @@ type defaultValueDesc: "50" name: "sync-horizon" .}: uint64 + deploymentPhase* {. + hidden + desc: "Configures the deployment phase" + defaultValue: DeploymentPhase.Mainnet + defaultValueDesc: $DeploymentPhase.Mainnet + name: "deployment-phase" .}: DeploymentPhase + # TODO nim-confutils on 32-bit platforms overflows decoding integers # requiring 64-bit representations and doesn't build when specifying # UInt256 directly, so pass this through for decoding elsewhere. diff --git a/beacon_chain/networking/network_metadata.nim b/beacon_chain/networking/network_metadata.nim index 7bc919217..99f02faf7 100644 --- a/beacon_chain/networking/network_metadata.nim +++ b/beacon_chain/networking/network_metadata.nim @@ -79,15 +79,6 @@ type else: incompatibilityDesc*: string -type DeploymentPhase* {.pure.} = enum - None, - Devnet, - Testnet, - Mainnet - -func deploymentPhase*(genesisData: string): DeploymentPhase = - DeploymentPhase.Devnet - const eth2NetworksDir = currentSourcePath.parentDir.replace('\\', '/') & "/../../vendor/eth2-networks" mergeTestnetsDir = currentSourcePath.parentDir.replace('\\', '/') & "/../../vendor/merge-testnets" diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 3f92342a3..023dd2f6b 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -624,7 +624,7 @@ proc init*(T: type BeaconNode, dag = loadChainDag( config, cfg, db, eventBus, validatorMonitor, networkGenesisValidatorsRoot, - genesisStateContents.deploymentPhase <= DeploymentPhase.Testnet) + config.deploymentPhase <= DeploymentPhase.Testnet) genesisTime = getStateField(dag.headState, genesis_time) beaconClock = BeaconClock.init(genesisTime) getBeaconTime = beaconClock.getBeaconTimeFn() From 4b7bb4796fd7752203fc120a0e062736cbe03ed8 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 4 Oct 2022 13:38:09 +0200 Subject: [PATCH 2/5] update for latest LC REST proposal (#4213) Implements the latest proposal for providing LC data via REST, as of https://github.com/ethereum/beacon-APIs/pull/247 with a v0 suffix. Requests: - `/eth/v0/beacon/light_client/bootstrap/{block_root}` - `/eth/v0/beacon/light_client/updates?start_period={start_period}&count={count}` - `/eth/v0/beacon/light_client/finality_update` - `/eth/v0/beacon/light_client/optimistic_update` HTTP Server-Sent Events (SSE): - `light_client_finality_update_v0` - `light_client_optimistic_update_v0` --- beacon_chain/rpc/rest_light_client_api.nim | 101 +++++++++++++++--- .../eth2_apis/eth2_rest_serialization.nim | 69 ++++++++++++ beacon_chain/spec/helpers.nim | 10 ++ beacon_chain/sync/sync_protocol.nim | 8 +- 4 files changed, 171 insertions(+), 17 deletions(-) diff --git a/beacon_chain/rpc/rest_light_client_api.nim b/beacon_chain/rpc/rest_light_client_api.nim index f1470adce..b3334c6a6 100644 --- a/beacon_chain/rpc/rest_light_client_api.nim +++ b/beacon_chain/rpc/rest_light_client_api.nim @@ -22,6 +22,14 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = "/eth/v0/beacon/light_client/bootstrap/{block_root}") do ( block_root: Eth2Digest) -> RestApiResponse: doAssert node.dag.lcDataStore.serve + let contentType = + block: + let res = preferredContentType(jsonMediaType, + sszMediaType) + if res.isErr(): + return RestApiResponse.jsonError(Http406, ContentNotAcceptableError) + res.get() + let vroot = block: if block_root.isErr(): return RestApiResponse.jsonError(Http400, InvalidBlockRootValueError, @@ -29,17 +37,35 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = block_root.get() let bootstrap = node.dag.getLightClientBootstrap(vroot) - if bootstrap.isOk: - return RestApiResponse.jsonResponse(bootstrap) - else: + if bootstrap.isNone: return RestApiResponse.jsonError(Http404, LCBootstrapUnavailable) + let + contextEpoch = bootstrap.get.contextEpoch + contextFork = node.dag.cfg.stateForkAtEpoch(contextEpoch) + return + if contentType == sszMediaType: + let headers = [("eth-consensus-version", contextFork.toString())] + RestApiResponse.sszResponse(bootstrap.get, headers) + elif contentType == jsonMediaType: + RestApiResponse.jsonResponseWVersion(bootstrap.get, contextFork) + else: + RestApiResponse.jsonError(Http500, InvalidAcceptError) + # https://github.com/ethereum/beacon-APIs/pull/181 router.api(MethodGet, "/eth/v0/beacon/light_client/updates") do ( start_period: Option[SyncCommitteePeriod], count: Option[uint64] ) -> RestApiResponse: doAssert node.dag.lcDataStore.serve + let contentType = + block: + let res = preferredContentType(jsonMediaType, + sszMediaType) + if res.isErr(): + return RestApiResponse.jsonError(Http406, ContentNotAcceptableError) + res.get() + let vstart = block: if start_period.isNone(): return RestApiResponse.jsonError(Http400, MissingStartPeriodValueError) @@ -58,7 +84,7 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = rcount.get() let headPeriod = node.dag.head.slot.sync_committee_period - # Limit number of updates in response + # Limit number of updates in response maxSupportedCount = if vstart > headPeriod: 0'u64 @@ -67,31 +93,80 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = numPeriods = min(vcount, maxSupportedCount) onePastPeriod = vstart + numPeriods - var updates = newSeqOfCap[LightClientUpdate](numPeriods) + var updates = newSeqOfCap[RestVersioned[LightClientUpdate]](numPeriods) for period in vstart.. RestApiResponse: doAssert node.dag.lcDataStore.serve + let contentType = + block: + let res = preferredContentType(jsonMediaType, + sszMediaType) + if res.isErr(): + return RestApiResponse.jsonError(Http406, ContentNotAcceptableError) + res.get() + let finality_update = node.dag.getLightClientFinalityUpdate() - if finality_update.isSome: - return RestApiResponse.jsonResponse(finality_update) - else: + if finality_update.isNone: return RestApiResponse.jsonError(Http404, LCFinUpdateUnavailable) + let + contextEpoch = finality_update.get.contextEpoch + contextFork = node.dag.cfg.stateForkAtEpoch(contextEpoch) + return + if contentType == sszMediaType: + let headers = [("eth-consensus-version", contextFork.toString())] + RestApiResponse.sszResponse(finality_update.get, headers) + elif contentType == jsonMediaType: + RestApiResponse.jsonResponseWVersion(finality_update.get, contextFork) + else: + RestApiResponse.jsonError(Http500, InvalidAcceptError) + # https://github.com/ethereum/beacon-APIs/pull/181 router.api(MethodGet, "/eth/v0/beacon/light_client/optimistic_update") do ( ) -> RestApiResponse: doAssert node.dag.lcDataStore.serve + let contentType = + block: + let res = preferredContentType(jsonMediaType, + sszMediaType) + if res.isErr(): + return RestApiResponse.jsonError(Http406, ContentNotAcceptableError) + res.get() + let optimistic_update = node.dag.getLightClientOptimisticUpdate() - if optimistic_update.isSome: - return RestApiResponse.jsonResponse(optimistic_update) - else: + if optimistic_update.isNone: return RestApiResponse.jsonError(Http404, LCOptUpdateUnavailable) + + let + contextEpoch = optimistic_update.get.contextEpoch + contextFork = node.dag.cfg.stateForkAtEpoch(contextEpoch) + return + if contentType == sszMediaType: + let headers = [("eth-consensus-version", contextFork.toString())] + RestApiResponse.sszResponse(optimistic_update.get, headers) + elif contentType == jsonMediaType: + RestApiResponse.jsonResponseWVersion(optimistic_update.get, contextFork) + else: + RestApiResponse.jsonError(Http500, InvalidAcceptError) diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index 51a02b46f..ea2e88fb5 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -279,6 +279,53 @@ proc jsonResponseWOpt*(t: typedesc[RestApiResponse], data: auto, default RestApiResponse.response(res, Http200, "application/json") +proc jsonResponseWVersion*(t: typedesc[RestApiResponse], data: auto, + version: BeaconStateFork): RestApiResponse = + let + headers = [("eth-consensus-version", version.toString())] + res = + block: + var default: seq[byte] + try: + var stream = memoryOutput() + var writer = JsonWriter[RestJson].init(stream) + writer.beginRecord() + writer.writeField("version", version.toString()) + writer.writeField("data", data) + writer.endRecord() + stream.getOutput(seq[byte]) + except SerializationError: + default + except IOError: + default + RestApiResponse.response(res, Http200, "application/json", headers = headers) + +type RestVersioned*[T] = object + data*: T + jsonVersion*: BeaconStateFork + sszContext*: ForkDigest + +proc jsonResponseVersionedList*[T](t: typedesc[RestApiResponse], + entries: openArray[RestVersioned[T]] + ): RestApiResponse = + let res = + block: + var default: seq[byte] + try: + var stream = memoryOutput() + var writer = JsonWriter[RestJson].init(stream) + for e in writer.stepwiseArrayCreation(entries): + writer.beginRecord() + writer.writeField("version", e.jsonVersion.toString()) + writer.writeField("data", e.data) + writer.endRecord() + stream.getOutput(seq[byte]) + except SerializationError: + default + except IOError: + default + RestApiResponse.response(res, Http200, "application/json") + proc jsonResponsePlain*(t: typedesc[RestApiResponse], data: auto): RestApiResponse = let res = @@ -415,6 +462,28 @@ proc jsonErrorList*(t: typedesc[RestApiResponse], default RestApiResponse.error(status, data, "application/json") +proc sszResponseVersionedList*[T](t: typedesc[RestApiResponse], + entries: openArray[RestVersioned[T]] + ): RestApiResponse = + let res = + block: + var default: seq[byte] + try: + var stream = memoryOutput() + for e in entries: + var cursor = stream.delayFixedSizeWrite(sizeof(uint64)) + let initPos = stream.pos + stream.write e.sszContext.data + var writer = SszWriter.init(stream) + writer.writeValue e.data + cursor.finalWrite (stream.pos - initPos).uint64.toBytesLE() + stream.getOutput(seq[byte]) + except SerializationError: + default + except IOError: + default + RestApiResponse.response(res, Http200, "application/octet-stream") + proc sszResponsePlain*(t: typedesc[RestApiResponse], res: seq[byte], headers: openArray[RestKeyValueTuple] = [] ): RestApiResponse = diff --git a/beacon_chain/spec/helpers.nim b/beacon_chain/spec/helpers.nim index 4863a005e..7210a8b35 100644 --- a/beacon_chain/spec/helpers.nim +++ b/beacon_chain/spec/helpers.nim @@ -308,6 +308,16 @@ template is_better_update*[A, B: SomeLightClientUpdate]( new_update: A, old_update: B): bool = is_better_data(toMeta(new_update), toMeta(old_update)) +# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/light-client/p2p-interface.md#getlightclientbootstrap +func contextEpoch*(bootstrap: altair.LightClientBootstrap): Epoch = + bootstrap.header.slot.epoch + +# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/light-client/p2p-interface.md#lightclientupdatesbyrange +# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/light-client/p2p-interface.md#getlightclientfinalityupdate +# https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/altair/light-client/p2p-interface.md#getlightclientoptimisticupdate +func contextEpoch*(update: SomeLightClientUpdate): Epoch = + update.attested_header.slot.epoch + # https://github.com/ethereum/consensus-specs/blob/v1.2.0/specs/bellatrix/beacon-chain.md#is_merge_transition_complete func is_merge_transition_complete*(state: bellatrix.BeaconState): bool = const defaultExecutionPayloadHeader = default(ExecutionPayloadHeader) diff --git a/beacon_chain/sync/sync_protocol.nim b/beacon_chain/sync/sync_protocol.nim index 7fa055ea7..e215199fa 100644 --- a/beacon_chain/sync/sync_protocol.nim +++ b/beacon_chain/sync/sync_protocol.nim @@ -561,7 +561,7 @@ p2pProtocol BeaconSync(version = 1, let bootstrap = dag.getLightClientBootstrap(blockRoot) if bootstrap.isOk: let - contextEpoch = bootstrap.get.header.slot.epoch + contextEpoch = bootstrap.get.contextEpoch contextBytes = peer.networkState.forkDigestAtEpoch(contextEpoch).data await response.send(bootstrap.get, contextBytes) else: @@ -605,7 +605,7 @@ p2pProtocol BeaconSync(version = 1, let update = dag.getLightClientUpdateForPeriod(period) if update.isSome: let - contextEpoch = update.get.attested_header.slot.epoch + contextEpoch = update.get.contextEpoch contextBytes = peer.networkState.forkDigestAtEpoch(contextEpoch).data await response.write(update.get, contextBytes) inc found @@ -629,7 +629,7 @@ p2pProtocol BeaconSync(version = 1, let finality_update = dag.getLightClientFinalityUpdate() if finality_update.isSome: let - contextEpoch = finality_update.get.attested_header.slot.epoch + contextEpoch = finality_update.get.contextEpoch contextBytes = peer.networkState.forkDigestAtEpoch(contextEpoch).data await response.send(finality_update.get, contextBytes) else: @@ -655,7 +655,7 @@ p2pProtocol BeaconSync(version = 1, let optimistic_update = dag.getLightClientOptimisticUpdate() if optimistic_update.isSome: let - contextEpoch = optimistic_update.get.attested_header.slot.epoch + contextEpoch = optimistic_update.get.contextEpoch contextBytes = peer.networkState.forkDigestAtEpoch(contextEpoch).data await response.send(optimistic_update.get, contextBytes) else: From 95aec9de12309444894e519df092a9a179bce5c2 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 12 Oct 2022 19:16:49 -0500 Subject: [PATCH 3/5] update to v1 of LC REST API (#4232) The LC REST API has been merged into the ethereum/beacon-APIs specs: - https://github.com/ethereum/beacon-APIs/pull/247 Update URLs to v1 and update REST tests. Note that REST tests do not start with Altair, so the tested BN will return empty / error responses. --- beacon_chain/rpc/rest_event_api.nim | 5 +- beacon_chain/rpc/rest_light_client_api.nim | 16 ++-- .../eth2_apis/eth2_rest_serialization.nim | 4 +- ncli/resttest-rules.json | 76 +++++++++++++++++++ ncli/resttest.nim | 2 +- 5 files changed, 89 insertions(+), 14 deletions(-) diff --git a/beacon_chain/rpc/rest_event_api.nim b/beacon_chain/rpc/rest_event_api.nim index e8336be39..c7d4036e0 100644 --- a/beacon_chain/rpc/rest_event_api.nim +++ b/beacon_chain/rpc/rest_event_api.nim @@ -86,7 +86,6 @@ proc eventHandler*[T](response: HttpResponseRef, proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) = # https://ethereum.github.io/beacon-APIs/#/Events/eventstream - # https://github.com/ethereum/beacon-APIs/pull/181 router.api(MethodGet, "/eth/v1/events") do ( topics: seq[EventTopic]) -> RestApiResponse: let eventTopics = @@ -151,12 +150,12 @@ proc installEventApiHandlers*(router: var RestRouter, node: BeaconNode) = if EventTopic.LightClientFinalityUpdate in eventTopics: doAssert node.dag.lcDataStore.serve let handler = response.eventHandler(node.eventBus.finUpdateQueue, - "light_client_finality_update_v0") + "light_client_finality_update") res.add(handler) if EventTopic.LightClientOptimisticUpdate in eventTopics: doAssert node.dag.lcDataStore.serve let handler = response.eventHandler(node.eventBus.optUpdateQueue, - "light_client_optimistic_update_v0") + "light_client_optimistic_update") res.add(handler) res diff --git a/beacon_chain/rpc/rest_light_client_api.nim b/beacon_chain/rpc/rest_light_client_api.nim index b3334c6a6..4fb47c850 100644 --- a/beacon_chain/rpc/rest_light_client_api.nim +++ b/beacon_chain/rpc/rest_light_client_api.nim @@ -17,9 +17,9 @@ import ../beacon_node, logScope: topics = "rest_light_client" proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = - # https://github.com/ethereum/beacon-APIs/pull/181 + # https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientBootstrap router.api(MethodGet, - "/eth/v0/beacon/light_client/bootstrap/{block_root}") do ( + "/eth/v1/beacon/light_client/bootstrap/{block_root}") do ( block_root: Eth2Digest) -> RestApiResponse: doAssert node.dag.lcDataStore.serve let contentType = @@ -52,9 +52,9 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = else: RestApiResponse.jsonError(Http500, InvalidAcceptError) - # https://github.com/ethereum/beacon-APIs/pull/181 + # https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientUpdatesByRange router.api(MethodGet, - "/eth/v0/beacon/light_client/updates") do ( + "/eth/v1/beacon/light_client/updates") do ( start_period: Option[SyncCommitteePeriod], count: Option[uint64] ) -> RestApiResponse: doAssert node.dag.lcDataStore.serve @@ -113,9 +113,9 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = else: RestApiResponse.jsonError(Http500, InvalidAcceptError) - # https://github.com/ethereum/beacon-APIs/pull/181 + # https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientFinalityUpdate router.api(MethodGet, - "/eth/v0/beacon/light_client/finality_update") do ( + "/eth/v1/beacon/light_client/finality_update") do ( ) -> RestApiResponse: doAssert node.dag.lcDataStore.serve let contentType = @@ -142,9 +142,9 @@ proc installLightClientApiHandlers*(router: var RestRouter, node: BeaconNode) = else: RestApiResponse.jsonError(Http500, InvalidAcceptError) - # https://github.com/ethereum/beacon-APIs/pull/181 + # https://ethereum.github.io/beacon-APIs/?urls.primaryName=dev#/Beacon/getLightClientOptimisticUpdate router.api(MethodGet, - "/eth/v0/beacon/light_client/optimistic_update") do ( + "/eth/v1/beacon/light_client/optimistic_update") do ( ) -> RestApiResponse: doAssert node.dag.lcDataStore.serve let contentType = diff --git a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim index ea2e88fb5..c4a22bdbc 100644 --- a/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim +++ b/beacon_chain/spec/eth2_apis/eth2_rest_serialization.nim @@ -2648,9 +2648,9 @@ proc decodeString*(t: typedesc[EventTopic], ok(EventTopic.ChainReorg) of "contribution_and_proof": ok(EventTopic.ContributionAndProof) - of "light_client_finality_update_v0": + of "light_client_finality_update": ok(EventTopic.LightClientFinalityUpdate) - of "light_client_optimistic_update_v0": + of "light_client_optimistic_update": ok(EventTopic.LightClientOptimisticUpdate) else: err("Incorrect event's topic value") diff --git a/ncli/resttest-rules.json b/ncli/resttest-rules.json index 54a8124cf..32e8d9491 100644 --- a/ncli/resttest-rules.json +++ b/ncli/resttest-rules.json @@ -2457,6 +2457,82 @@ }, "response": {"status": {"operator": "equals", "value": "400"}} }, + { + "topics": ["beacon", "beacon_light_client_bootstrap_blockroot"], + "request": { + "url": "/eth/v1/beacon/light_client/bootstrap/0x0000000000000000000000000000000000000000000000000000000000000000", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "404"}} + }, + { + "topics": ["beacon", "beacon_light_client_bootstrap_blockroot"], + "request": { + "url": "/eth/v1/beacon/light_client/bootstrap/head", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "400"}} + }, + { + "topics": ["beacon", "beacon_light_client_updates"], + "request": { + "url": "/eth/v1/beacon/light_client/updates?start_period=0&count=50", + "headers": {"Accept": "application/json"} + }, + "response": { + "status": {"operator": "equals", "value": "200"}, + "headers": [{"key": "Content-Type", "value": "application/json", "operator": "equals"}], + "body": [{"operator": "jstructcmps", "start": [],"value": [[]]}] + } + }, + { + "topics": ["beacon", "beacon_light_client_updates"], + "request": { + "url": "/eth/v1/beacon/light_client/updates?start_period=X&count=50", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "400"}} + }, + { + "topics": ["beacon", "beacon_light_client_updates"], + "request": { + "url": "/eth/v1/beacon/light_client/updates?start_period=0&count=X", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "400"}} + }, + { + "topics": ["beacon", "beacon_light_client_updates"], + "request": { + "url": "/eth/v1/beacon/light_client/updates?count=50", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "400"}} + }, + { + "topics": ["beacon", "beacon_light_client_updates"], + "request": { + "url": "/eth/v1/beacon/light_client/updates?start_period=0", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "400"}} + }, + { + "topics": ["beacon", "beacon_light_client_finality_update"], + "request": { + "url": "/eth/v1/beacon/light_client/finality_update", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "404"}} + }, + { + "topics": ["beacon", "beacon_light_client_optimistic_update"], + "request": { + "url": "/eth/v1/beacon/light_client/optimistic_update", + "headers": {"Accept": "application/json"} + }, + "response": {"status": {"operator": "equals", "value": "404"}} + }, { "topics": ["beacon", "pool_attestations"], "request": { diff --git a/ncli/resttest.nim b/ncli/resttest.nim index 8ad0bdbc4..e552a398a 100644 --- a/ncli/resttest.nim +++ b/ncli/resttest.nim @@ -19,7 +19,7 @@ const $RestTesterPatch RestTesterIdent* = "RestTester/$1 ($2/$3)" % [RestTesterVersion, hostCPU, hostOS] - RestTesterCopyright* = "Copyright(C) 2021" & + RestTesterCopyright* = "Copyright(C) 2021-2022" & " Status Research & Development GmbH" RestTesterHeader* = RestTesterName & ", Version " & RestTesterVersion & " [" & hostOS & ": " & hostCPU & "]\r\n" & From 5ff99b9bf077b97f363a2e14664a74009dae4210 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 13 Oct 2022 13:46:11 +0300 Subject: [PATCH 4/5] Bump Chronos to fix a resource leak when using an external builder --- vendor/nim-chronos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/nim-chronos b/vendor/nim-chronos index be2352027..266e2c0ed 160000 --- a/vendor/nim-chronos +++ b/vendor/nim-chronos @@ -1 +1 @@ -Subproject commit be2352027ecd54bb63509c6347fc7bccb01550c6 +Subproject commit 266e2c0ed26b455872bccb3ddbd316815a283659 From 47c4a2f4467f8597175efbb02860e23fa547bce1 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 13 Oct 2022 14:44:21 +0300 Subject: [PATCH 5/5] Final release notes for v22.10.1 --- CHANGELOG.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3cf8e3ac..9cfa3b741 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,22 @@ -2022-10-10 v22.10.1 +2022-10-13 v22.10.1 =================== -Nimbus `v22.10.1` is a `low-urgency` hotfix release addressing a frequently encountered crash when Nimbus has poor network connectivity to an external block builder: +Nimbus `v22.10.1` is a `low-urgency` point release introducing support for the official light client REST API and improving the stability of Nimbus when paired with an external block builder. +### Improvements + +* Support for the official light client REST API: + https://github.com/ethereum/beacon-APIs/pull/247 + https://github.com/status-im/nimbus-eth2/pull/4213 + https://github.com/status-im/nimbus-eth2/pull/4232 + +### Fixes: + +* Nimbus was slowly leaking file descriptors when paired with an external builder: +https://github.com/status-im/nim-chronos/pull/323 + + +* Nimbus could potentially crash under a poor network connectivity to an external builder: https://github.com/status-im/nimbus-eth2/pull/4222