Skip to content
Open
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
41 changes: 41 additions & 0 deletions packages/portalnetwork/src/networks/headState/headStateNetwork.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { ENR } from '@chainsafe/enr'
import {
BaseNetwork,
type ContentLookupResponse,
NetworkId,
type BaseNetworkConfig,
} from '../../index.js'
import debug from 'debug'
import { bytesToUnprefixedHex } from '@ethereumjs/util'
import { distance } from '@chainsafe/discv5'

export class HeadStateNetwork extends BaseNetwork {
networkName = 'HeadStateNetwork'
networkId = NetworkId.HeadStateNetwork

constructor({ client, db, radius, maxStorage }: BaseNetworkConfig) {
super({ client, networkId: NetworkId.HeadStateNetwork, db, radius, maxStorage })
this.logger = debug(this.enr.nodeId.slice(0, 5)).extend('Portal').extend('HeadStateNetwork')
this.routingTable.setLogger(this.logger)
}

public interested = (contentId: Uint8Array) => {
const bits = contentId.length
const compareId = this.enr.nodeId.slice(0, bits)
const d = distance(compareId, bytesToUnprefixedHex(contentId))
return d <= this.nodeRadius
}

store(contentKey: Uint8Array, value: Uint8Array): Promise<void> {
throw new Error('Method not implemented.')
}
public findContentLocally = async (contentKey: Uint8Array): Promise<Uint8Array | undefined> => {
throw new Error('Method not implemented')
}
public sendFindContent = async (
enr: ENR,
key: Uint8Array,
): Promise<ContentLookupResponse | undefined> => {
throw new Error('Method not implemented')
}
}
171 changes: 171 additions & 0 deletions packages/portalnetwork/src/networks/headState/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import { ByteVectorType, ContainerType, ListCompositeType } from '@chainsafe/ssz'
import { Bytes32Type } from '../types.js'
import { Nibbles, TrieNode, TrieProof, type AddressHash, type TNibbles, type TTrieProof } from '../state/types.js'

// Network content type definitions
export enum HeadStateNetworkContentType {
AccountTrieDiff = 0x30,
AccountTrieNode = 0x31,
ContractTrieDiff = 0x32,
ContractTrieNode = 0x33,
}

// Common type aliases
type BlockHash = Uint8Array
type Path = Uint8Array

// Trie node and diff base types
export const TrieNodeListType = new ListCompositeType(TrieNode, 65536)
export const TrieDiffType = new ContainerType({
before: TrieNodeListType,
after: TrieNodeListType,
})

// Account Trie types
export type AccountTrieNode = {
path: TNibbles
blockHash: BlockHash
}

export type AccountTrieNodeValue = {
proof: TTrieProof
}

export type AccountTrieDiff = {
path: Path
blockHash: BlockHash
}

export type AccountTrieDiffValue = {
subtrieDiff: {
before: TTrieProof
after: TTrieProof
}
}

// Contract Trie types
export type ContractTrieNode = {
path: TNibbles
addressHash: AddressHash
blockHash: BlockHash
}

export type ContractTrieNodeValue = {
storageProof: TTrieProof
accountProof: TTrieProof
}

export type ContractTrieDiff = {
path: Path
blockHash: BlockHash
}

export type ContractTrieDiffValue = {
subtrieDiff: {
before: TTrieProof
after: TTrieProof
}
accountProof: TTrieProof
}

// SSZ serialization types
const PathType = new ByteVectorType(1)

export const AccountTrieNodeSszType = new ContainerType({
path: Nibbles,
blockHash: Bytes32Type,
})

export const AccountTrieNodeValueSszType = new ContainerType({
proof: TrieProof,
})

export const AccountTrieDiffSszType = new ContainerType({
path: PathType,
blockHash: Bytes32Type,
})

export const AccountTrieDiffValueSszType = new ContainerType({
subtrieDiff: TrieDiffType,
})

export const ContractTrieNodeSszType = new ContainerType({
path: Nibbles,
addressHash: Bytes32Type,
blockHash: Bytes32Type,
})

export const ContractTrieNodeValueSszType = new ContainerType({
storageProof: TrieProof,
accountProof: TrieProof,
})

export const ContractTrieDiffSszType = new ContainerType({
path: PathType,
blockHash: Bytes32Type,
})

export const ContractTrieDiffValueSszType = new ContainerType({
subtrieDiff: TrieDiffType,
accountProof: TrieProof,
})

// Content type mapping
export type HeadStateNetworkContent<T extends HeadStateNetworkContentType> =
T extends HeadStateNetworkContentType.AccountTrieDiff
? AccountTrieDiff
: T extends HeadStateNetworkContentType.AccountTrieNode
? AccountTrieNode
: T extends HeadStateNetworkContentType.ContractTrieDiff
? ContractTrieDiff
: T extends HeadStateNetworkContentType.ContractTrieNode
? ContractTrieNode
: never

export type HeadStateNetworkContentValue<T extends HeadStateNetworkContentType> =
T extends HeadStateNetworkContentType.AccountTrieDiff
? AccountTrieDiffValue
: T extends HeadStateNetworkContentType.AccountTrieNode
? AccountTrieNodeValue
: T extends HeadStateNetworkContentType.ContractTrieDiff
? ContractTrieDiffValue
: T extends HeadStateNetworkContentType.ContractTrieNode
? ContractTrieNodeValue
: never

// Serialization helpers
const contentKeySerializers: {
[T in HeadStateNetworkContentType]: {
serialize: (content: HeadStateNetworkContent<T>) => Uint8Array
}
} = {
[HeadStateNetworkContentType.AccountTrieDiff]: AccountTrieDiffSszType,
[HeadStateNetworkContentType.AccountTrieNode]: AccountTrieNodeSszType,
[HeadStateNetworkContentType.ContractTrieDiff]: ContractTrieDiffSszType,
[HeadStateNetworkContentType.ContractTrieNode]: ContractTrieNodeSszType,
}

const contentValueSerializers: {
[T in HeadStateNetworkContentType]: {
serialize: (content: HeadStateNetworkContentValue<T>) => Uint8Array
}
} = {
[HeadStateNetworkContentType.AccountTrieDiff]: AccountTrieDiffValueSszType,
[HeadStateNetworkContentType.AccountTrieNode]: AccountTrieNodeValueSszType,
[HeadStateNetworkContentType.ContractTrieDiff]: ContractTrieDiffValueSszType,
[HeadStateNetworkContentType.ContractTrieNode]: ContractTrieNodeValueSszType,
}

export function getContentKey<T extends HeadStateNetworkContentType>(
type: T,
content: HeadStateNetworkContent<T>,
) {
return Uint8Array.from([type, ...contentKeySerializers[type].serialize(content)])
}

export function getContentValue<T extends HeadStateNetworkContentType>(
type: T,
content: HeadStateNetworkContentValue<T>,
) {
return contentValueSerializers[type].serialize(content)
}
32 changes: 19 additions & 13 deletions packages/portalnetwork/src/networks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ const BYTE_SIZE = 256

// subnetwork IDs
export enum NetworkId {
HeadStateNetwork = '0x5009',
StateNetwork = '0x500a',
HistoryNetwork = '0x500b',
BeaconChainNetwork = '0x500c',
CanonicalTxIndexNetwork = '0x500d',
VerkleStateNetwork = '0x500e',
TransactionGossipNetwork = '0x500f',
Angelfood_HeadStateNetwork = '0x5049',
Angelfood_StateNetwork = '0x504a',
Angelfood_HistoryNetwork = '0x504b',
Angelfood_BeaconChainNetwork = '0x504c',
Expand All @@ -39,19 +41,23 @@ export enum NetworkId {
UTPNetwork = '0x757470',
}

export type SubNetwork<T extends NetworkId> = T extends '0x500a'
? HistoryNetwork
: T extends '0x504a'
? HistoryNetwork
: T extends '0x500b'
? StateNetwork
: T extends '0x504b'
? StateNetwork
: T extends '0x500c'
? BeaconNetwork
: T extends '0x504c'
? BeaconNetwork
: never
export type SubNetwork<T extends NetworkId> = T extends '0x5009'
? HeadStateNetwork
: T extends '0x5049'
? HeadStateNetwork
: T extends '0x500a'
? HistoryNetwork
: T extends '0x504a'
? HistoryNetwork
: T extends '0x500b'
? StateNetwork
: T extends '0x504b'
? StateNetwork
: T extends '0x500c'
? BeaconNetwork
: T extends '0x504c'
? BeaconNetwork
: never

export class Bloom {
bitvector: Uint8Array
Expand Down