Skip to content

Commit

Permalink
Sec 158 (#3)
Browse files Browse the repository at this point in the history
* SEC-158: Added robust query and check in calling function

* rebase and some linting fixes

---------

Co-authored-by: “Sanidhya <[email protected]>
  • Loading branch information
mssabr01 and “Sanidhya authored Apr 22, 2024
1 parent f1c9aa3 commit 383aaea
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 27 deletions.
1 change: 1 addition & 0 deletions src/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1202,6 +1202,7 @@ export const queryFromArchivers = async (
const randomArchivers = Utils.getRandomItemFromArr(filteredArchivers, 0, maxNumberofArchiversToRetry)
let retry = 0
while (retry < maxNumberofArchiversToRetry) {
// eslint-disable-next-line security/detect-object-injection
let randomArchiver = randomArchivers[retry]
if (!randomArchiver) randomArchiver = randomArchivers[0]
try {
Expand Down
81 changes: 57 additions & 24 deletions src/Data/Data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import { queryFromArchivers, RequestDataType } from '../API'
import ioclient = require('socket.io-client')
import { Transaction } from '../dbstore/transactions'
import { AccountCopy } from '../dbstore/accounts'
import { robustQuery } from '../Utils'
export let socketServer: SocketIO.Server
export const socketClients: Map<string, SocketIOClientStatic['Socket']> = new Map()
// let socketConnectionsTracker: Map<string, string> = new Map()
export let combineAccountsData = {
Expand Down Expand Up @@ -533,36 +535,61 @@ export function addDataSender(sender: DataSender): void {
dataSenders.set(sender.nodeInfo.publicKey, sender)
}

interface configConsensusResponse {
config?: {
sharding?: {
nodesPerConsensusGroup?: number
nodesPerEdge?: number
}
}
}

async function getConsensusRadius(): Promise<number> {
// If there is no node, return existing currentConsensusRadius
if (NodeList.getList().length === 0) return currentConsensusRadius
const randomNode =

// Define the query function to get the network config from a node
const queryFn = async (node): Promise<object> => {
const REQUEST_NETCONFIG_TIMEOUT_SECOND = 2 // 2s timeout
try {
const response = await P2P.getJson(
`http://${node.ip}:${node.port}/netconfig`,
REQUEST_NETCONFIG_TIMEOUT_SECOND
)
return response
} catch (error) {
Logger.mainLogger.error(`Error querying node ${node.ip}:${node.port}: ${error}`)
return null
}
}

// Define the equality function to compare two responses
const equalityFn = (responseA, responseB): boolean => {
return (
responseA.config.sharding.nodesPerConsensusGroup === responseB.config.sharding.nodesPerConsensusGroup
)
}

// Get the list of active nodes or the first node if no active nodes are available
const nodes =
NodeList.getActiveNodeCount() > 0
? NodeList.getRandomActiveNodes(1)[0]
: NodeList.getList().slice(0, 1)[0]
Logger.mainLogger.debug(`Checking network configs from random node ${randomNode.ip}:${randomNode.port}`)
// TODO: Should try to get the network config from multiple nodes and use the consensusRadius that has the majority
const REQUEST_NETCONFIG_TIMEOUT_SECOND = 2 // 2s timeout
const response = (await P2P.getJson(
`http://${randomNode.ip}:${randomNode.port}/netconfig`,
REQUEST_NETCONFIG_TIMEOUT_SECOND
)) as configConsensusResponse

if (response && response.config) {
nodesPerConsensusGroup = response.config.sharding.nodesPerConsensusGroup
nodesPerEdge = response.config.sharding.nodesPerEdge
// Upgrading consensus size to odd number
? NodeList.getRandomActiveNodes(NodeList.getActiveNodeCount())
: NodeList.getList().slice(0, 1)

// Use robustQuery to get the consensusRadius from multiple nodes
const tallyItem = await robustQuery(
nodes,
queryFn,
equalityFn,
3, // Redundancy
true, // Shuffle nodes
0, // No delay
false // Disable fail log
)

// Check if a consensus was reached
if (tallyItem && tallyItem.value && tallyItem.value.config) {
nodesPerConsensusGroup = tallyItem.value.config.sharding.nodesPerConsensusGroup
nodesPerEdge = tallyItem.value.config.sharding.nodesPerEdge
// Upgrading consensus size to an odd number
if (nodesPerConsensusGroup % 2 === 0) nodesPerConsensusGroup++
const consensusRadius = Math.floor((nodesPerConsensusGroup - 1) / 2)
// Validation: Ensure consensusRadius is a number and greater than zero
if (typeof consensusRadius !== 'number' || isNaN(consensusRadius) || consensusRadius <= 0) {
Logger.mainLogger.error('Invalid consensusRadius:', consensusRadius)
return currentConsensusRadius // Return the existing currentConsensusRadius in case of invalid consensusRadius
}
Logger.mainLogger.debug(
'consensusRadius',
consensusRadius,
Expand All @@ -574,6 +601,8 @@ async function getConsensusRadius(): Promise<number> {
if (config.VERBOSE) console.log('consensusRadius', consensusRadius)
return consensusRadius
}

// If no consensus was reached, return the existing currentConsensusRadius
return currentConsensusRadius
}

Expand Down Expand Up @@ -604,6 +633,10 @@ export async function createDataTransferConnection(

export async function createNodesGroupByConsensusRadius(): Promise<void> {
const consensusRadius = await getConsensusRadius()
if (consensusRadius === 0) {
Logger.mainLogger.error('Consensus radius is 0, unable to create nodes group.')
return // Early return to prevent further execution
}
currentConsensusRadius = consensusRadius
const activeList = [...NodeList.activeListByIdSorted]
if (config.VERBOSE) Logger.mainLogger.debug('activeList', activeList.length, activeList)
Expand Down
1 change: 1 addition & 0 deletions src/GlobalAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export const syncGlobalAccount = async (): Promise<void> => {
)
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const equalFn = (info1: any, info2: any): boolean => {
const cm1 = deepCopy(info1)
const cm2 = deepCopy(info2)
Expand Down
4 changes: 3 additions & 1 deletion src/shardeum/calculateAccountHash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export enum AccountType {
}

export const accountSpecificHash = (account: any): string => {
let hash
let hash: string
delete account.hash
if (
account.accountType === AccountType.NetworkAccount ||
Expand Down Expand Up @@ -58,6 +58,7 @@ export const accountSpecificHash = (account: any): string => {
}

// Converting the correct account data format to get the correct hash
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const fixAccountUint8Arrays = (account: any): void => {
if (!account) return // if account is null, return
if (account.storageRoot) account.storageRoot = Uint8Array.from(Object.values(account.storageRoot)) // Account
Expand Down Expand Up @@ -93,6 +94,7 @@ export const verifyAccountHash = (receipt: ArchiverReceipt): boolean => {
)
return false
}
// eslint-disable-next-line security/detect-object-injection
const expectedAccountHash = receipt.appliedReceipt.appliedVote.account_state_hash_after[indexOfAccount]
if (calculatedAccountHash !== expectedAccountHash) {
Logger.mainLogger.error(
Expand Down
2 changes: 1 addition & 1 deletion src/shardeum/verifyAppReceiptData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export const verifyAppReceiptData = async (
}

// Converting the correct appReceipt data format to get the correct hash
const calculateAppReceiptDataHash = (appReceiptData: any): string => {
const calculateAppReceiptDataHash = (appReceiptData): string => {
try {
if (appReceiptData.data && appReceiptData.data.receipt) {
if (appReceiptData.data.receipt.bitvector)
Expand Down
2 changes: 1 addition & 1 deletion src/sync-v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { ArchiverNodeInfo } from '../State'
import { getActiveNodeListFromArchiver } from '../NodeList'
import * as NodeList from '../NodeList'
import { verifyCycleRecord, verifyStandbyList, verifyValidatorList } from './verify'
import { verifyCycleRecord, verifyValidatorList } from './verify'
import * as Logger from '../Logger'

/**
Expand Down
1 change: 1 addition & 0 deletions src/utils/stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const defaultStringifierOptions: stringifierOptions = {
bufferEncoding: 'base64',
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function stringify(val: any, options: stringifierOptions = defaultStringifierOptions): string {
const returnVal = stringifier(val, false, options)
if (returnVal !== undefined) {
Expand Down

0 comments on commit 383aaea

Please sign in to comment.