From c62af037974bd23f7438de1c76431c25a8c4c382 Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:27:02 +0000 Subject: [PATCH 1/8] Add in code to extract event from protocol result --- .../production/sequencing/TransactionExecutionService.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index 922826e44..ef3682db8 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -281,6 +281,7 @@ export class TransactionExecutionService { // Reset proofs enabled appChain.setProofsEnabled(previousProofsEnabled); + const protocolHookEvents = extractEvents(protocolResult); const events = extractEvents(runtimeResult); return { @@ -296,7 +297,7 @@ export class TransactionExecutionService { UntypedStateTransition.fromStateTransition(st) ), - events, + events: { ...events, ...protocolHookEvents }, }; } } From b1b02cb004cdd69ca879661ea91a5a127504ead5 Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Thu, 13 Feb 2025 14:53:58 +0000 Subject: [PATCH 2/8] Add in comment --- .../production/sequencing/TransactionExecutionService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index d2a2875ba..8e9a9b388 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -32,6 +32,7 @@ import { toEventsHash, toStateTransitionsHash, } from "@proto-kit/module"; +// eslint-disable-next-line import/no-extraneous-dependencies import zip from "lodash/zip"; import { PendingTransaction } from "../../../mempool/PendingTransaction"; From b1c8a41ab798517b30a57286f1fcb51599838dab Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Thu, 13 Feb 2025 15:08:34 +0000 Subject: [PATCH 3/8] Add in comment --- .../production/sequencing/TransactionExecutionService.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index 8e9a9b388..2e17c7b02 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -396,11 +396,7 @@ export class TransactionExecutionService { statusMessage: runtimeResult.statusMessage, stateTransitions, - events: { - ...beforeHookEvents, - ...afterHookEvents, - ...runtimeResultEvents, - }, + events: beforeHookEvents.concat(afterHookEvents, runtimeResultEvents), }, ]; } From 4a0d34d3c9493967167831c3c0e2c86f391b790a Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Thu, 13 Feb 2025 16:21:55 +0000 Subject: [PATCH 4/8] Add in source to event --- .../sequencing/TransactionExecutionService.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index 2e17c7b02..355e0579d 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -111,7 +111,8 @@ async function decodeTransaction( } function extractEvents( - runtimeResult: RuntimeContextReducedExecutionResult + runtimeResult: RuntimeContextReducedExecutionResult, + source: string ): { eventName: string; data: Field[] }[] { return runtimeResult.events.reduce( (acc, event) => { @@ -120,13 +121,14 @@ function extractEvents( eventName: event.eventName, // eslint-disable-next-line @typescript-eslint/no-unsafe-argument data: event.eventType.toFields(event.event), + source: source, }; acc.push(obj); } return acc; }, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - [] as { eventName: string; data: Field[] }[] + [] as { eventName: string; data: Field[]; source: string }[] ); } @@ -314,7 +316,7 @@ export class TransactionExecutionService { async (hook, hookArgs) => await hook.beforeTransaction(hookArgs), "beforeTx" ); - const beforeHookEvents = extractEvents(beforeTxHookResult); + const beforeHookEvents = extractEvents(beforeTxHookResult, "beforeTxHook"); await recordingStateService.applyStateTransitions( beforeTxHookResult.stateTransitions @@ -364,7 +366,7 @@ export class TransactionExecutionService { async (hook, hookArgs) => await hook.afterTransaction(hookArgs), "afterTx" ); - const afterHookEvents = extractEvents(afterTxHookResult); + const afterHookEvents = extractEvents(afterTxHookResult, "afterTxHook"); await recordingStateService.applyStateTransitions( afterTxHookResult.stateTransitions ); @@ -378,7 +380,7 @@ export class TransactionExecutionService { appChain.setProofsEnabled(previousProofsEnabled); // Extract sequencing results - const runtimeResultEvents = extractEvents(runtimeResult); + const runtimeResultEvents = extractEvents(runtimeResult, "runtime"); const stateTransitions = this.buildSTBatches( [ beforeTxHookResult.stateTransitions, From ea17cbbdc7e5ca897fa014f963b6c2a027b70521 Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Thu, 13 Feb 2025 16:48:01 +0000 Subject: [PATCH 5/8] Update mappers and make type narrow --- .../services/prisma/mappers/EventMapper.ts | 52 ++++++++++++++++--- .../sequencing/TransactionExecutionService.ts | 14 +++-- packages/sequencer/src/storage/model/Block.ts | 6 ++- 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/packages/persistance/src/services/prisma/mappers/EventMapper.ts b/packages/persistance/src/services/prisma/mappers/EventMapper.ts index 10d1488fc..e2cc97d10 100644 --- a/packages/persistance/src/services/prisma/mappers/EventMapper.ts +++ b/packages/persistance/src/services/prisma/mappers/EventMapper.ts @@ -7,42 +7,74 @@ import { ObjectMapper } from "../../../ObjectMapper"; @singleton() export class EventMapper implements - ObjectMapper<{ eventName: string; data: Field[] }, Prisma.JsonObject> + ObjectMapper< + { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; + }, + Prisma.JsonObject + > { - public mapIn(input: Prisma.JsonObject): { eventName: string; data: Field[] } { - if (input === undefined) return { eventName: "", data: [] }; + public mapIn(input: Prisma.JsonObject): { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; + } { + if (input === undefined) + return { eventName: "", data: [], source: "runtime" }; return { eventName: input.eventName as string, data: (input.data as Prisma.JsonArray).map((field) => Field.fromJSON(field as string) ), + source: this.sourceConvert(input.source as string), }; } public mapOut(input: { eventName: string; data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; }): Prisma.JsonObject { return { eventName: input.eventName, data: input.data.map((field) => field.toString()), + source: input.source, } as Prisma.JsonObject; } + + private sourceConvert(input: string) { + if ( + input === "beforeTxHook" || + input === "afterTxHook" || + input === "runtime" + ) { + return input; + } + throw new Error(); + } } @singleton() export class EventArrayMapper implements ObjectMapper< - { eventName: string; data: Field[] }[], + { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; + }[], Prisma.JsonValue | undefined > { public constructor(private readonly eventMapper: EventMapper) {} - public mapIn( - input: Prisma.JsonValue | undefined - ): { eventName: string; data: Field[] }[] { + public mapIn(input: Prisma.JsonValue | undefined): { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; + }[] { if (input === undefined) return []; if (Array.isArray(input)) { @@ -54,7 +86,11 @@ export class EventArrayMapper } public mapOut( - input: { eventName: string; data: Field[] }[] + input: { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; + }[] ): Prisma.JsonValue { return input.map((event) => this.eventMapper.mapOut(event) diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index 355e0579d..06effedfd 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -112,8 +112,12 @@ async function decodeTransaction( function extractEvents( runtimeResult: RuntimeContextReducedExecutionResult, - source: string -): { eventName: string; data: Field[] }[] { + source: "afterTxHook" | "beforeTxHook" | "runtime" +): { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; +}[] { return runtimeResult.events.reduce( (acc, event) => { if (event.condition.toBoolean()) { @@ -128,7 +132,11 @@ function extractEvents( return acc; }, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - [] as { eventName: string; data: Field[]; source: string }[] + [] as { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; + }[] ); } diff --git a/packages/sequencer/src/storage/model/Block.ts b/packages/sequencer/src/storage/model/Block.ts index 8f1da00a4..823b3c8c6 100644 --- a/packages/sequencer/src/storage/model/Block.ts +++ b/packages/sequencer/src/storage/model/Block.ts @@ -20,7 +20,11 @@ export interface TransactionExecutionResult { stateTransitions: StateTransitionBatch[]; status: Bool; statusMessage?: string; - events: { eventName: string; data: Field[] }[]; + events: { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; + }[]; } // TODO Why is Block using Fields, but BlockResult bigints? Align that towards the best option From 576f1161ffe0770ecc39273559121dc875ea5c85 Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Fri, 14 Feb 2025 08:20:18 +0000 Subject: [PATCH 6/8] Get BlockProduction.test.ts working with new event --- packages/sequencer/test/integration/BlockProduction.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/sequencer/test/integration/BlockProduction.test.ts b/packages/sequencer/test/integration/BlockProduction.test.ts index 644427239..b24a6a732 100644 --- a/packages/sequencer/test/integration/BlockProduction.test.ts +++ b/packages/sequencer/test/integration/BlockProduction.test.ts @@ -684,11 +684,13 @@ describe("block production", () => { const firstEventReduced = { eventName: firstExpectedEvent.eventName, data: firstExpectedEvent.eventType.toFields(firstExpectedEvent.event), + source: "runtime", }; const secondEventReduced = { eventName: secondExpectedEvent.eventName, data: secondExpectedEvent.eventType.toFields(secondExpectedEvent.event), + source: "runtime", }; const block = await test.produceBlock(); From 57485088c114ca042b9ea2556c785e3e483f0e68 Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Fri, 14 Feb 2025 08:39:01 +0000 Subject: [PATCH 7/8] Update error for conversion of source. --- .../persistance/src/services/prisma/mappers/EventMapper.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/persistance/src/services/prisma/mappers/EventMapper.ts b/packages/persistance/src/services/prisma/mappers/EventMapper.ts index e2cc97d10..84e5cbaf3 100644 --- a/packages/persistance/src/services/prisma/mappers/EventMapper.ts +++ b/packages/persistance/src/services/prisma/mappers/EventMapper.ts @@ -52,7 +52,9 @@ export class EventMapper ) { return input; } - throw new Error(); + throw new Error( + "Event Source must be one of 'beforeTxHook', 'afterTxHook' or 'runtime'" + ); } } From 6bfbc510b3654968b92485322e33ac6181340365 Mon Sep 17 00:00:00 2001 From: ejMina226 <118474890+ejMina226@users.noreply.github.com> Date: Mon, 17 Feb 2025 07:35:29 +0000 Subject: [PATCH 8/8] Code-review changes --- .../services/prisma/mappers/EventMapper.ts | 56 ++++--------------- .../sequencing/TransactionExecutionService.ts | 2 +- 2 files changed, 13 insertions(+), 45 deletions(-) diff --git a/packages/persistance/src/services/prisma/mappers/EventMapper.ts b/packages/persistance/src/services/prisma/mappers/EventMapper.ts index 84e5cbaf3..b56416a87 100644 --- a/packages/persistance/src/services/prisma/mappers/EventMapper.ts +++ b/packages/persistance/src/services/prisma/mappers/EventMapper.ts @@ -4,25 +4,15 @@ import { Field } from "o1js"; import { ObjectMapper } from "../../../ObjectMapper"; +type EventData = { + eventName: string; + data: Field[]; + source: "afterTxHook" | "beforeTxHook" | "runtime"; +}; + @singleton() -export class EventMapper - implements - ObjectMapper< - { - eventName: string; - data: Field[]; - source: "afterTxHook" | "beforeTxHook" | "runtime"; - }, - Prisma.JsonObject - > -{ - public mapIn(input: Prisma.JsonObject): { - eventName: string; - data: Field[]; - source: "afterTxHook" | "beforeTxHook" | "runtime"; - } { - if (input === undefined) - return { eventName: "", data: [], source: "runtime" }; +export class EventMapper implements ObjectMapper { + public mapIn(input: Prisma.JsonObject): EventData { return { eventName: input.eventName as string, data: (input.data as Prisma.JsonArray).map((field) => @@ -32,11 +22,7 @@ export class EventMapper }; } - public mapOut(input: { - eventName: string; - data: Field[]; - source: "afterTxHook" | "beforeTxHook" | "runtime"; - }): Prisma.JsonObject { + public mapOut(input: EventData): Prisma.JsonObject { return { eventName: input.eventName, data: input.data.map((field) => field.toString()), @@ -60,23 +46,11 @@ export class EventMapper @singleton() export class EventArrayMapper - implements - ObjectMapper< - { - eventName: string; - data: Field[]; - source: "afterTxHook" | "beforeTxHook" | "runtime"; - }[], - Prisma.JsonValue | undefined - > + implements ObjectMapper { public constructor(private readonly eventMapper: EventMapper) {} - public mapIn(input: Prisma.JsonValue | undefined): { - eventName: string; - data: Field[]; - source: "afterTxHook" | "beforeTxHook" | "runtime"; - }[] { + public mapIn(input: Prisma.JsonValue | undefined): EventData[] { if (input === undefined) return []; if (Array.isArray(input)) { @@ -87,13 +61,7 @@ export class EventArrayMapper return []; } - public mapOut( - input: { - eventName: string; - data: Field[]; - source: "afterTxHook" | "beforeTxHook" | "runtime"; - }[] - ): Prisma.JsonValue { + public mapOut(input: EventData[]): Prisma.JsonValue { return input.map((event) => this.eventMapper.mapOut(event) ) as Prisma.JsonArray; diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index 06effedfd..8073d7507 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -406,7 +406,7 @@ export class TransactionExecutionService { statusMessage: runtimeResult.statusMessage, stateTransitions, - events: beforeHookEvents.concat(afterHookEvents, runtimeResultEvents), + events: beforeHookEvents.concat(runtimeResultEvents, afterHookEvents), }, ]; }