Skip to content

Commit

Permalink
Adds some better tests for the offer/accept flow (#696)
Browse files Browse the repository at this point in the history
  • Loading branch information
acolytec3 authored Dec 18, 2024
1 parent a6a25c3 commit 4fc8f1d
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 3 deletions.
11 changes: 9 additions & 2 deletions packages/portalnetwork/src/networks/history/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ export const BlockHeaderByNumberKey = (blockNumber: bigint) => {
}

/**
* Generates the Content ID used to calculate the distance between a node ID and the content Key
* Generates the serialized contentKey for a given History Network content type and key (i.e. block hash or block number)
* @param contentKey an object containing the and `blockHash` used to generate the content Key
* @param contentType a number identifying the type of content (block header, block body, receipt, header_by_number)
* @param key the hash of the content represented (i.e. block hash for header, body, or receipt, or block number for header_by_number)
* @returns the hex encoded string representation of the SHA256 hash of the serialized contentKey
* @returns the serialized contentKey
*/
export const getContentKey = (
contentType: HistoryNetworkContentType,
Expand All @@ -80,6 +80,13 @@ export const getContentKey = (
}
return encodedKey
}

/**
* Generates the contentId from a serialized History Network Content Key used to calculate the distance between a node ID and the content key
* @param contentType the type of content (block header, block body, receipt, header_by_number)
* @param key the hash of the content represented (i.e. block hash for header, body, or receipt, or block number for header_by_number)
* @returns the hex encoded string representation of the SHA256 hash of the serialized contentKey
*/
export const getContentId = (contentType: HistoryNetworkContentType, key: Uint8Array | bigint) => {
const encodedKey = getContentKey(contentType, key)
return bytesToUnprefixedHex(digest(encodedKey))
Expand Down
68 changes: 67 additions & 1 deletion packages/portalnetwork/test/integration/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { readFileSync } from 'fs'
import { createRequire } from 'module'
import { SignableENR } from '@chainsafe/enr'
import { Block, BlockHeader } from '@ethereumjs/block'
import { bytesToHex, hexToBytes } from '@ethereumjs/util'
import { bytesToHex, hexToBytes, randomBytes } from '@ethereumjs/util'
import { keys } from '@libp2p/crypto'
import { multiaddr } from '@multiformats/multiaddr'
import { assert, describe, it } from 'vitest'
Expand All @@ -18,9 +18,13 @@ import {
addRLPSerializedBlock,
generateRandomNodeIdAtDistance,
getContentKey,
log2Distance,
log2Distance,
serializedContentKeyToContentId,
} from '../../src/index.js'

import type { HistoryNetwork } from '../../src/index.js'
import { BitArray } from '@chainsafe/ssz'
const require = createRequire(import.meta.url)

const privateKeys = [
Expand Down Expand Up @@ -324,4 +328,66 @@ describe('Offer/Accept', () => {
const res = await network1.sendOffer(node2.discv5.enr.toENR(), [veryFarFakeContentKey])
assert.deepEqual(res, [], 'no accepts should be received')
})
it('should send offer and get correct number of accepted content keys', async () => {
const initMa: any = multiaddr(`/ip4/127.0.0.1/udp/3092`)
enr1.setLocationMultiaddr(initMa)
const initMa2: any = multiaddr(`/ip4/127.0.0.1/udp/3093`)
enr2.setLocationMultiaddr(initMa2)
const node1 = await PortalNetwork.create({
transport: TransportLayer.NODE,
supportedNetworks: [{ networkId: NetworkId.HistoryNetwork }],
config: {
enr: enr1,
bindAddrs: {
ip4: initMa,
},
privateKey: pk1,
},
})

const node2 = await PortalNetwork.create({
transport: TransportLayer.NODE,
supportedNetworks: [{ networkId: NetworkId.HistoryNetwork }],
config: {
enr: enr2,
bindAddrs: {
ip4: initMa2,
},
privateKey: pk2,
},
})

await node1.start()
await node2.start()
const network1 = node1.networks.get(NetworkId.HistoryNetwork) as HistoryNetwork
const network2 = node2.networks.get(NetworkId.HistoryNetwork) as HistoryNetwork
await network1.sendPing(network2?.enr!.toENR())
const contentKeys: Uint8Array[] = []

// Generate 2 content keys that are at log2 distance 253 and 254
for (let i = 253; i < 255; i++) {
let distance = 256
let key
while (distance !== i) {
key = getContentKey(0, randomBytes(32))
const contentId = serializedContentKeyToContentId(key)
distance = log2Distance(contentId, node2.discv5.enr.nodeId)
}
contentKeys.push(key)
}

// Set node radius to 253
await network2.setRadius(2n ** 253n - 1n)
const res = await network1.sendOffer(node2.discv5.enr.toENR(), contentKeys)
assert.ok(res instanceof BitArray, 'should get a bitarray')
assert.equal((res as BitArray).bitLen, 2, 'should get matching length accepts')
assert.equal((res as BitArray).getTrueBitIndexes().length, 1, 'should only accept one content key')

// Set node radius to 254
await network2.setRadius(2n ** 254n - 1n)
const res2 = await network1.sendOffer(node2.discv5.enr.toENR(), contentKeys)
assert.ok(res2 instanceof BitArray, 'should get a bitarray')
assert.equal((res2 as BitArray).bitLen, 2, 'should get matching length accepts')
assert.equal((res2 as BitArray).getTrueBitIndexes().length, 2, 'should accept two content keys')
})
})

0 comments on commit 4fc8f1d

Please sign in to comment.