1+ import { readFileSync } from 'fs'
2+ import { ssz } from '@lodestar/types'
3+ import { concatBytes , hexToBytes } from '@ethereumjs/util'
4+ import {
5+ BeaconLightClientNetworkContentType ,
6+ HistoricalSummariesKey ,
7+ HistoricalSummariesWithProof ,
8+ HistoryNetworkContentType ,
9+ LightClientBootstrapKey ,
10+ NetworkId ,
11+ PortalNetwork ,
12+ getBeaconContentKey ,
13+ getContentKey
14+ } from '../../src/index.js'
15+ import { createBeaconConfig } from '@lodestar/config'
16+ import { mainnetChainConfig } from '@lodestar/config/configs'
17+ import { genesisData } from '@lodestar/config/networks'
18+ import { computeEpochAtSlot , getChainForkConfigFromNetwork } from '@lodestar/light-client/utils'
19+ import { assert , describe , it } from 'vitest'
20+ import { multiaddr } from '@multiformats/multiaddr'
21+ import { SignableENR } from '@chainsafe/enr'
22+ import { keys } from '@libp2p/crypto'
23+
24+
25+ describe ( 'Block Bridge Data Test' , ( ) => {
26+ it ( 'should store and retrieve block header data' , async ( ) => {
27+ const privateKeys = [
28+ '0x0a2700250802122102273097673a2948af93317235d2f02ad9cf3b79a34eeb37720c5f19e09f11783c12250802122102273097673a2948af93317235d2f02ad9cf3b79a34eeb37720c5f19e09f11783c1a2408021220aae0fff4ac28fdcdf14ee8ecb591c7f1bc78651206d86afe16479a63d9cb73bd' ,
29+ '0x0a27002508021221039909a8a7e81dbdc867480f0eeb7468189d1e7a1dd7ee8a13ee486c8cbd743764122508021221039909a8a7e81dbdc867480f0eeb7468189d1e7a1dd7ee8a13ee486c8cbd7437641a2408021220c6eb3ae347433e8cfe7a0a195cc17fc8afcd478b9fb74be56d13bccc67813130' ,
30+ ]
31+ const pk1 = keys . privateKeyFromProtobuf ( hexToBytes ( privateKeys [ 0 ] ) . slice ( - 36 ) )
32+ const enr1 = SignableENR . createFromPrivateKey ( pk1 )
33+ const initMa : any = multiaddr ( `/ip4/127.0.0.1/udp/5034` )
34+
35+ const client = await PortalNetwork . create ( {
36+ supportedNetworks : [ { networkId : NetworkId . HistoryNetwork } , { networkId : NetworkId . BeaconChainNetwork } ] , config : { enr : enr1 , bindAddrs : { ip4 : initMa } , privateKey : pk1 }
37+ } )
38+ await client . start ( )
39+
40+ const bootstrapHex = JSON . parse ( readFileSync ( './test/integration/testdata/postCapellaData/bootstrap.json' , 'utf8' ) )
41+ const historicalSummariesJson = JSON . parse ( readFileSync ( './test/integration/testdata/postCapellaData/historical_summaries.json' , 'utf8' ) )
42+ const fullBlock = JSON . parse ( readFileSync ( './test/integration/testdata/postCapellaData/full_block.json' , 'utf8' ) )
43+ const headerWithProof = JSON . parse ( readFileSync ( './test/integration/testdata/postCapellaData/header_with_proof.json' , 'utf8' ) )
44+
45+ const bootstrap = ssz . deneb . LightClientBootstrap . deserialize ( hexToBytes ( bootstrapHex . bootstrap ) )
46+ const bootstrapRoot = '0x47a956b9cd45c73a60dac4c89dc869a5faa46a9d5d802486f31025c74d41ef39'
47+
48+ // Get fork info
49+ const forkConfig = getChainForkConfigFromNetwork ( 'mainnet' )
50+ const bootstrapSlot = bootstrap . header . beacon . slot
51+ const forkName = forkConfig . getForkName ( bootstrapSlot )
52+ const forkDigest = createBeaconConfig (
53+ mainnetChainConfig ,
54+ hexToBytes ( genesisData . mainnet . genesisValidatorsRoot )
55+ ) . forkName2ForkDigest ( forkName )
56+
57+ // Store bootstrap
58+
59+ const bootstrapKey = getBeaconContentKey (
60+ BeaconLightClientNetworkContentType . LightClientBootstrap ,
61+ LightClientBootstrapKey . serialize ( { blockHash : hexToBytes ( bootstrapRoot ) } )
62+ )
63+ const bootstrapValue = concatBytes (
64+ forkDigest ,
65+ ssz . deneb . LightClientBootstrap . serialize ( bootstrap )
66+ )
67+
68+ const beacon = client . network ( ) [ '0x500c' ]
69+ const history = client . network ( ) [ '0x500b' ]
70+
71+ await beacon ?. store ( bootstrapKey , bootstrapValue )
72+
73+ // Start light client
74+ await beacon ?. initializeLightClient ( bootstrapRoot )
75+
76+ const historicalSummariesEpoch = computeEpochAtSlot ( bootstrapSlot )
77+
78+ // Store historical summaries
79+ const historicalSummariesObj = HistoricalSummariesWithProof . fromJson ( {
80+ epoch : historicalSummariesEpoch ,
81+ historical_summaries : historicalSummariesJson . historical_summaries ,
82+ proof : historicalSummariesJson . proof
83+ } )
84+ const summariesKey = getBeaconContentKey (
85+ BeaconLightClientNetworkContentType . HistoricalSummaries ,
86+ HistoricalSummariesKey . serialize ( { epoch : BigInt ( historicalSummariesEpoch ) } )
87+ )
88+ const summariesValue = concatBytes (
89+ forkDigest ,
90+ HistoricalSummariesWithProof . serialize ( historicalSummariesObj )
91+ )
92+ await beacon ?. store ( summariesKey , summariesValue )
93+
94+ // Store header with proof
95+ const blockHash = fullBlock . data . message . body . execution_payload . block_hash
96+
97+ const headerKey = getContentKey (
98+ HistoryNetworkContentType . BlockHeader ,
99+ hexToBytes ( blockHash )
100+ )
101+ await history ?. store ( headerKey , hexToBytes ( headerWithProof . proof ) )
102+
103+ // Verify block header can be retrieved
104+ const retrievedHeader = await client . ETH . getBlockByHash ( hexToBytes ( blockHash ) , false )
105+ assert . equal ( retrievedHeader ! . header . number , fullBlock . data . message . body . execution_payload . block_number )
106+ // Cleanup
107+ await client . stop ( )
108+ } , 30000 ) // Increased timeout to 30 seconds
109+ } )
0 commit comments