Skip to content

Commit

Permalink
RPC: implement portal_*PutContent (#701)
Browse files Browse the repository at this point in the history
* RPC: implement portal_*PutContent

* simplify contentKnownToPeer

* implement markContentKeyAsKnownToPeer method
  • Loading branch information
ScottyPoi authored Jan 9, 2025
1 parent 4be0de4 commit 9e38af5
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 12 deletions.
80 changes: 79 additions & 1 deletion packages/cli/src/rpc/modules/portal.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EntryStatus } from '@chainsafe/discv5'
import { EntryStatus, distance } from '@chainsafe/discv5'
import { ENR } from '@chainsafe/enr'
import { bigIntToHex, bytesToHex, hexToBytes, short } from '@ethereumjs/util'
import {
Expand Down Expand Up @@ -34,6 +34,7 @@ const methods = [
'portal_statePing',
'portal_stateRoutingTableInfo',
'portal_stateStore',
'portal_statePutContent',
'portal_stateLocalContent',
'portal_stateGossip',
'portal_stateFindContent',
Expand All @@ -54,6 +55,7 @@ const methods = [
'portal_historyGetContent',
'portal_historyTraceGetContent',
'portal_historyStore',
'portal_historyPutContent',
'portal_historyLocalContent',
'portal_historyGossip',
'portal_historyAddEnr',
Expand All @@ -65,6 +67,7 @@ const methods = [
'portal_beaconGetContent',
'portal_beaconTraceGetContent',
'portal_beaconStore',
'portal_beaconPutContent',
'portal_beaconLocalContent',
'portal_beaconAddEnr',
'portal_beaconGetEnr',
Expand Down Expand Up @@ -187,6 +190,19 @@ export class portal {
[validators.hex],
[validators.hex],
])
// portal_*PutContent
this.historyPutContent = middleware(this.historyPutContent.bind(this), 2, [
[validators.contentKey],
[validators.hex],
])
this.statePutContent = middleware(this.statePutContent.bind(this), 2, [
[validators.hex],
[validators.hex],
])
this.beaconPutContent = middleware(this.beaconPutContent.bind(this), 2, [
[validators.hex],
[validators.hex],
])

// portal_*FindContent
this.historyFindContent = middleware(this.historyFindContent.bind(this), 2, [
Expand Down Expand Up @@ -763,6 +779,68 @@ export class portal {
return false
}
}
// portal_*PutContent
async historyPutContent(params: [string, string]) {
const [contentKey, content] = params.map((param) => hexToBytes(param))
const contentId = this._history.contentKeyToId(contentKey)
const d = distance(contentId, this._client.discv5.enr.nodeId)
let storedLocally = false
try {
if (d <= this._history.nodeRadius) {
await this._history.store(contentKey, content)
storedLocally = true
}
const peerCount = await this._history.gossipContent(contentKey, content)
return {
peerCount,
storedLocally,
}
} catch {
return {
peerCount: 0,
storedLocally,
}
}
}
async statePutContent(params: [string, string]) {
const [contentKey, content] = params.map((param) => hexToBytes(param))
const contentId = this._history.contentKeyToId(contentKey)
const d = distance(contentId, this._client.discv5.enr.nodeId)
let storedLocally = false
try {
if (d <= this._history.nodeRadius) {
await this._history.store(contentKey, content)
storedLocally = true
}
const peerCount = await this._history.gossipContent(contentKey, content)
return {
peerCount,
storedLocally,
}
} catch {
return {
peerCount: 0,
storedLocally,
}
}
}
async beaconPutContent(params: [string, string]) {
const [contentKey, content] = params.map((param) => hexToBytes(param))
const contentId = this._history.contentKeyToId(contentKey)
const d = distance(contentId, this._client.discv5.enr.nodeId)
let storedLocally = false
try {
if (d <= this._history.nodeRadius) {
await this._history.store(contentKey, content)
storedLocally = true
}
} catch {
return {
peerCount: 0,
storedLocally,
}
}
}

// portal_*FindContent
async historyFindContent(params: [string, string]) {
Expand Down
21 changes: 10 additions & 11 deletions packages/portalnetwork/src/client/routingTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,21 @@ export class PortalNetworkRoutingTable extends KademliaRoutingTable {
* @returns boolean indicating if node has previously been OFFERed `contentKey` already
*/
public contentKeyKnownToPeer = (nodeId: NodeId, contentKey: Uint8Array) => {
const gossipList = this.gossipMap.get(nodeId)
if (gossipList !== undefined) {
const alreadyKnownToPeer = gossipList.has(contentKey)
if (alreadyKnownToPeer) return true
}
return false
}

public markContentKeyAsKnownToPeer = (nodeId: NodeId, contentKey: Uint8Array) => {
let gossipList = this.gossipMap.get(nodeId)
if (!gossipList) {
// If no gossipList exists, create new one for `nodeId` and add contentKey to it
gossipList = new Set<Uint8Array>()
gossipList.add(contentKey)
this.gossipMap.set(nodeId, gossipList)
return false
}
const alreadyKnownToPeer = gossipList.has(contentKey)
if (alreadyKnownToPeer) return true
else {
// If contentKey has not been shared with peer, add contentKey to gossipList
gossipList.add(contentKey)
this.gossipMap.set(nodeId, gossipList)
return false
}
gossipList.add(contentKey)
}

/**
Expand Down
1 change: 1 addition & 0 deletions packages/portalnetwork/src/networks/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,7 @@ export abstract class BaseNetwork extends EventEmitter {
`Offering ${bytesToHex(contentKey)} to ${shortId(peer.nodeId)}`,
)
const res = await this.sendMessage(peer, payload, this.networkId)
this.routingTable.markContentKeyAsKnownToPeer(peer.nodeId, contentKey)
return [peer, res]
}),
)
Expand Down

0 comments on commit 9e38af5

Please sign in to comment.