Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
534 changes: 0 additions & 534 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
"@types/yargs": "^17.0.7",
"@vitest/ui": "^3.0.2",
"alchemy-sdk": "^3.0.0",
"eslint": "^8.6.0",
"kzg-wasm": "^0.5.0",
"nodemon": "^2.0.19",
"vitest": "^3.0.2"
Expand Down Expand Up @@ -65,6 +64,9 @@
"author": "acolytec3",
"license": "MIT",
"nodemonConfig": {
"watch": ["src", "../portalnetwork/dist"]
"watch": [
"src",
"../portalnetwork/dist"
]
}
}
}
40 changes: 20 additions & 20 deletions packages/portal-client/src/hooks/useJsonRpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export const useJsonRpc = () => {
break
case 'portal_historyPing': {
const res = await historyNetwork?.sendPing(params[0])
if (!res) {
if (res === undefined) {
throw new Error('Pong not received')
}
const { customPayload, ...rest } = res
Expand All @@ -65,41 +65,41 @@ export const useJsonRpc = () => {
break
}
case 'portal_historyFindContent': {
const res = await historyNetwork?.sendFindContent(params[0], params[1]);
if (!res) {
throw new Error('Content not received');
const res = await historyNetwork?.sendFindContent(params[0], params[1])

if (res === undefined) {
throw new Error('Content not received')
}
if ('enrs' in res) {
result = {
...res,
enrs: res.enrs.map(enr => ENR.decode(enr).encodeTxt()),
type: 'enrs' as const
};
enrs: res.enrs.map((enr: Uint8Array) => ENR.decode(enr).encodeTxt()),
type: 'enrs' as const,
}
} else {
result = {
...res,
type: 'content' as const
};
type: 'content' as const,
}
}
responseType = 'generic';
break;

responseType = 'generic'
break
}
case 'portal_historyFindNodes': {
const res = await historyNetwork?.sendFindNodes(params[0], params[1]);
if (!res) {
throw new Error('No nodes found');
const res = await historyNetwork?.sendFindNodes(params[0], params[1])

if (res === undefined) {
throw new Error('No nodes found')
}

result = {
...res,
enrs: res.enrs.map(enr => ENR.decode(enr).encodeTxt()),
enrs: res.enrs.map((enr: Uint8Array) => ENR.decode(enr).encodeTxt()),
type: 'enrs' as const,
}
responseType = 'generic'
break;
break
}
default:
throw new Error(`Unsupported method: ${method}`)
Expand Down
3 changes: 1 addition & 2 deletions packages/portalnetwork/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@
"@types/ws": "^7.4.7",
"@vitest/coverage-v8": "^3.0.2",
"@vitest/ui": "^3.0.2",
"eslint": "^8.6.0",
"js-yaml": "^4.1.0",
"tslib": "^2.3.1",
"typedoc": "^0.28.0",
Expand Down Expand Up @@ -104,4 +103,4 @@
"optional": true
}
}
}
}
24 changes: 16 additions & 8 deletions packages/portalnetwork/src/networks/history/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import type {
INodeAddress,
} from '../../index.js'
import {
BasicRadius,
BiMap,
ClientInfoAndCapabilities,
ContentMessageType,
FoundContent,
HistoricalSummariesBlockProof,
HistoricalSummariesBlockProofDeneb,
HistoryRadius,
MAX_UDP_PACKET_SIZE,
MessageCodes,
Expand All @@ -32,13 +32,14 @@ import {
saveReceipts,
shortId,
} from '../../index.js'
import { PingPongPayloadExtensions } from '../../wire/payloadExtensions.js'
import { BasicRadius, PingPongPayloadExtensions } from '../../wire/payloadExtensions.js'
import { BaseNetwork } from '../network.js'
import { NetworkId } from '../types.js'
import {
AccumulatorProofType,
BlockHeaderWithProof,
BlockNumberKey,
CANCUN_BLOCK,
EphemeralHeaderPayload,
HistoricalRootsBlockProof,
HistoryNetworkContentType,
Expand All @@ -49,8 +50,8 @@ import {
import {
getContentKey,
getEphemeralHeaderDbKey,
verifyPostCapellaHeaderProof,
verifyPreCapellaHeaderProof,
verifyHistoricalRootsHeaderProof,
verifyHistoricalSummariesHeaderProof,
verifyPreMergeHeaderProof,
} from './util.js'

Expand Down Expand Up @@ -224,7 +225,7 @@ export class HistoryNetwork extends BaseNetwork {
}
let validated = false
try {
validated = verifyPreCapellaHeaderProof(deserializedProof, header.hash())
validated = verifyHistoricalRootsHeaderProof(deserializedProof, header.hash())
} catch (err: any) {
const msg = `Unable to validate proof for post-merge header: ${err.message}`
this.logger(msg)
Expand All @@ -236,17 +237,24 @@ export class HistoryNetwork extends BaseNetwork {
} else {
// TODO: Check proof slot to ensure header is from previous sync period and handle ephemeral headers separately

let deserializedProof: ReturnType<typeof HistoricalSummariesBlockProof.deserialize>
let deserializedProof: ReturnType<
| typeof HistoricalSummariesBlockProof.deserialize
| typeof HistoricalSummariesBlockProofDeneb.deserialize
>
try {
deserializedProof = HistoricalSummariesBlockProof.deserialize(proof)
if (header.number < CANCUN_BLOCK) {
deserializedProof = HistoricalSummariesBlockProof.deserialize(proof)
} else {
deserializedProof = HistoricalSummariesBlockProofDeneb.deserialize(proof)
}
} catch (err: any) {
this.logger(`invalid proof for block ${bytesToHex(header.hash())}`)
throw new Error(`invalid proof for block ${bytesToHex(header.hash())}`)
}
const beacon = this.portal.network()['0x500c']
if (beacon !== undefined && beacon.lightClient?.status === RunStatusCode.started) {
try {
verifyPostCapellaHeaderProof(
verifyHistoricalSummariesHeaderProof(
deserializedProof,
header.hash(),
beacon.historicalSummaries,
Expand Down
18 changes: 14 additions & 4 deletions packages/portalnetwork/src/networks/history/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ export const MAX_RECEIPT_LENGTH = 134217728 // 2 ** 27
export const MAX_HEADER_LENGTH = 8192 // 2 ** 13
export const MAX_ENCODED_UNCLES_LENGTH = 131072 // MAX_HEADER_LENGTH * 2 ** 4
export const MAX_HEADER_PROOF_LENGTH = 1024
export const MERGE_BLOCK = 15537393n
export const MERGE_BLOCK = 15537394n
export const SHANGHAI_BLOCK = 17034871n
export const CANCUN_BLOCK = 19426587n

export const CAPELLA_ERA = 758 // The era/period in which the Capella fork happened on CL

Expand Down Expand Up @@ -200,12 +201,12 @@ export const HistoricalRootsBlockProof = new ContainerType({
})

/** Post-Capella block header proof types */
export const PostCapellaExecutionBlockProof = new ListCompositeType(Bytes32Type, 12)
export const PostCapellaExecutionBlockProof = new VectorCompositeType(Bytes32Type, 12)
export const BeaconBlockProofHistoricalSummaries = new VectorCompositeType(Bytes32Type, 13)
export const HistoricalSummariesBlockProof = new ContainerType({
historicalSummariesProof: BeaconBlockProofHistoricalSummaries,
beaconBlockProof: BeaconBlockProofHistoricalSummaries,
beaconBlockRoot: Bytes32Type,
beaconBlockProof: PostCapellaExecutionBlockProof,
executionBlockProof: PostCapellaExecutionBlockProof,
slot: SlotType,
})

Expand All @@ -214,6 +215,15 @@ export const BlockHeaderWithProof = new ContainerType({
proof: new ByteListType(MAX_HEADER_PROOF_LENGTH),
})

/** Post-Deneb proof types */
export const PostDenebExecutionBlockProof = new VectorCompositeType(Bytes32Type, 12)
export const HistoricalSummariesBlockProofDeneb = new ContainerType({
beaconBlockProof: BeaconBlockProofHistoricalSummaries,
beaconBlockRoot: Bytes32Type,
executionBlockProof: PostDenebExecutionBlockProof,
slot: SlotType,
})

/** Ephemeral header types */
export const EphemeralHeaderKey = new ContainerType({
blockHash: Bytes32Type,
Expand Down
23 changes: 12 additions & 11 deletions packages/portalnetwork/src/networks/history/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ import type {
} from '@ethereumjs/block'
import type { WithdrawalBytes } from '@ethereumjs/util'
import type { ForkConfig } from '@lodestar/config'
import type { EphemeralHeaderKeyValues } from '../history/types.js'
import type {
EphemeralHeaderKeyValues,
HistoricalSummariesBlockProof,
HistoricalSummariesBlockProofDeneb,
} from '../history/types.js'
import type { HistoryNetwork } from './history.js'
import type { BlockBodyContent, Witnesses } from './types.js'

Expand Down Expand Up @@ -322,7 +326,7 @@ export const verifyPreMergeHeaderProof = (
}
}

export const verifyPreCapellaHeaderProof = (
export const verifyHistoricalRootsHeaderProof = (
proof: ValueOfFields<{
beaconBlockProof: VectorCompositeType<ByteVectorType>
beaconBlockRoot: ByteVectorType
Expand Down Expand Up @@ -366,13 +370,10 @@ export const verifyPreCapellaHeaderProof = (
return true
}

export const verifyPostCapellaHeaderProof = (
proof: ValueOfFields<{
beaconBlockProof: ListCompositeType<ByteVectorType>
beaconBlockRoot: ByteVectorType
historicalSummariesProof: VectorCompositeType<ByteVectorType>
slot: UintBigintType
}>,
export const verifyHistoricalSummariesHeaderProof = (
proof: ValueOfFields<
typeof HistoricalSummariesBlockProof.fields | typeof HistoricalSummariesBlockProofDeneb.fields
>,
elBlockHash: Uint8Array,
historicalSummaries: { blockSummaryRoot: Uint8Array; stateSummaryRoot: Uint8Array }[],
chainConfig: ForkConfig,
Expand All @@ -383,7 +384,7 @@ export const verifyPostCapellaHeaderProof = (
Number(eraIndex),
])
const reconstructedBatch = ssz[forkName].BeaconState.fields.blockRoots.createFromProof({
witnesses: proof.historicalSummariesProof,
witnesses: proof.beaconBlockProof,
type: ProofType.single,
gindex: historicalSummariesPath.gindex,
leaf: proof.beaconBlockRoot, // This should be the leaf value this proof is verifying
Expand All @@ -405,7 +406,7 @@ export const verifyPostCapellaHeaderProof = (
'blockHash',
])
const reconstructedBlock = ssz[forkName].BeaconBlock.createFromProof({
witnesses: proof.beaconBlockProof,
witnesses: proof.executionBlockProof,
type: ProofType.single,
gindex: elBlockHashPath.gindex,
leaf: elBlockHash,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { readFileSync } from 'fs'
import { SignableENR } from '@chainsafe/enr'
import { concatBytes, hexToBytes } from '@ethereumjs/util'
import { bytesToHex, concatBytes, hexToBytes } from '@ethereumjs/util'
import { keys } from '@libp2p/crypto'
import { createBeaconConfig } from '@lodestar/config'
import { mainnetChainConfig } from '@lodestar/config/configs'
Expand All @@ -11,6 +11,8 @@ import { multiaddr } from '@multiformats/multiaddr'
import { assert, describe, it, vi } from 'vitest'
import {
BeaconNetworkContentType,
BlockHeaderWithProof,
HistoricalSummariesBlockProof,
HistoricalSummariesKey,
HistoricalSummariesWithProof,
HistoryNetworkContentType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"0x080000006f020000f90264a01624e3d62872568e41233178997c38dd75fa3baccc89351026beff7026179bfba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944838b106fce9647bdf1e7877bf73ce8b0bad5f97a02e065520386645261b7a6153924904a31c07bf6d37bca90fe35b21d864499c05a0eaa4d1ba5182915e8732ddd43e557a6ec713732e72964593275124fddf28a2aba0a9f528fe24151b34969ceb581a59f107d7bf38d8f364072dd50908f326226e71b90100f5bbd9423d137076afdb9b31d2f1db9239cff06e951d0dee6e2d8a302cfb14632d9c2725ed7a08043a5f6e97df7dc311867ba9749f08ed735fbb6a03802ce196f5eed77c97d3bd3dc81ce76fdd61b3ec55cc71d511567e685d0c2cec8c24ffee35856338dae6da75f20f9c8efe338fcffb7d515fde9d7fe7f5305bb4da1a3585a3be7e0e378581692dd9bbfa95b1c7565419eed5eff471ff29296fdd7d733efddfec7f62e4e3fa9eb3f159c609c7dd5f23bdd1b4baff8e283f65ea3d24680bd4cb36f61f00dd5b56ff49bdb77a3d98ee56a7b6438c48dfba4aa5034e6ad3e2e63ff7fccb69b5b492c5ed93cffd71a92e5dddf6ff5161ace6da24c0bb9d00ec5f8084014977bd8401c9c38083f94439846780b05798546974616e2028746974616e6275696c6465722e78797a29a07737f9743d49ab14e32b78a4989729b13bfd28f09c7729669d14c35a3e265d5288000000000000000084bc232c85a01fd1ee2a1b4008ac9f8749a3a5980645510788ccbf0922b77efd67224f8a2234830200008403cc0000a0e1c45ed325063d2380fb27927e7dd5024dada52070c9af2889ee51a105040bcfc2c38585972af1a49f5358e96748e08f62d9e06883d6d3bbc285f5bbdc3fdde7b87b8f3009f2311f723310e9600cd62f3a0ba54257645d03dbb94700997c2ff1bea5a1dbb8434febb2338912ebd94cfb183cc76b79a1449374aca82445a60e1641d6c37404381727480db4e3e124c9ce9345eb3761882ba31a2444e19f7f4be6446d9460a465986305984f731af89318ee7a965c33d5f6e293bd7c77050a7275d50d2f96d67ae9ec187ef09d1c19c8688ad0a9c00675a55bf61e5e412d5b0b309b9b4a4f9baaa4e6d6cd518eb62f41a133594cab49cf290ffa3570b65376b9dab2632457193d929218ee57d4d2dc8df537f9e2929746d934595d00ff258485173737414bac51a48ca8e03d442cca16a9d9d485ff0447a52427aada4c790ac75fdb8c75ab9503bd1eb67bfb5e2f8f403654b57a1e206aac23546088f1d7284b27d0fc56523cfafc7fb5d233f5faee241365fa4cb0c1d90792d8b558a3d0d5a63121993447a9a5d26cda2d9ad060c8d13f66d84623cc800e3dbb00097ce81a4debe6e5bf0ec7b02915aefabb6e7b1fb8468f228ab04e8e789a26ad9d727ac843043a317faa00ffbca7c1fc9464025ada6aa0db71fd9c050ed433bab104834f0f26cc01000000e0a40000000000f5a23c1219f35dd7d4dc73e816727b6062b26168d5de32a8c44a5e91eeca9f1e04a8748db8fd9595375edfe16660a66ca721079109bd18775eeb54ce07b1400f37d1c9f9c839443ae1aff0d273f1801ffe724770a23d81a63f22f7babe39715d5b5687af2260ef0ed892a68d169c580b03ccb5bc59b0596a4221568de8bf1c7091e37807ec7706f1534c3c24b6664110fa6cf57c3512bb58d4ae666eb8aaed347bdd0fcc693ae5642a10264eb24e1274823f434d66307d9c1cd3c15be194a462b19dea48b339562bd54eac0517d81d7c1d6897ccbf3df258cb75677a235768dfdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d7134fd95b5494fd350c63f8bff9d7be30f0bfb3a78daae9f2a0f1ef38f358fd6010000000000000000000000000000000000000000000000000000000000000000f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b6e1e55e9e4793d44338f52522fd838eb70bd3ac0bb6492923efa3cabf6f5cae3"
"0x080000006f020000f90264a01624e3d62872568e41233178997c38dd75fa3baccc89351026beff7026179bfba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347944838b106fce9647bdf1e7877bf73ce8b0bad5f97a02e065520386645261b7a6153924904a31c07bf6d37bca90fe35b21d864499c05a0eaa4d1ba5182915e8732ddd43e557a6ec713732e72964593275124fddf28a2aba0a9f528fe24151b34969ceb581a59f107d7bf38d8f364072dd50908f326226e71b90100f5bbd9423d137076afdb9b31d2f1db9239cff06e951d0dee6e2d8a302cfb14632d9c2725ed7a08043a5f6e97df7dc311867ba9749f08ed735fbb6a03802ce196f5eed77c97d3bd3dc81ce76fdd61b3ec55cc71d511567e685d0c2cec8c24ffee35856338dae6da75f20f9c8efe338fcffb7d515fde9d7fe7f5305bb4da1a3585a3be7e0e378581692dd9bbfa95b1c7565419eed5eff471ff29296fdd7d733efddfec7f62e4e3fa9eb3f159c609c7dd5f23bdd1b4baff8e283f65ea3d24680bd4cb36f61f00dd5b56ff49bdb77a3d98ee56a7b6438c48dfba4aa5034e6ad3e2e63ff7fccb69b5b492c5ed93cffd71a92e5dddf6ff5161ace6da24c0bb9d00ec5f8084014977bd8401c9c38083f94439846780b05798546974616e2028746974616e6275696c6465722e78797a29a07737f9743d49ab14e32b78a4989729b13bfd28f09c7729669d14c35a3e265d5288000000000000000084bc232c85a01fd1ee2a1b4008ac9f8749a3a5980645510788ccbf0922b77efd67224f8a2234830200008403cc0000a0e1c45ed325063d2380fb27927e7dd5024dada52070c9af2889ee51a105040bcfc2c38585972af1a49f5358e96748e08f62d9e06883d6d3bbc285f5bbdc3fdde7b87b8f3009f2311f723310e9600cd62f3a0ba54257645d03dbb94700997c2ff1bea5a1dbb8434febb2338912ebd94cfb183cc76b79a1449374aca82445a60e1641d6c37404381727480db4e3e124c9ce9345eb3761882ba31a2444e19f7f4be6446d9460a465986305984f731af89318ee7a965c33d5f6e293bd7c77050a7275d50d2f96d67ae9ec187ef09d1c19c8688ad0a9c00675a55bf61e5e412d5b0b309b9b4a4f9baaa4e6d6cd518eb62f41a133594cab49cf290ffa3570b65376b9dab2632457193d929218ee57d4d2dc8df537f9e2929746d934595d00ff258485173737414bac51a48ca8e03d442cca16a9d9d485ff0447a52427aada4c790ac75fdb8c75ab9503bd1eb67bfb5e2f8f403654b57a1e206aac23546088f1d7284b27d0fc56523cfafc7fb5d233f5faee241365fa4cb0c1d90792d8b558a3d0d5a63121993447a9a5d26cda2d9ad060c8d13f66d84623cc800e3dbb00097ce81a4debe6e5bf0ec7b02915aefabb6e7b1fb8468f228ab04e8e789a26ad9d727ac843043a317faa00ffbca7c1fc9464025ada6aa0db71fd9c050ed433bab104834f0f26f5a23c1219f35dd7d4dc73e816727b6062b26168d5de32a8c44a5e91eeca9f1e04a8748db8fd9595375edfe16660a66ca721079109bd18775eeb54ce07b1400f37d1c9f9c839443ae1aff0d273f1801ffe724770a23d81a63f22f7babe39715d5b5687af2260ef0ed892a68d169c580b03ccb5bc59b0596a4221568de8bf1c7091e37807ec7706f1534c3c24b6664110fa6cf57c3512bb58d4ae666eb8aaed347bdd0fcc693ae5642a10264eb24e1274823f434d66307d9c1cd3c15be194a462b19dea48b339562bd54eac0517d81d7c1d6897ccbf3df258cb75677a235768dfdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d7134fd95b5494fd350c63f8bff9d7be30f0bfb3a78daae9f2a0f1ef38f358fd6010000000000000000000000000000000000000000000000000000000000000000f5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b6e1e55e9e4793d44338f52522fd838eb70bd3ac0bb6492923efa3cabf6f5cae300e0a40000000000"
24 changes: 12 additions & 12 deletions packages/portalnetwork/test/networks/history/headerProof.spec.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { readFileSync } from 'fs'
import { createRequire } from 'module'
import { resolve } from 'path'
import { ProofType, createProof } from '@chainsafe/persistent-merkle-tree'
import { createBlockHeaderFromRLP } from '@ethereumjs/block'
import { bytesToHex, hexToBytes } from '@ethereumjs/util'
import { createChainForkConfig } from '@lodestar/config'
import { ssz } from '@lodestar/types'
import { readFileSync } from 'fs'
import yaml from 'js-yaml'
import { createRequire } from 'module'
import { resolve } from 'path'
import { assert, beforeAll, describe, it } from 'vitest'

import {
EpochAccumulator,
HeaderRecordType,
HistoricalEpochsType,
HistoricalRootsBlockProof,
HistoricalSummariesBlockProof,
HistoricalSummariesBlockProofDeneb,
blockNumberToGindex,
blockNumberToLeafIndex,
slotToHistoricalBatch,
slotToHistoricalBatchIndex,
verifyPostCapellaHeaderProof,
verifyPreCapellaHeaderProof,
verifyHistoricalRootsHeaderProof,
verifyHistoricalSummariesHeaderProof,
} from '../../../src/index.js'
import { historicalRoots } from '../../../src/networks/history/data/historicalRoots.js'

Expand Down Expand Up @@ -210,7 +210,7 @@ describe('Bellatrix - Capella header proof tests', () => {
executionBlockHeader: testVector.execution_block_header,
})
assert.ok(
verifyPreCapellaHeaderProof(fluffyProof, hexToBytes(testVector.execution_block_header)),
verifyHistoricalRootsHeaderProof(fluffyProof, hexToBytes(testVector.execution_block_header)),
)
})
})
Expand All @@ -221,8 +221,8 @@ describe('it should verify a post-Capella header proof', () => {
beforeAll(async () => {
proof = await import('./testData/slot9682944Proof.json')
})
it('should instantiate a proof from json', () => {
const headerProof = HistoricalSummariesBlockProof.fromJson(proof)
it('should instantiate a proof from json', async () => {
const headerProof = HistoricalSummariesBlockProofDeneb.fromJson(proof)
assert.equal(headerProof.slot, proof.slot)
})
it('should verify a post-capella header proof', async () => {
Expand All @@ -232,9 +232,9 @@ describe('it should verify a post-Capella header proof', () => {
historicalSummariesJson.default,
)

const headerProof = HistoricalSummariesBlockProof.fromJson(proof)
assert.ok(
verifyPostCapellaHeaderProof(
const headerProof = HistoricalSummariesBlockProofDeneb.fromJson(proof)
assert.isTrue(
verifyHistoricalSummariesHeaderProof(
headerProof,
hexToBytes('0xb2044cada59c3479ed264454466610e84fa852547138ccc12a874e921779a983'),
historicalSummaries,
Expand Down
Loading