Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RPC: add radius and storage methods to ultralight namespace #589

Merged
merged 12 commits into from
Jul 10, 2024
150 changes: 142 additions & 8 deletions packages/cli/src/rpc/modules/ultralight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,38 @@ import { INTERNAL_ERROR } from '../error-code.js'
import { middleware, validators } from '../validators.js'

import type { Debugger } from 'debug'
import type { HistoryNetwork, PortalNetwork } from 'portalnetwork'
import type {
BeaconLightClientNetwork,
HistoryNetwork,
PortalNetwork,
StateNetwork,
} from 'portalnetwork'

const methods = ['ultralight_store', 'ultralight_addBlockToHistory']
const methods = [
'ultralight_methods',
'ultralight_addContentToDB',
'ultralight_addBlockToHistory',
'ultralight_indexBlock',
'ultralight_setNetworkRadius',
'ultralight_getNetworkRadius',
'ultralight_getNetworkStorageInfo',
'ultralight_getNetworkDBSize',
'ultralight_pruneNetworkDB',
'ultralight_setNetworkStorage',
]

export class ultralight {
private _client: PortalNetwork
private _history: HistoryNetwork
private _history?: HistoryNetwork
private _state?: StateNetwork
private _beacon?: BeaconLightClientNetwork
private logger: Debugger

constructor(client: PortalNetwork, logger: Debugger) {
this._client = client
this._history = this._client.networks.get(NetworkId.HistoryNetwork) as HistoryNetwork
this._history = this._client.network()[NetworkId.HistoryNetwork]
this._state = this._client.network()[NetworkId.StateNetwork]
this._beacon = this._client.network()[NetworkId.BeaconChainNetwork]
this.logger = logger
this.methods = middleware(this.methods.bind(this), 0, [])
this.addContentToDB = middleware(this.addContentToDB.bind(this), 2, [
Expand All @@ -35,6 +55,24 @@ export class ultralight {
[validators.hex],
[validators.blockHash],
])
this.setNetworkRadius = middleware(this.setNetworkRadius.bind(this), 2, [
[validators.networkId],
[validators.distance],
])
this.getNetworkRadius = middleware(this.getNetworkRadius.bind(this), 1, [
[validators.networkId],
])
this.getNetworkStorageInfo = middleware(this.getNetworkStorageInfo.bind(this), 1, [
[validators.networkId],
])
this.getNetworkDBSize = middleware(this.getNetworkDBSize.bind(this), 1, [
[validators.networkId],
])
this.pruneNetworkDB = middleware(this.pruneNetworkDB.bind(this), 1, [[validators.networkId]])
this.setNetworkStorage = middleware(this.setNetworkStorage.bind(this), 2, [
[validators.networkId],
[validators.megabytes],
])
}
async methods() {
return methods
Expand All @@ -43,9 +81,8 @@ export class ultralight {
this.logger(`ultralight_addBlockToHistory request received`)

const [blockHash, rlpHex] = params
const network = this._client.networks.get(NetworkId.HistoryNetwork) as never as HistoryNetwork
try {
await addRLPSerializedBlock(rlpHex, blockHash, network)
await addRLPSerializedBlock(rlpHex, blockHash, this._history!)
this.logger(`Block ${blockHash} added to content DB`)
return `Block ${blockHash} added to content DB`
} catch (err: any) {
Expand All @@ -61,7 +98,7 @@ export class ultralight {
`ultralight_addContentToDB request received for ${HistoryNetworkContentType[type]} ${contentKey}`,
)
try {
await this._history.store(contentKey, fromHexString(value))
await this._history!.store(contentKey, fromHexString(value))
this.logger(`${type} value for ${contentKey} added to content DB`)
return `${type} value for ${contentKey} added to content DB`
} catch (err: any) {
Expand All @@ -74,7 +111,7 @@ export class ultralight {
const [blockNum, blockHash] = params
try {
this.logger(`Indexed block ${BigInt(blockNum)} / ${blockNum} to ${blockHash} `)
await this._history.indexBlockhash(BigInt(blockNum), blockHash)
await this._history!.indexBlockhash(BigInt(blockNum), blockHash)
return `Added ${blockNum} to block index`
} catch (err: any) {
throw {
Expand All @@ -83,4 +120,101 @@ export class ultralight {
}
}
}
async setNetworkRadius(params: [NetworkId, string]) {
const [networkId, radius] = params
try {
switch (networkId) {
case NetworkId.HistoryNetwork: {
this._history!.nodeRadius = 2n ** BigInt(parseInt(radius)) - 1n
return '0x' + this._history!.nodeRadius.toString(16)
}
case NetworkId.StateNetwork: {
this._state!.nodeRadius = 2n ** BigInt(parseInt(radius)) - 1n
return '0x' + this._state!.nodeRadius.toString(16)
}
case NetworkId.BeaconChainNetwork: {
this._beacon!.nodeRadius = 2n ** BigInt(parseInt(radius)) - 1n
return '0x' + this._beacon!.nodeRadius.toString(16)
}
default: {
throw {
code: INTERNAL_ERROR,
message: `Invalid network id ${networkId}`,
}
}
}
} catch (err: any) {
return `Error setting radius ${err.message.toString()}`
}
}
async getNetworkRadius(params: [NetworkId]) {
const [networkId] = params
const network = this._client.networks.get(networkId)
if (!network) {
throw {
code: INTERNAL_ERROR,
message: `Invalid network id ${networkId}`,
}
}
return { radius: '0x' + network.nodeRadius.toString(16) }
}
async getNetworkStorageInfo(params: [NetworkId]) {
const [networkId] = params
const network = this._client.networks.get(networkId)
if (!network) {
throw {
code: INTERNAL_ERROR,
message: `Invalid network id ${networkId}`,
}
}
return {
maxStorage: network.maxStorage,
dbSize: await network.db.size(),
radius: '0x' + network.nodeRadius.toString(16),
}
}
async getNetworkDBSize(params: [NetworkId]) {
const [networkId] = params
const network = this._client.networks.get(networkId)
if (!network) {
throw {
code: INTERNAL_ERROR,
message: `Invalid network id ${networkId}`,
}
}
const size = await network.db.size()
return size
}
async pruneNetworkDB(params: [NetworkId]) {
const [networkId] = params
const network = this._client.networks.get(networkId)
if (!network) {
throw {
code: INTERNAL_ERROR,
message: `Invalid network id ${networkId}`,
}
}
await network.prune()
return {
maxStorage: network.maxStorage,
dbSize: await network.db.size(),
radius: '0x' + network.nodeRadius.toString(16),
}
}
async setNetworkStorage(params: [NetworkId, number]) {
const [networkId, maxStorage] = params
const network = this._client.networks.get(networkId)
if (!network) {
throw {
code: INTERNAL_ERROR,
message: `Invalid network id ${networkId}`,
}
}
await network.prune(maxStorage)
return {
maxStorage,
dbSize: await network.db.size(),
radius: '0x' + network.nodeRadius.toString(16),
}
}
}
19 changes: 19 additions & 0 deletions packages/cli/src/rpc/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,25 @@ export const validators = {
}
}
},
/**
* MB validator to check if type is positive integer
* @param params parameters of method
* @param index index of parameter
*/
get megabytes() {
return (params: any[], index: number) => {
if (
typeof params[index] !== 'number' ||
params[index] < 1 ||
!Number.isInteger(params[index])
) {
return {
code: INVALID_PARAMS,
message: `invalid argument ${index}: argument is not whole number megabytes`,
}
}
}
},

/**
* validator to ensure required transaction fields are present, and checks for valid address and hex values.
Expand Down
Loading