From bc33fb656959c2b969de6b5964a99119be592c39 Mon Sep 17 00:00:00 2001 From: municorn Date: Wed, 24 Apr 2024 08:19:00 -0600 Subject: [PATCH] SYS-126: Add handling for adding and refreshing standby nodes (#6) * refactor: replace `addStandbyNodes` with standard `addNodes` * feat(NodeList): handle standby nodes in `refreshNodes` * feat(sync-v2): verify standby node list when received --- src/Data/Cycles.ts | 2 +- src/NodeList.ts | 22 ++++++++++++---------- src/sync-v2/index.ts | 8 +++++--- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Data/Cycles.ts b/src/Data/Cycles.ts index f4aa04ce..aaffe8e6 100644 --- a/src/Data/Cycles.ts +++ b/src/Data/Cycles.ts @@ -266,7 +266,7 @@ function updateNodeList(cycle: P2PTypes.CycleCreatorTypes.CycleData): void { ip: joinRequest.nodeInfo.externalIp, port: joinRequest.nodeInfo.externalPort, })) - NodeList.addStandbyNodes(standbyNodeList) + NodeList.addNodes(NodeList.NodeStatus.STANDBY, standbyNodeList) } if (standbyRemove.length > 0) { diff --git a/src/NodeList.ts b/src/NodeList.ts index c0b92c26..aec5daa1 100644 --- a/src/NodeList.ts +++ b/src/NodeList.ts @@ -146,6 +146,14 @@ export function addNodes(status: NodeStatus, nodes: Node[]): void { // activeListByIdSorted.map((node) => node.id) // ) break + case NodeStatus.STANDBY: + if (activeList.has(key)) { + activeList.delete(key) + activeListByIdSorted = activeListByIdSorted.filter((node) => node.publicKey === key) + } + if (syncingList.has(key)) syncingList.delete(key) + if (!standbyList.has(key)) standbyList.set(key, node) + break } /* eslint-disable security/detect-object-injection */ byPublicKey[node.publicKey] = node @@ -164,7 +172,7 @@ export function addNodes(status: NodeStatus, nodes: Node[]): void { } } } -export function refreshNodes(status: NodeStatus, nodes: ConsensusNodeInfo[] | JoinedConsensor[]): void { +export function refreshNodes(status: NodeStatus, nodes: Node[]): void { if (nodes.length === 0) return Logger.mainLogger.debug('Refreshing nodes', nodes.length, nodes) for (const node of nodes) { @@ -176,6 +184,9 @@ export function refreshNodes(status: NodeStatus, nodes: ConsensusNodeInfo[] | Jo Logger.mainLogger.debug('adding new node during refresh', node.publicKey) list.push(node) switch (status) { + case NodeStatus.STANDBY: + standbyList.set(node.publicKey, node) + break case NodeStatus.SYNCING: syncingList.set(node.publicKey, node) break @@ -243,15 +254,6 @@ export function removeNodes(publicKeys: string[]): void { } } -export const addStandbyNodes = (nodes: ConsensusNodeInfo[]): void => { - if (nodes.length === 0) return - Logger.mainLogger.debug('Adding standby nodes to the list', nodes.length, nodes) - for (const node of nodes) { - if (standbyList.has(node.publicKey)) continue - standbyList.set(node.publicKey, node) - } -} - export const removeStandbyNodes = (publicKeys: string[]): void => { if (publicKeys.length > 0) Logger.mainLogger.debug('Removing standby nodes', publicKeys) for (const key of publicKeys) { diff --git a/src/sync-v2/index.ts b/src/sync-v2/index.ts index d13359c4..ab8677dc 100644 --- a/src/sync-v2/index.ts +++ b/src/sync-v2/index.ts @@ -18,7 +18,7 @@ import { import { ArchiverNodeInfo, resetActiveArchivers } from '../State' import { getActiveNodeListFromArchiver } from '../NodeList' import * as NodeList from '../NodeList' -import { verifyArchiverList, verifyCycleRecord, verifyValidatorList } from './verify' +import { verifyArchiverList, verifyCycleRecord, verifyStandbyList, verifyValidatorList } from './verify' import * as Logger from '../Logger' /** @@ -112,7 +112,7 @@ export function syncV2( })) NodeList.addNodes(NodeList.NodeStatus.SYNCING, syncingNodeList) NodeList.addNodes(NodeList.NodeStatus.ACTIVE, activeNodeList) - NodeList.addStandbyNodes(standbyNodeList) + NodeList.addNodes(NodeList.NodeStatus.STANDBY, standbyNodeList) // reset the active archivers list with the new list resetActiveArchivers(archiverList) @@ -172,7 +172,9 @@ function syncStandbyNodeList( return robustQueryForStandbyNodeListHash(activeNodes).andThen(({ value, winningNodes }) => // get full standby list from one of the winning nodes getStandbyNodeListFromNode(winningNodes[0], value.standbyNodeListHash).andThen((standbyList) => - okAsync([standbyList, value.standbyNodeListHash] as [P2PTypes.JoinTypes.JoinRequest[], hexstring]) + verifyStandbyList(standbyList, value.standbyNodeListHash).map( + () => [standbyList, value.standbyNodeListHash] as [P2PTypes.JoinTypes.JoinRequest[], hexstring] + ) ) ) }