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

feat: mark finalized blocks #1096

Merged
merged 9 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/nova-build-temp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion api/src/models/api/nova/feed/IFeedUpdate.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -11,4 +11,5 @@ export interface IFeedUpdate {
subscriptionId: string;
blockUpdate?: IFeedBlockUpdate;
blockMetadataUpdate?: IBlockMetadata;
slotFinalized?: SlotIndex;
}
18 changes: 17 additions & 1 deletion api/src/services/nova/feed/novaFeed.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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<IFeedUpdate> = { slotFinalized };

// eslint-disable-next-line no-void
void this.broadcastBlock(update);
} catch {
logger.error("[NovaFeed]: Failed broadcasting finalized slot downstream.");
}
});
}

private parseMqttPayloadMessage<T>(cls: ClassConstructor<T>, serializedMessage: string): T {
Expand Down
32 changes: 30 additions & 2 deletions client/src/features/visualizer-threejs/VisualizerInstance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ 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";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
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 "./Visualizer.scss";
Expand Down Expand Up @@ -68,6 +69,11 @@ const VisualizerInstance: React.FC<RouteComponentProps<VisualizerRouteProps>> =
const indexToBlockId = useTangleStore((s) => s.indexToBlockId);
const clickedInstanceId = useTangleStore((s) => s.clickedInstanceId);

// Confirmed or accepted blocks by slot
const confirmedBlocksBySlot = useTangleStore((s) => s.confirmedBlocksBySlot);
begonaalvarezd marked this conversation as resolved.
Show resolved Hide resolved
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);

Expand Down Expand Up @@ -171,7 +177,7 @@ const VisualizerInstance: React.FC<RouteComponentProps<VisualizerRouteProps>> =
if (!feedService) {
return;
}
feedService.subscribeBlocks(onNewBlock, onBlockMetadataUpdate);
feedService.subscribeBlocks(onNewBlock, onBlockMetadataUpdate, onSlotFinalized);

bpsCounter.start();
};
Expand Down Expand Up @@ -239,7 +245,29 @@ const VisualizerInstance: React.FC<RouteComponentProps<VisualizerRouteProps>> =
if (selectedColor) {
addToColorQueue(metadataUpdate.blockId, selectedColor);
}

const acceptedStates: BlockState[] = ["confirmed", "accepted"];

if (acceptedStates.includes(metadataUpdate.blockState)) {
const slot = Utils.computeSlotIndex(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);
}

return (
Expand Down
35 changes: 35 additions & 0 deletions client/src/features/visualizer-threejs/store/tangle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -64,6 +65,11 @@ interface TangleState {

updateBlockIdToAnimationPosition: (updatedPositions: Map<string, IBlockInitPosition>) => void;
resetConfigState: () => void;

// Confirmed/accepted blocks by slot
confirmedBlocksBySlot: Map<number, string[]>;
addToConfirmedBlocksBySlot: (blockId: BlockId, slot: SlotIndex) => void;
removeConfirmedBlocksSlot: (slot: SlotIndex) => void;
}

const INITIAL_STATE = {
Expand All @@ -79,6 +85,7 @@ const INITIAL_STATE = {
zoom: ZOOM_DEFAULT,
bps: 0,
clickedInstanceId: null,
confirmedBlocksBySlot: new Map(),
};

export const useTangleStore = create<TangleState>()(
Expand Down Expand Up @@ -204,5 +211,33 @@ export const useTangleStore = create<TangleState>()(
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);
}
}
VmMad marked this conversation as resolved.
Show resolved Hide resolved

return {
...state,
confirmedBlocksBySlot: state.confirmedBlocksBySlot,
};
});
},
})),
);
3 changes: 2 additions & 1 deletion client/src/models/api/nova/feed/IFeedUpdate.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,4 +9,5 @@ export interface IFeedUpdate {
subscriptionId: string;
blockUpdate?: IFeedBlockUpdate;
blockMetadataUpdate?: IBlockMetadata;
slotFinalized?: SlotIndex;
}
7 changes: 6 additions & 1 deletion client/src/services/nova/novaFeedClient.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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"] });

Expand Down Expand Up @@ -88,6 +89,10 @@ export class NovaFeedClient {
if (update.blockMetadataUpdate) {
onMetadataUpdatedCallback?.(update.blockMetadataUpdate);
}

if (update.slotFinalized) {
onSlotFinalizedCallback?.(update.slotFinalized);
}
}
});

Expand Down
2 changes: 1 addition & 1 deletion setup_nova.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
SDK_DIR="iota-sdk"
TARGET_COMMIT="133f911b18191cda9099f1b4aeaf7d0022dfe0fb"
TARGET_COMMIT="8f0ff5e1e899a0d960ddfea09237739a88c3bcf1"

if [ ! -d "$SDK_DIR" ]; then
git clone -b 2.0 [email protected]:iotaledger/iota-sdk.git
Expand Down
Loading