Skip to content

Commit

Permalink
Cleanup PR (#480)
Browse files Browse the repository at this point in the history
* Fix logging

* Dont ping ourselves

* Clear ping timeout if other resolution occurs

* Update optimistic and finality update keys to spec

* Fix field naming in transport

* Update beaconBridge script

* more nits

* fix tests

* fix test
  • Loading branch information
acolytec3 authored Oct 16, 2023
1 parent af42e43 commit 91ae74e
Show file tree
Hide file tree
Showing 13 changed files with 71 additions and 67 deletions.
27 changes: 9 additions & 18 deletions packages/cli/scripts/beaconBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,14 @@ import jayson from 'jayson/promise/index.js'
import { createBeaconConfig, defaultChainConfig, BeaconConfig } from '@lodestar/config'
import { genesisData } from '@lodestar/config/networks'
import { BeaconLightClientNetworkContentType, fromHexString, getBeaconContentKey, LightClientBootstrapKey, LightClientOptimisticUpdateKey, LightClientUpdatesByRange, LightClientUpdatesByRangeKey, ProtocolId, toHexString } from 'portalnetwork'
import yargs from 'yargs'
import { hideBin } from 'yargs/helpers'
import { capella, ssz } from '@lodestar/types'
import { EPOCHS_PER_SYNC_COMMITTEE_PERIOD, ForkName } from '@lodestar/params'
import { ssz } from '@lodestar/types'
import { ForkName } from '@lodestar/params'
import { computeSyncPeriodAtSlot } from '@lodestar/light-client/utils'
import { concatBytes, hexToBytes } from '@ethereumjs/util'
import { serialize } from 'v8'


const { Client } = jayson
/*
const args: any = yargs(hideBin(process.argv))
.option('blockHeight', {
describe: 'block height to build accumulator to',
number: true,
default: 9000
}).argv
*/

const main = async () => {
const beaconConfig = createBeaconConfig(defaultChainConfig, hexToBytes(genesisData.mainnet.genesisValidatorsRoot))
const capellaForkDigest = beaconConfig.forkName2ForkDigest(ForkName.capella)
Expand All @@ -28,10 +19,10 @@ const main = async () => {

console.log('Retrieving bootstrap and updates from Beacon node...')
let optimisticUpdate = ssz.capella.LightClientOptimisticUpdate.fromJson((await (await fetch(beaconNode + 'eth/v1/beacon/light_client/optimistic_update')).json()).data)
let optimisticUpdateKey = getBeaconContentKey(BeaconLightClientNetworkContentType.LightClientOptimisticUpdate, LightClientOptimisticUpdateKey.serialize({ optimisticSlot: BigInt(optimisticUpdate.attestedHeader.beacon.slot) }))
let optimisticUpdateKey = getBeaconContentKey(BeaconLightClientNetworkContentType.LightClientOptimisticUpdate, LightClientOptimisticUpdateKey.serialize({ signatureSlot: BigInt(optimisticUpdate.signatureSlot) }))
const currentPeriod = computeSyncPeriodAtSlot(optimisticUpdate.signatureSlot)
const oldPeriod = (currentPeriod - 6)
const updatesByRange = (await (await fetch(beaconNode + `eth/v1/beacon/light_client/updates?start_period=${oldPeriod}&count=7`)).json())
const oldPeriod = (currentPeriod - 1)
const updatesByRange = (await (await fetch(beaconNode + `eth/v1/beacon/light_client/updates?start_period=${oldPeriod}&count=2`)).json())
const range: Uint8Array[] = []
for (const update of updatesByRange) {
range.push(concatBytes(
Expand All @@ -42,7 +33,7 @@ const main = async () => {
))
}
const serializedRange = LightClientUpdatesByRange.serialize(range)
const rangeKey = getBeaconContentKey(BeaconLightClientNetworkContentType.LightClientUpdatesByRange, LightClientUpdatesByRangeKey.serialize({ startPeriod: BigInt(oldPeriod), count: 6n }))
const rangeKey = getBeaconContentKey(BeaconLightClientNetworkContentType.LightClientUpdatesByRange, LightClientUpdatesByRangeKey.serialize({ startPeriod: BigInt(oldPeriod), count: 2n }))
const bootstrapSlot = updatesByRange[0].data.finalized_header.beacon.slot
const bootstrapRoot = (await (await fetch(beaconNode + `eth/v1/beacon/blocks/${bootstrapSlot}/root`)).json()).data.root
const bootstrap = ssz.capella.LightClientBootstrap.fromJson((await (await fetch(beaconNode + `eth/v1/beacon/light_client/bootstrap/${bootstrapRoot}`)).json()).data)
Expand All @@ -62,7 +53,7 @@ const main = async () => {
while (true) {
await new Promise(resolve => setTimeout(() => resolve(undefined), 13000))
let optimisticUpdate = ssz.capella.LightClientOptimisticUpdate.fromJson((await (await fetch(beaconNode + 'eth/v1/beacon/light_client/optimistic_update')).json()).data)
let optimisticUpdateKey = getBeaconContentKey(BeaconLightClientNetworkContentType.LightClientOptimisticUpdate, LightClientOptimisticUpdateKey.serialize({ optimisticSlot: BigInt(optimisticUpdate.attestedHeader.beacon.slot) }))
let optimisticUpdateKey = getBeaconContentKey(BeaconLightClientNetworkContentType.LightClientOptimisticUpdate, LightClientOptimisticUpdateKey.serialize({ signatureSlot: BigInt(optimisticUpdate.signatureSlot) }))
const res = await ultralight.request('portal_beaconStore', [optimisticUpdateKey, toHexString(concatBytes(capellaForkDigest, ssz.capella.LightClientOptimisticUpdate.serialize(optimisticUpdate)))])
console.log(`Pushed optimistic update for signature slot ${optimisticUpdate.signatureSlot}`, res)
}
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ const main = async () => {
portal.discv5.enableLogs()

// portal.enableLog(
// 'ultralight,-FINDNODES,*LightClient:DEBUG,*LightClient:INFO,*BeaconLightClientNetwork,*BOOTSTRAP,*OFFER,*ACCEPT,*FINDCONTENT,*FOUNDCONTENT,*uTP',
// )
// 'ultralight,-FINDNODES,*LightClient:DEBUG,*LightClient:INFO,*BeaconLightClientNetwork,*BOOTSTRAP,*OFFER,*ACCEPT,*FINDCONTENT,*FOUNDCONTENT,*uTP:FINISHED',
// )
portal.enableLog('*Portal*,uTP*')

const rpcAddr = args.rpcAddr ?? ip // Set RPC address (used by metrics server and rpc server)
Expand Down
27 changes: 14 additions & 13 deletions packages/portalnetwork/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
NodeId,
ENR,
createKeypairFromPeerId,
createPeerIdFromKeypair,
} from '@chainsafe/discv5'
import { ITalkReqMessage, ITalkRespMessage } from '@chainsafe/discv5/message'
import { EventEmitter } from 'events'
Expand Down Expand Up @@ -224,21 +225,21 @@ export class PortalNetwork extends (EventEmitter as { new (): PortalNetworkEvent
// if (this.discv5.sessionService.transport instanceof HybridTransportService) {
// ;(this.discv5.sessionService as any).send = this.send.bind(this)
// }
this.discv5.sessionService.on('established', async (nodeAddr, enr, _, _verified) => {
this.discv5.sessionService.on('established', async (nodeAddr, enr, _, verified) => {
this.discv5.findEnr(enr.nodeId) === undefined && this.discv5.addEnr(enr)

// if (!verified || !enr.getLocationMultiaddr('udp')) {
// // If a node provides an invalid ENR during the discv5 handshake, we cache the multiaddr
// // corresponding to the node's observed IP/Port so that we can send outbound messages to
// // those nodes later on if needed. This is currently used by uTP when responding to
// // FINDCONTENT requests from nodes with invalid ENRs.
// const peerId = await createPeerIdFromKeypair(enr.keypair)
// this.unverifiedSessionCache.set(
// enr.nodeId,
// multiaddr(nodeAddr.socketAddr.toString() + '/p2p/' + peerId.toString())
// )
// this.logger(this.unverifiedSessionCache.get(enr.nodeId))
// }
if (!verified || !enr.getLocationMultiaddr('udp')) {
// If a node provides an invalid ENR during the discv5 handshake, we cache the multiaddr
// corresponding to the node's observed IP/Port so that we can send outbound messages to
// those nodes later on if needed. This is currently used by uTP when responding to
// FINDCONTENT requests from nodes with invalid ENRs.
const peerId = await createPeerIdFromKeypair(enr.keypair)
this.unverifiedSessionCache.set(
enr.nodeId,
multiaddr(nodeAddr.socketAddr.toString() + '/p2p/' + peerId.toString()),
)
this.logger(this.unverifiedSessionCache.get(enr.nodeId))
}
})

if (opts.metrics) {
Expand Down
10 changes: 5 additions & 5 deletions packages/portalnetwork/src/subprotocols/beacon/beacon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ export class BeaconLightClientNetwork extends BaseProtocol {
key = LightClientOptimisticUpdateKey.deserialize(contentKey.slice(1))
if (
this.lightClient !== undefined &&
key.optimisticSlot === BigInt(this.lightClient.getHead().beacon.slot)
key.signatureSlot === BigInt(this.lightClient.getHead().beacon.slot)
) {
// We only store the most recent optimistic update so only retrieve the optimistic update if the slot
// in the key matches the current head known to our light client
Expand All @@ -354,7 +354,7 @@ export class BeaconLightClientNetwork extends BaseProtocol {
key = LightClientFinalityUpdateKey.deserialize(contentKey.slice(1))
if (
this.lightClient !== undefined &&
key.finalizedSlot === BigInt(this.lightClient.getFinalized().beacon.slot)
key.signatureSlot === BigInt(this.lightClient.getFinalized().beacon.slot)
) {
// We only store the most recent finality update so only retrieve the optimistic update if the slot
// in the key matches the current finalized slot known to our light client
Expand Down Expand Up @@ -514,7 +514,7 @@ export class BeaconLightClientNetwork extends BaseProtocol {
this.metrics?.contentMessagesSent.inc()

this.logger(
`Received handleFindContent request for contentKey: ${toHexString(
`Received FindContent request for contentKey: ${toHexString(
decodedContentMessage.contentKey,
)}`,
)
Expand Down Expand Up @@ -792,7 +792,7 @@ export class BeaconLightClientNetwork extends BaseProtocol {
}
case BeaconLightClientNetworkContentType.LightClientFinalityUpdate:
{
const slot = LightClientFinalityUpdateKey.deserialize(key.slice(1)).finalizedSlot
const slot = LightClientFinalityUpdateKey.deserialize(key.slice(1)).signatureSlot
if (
this.lightClient !== undefined &&
slot > this.lightClient.getFinalized().beacon.slot
Expand All @@ -809,7 +809,7 @@ export class BeaconLightClientNetwork extends BaseProtocol {
break
case BeaconLightClientNetworkContentType.LightClientOptimisticUpdate:
{
const slot = LightClientOptimisticUpdateKey.deserialize(key.slice(1)).optimisticSlot
const slot = LightClientOptimisticUpdateKey.deserialize(key.slice(1)).signatureSlot
if (
this.lightClient !== undefined &&
slot > this.lightClient.getHead().beacon.slot
Expand Down
4 changes: 2 additions & 2 deletions packages/portalnetwork/src/subprotocols/beacon/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ export const LightClientUpdatesByRangeKey = new ContainerType({
count: new UintBigintType(8),
})
export const LightClientFinalityUpdateKey = new ContainerType({
finalizedSlot: new UintBigintType(8),
signatureSlot: new UintBigintType(8),
})
export const LightClientOptimisticUpdateKey = new ContainerType({
optimisticSlot: new UintBigintType(8),
signatureSlot: new UintBigintType(8),
})

export enum SyncStrategy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class UltralightTransport implements LightClientTransport {
concatBytes(
new Uint8Array([BeaconLightClientNetworkContentType.LightClientOptimisticUpdate]),
LightClientOptimisticUpdateKey.serialize({
optimisticSlot: currentSlot,
signatureSlot: currentSlot,
}),
),
)
Expand Down Expand Up @@ -122,7 +122,7 @@ export class UltralightTransport implements LightClientTransport {
this.protocol.routingTable.random()!.nodeId,
concatBytes(
new Uint8Array([BeaconLightClientNetworkContentType.LightClientFinalityUpdate]),
LightClientFinalityUpdateKey.serialize({ finalizedSlot: currentSlot }),
LightClientFinalityUpdateKey.serialize({ signatureSlot: currentSlot }),
),
)
if (decoded !== undefined) {
Expand Down
20 changes: 15 additions & 5 deletions packages/portalnetwork/src/subprotocols/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ export abstract class BaseProtocol extends EventEmitter {
const deserialized = PortalWireMessageType.deserialize(request)
const decoded = deserialized.value
const messageType = deserialized.selector
this.logger.extend(MessageCodes[messageType])(`Received from ${shortId(src.nodeId)}`)
const srcEnr = this.routingTable.getWithPending(src.nodeId)
this.logger.extend(MessageCodes[messageType])(
`Received from ${shortId(srcEnr !== undefined ? srcEnr.value : src.nodeId)}`,
)
switch (messageType) {
case MessageCodes.PING:
this.handlePing(src, id, decoded as PingMessage)
Expand Down Expand Up @@ -132,14 +135,18 @@ export abstract class BaseProtocol extends EventEmitter {
if (!(enr instanceof ENR)) {
enr = ENR.decodeTxt(enr)
}
// 3000ms tolerance for ping timeout
setTimeout(() => {
if (enr.nodeId === this.portal.discv5.enr.nodeId) {
// Don't ping ourselves
return undefined
}, 3000)
}
// 3000ms tolerance for ping timeout
if (!enr.nodeId) {
this.logger(`Invalid ENR provided. PING aborted`)
return
}
const timeout = setTimeout(() => {
return undefined
}, 3000)
try {
const pingMsg = PortalWireMessageType.serialize({
selector: MessageCodes.PING,
Expand All @@ -156,13 +163,16 @@ export abstract class BaseProtocol extends EventEmitter {
const pongMessage = decoded.value as PongMessage
// Received a PONG message so node is reachable, add to routing table
this.updateRoutingTable(enr, pongMessage.customPayload)
clearTimeout(timeout)
return pongMessage
} else {
clearTimeout(timeout)
this.routingTable.evictNode(enr.nodeId)
}
} catch (err: any) {
this.logger(`Error during PING request: ${err.toString()}`)
enr.nodeId && this.routingTable.evictNode(enr.nodeId)
clearTimeout(timeout)
return
}
}
Expand Down Expand Up @@ -486,7 +496,7 @@ export abstract class BaseProtocol extends EventEmitter {
this.metrics?.contentMessagesSent.inc()

this.logger(
`Received handleFindContent request for contentKey: ${toHexString(
`Received FindContent request for contentKey: ${toHexString(
decodedContentMessage.contentKey,
)}`,
)
Expand Down
2 changes: 1 addition & 1 deletion packages/portalnetwork/src/util/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const shortId = (nodeId: string | ENR) => {
return nodeId.slice(0, 5) + '...' + nodeId.slice(nodeId.length - 5)
const nodeType = nodeId.kvs.get('c')
const nodeTypeString =
nodeType !== undefined && nodeType.length > 0 ? `${bytesToUtf8(nodeType)}:` : undefined
nodeType !== undefined && nodeType.length > 0 ? `${bytesToUtf8(nodeType)}:` : ''
return (
nodeTypeString +
nodeId.nodeId.slice(0, 5) +
Expand Down
1 change: 0 additions & 1 deletion packages/portalnetwork/src/wire/utp/Socket/UtpSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ export class UtpSocket extends EventEmitter {
try {
await this.packetManager.congestionControl.canSend()
} catch (e) {
console.trace(e)
this.logger(`DATA packet not acked. Closing connection to ${this.remoteAddress}`)
await this.sendResetPacket()
this.close()
Expand Down
12 changes: 6 additions & 6 deletions packages/portalnetwork/test/integration/beaconProtocol.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ describe('Find Content tests', () => {
node1.discv5.enr.nodeId,
concatBytes(
new Uint8Array([3]),
LightClientOptimisticUpdateKey.serialize({ optimisticSlot: 6718463n }),
LightClientOptimisticUpdateKey.serialize({ signatureSlot: 6718463n }),
),
)

Expand All @@ -200,7 +200,7 @@ describe('Find Content tests', () => {
const content = await protocol2.findContentLocally(
concatBytes(
new Uint8Array([3]),
LightClientOptimisticUpdateKey.serialize({ optimisticSlot: 6718463n }),
LightClientOptimisticUpdateKey.serialize({ signatureSlot: 6718463n }),
),
)

Expand Down Expand Up @@ -369,7 +369,7 @@ describe('OFFER/ACCEPT tests', () => {
BeaconLightClientNetworkContentType.LightClientOptimisticUpdate,
getBeaconContentKey(
BeaconLightClientNetworkContentType.LightClientOptimisticUpdate,
LightClientOptimisticUpdateKey.serialize({ optimisticSlot: 6718463n }),
LightClientOptimisticUpdateKey.serialize({ signatureSlot: 6718463n }),
),
hexToBytes(optimisticUpdate.content_value),
)
Expand All @@ -395,7 +395,7 @@ describe('OFFER/ACCEPT tests', () => {
hexToBytes(
getBeaconContentKey(
BeaconLightClientNetworkContentType.LightClientOptimisticUpdate,
LightClientOptimisticUpdateKey.serialize({ optimisticSlot: 6718463n }),
LightClientOptimisticUpdateKey.serialize({ signatureSlot: 6718463n }),
),
),
)
Expand Down Expand Up @@ -485,7 +485,7 @@ describe('OFFER/ACCEPT tests', () => {

const staleOptimisticUpdateContentKey = getBeaconContentKey(
BeaconLightClientNetworkContentType.LightClientOptimisticUpdate,
LightClientOptimisticUpdateKey.serialize({ optimisticSlot: 6718463n }),
LightClientOptimisticUpdateKey.serialize({ signatureSlot: 6718463n }),
)
await protocol1.store(
BeaconLightClientNetworkContentType.LightClientOptimisticUpdate,
Expand Down Expand Up @@ -679,7 +679,7 @@ describe('beacon light client sync tests', () => {
getBeaconContentKey(
BeaconLightClientNetworkContentType.LightClientOptimisticUpdate,
// FIXME
LightClientOptimisticUpdateKey.serialize({ optimisticSlot: 0n }),
LightClientOptimisticUpdateKey.serialize({ signatureSlot: 0n }),
),
concatBytes(
capellaForkDigest,
Expand Down
12 changes: 6 additions & 6 deletions packages/portalnetwork/test/subprotocols/beacon/beacon.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ describe('portal network spec test vectors', () => {

it('deserializes optimistic update key', () => {
assert.equal(
optimisticUpdateKey.optimisticSlot,
0n,
optimisticUpdateKey.signatureSlot,
6718464n,
'correctly deserialized optimistic update key',
)
})
Expand All @@ -81,8 +81,8 @@ describe('portal network spec test vectors', () => {

it('deserializes finality update key', () => {
assert.equal(
LightClientFinalityUpdateKey.deserialize(finalityUpdateKey).finalizedSlot,
0n,
LightClientFinalityUpdateKey.deserialize(finalityUpdateKey).signatureSlot,
6718464n,
'deserialized finality update key',
)
})
Expand Down Expand Up @@ -191,7 +191,7 @@ describe('API tests', async () => {
const retrievedFinalityUpdate = await protocol.findContentLocally(
concatBytes(
new Uint8Array([BeaconLightClientNetworkContentType.LightClientFinalityUpdate]),
LightClientFinalityUpdateKey.serialize({ finalizedSlot: 6718463n }),
LightClientFinalityUpdateKey.serialize({ signatureSlot: 6718463n }),
),
)

Expand Down Expand Up @@ -226,7 +226,7 @@ describe('API tests', async () => {
const retrievedOptimisticUpdate = await protocol.findContentLocally(
concatBytes(
new Uint8Array([BeaconLightClientNetworkContentType.LightClientOptimisticUpdate]),
LightClientOptimisticUpdateKey.serialize({ optimisticSlot: 6718463n }),
LightClientOptimisticUpdateKey.serialize({ signatureSlot: 6718463n }),
),
)

Expand Down
Loading

0 comments on commit 91ae74e

Please sign in to comment.