From 6517e8d0f3a8f8931496c2be7d0e85a6c1a17849 Mon Sep 17 00:00:00 2001 From: acolytec3 Date: Sat, 5 Aug 2023 06:00:29 -0400 Subject: [PATCH] add types and tests for beacon network content keys (#427) --- package-lock.json | 16 ++++--- .../src/subprotocols/beacon/beacon.ts | 6 +-- .../src/subprotocols/beacon/types.ts | 11 ++++- .../test/subprotocols/beacon/beacon.spec.ts | 42 +++++++++++++++++-- 4 files changed, 59 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16faa283a..f106d6f14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9265,9 +9265,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==", + "version": "1.0.30001518", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz", + "integrity": "sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==", "funding": [ { "type": "opencollective", @@ -9276,6 +9276,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -26087,9 +26091,9 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caniuse-lite": { - "version": "1.0.30001450", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001450.tgz", - "integrity": "sha512-qMBmvmQmFXaSxexkjjfMvD5rnDL0+m+dUMZKoDYsGG8iZN29RuYh9eRoMvKsT6uMAWlyUUGDEQGJJYjzCIO9ew==" + "version": "1.0.30001518", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001518.tgz", + "integrity": "sha512-rup09/e3I0BKjncL+FesTayKtPrdwKhUufQFd3riFw1hHg8JmIFoInYfB102cFcY/pPgGmdyl/iy+jgiDi2vdA==" }, "catering": { "version": "2.1.1", diff --git a/packages/portalnetwork/src/subprotocols/beacon/beacon.ts b/packages/portalnetwork/src/subprotocols/beacon/beacon.ts index a5290474f..6e02453a5 100644 --- a/packages/portalnetwork/src/subprotocols/beacon/beacon.ts +++ b/packages/portalnetwork/src/subprotocols/beacon/beacon.ts @@ -7,11 +7,7 @@ import { Union } from '@chainsafe/ssz/lib/interface.js' import { fromHexString, toHexString } from '@chainsafe/ssz' import { shortId } from '../../util/util.js' import { createBeaconConfig, defaultChainConfig, BeaconConfig } from '@lodestar/config' -import { - Forks, - MainnetGenesisValidatorsRoot, - BeaconLightClientNetworkContentType, -} from './types.js' +import { MainnetGenesisValidatorsRoot, BeaconLightClientNetworkContentType } from './types.js' import { ContentMessageType, FindContentMessage, diff --git a/packages/portalnetwork/src/subprotocols/beacon/types.ts b/packages/portalnetwork/src/subprotocols/beacon/types.ts index 8b79af84b..c0faa9f44 100644 --- a/packages/portalnetwork/src/subprotocols/beacon/types.ts +++ b/packages/portalnetwork/src/subprotocols/beacon/types.ts @@ -1,5 +1,6 @@ -import { ByteListType, ListCompositeType } from '@chainsafe/ssz' +import { ByteListType, ContainerType, ListCompositeType, UintBigintType } from '@chainsafe/ssz' import { ForkName } from '@lodestar/params' +import { Bytes32Type } from '../history/index.js' export const MainnetGenesisValidatorsRoot = '0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95' @@ -21,3 +22,11 @@ export enum Forks { // TODO - figure out what a theoretical maximum byte size for a LightClientUpdate is (the `ByteListType`) in the below ssz list export const LightClientUpdatesByRange = new ListCompositeType(new ByteListType(2 ** 18), 128) + +export const LightClientBootstrapKey = new ContainerType({ blockHash: Bytes32Type }) +export const LightClientUpdatesByRangeKey = new ContainerType({ + startPeriod: new UintBigintType(8), + count: new UintBigintType(8), +}) +export const LightClientFinalityUpdateKey = new ContainerType({ zero: new UintBigintType(8) }) +export const LightClientOptimisticUpdateKey = new ContainerType({ zero: new UintBigintType(8) }) diff --git a/packages/portalnetwork/test/subprotocols/beacon/beacon.spec.ts b/packages/portalnetwork/test/subprotocols/beacon/beacon.spec.ts index 6a4305c8c..699b02fe2 100644 --- a/packages/portalnetwork/test/subprotocols/beacon/beacon.spec.ts +++ b/packages/portalnetwork/test/subprotocols/beacon/beacon.spec.ts @@ -1,33 +1,48 @@ import tape from 'tape' import { createRequire } from 'module' const require = createRequire(import.meta.url) -import { fromHexString } from '@chainsafe/ssz' +import { fromHexString, toHexString } from '@chainsafe/ssz' import { ssz } from '@lodestar/types' import { createBeaconConfig, defaultChainConfig } from '@lodestar/config' import { + LightClientBootstrapKey, + LightClientFinalityUpdateKey, + LightClientOptimisticUpdateKey, LightClientUpdatesByRange, + LightClientUpdatesByRangeKey, MainnetGenesisValidatorsRoot, } from '../../../src/subprotocols/beacon/types.js' tape('portal network spec test vectors', (t) => { const specTestVectors = require('./specTestVectors.json') const genesisRoot = fromHexString(MainnetGenesisValidatorsRoot) // Genesis Validators Root + const config = createBeaconConfig(defaultChainConfig, genesisRoot) const serializedOptimistincUpdate = fromHexString( specTestVectors.optimisticUpdate['6718463'].content_value ) + const serializedOptimistincUpdateKey = fromHexString( + specTestVectors.optimisticUpdate['6718463'].content_key + ) const forkDigest = ssz.ForkDigest.deserialize(serializedOptimistincUpdate.slice(0, 4)) - const config = createBeaconConfig(defaultChainConfig, genesisRoot) t.equal(config.forkDigest2ForkName(forkDigest), 'capella', 'derived correct fork') const deserializedOptimisticUpdate = ssz.capella.LightClientOptimisticUpdate.deserialize( serializedOptimistincUpdate.slice(4) ) + const optimisticUpdateKey = LightClientOptimisticUpdateKey.deserialize( + serializedOptimistincUpdateKey.slice(1) + ) t.equal( deserializedOptimisticUpdate.attestedHeader.beacon.slot, 6718463, 'deserialized optimistic update' ) + t.equal(optimisticUpdateKey.zero, 0n, 'correctly deserialized optimstic update key') + const finalityUpdate = fromHexString(specTestVectors.finalityUpdate['6718463'].content_value) + const finalityUpdateKey = fromHexString( + specTestVectors.finalityUpdate['6718463'].content_key + ).slice(1) const deserializedFinalityUpdate = ssz.capella.LightClientFinalityUpdate.deserialize( finalityUpdate.slice(4) ) @@ -36,23 +51,42 @@ tape('portal network spec test vectors', (t) => { 6718463, 'deserialized finality update' ) + t.equal( + LightClientFinalityUpdateKey.deserialize(finalityUpdateKey).zero, + 0n, + 'deserialized finality update key' + ) const bootstrap = specTestVectors.bootstrap['6718368'] const deserializedBootstrap = ssz.capella.LightClientBootstrap.deserialize( fromHexString(bootstrap.content_value).slice(4) ) - t.equal(deserializedBootstrap.header.beacon.slot, 6718368, 'deserialized bootstrap') + const bootstrapKey = fromHexString(bootstrap.content_key).slice(1) + t.equal(deserializedBootstrap.header.beacon.slot, 6718368, 'deserialized bootstrap') + t.equal( + toHexString(LightClientBootstrapKey.deserialize(bootstrapKey).blockHash), + '0xbd9f42d9a42d972bdaf4dee84e5b419dd432b52867258acb7bcc7f567b6e3af1', + 'deserialized light client bootstrap key' + ) const updateByRange = fromHexString(specTestVectors.updateByRange['6684738'].content_value) + const updateByRangeKey = fromHexString( + specTestVectors.updateByRange['6684738'].content_key + ).slice(1) const deserializedRange = LightClientUpdatesByRange.deserialize(updateByRange) let numUpdatesDeserialized = 0 for (const update of deserializedRange) { const forkdigest = update.slice(0, 4) const forkname = config.forkDigest2ForkName(forkdigest) - //@ts-ignore - ssz won't let me + //@ts-ignore - typescript won't let me set `forkname` to a value from of the Forks type ssz[forkname].LightClientUpdate.deserialize(update.slice(4)).attestedHeader.beacon.slot numUpdatesDeserialized++ } t.equal(numUpdatesDeserialized, 4, 'deserialized LightClientUpdatesByRange') + t.equal( + LightClientUpdatesByRangeKey.deserialize(updateByRangeKey).count, + 4n, + 'deserialized update by range key' + ) t.end() })