Skip to content

Commit

Permalink
State distance function (#540)
Browse files Browse the repository at this point in the history
* state: remove custom distance function

* state: compare distance function using xor

* remove distance export

* state: change distance test to xor

* state: change distance import in routingTable
  • Loading branch information
ScottyPoi authored Feb 9, 2024
1 parent f60e3d0 commit 84bdf9c
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 34 deletions.
2 changes: 1 addition & 1 deletion packages/portalnetwork/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export { PortalNetwork } from './client/client.js'
export * from './client/index.js'
export * from './networks/index.js'
export { distance, StateNetworkRoutingTable } from './networks/state/index.js'
export { StateNetworkRoutingTable } from './networks/state/index.js'
export * from './transports/index.js'
export * from './util/index.js'
export * from './wire/index.js'
6 changes: 3 additions & 3 deletions packages/portalnetwork/src/networks/state/routingTable.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { PortalNetworkRoutingTable } from '../../client/routingTable.js'
import { distance } from '@chainsafe/discv5'

import { distance } from './util.js'
import { PortalNetworkRoutingTable } from '../../client/routingTable.js'

import type { ENR, NodeId } from '@chainsafe/discv5'

Expand All @@ -17,7 +17,7 @@ export class StateNetworkRoutingTable extends PortalNetworkRoutingTable {
results.push(...bucket.values())
}
results.sort((a, b) => {
const diff = distance(BigInt(id), BigInt(a.nodeId)) - distance(BigInt(id), BigInt(b.nodeId))
const diff = distance(id, a.nodeId) - distance(id, b.nodeId)
if (diff < 0) return -1
if (diff === 0n) return 0
return 1
Expand Down
28 changes: 11 additions & 17 deletions packages/portalnetwork/src/networks/state/util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { digest as sha256 } from '@chainsafe/as-sha256'
import { distance } from '@chainsafe/discv5'
import { equalsBytes } from '@ethereumjs/util'

import {
AccountTrieNodeKey,
Expand All @@ -16,23 +18,6 @@ import type {
TStorageTrieNodeKey,
} from './types.js'

export const MODULO = 2n ** 256n
const MID = 2n ** 255n

/**
* Calculates the distance between two ids using the distance function defined here
* https://github.com/ethereum/portal-network-specs/blob/master/state-network.md#distance-function
*/
export const distance = (id1: bigint, id2: bigint): bigint => {
if (id1 >= MODULO || id2 >= MODULO) {
throw new Error('numeric representation of node id cannot be greater than 2^256')
}
let diff: bigint
id1 > id2 ? (diff = id1 - id2) : (diff = id2 - id1)
diff > MID ? (diff = MODULO - diff) : diff
return diff
}

/* ContentKeys */

export const keyType = (contentKey: Uint8Array): StateNetworkContentType => {
Expand Down Expand Up @@ -146,3 +131,12 @@ export const tightlyPackNibbles = (nibbles: TNibble[]): TNibbles => {
})
return { isOddLength, packedNibbles: Uint8Array.from(packedBytes) }
}

export const compareDistance = (nodeId: string, nodeA: Uint8Array, nodeB: Uint8Array) => {
if (equalsBytes(nodeA, nodeB)) {
return nodeA
}
const distanceA = distance(nodeId, nodeA.toString())
const distanceB = distance(nodeId, nodeB.toString())
return distanceA < distanceB ? nodeA : nodeB
}
24 changes: 11 additions & 13 deletions packages/portalnetwork/test/networks/state/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
import { distance } from '@chainsafe/discv5'
import { randomBytes } from '@ethereumjs/util'
import { assert, describe, it } from 'vitest'

import { StateNetworkContentType } from '../../../src/networks/state/types.js'
import {
MODULO,
calculateAddressRange,
distance,
keyType,
} from '../../../src/networks/state/util.js'
import { calculateAddressRange, keyType } from '../../../src/networks/state/util.js'

describe('distance()', () => {
it('should calculate distance between two values', () => {
assert.ok(distance(10n, 10n) === 0n, 'calculates correct distance')
assert.ok(distance(5n, MODULO - 1n) === 6n, 'calculates correct distance')
assert.ok(distance(MODULO - 1n, 6n) === 7n, 'calculates correct distance')
assert.ok(distance(5n, 1n) === 4n, 'calculates correct distance')
assert.ok(distance(1n, 5n) === 4n, 'calculates correct distance')
assert.ok(distance(0n, 2n ** 255n) === 2n ** 255n, 'calculates correct distance')
assert.ok(distance(0n, 2n ** 255n + 1n) === 2n ** 255n - 1n, 'calculates correct distance')
assert.equal(distance('00', '08'), 8n, 'calculates correct distance')
assert.equal(distance('00', '09'), 9n, 'calculates correct distance')
assert.equal(distance('00', '0a'), 10n, 'calculates correct distance')
assert.equal(distance('01', '0a'), 11n, 'calculates correct distance')
assert.equal(distance('02', '0a'), 8n, 'calculates correct distance')
assert.equal(distance('03', '0a'), 9n, 'calculates correct distance')
assert.equal(distance('0a', '00'), 10n, 'calculates correct distance')
assert.equal(distance('0a', '01'), 11n, 'calculates correct distance')
assert.equal(distance('0a', '0a'), 0n, 'calculates correct distance')
})
})

Expand Down

0 comments on commit 84bdf9c

Please sign in to comment.