From 0a26b1be3e8351b2050d50d2d4289d131180fbee Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Wed, 7 Feb 2024 18:46:32 +0100 Subject: [PATCH 1/6] feat: mark finalized blocks --- api/src/models/api/nova/feed/IFeedUpdate.ts | 3 +- api/src/services/nova/feed/novaFeed.ts | 18 ++++++++- .../visualizer-threejs/VisualizerInstance.tsx | 37 ++++++++++++++++++- .../visualizer-threejs/store/tangle.ts | 35 ++++++++++++++++++ .../src/models/api/nova/feed/IFeedUpdate.ts | 3 +- client/src/services/nova/novaFeedClient.ts | 7 +++- setup_nova.sh | 2 +- 7 files changed, 98 insertions(+), 7 deletions(-) diff --git a/api/src/models/api/nova/feed/IFeedUpdate.ts b/api/src/models/api/nova/feed/IFeedUpdate.ts index 04818b2fb..384062fe9 100644 --- a/api/src/models/api/nova/feed/IFeedUpdate.ts +++ b/api/src/models/api/nova/feed/IFeedUpdate.ts @@ -1,6 +1,6 @@ /* eslint-disable import/no-unresolved */ /* eslint-disable @typescript-eslint/no-redundant-type-constituents */ -import { Block, IBlockMetadata } from "@iota/sdk-nova"; +import { Block, IBlockMetadata, SlotIndex } from "@iota/sdk-nova"; interface IFeedBlockUpdate { blockId: string; @@ -11,4 +11,5 @@ export interface IFeedUpdate { subscriptionId: string; blockUpdate?: IFeedBlockUpdate; blockMetadataUpdate?: IBlockMetadata; + slotFinalized?: SlotIndex; } diff --git a/api/src/services/nova/feed/novaFeed.ts b/api/src/services/nova/feed/novaFeed.ts index 4c04b50f4..537f70521 100644 --- a/api/src/services/nova/feed/novaFeed.ts +++ b/api/src/services/nova/feed/novaFeed.ts @@ -1,6 +1,6 @@ /* eslint-disable import/no-unresolved */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ -import { Block, Client, IBlockMetadata } from "@iota/sdk-nova"; +import { Block, Client, IBlockMetadata, SlotCommitment } from "@iota/sdk-nova"; import { ClassConstructor, plainToInstance } from "class-transformer"; import { ServiceFactory } from "../../../factories/serviceFactory"; import logger from "../../../logger"; @@ -112,6 +112,22 @@ export class NovaFeed { logger.error("[NovaFeed]: Failed broadcasting block-metadata downstream."); } }); + + // eslint-disable-next-line no-void + void this._mqttClient.listenMqtt(["commitments/finalized"], async (_, message) => { + try { + const deserializedMessage: { topic: string; payload: string } = JSON.parse(message); + const slotCommitment: SlotCommitment = JSON.parse(deserializedMessage.payload); + const slotFinalized = slotCommitment.slot; + + const update: Partial = { slotFinalized }; + + // eslint-disable-next-line no-void + void this.broadcastBlock(update); + } catch { + logger.error("[NovaFeed]: Failed broadcasting block-metadata downstream."); + } + }); } private parseMqttPayloadMessage(cls: ClassConstructor, serializedMessage: string): T { diff --git a/client/src/features/visualizer-threejs/VisualizerInstance.tsx b/client/src/features/visualizer-threejs/VisualizerInstance.tsx index b25b7cf27..7d70ea4e1 100644 --- a/client/src/features/visualizer-threejs/VisualizerInstance.tsx +++ b/client/src/features/visualizer-threejs/VisualizerInstance.tsx @@ -27,9 +27,11 @@ import { Wrapper } from "./wrapper/Wrapper"; import { CanvasElement } from "./enums"; import { useGetThemeMode } from "~/helpers/hooks/useGetThemeMode"; import { TSelectFeedItemNova } from "~/app/types/visualizer.types"; -import { BasicBlockBody, IBlockMetadata } from "@iota/sdk-wasm-nova/web"; +import { BasicBlockBody, BlockState, IBlockMetadata, SlotIndex } from "@iota/sdk-wasm-nova/web"; import { IFeedBlockData } from "~/models/api/nova/feed/IFeedBlockData"; import CameraControls from "./CameraControls"; +import { BlockId } from "@iota/sdk-wasm/web"; +import { Converter } from "~/helpers/stardust/convertUtils"; import "./Visualizer.scss"; const features = { @@ -67,6 +69,9 @@ const VisualizerInstance: React.FC> = const blockMetadata = useTangleStore((s) => s.blockMetadata); const indexToBlockId = useTangleStore((s) => s.indexToBlockId); const clickedInstanceId = useTangleStore((s) => s.clickedInstanceId); + const confirmedBlocksBySlot = useTangleStore((s) => s.confirmedBlocksBySlot); + const addToConfirmedBlocksSlot = useTangleStore((s) => s.addToConfirmedBlocksBySlot); + const removeConfirmedBlocksSlot = useTangleStore((s) => s.removeConfirmedBlocksSlot); const selectedFeedItem: TSelectFeedItemNova = clickedInstanceId ? blockMetadata.get(clickedInstanceId) ?? null : null; const resetConfigState = useTangleStore((s) => s.resetConfigState); @@ -217,9 +222,37 @@ const VisualizerInstance: React.FC> = if (selectedColor) { addToColorQueue(metadataUpdate.blockId, selectedColor); } + + const acceptedStates: (BlockState | "accepted")[] = ["confirmed", "accepted"]; + + if (acceptedStates.includes(metadataUpdate.blockState)) { + const slot = getSlotIndexFromBlockId(metadataUpdate.blockId); + addToConfirmedBlocksSlot(metadataUpdate.blockId, slot); + } } } + function onSlotFinalized(slot: SlotIndex): void { + const blocks = confirmedBlocksBySlot.get(slot); + + if (blocks?.length) { + blocks.forEach((blockId) => { + const selectedColor = BLOCK_STATE_TO_COLOR.get("finalized"); + if (selectedColor) { + addToColorQueue(blockId, selectedColor); + } + }); + } + + removeConfirmedBlocksSlot(slot); + } + + function getSlotIndexFromBlockId(blockId: BlockId): SlotIndex { + const hexalLittleEndian = blockId.slice(-8); + const hexalBigEndian = Converter.convertToBigEndian(hexalLittleEndian); + return Number.parseInt(hexalBigEndian, 16); + } + useEffect(() => { if (!runListeners) { return; @@ -235,7 +268,7 @@ const VisualizerInstance: React.FC> = if (!feedService) { return; } - feedService.subscribeBlocks(onNewBlock, onBlockMetadataUpdate); + feedService.subscribeBlocks(onNewBlock, onBlockMetadataUpdate, onSlotFinalized); bpsCounter.start(); }; diff --git a/client/src/features/visualizer-threejs/store/tangle.ts b/client/src/features/visualizer-threejs/store/tangle.ts index 9c437d7fb..a646966a1 100644 --- a/client/src/features/visualizer-threejs/store/tangle.ts +++ b/client/src/features/visualizer-threejs/store/tangle.ts @@ -3,6 +3,7 @@ import { create } from "zustand"; import { devtools } from "zustand/middleware"; import { ZOOM_DEFAULT, ANIMATION_TIME_SECONDS } from "../constants"; import { IFeedBlockData } from "~models/api/nova/feed/IFeedBlockData"; +import { BlockId, SlotIndex } from "@iota/sdk-wasm-nova/web"; interface IPosition { x: number; @@ -64,6 +65,11 @@ interface TangleState { updateBlockIdToAnimationPosition: (updatedPositions: Map) => void; resetConfigState: () => void; + + // Handle finalized blocks + confirmedBlocksBySlot: Map; + addToConfirmedBlocksBySlot: (blockId: BlockId, slot: SlotIndex) => void; + removeConfirmedBlocksSlot: (slot: SlotIndex) => void; } const INITIAL_STATE = { @@ -79,6 +85,7 @@ const INITIAL_STATE = { zoom: ZOOM_DEFAULT, bps: 0, clickedInstanceId: null, + confirmedBlocksBySlot: new Map(), }; export const useTangleStore = create()( @@ -202,5 +209,33 @@ export const useTangleStore = create()( clickedInstanceId, })); }, + addToConfirmedBlocksBySlot: (blockId, slot) => { + set((state) => { + state.confirmedBlocksBySlot.has(slot) + ? state.confirmedBlocksBySlot.get(slot)?.push(blockId) + : state.confirmedBlocksBySlot.set(slot, [blockId]); + return { + ...state, + confirmedBlocksBySlot: state.confirmedBlocksBySlot, + }; + }); + }, + removeConfirmedBlocksSlot: (slot) => { + set((state) => { + state.confirmedBlocksBySlot.delete(slot); + + // Cleanup all slots that are lower than the current slot + for (const existingSlot of state.confirmedBlocksBySlot.keys()) { + if (existingSlot < slot) { + state.confirmedBlocksBySlot.delete(existingSlot); + } + } + + return { + ...state, + confirmedBlocksBySlot: state.confirmedBlocksBySlot, + }; + }); + }, })), ); diff --git a/client/src/models/api/nova/feed/IFeedUpdate.ts b/client/src/models/api/nova/feed/IFeedUpdate.ts index d9d5832c8..e66b46181 100644 --- a/client/src/models/api/nova/feed/IFeedUpdate.ts +++ b/client/src/models/api/nova/feed/IFeedUpdate.ts @@ -1,4 +1,4 @@ -import { Block, IBlockMetadata } from "@iota/sdk-wasm-nova/web"; +import { Block, IBlockMetadata, SlotIndex } from "@iota/sdk-wasm-nova/web"; interface IFeedBlockUpdate { blockId: string; @@ -9,4 +9,5 @@ export interface IFeedUpdate { subscriptionId: string; blockUpdate?: IFeedBlockUpdate; blockMetadataUpdate?: IBlockMetadata; + slotFinalized?: SlotIndex; } diff --git a/client/src/services/nova/novaFeedClient.ts b/client/src/services/nova/novaFeedClient.ts index 159b570b7..fb6781487 100644 --- a/client/src/services/nova/novaFeedClient.ts +++ b/client/src/services/nova/novaFeedClient.ts @@ -1,4 +1,4 @@ -import { IBlockMetadata } from "@iota/sdk-wasm-nova/web"; +import { IBlockMetadata, SlotIndex } from "@iota/sdk-wasm-nova/web"; import { io, Socket } from "socket.io-client"; import { ServiceFactory } from "~/factories/serviceFactory"; import { IFeedSubscribeResponse } from "~/models/api/IFeedSubscribeResponse"; @@ -54,6 +54,7 @@ export class NovaFeedClient { public subscribeBlocks( onBlockDataCallback?: (blockData: IFeedBlockData) => void, onMetadataUpdatedCallback?: (blockMetadata: IBlockMetadata) => void, + onSlotFinalizedCallback?: (slotFinalized: SlotIndex) => void, ) { this.socket = io(this.endpoint, { upgrade: true, transports: ["websocket"] }); @@ -88,6 +89,10 @@ export class NovaFeedClient { if (update.blockMetadataUpdate) { onMetadataUpdatedCallback?.(update.blockMetadataUpdate); } + + if (update.slotFinalized) { + onSlotFinalizedCallback?.(update.slotFinalized); + } } }); diff --git a/setup_nova.sh b/setup_nova.sh index c0e6efecb..8edec1b3c 100755 --- a/setup_nova.sh +++ b/setup_nova.sh @@ -1,6 +1,6 @@ #!/bin/bash SDK_DIR="iota-sdk" -TARGET_COMMIT="7d32ae0bb7e93552618923fb272a5c1cc67c2c60" +TARGET_COMMIT="85e4a097fe5badebb57d01975264b3538d981687" if [ ! -d "$SDK_DIR" ]; then git clone -b 2.0 git@github.com:iotaledger/iota-sdk.git From 586aaad67600f230b7cb14eb5d2a16775a76cae9 Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Mon, 12 Feb 2024 13:44:31 +0100 Subject: [PATCH 2/6] chore: try to use the new sdk changes (wip) --- .../visualizer-threejs/VisualizerInstance.tsx | 27 +++++++++++++++++-- setup_nova.sh | 2 +- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/client/src/features/visualizer-threejs/VisualizerInstance.tsx b/client/src/features/visualizer-threejs/VisualizerInstance.tsx index 7d70ea4e1..f8627610f 100644 --- a/client/src/features/visualizer-threejs/VisualizerInstance.tsx +++ b/client/src/features/visualizer-threejs/VisualizerInstance.tsx @@ -27,10 +27,10 @@ import { Wrapper } from "./wrapper/Wrapper"; import { CanvasElement } from "./enums"; import { useGetThemeMode } from "~/helpers/hooks/useGetThemeMode"; import { TSelectFeedItemNova } from "~/app/types/visualizer.types"; -import { BasicBlockBody, BlockState, IBlockMetadata, SlotIndex } from "@iota/sdk-wasm-nova/web"; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { BasicBlockBody, BlockState, IBlockMetadata, SlotIndex, BlockId, IdWithSlotIndex } from "@iota/sdk-wasm-nova/web"; import { IFeedBlockData } from "~/models/api/nova/feed/IFeedBlockData"; import CameraControls from "./CameraControls"; -import { BlockId } from "@iota/sdk-wasm/web"; import { Converter } from "~/helpers/stardust/convertUtils"; import "./Visualizer.scss"; @@ -226,6 +226,12 @@ const VisualizerInstance: React.FC> = const acceptedStates: (BlockState | "accepted")[] = ["confirmed", "accepted"]; if (acceptedStates.includes(metadataUpdate.blockState)) { + // console.log({ blockId: new BlockId(metadataUpdate.blockId), copiedBlockId: new _BlockId(metadataUpdate.blockId) }); + // console.log("============================="); + // console.log({ + // slotIndex: new IdWithSlotIndex(metadataUpdate.blockId).slotIndex(), + // copiedSlotIndex: new _IdWithSlotIndex(metadataUpdate.blockId).slotIndex(), + // }); const slot = getSlotIndexFromBlockId(metadataUpdate.blockId); addToConfirmedBlocksSlot(metadataUpdate.blockId, slot); } @@ -319,3 +325,20 @@ const VisualizerInstance: React.FC> = }; export default VisualizerInstance; + +class _IdWithSlotIndex extends String { + slotIndex(): SlotIndex { + const numberString = super.slice(-8); + const chunks = []; + for (let i = 0, charsLength = numberString.length; i < charsLength; i += 2) { + chunks.push(numberString.substring(i, i + 2)); + } + const separated = chunks.map((n) => parseInt(n, 16)); + const buf = Uint8Array.from(separated).buffer; + const view = new DataView(buf); + return view.getUint32(0, true); + } +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +class _BlockId extends _IdWithSlotIndex {} diff --git a/setup_nova.sh b/setup_nova.sh index 8edec1b3c..c197e5b8f 100755 --- a/setup_nova.sh +++ b/setup_nova.sh @@ -1,6 +1,6 @@ #!/bin/bash SDK_DIR="iota-sdk" -TARGET_COMMIT="85e4a097fe5badebb57d01975264b3538d981687" +TARGET_COMMIT="7fb722c7079aaaab7ae51fad30c0ddf5215d9f6f" if [ ! -d "$SDK_DIR" ]; then git clone -b 2.0 git@github.com:iotaledger/iota-sdk.git From 9670dff6182508aa7db29784d9b55c252c104ab1 Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Wed, 14 Feb 2024 16:56:03 +0100 Subject: [PATCH 3/6] feat: use new sdk version --- .../visualizer-threejs/VisualizerInstance.tsx | 36 ++----------------- setup_nova.sh | 2 +- 2 files changed, 4 insertions(+), 34 deletions(-) diff --git a/client/src/features/visualizer-threejs/VisualizerInstance.tsx b/client/src/features/visualizer-threejs/VisualizerInstance.tsx index f8627610f..8b8d6c521 100644 --- a/client/src/features/visualizer-threejs/VisualizerInstance.tsx +++ b/client/src/features/visualizer-threejs/VisualizerInstance.tsx @@ -28,10 +28,9 @@ import { CanvasElement } from "./enums"; import { useGetThemeMode } from "~/helpers/hooks/useGetThemeMode"; import { TSelectFeedItemNova } from "~/app/types/visualizer.types"; // eslint-disable-next-line @typescript-eslint/no-unused-vars -import { BasicBlockBody, BlockState, IBlockMetadata, SlotIndex, BlockId, IdWithSlotIndex } from "@iota/sdk-wasm-nova/web"; +import { BasicBlockBody, Utils, type IBlockMetadata, type BlockState, type SlotIndex, type BlockId } from "@iota/sdk-wasm-nova/web"; import { IFeedBlockData } from "~/models/api/nova/feed/IFeedBlockData"; import CameraControls from "./CameraControls"; -import { Converter } from "~/helpers/stardust/convertUtils"; import "./Visualizer.scss"; const features = { @@ -223,16 +222,10 @@ const VisualizerInstance: React.FC> = addToColorQueue(metadataUpdate.blockId, selectedColor); } - const acceptedStates: (BlockState | "accepted")[] = ["confirmed", "accepted"]; + const acceptedStates: BlockState[] = ["confirmed", "accepted"]; if (acceptedStates.includes(metadataUpdate.blockState)) { - // console.log({ blockId: new BlockId(metadataUpdate.blockId), copiedBlockId: new _BlockId(metadataUpdate.blockId) }); - // console.log("============================="); - // console.log({ - // slotIndex: new IdWithSlotIndex(metadataUpdate.blockId).slotIndex(), - // copiedSlotIndex: new _IdWithSlotIndex(metadataUpdate.blockId).slotIndex(), - // }); - const slot = getSlotIndexFromBlockId(metadataUpdate.blockId); + const slot = Utils.computeSlotIndex(metadataUpdate.blockId); addToConfirmedBlocksSlot(metadataUpdate.blockId, slot); } } @@ -253,12 +246,6 @@ const VisualizerInstance: React.FC> = removeConfirmedBlocksSlot(slot); } - function getSlotIndexFromBlockId(blockId: BlockId): SlotIndex { - const hexalLittleEndian = blockId.slice(-8); - const hexalBigEndian = Converter.convertToBigEndian(hexalLittleEndian); - return Number.parseInt(hexalBigEndian, 16); - } - useEffect(() => { if (!runListeners) { return; @@ -325,20 +312,3 @@ const VisualizerInstance: React.FC> = }; export default VisualizerInstance; - -class _IdWithSlotIndex extends String { - slotIndex(): SlotIndex { - const numberString = super.slice(-8); - const chunks = []; - for (let i = 0, charsLength = numberString.length; i < charsLength; i += 2) { - chunks.push(numberString.substring(i, i + 2)); - } - const separated = chunks.map((n) => parseInt(n, 16)); - const buf = Uint8Array.from(separated).buffer; - const view = new DataView(buf); - return view.getUint32(0, true); - } -} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -class _BlockId extends _IdWithSlotIndex {} diff --git a/setup_nova.sh b/setup_nova.sh index c197e5b8f..3a84bcb80 100755 --- a/setup_nova.sh +++ b/setup_nova.sh @@ -1,6 +1,6 @@ #!/bin/bash SDK_DIR="iota-sdk" -TARGET_COMMIT="7fb722c7079aaaab7ae51fad30c0ddf5215d9f6f" +TARGET_COMMIT="8f0ff5e1e899a0d960ddfea09237739a88c3bcf1" if [ ! -d "$SDK_DIR" ]; then git clone -b 2.0 git@github.com:iotaledger/iota-sdk.git From 8d14829332f8c1596e951692841e4fae8bb4e8eb Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Wed, 14 Feb 2024 18:36:09 +0100 Subject: [PATCH 4/6] chore: remove duplicate useEffect --- .../visualizer-threejs/VisualizerInstance.tsx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/client/src/features/visualizer-threejs/VisualizerInstance.tsx b/client/src/features/visualizer-threejs/VisualizerInstance.tsx index dffbea9db..3d0b0fb53 100644 --- a/client/src/features/visualizer-threejs/VisualizerInstance.tsx +++ b/client/src/features/visualizer-threejs/VisualizerInstance.tsx @@ -171,17 +171,6 @@ const VisualizerInstance: React.FC> = }; }, [runListeners]); - useEffect(() => { - if (!runListeners) { - return; - } - setIsPlaying(true); - - return () => { - bpsCounter.stop(); - }; - }, [runListeners]); - const feedSubscriptionStart = () => { if (!feedService) { return; From 662d691bca5f070ddd2415206e1e73ac130e8fcf Mon Sep 17 00:00:00 2001 From: Mario Sarcevic Date: Fri, 16 Feb 2024 11:57:41 +0100 Subject: [PATCH 5/6] chore: Set the same SDK commit in nova CI as in setup_sdk_local --- .github/workflows/nova-build-temp.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nova-build-temp.yaml b/.github/workflows/nova-build-temp.yaml index f5d16f647..2508da903 100644 --- a/.github/workflows/nova-build-temp.yaml +++ b/.github/workflows/nova-build-temp.yaml @@ -6,7 +6,7 @@ on: TARGET_COMMIT: description: "Target Commit Hash for the SDK" required: false - default: "133f911b18191cda9099f1b4aeaf7d0022dfe0fb" + default: "8f0ff5e1e899a0d960ddfea09237739a88c3bcf1" environment: type: choice description: "Select the environment to deploy to" From 2cc8798c052c274cfea77cafb49c7216ab002e82 Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Fri, 16 Feb 2024 16:30:05 +0100 Subject: [PATCH 6/6] chore: improve error message and code comments --- api/src/services/nova/feed/novaFeed.ts | 2 +- client/src/features/visualizer-threejs/VisualizerInstance.tsx | 2 ++ client/src/features/visualizer-threejs/store/tangle.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/api/src/services/nova/feed/novaFeed.ts b/api/src/services/nova/feed/novaFeed.ts index 537f70521..1fc1a2447 100644 --- a/api/src/services/nova/feed/novaFeed.ts +++ b/api/src/services/nova/feed/novaFeed.ts @@ -125,7 +125,7 @@ export class NovaFeed { // eslint-disable-next-line no-void void this.broadcastBlock(update); } catch { - logger.error("[NovaFeed]: Failed broadcasting block-metadata downstream."); + logger.error("[NovaFeed]: Failed broadcasting finalized slot downstream."); } }); } diff --git a/client/src/features/visualizer-threejs/VisualizerInstance.tsx b/client/src/features/visualizer-threejs/VisualizerInstance.tsx index 3d0b0fb53..64a86fc0d 100644 --- a/client/src/features/visualizer-threejs/VisualizerInstance.tsx +++ b/client/src/features/visualizer-threejs/VisualizerInstance.tsx @@ -68,6 +68,8 @@ const VisualizerInstance: React.FC> = const blockMetadata = useTangleStore((s) => s.blockMetadata); const indexToBlockId = useTangleStore((s) => s.indexToBlockId); const clickedInstanceId = useTangleStore((s) => s.clickedInstanceId); + + // Confirmed or accepted blocks by slot const confirmedBlocksBySlot = useTangleStore((s) => s.confirmedBlocksBySlot); const addToConfirmedBlocksSlot = useTangleStore((s) => s.addToConfirmedBlocksBySlot); const removeConfirmedBlocksSlot = useTangleStore((s) => s.removeConfirmedBlocksSlot); diff --git a/client/src/features/visualizer-threejs/store/tangle.ts b/client/src/features/visualizer-threejs/store/tangle.ts index ad24c4260..9633cb195 100644 --- a/client/src/features/visualizer-threejs/store/tangle.ts +++ b/client/src/features/visualizer-threejs/store/tangle.ts @@ -66,7 +66,7 @@ interface TangleState { updateBlockIdToAnimationPosition: (updatedPositions: Map) => void; resetConfigState: () => void; - // Handle finalized blocks + // Confirmed/accepted blocks by slot confirmedBlocksBySlot: Map; addToConfirmedBlocksBySlot: (blockId: BlockId, slot: SlotIndex) => void; removeConfirmedBlocksSlot: (slot: SlotIndex) => void;