diff --git a/packages/api/src/graphql/modules/BlockResolver.ts b/packages/api/src/graphql/modules/BlockResolver.ts index 036184873..5313b0d39 100644 --- a/packages/api/src/graphql/modules/BlockResolver.ts +++ b/packages/api/src/graphql/modules/BlockResolver.ts @@ -10,17 +10,17 @@ import { BatchTransactionModel } from "./model/BatchTransactionModel"; export class BlockModel { public static fromServiceLayerModel(block: Block) { return new BlockModel( - Number(block.networkState.during.block.height.toBigInt()), + Number(block.networkState.during.block.height), block.transactions.map((tx) => BatchTransactionModel.fromServiceLayerModel({ tx: tx.tx, - status: tx.status.toBoolean(), + status: tx.status, statusMessage: tx.statusMessage, }) ), - block.transactionsHash.toString(), - block.hash.toString(), - block.previousBlockHash?.toString() + block.transactionsHash, + block.hash, + block.previousBlockHash ); } diff --git a/packages/api/src/graphql/modules/MempoolResolver.ts b/packages/api/src/graphql/modules/MempoolResolver.ts index 034eee651..0d97b618a 100644 --- a/packages/api/src/graphql/modules/MempoolResolver.ts +++ b/packages/api/src/graphql/modules/MempoolResolver.ts @@ -49,7 +49,7 @@ export class TransactionObject { isMessage, } = pt.toJSON(); return new TransactionObject( - pt.hash().toString(), + pt.hash, methodId, sender, nonce, @@ -128,7 +128,7 @@ export class MempoolResolver extends GraphqlModule { const decoded = PendingTransaction.fromJSON(tx); await this.mempool.add(decoded); - return decoded.hash().toString(); + return decoded.hash; } // TODO Add retrieval of pending messages somewhere as well @@ -162,6 +162,6 @@ export class MempoolResolver extends GraphqlModule { }) public async transactions() { const txs = await this.transactionStorage.getPendingUserTransactions(); - return txs.map((x) => x.hash().toString()); + return txs.map((x) => x.hash); } } diff --git a/packages/api/src/graphql/modules/QueryGraphqlModule.ts b/packages/api/src/graphql/modules/QueryGraphqlModule.ts index c7c427939..a645b3535 100644 --- a/packages/api/src/graphql/modules/QueryGraphqlModule.ts +++ b/packages/api/src/graphql/modules/QueryGraphqlModule.ts @@ -24,7 +24,7 @@ import { } from "@proto-kit/module"; import { MandatoryProtocolModulesRecord, - NetworkState, + ProvableNetworkState, Protocol, ProtocolModulesRecord, State, @@ -385,7 +385,7 @@ export class QueryGraphqlModule< this.networkStateTransportModule ); const networkType = this.flexiblePureToGraphql( - NetworkState, + ProvableNetworkState, "Network", this.jsonToGraphQl.bind(this) ); diff --git a/packages/api/src/metrics/SequencerInstrumentation.ts b/packages/api/src/metrics/SequencerInstrumentation.ts index 846daf704..491a74912 100644 --- a/packages/api/src/metrics/SequencerInstrumentation.ts +++ b/packages/api/src/metrics/SequencerInstrumentation.ts @@ -15,7 +15,7 @@ export class SequencerInstrumentation extends InstrumentationBase<{}> { super("protokit", "canary", {}); if (trigger !== undefined) { trigger.events.on("block-produced", (block) => { - this.blockProduced(parseInt(block.height.toString(), 10)); + this.blockProduced(block.height); }); } } diff --git a/packages/common/src/utils.ts b/packages/common/src/utils.ts index 0576aacb5..0cca60cee 100644 --- a/packages/common/src/utils.ts +++ b/packages/common/src/utils.ts @@ -295,3 +295,17 @@ export function assertDefined( throw new Error(msg ?? "Value is undefined"); } } + +/** + * Type for serialized {@link Field}. + */ +export type FieldString = string; +/** + * + * @param value Value to be converted to {@link Field}. + * @returns + */ +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const FieldString = ( + value: number | string | bigint | Field +): FieldString => String(value); diff --git a/packages/indexer/src/IndexerNotifier.ts b/packages/indexer/src/IndexerNotifier.ts index 5f6816f8b..651249b7b 100644 --- a/packages/indexer/src/IndexerNotifier.ts +++ b/packages/indexer/src/IndexerNotifier.ts @@ -48,10 +48,7 @@ export class IndexerNotifier extends SequencerModule> { this.indexSettlementTask.inputSerializer(); this.sequencer.events.on("block-metadata-produced", async (block) => { - log.debug( - "Notifiying the indexer about block", - block.block.height.toBigInt() - ); + log.debug("Notifiying the indexer about block", block.block.height); const payload = await inputSerializer.toJSON(block); const sequencerId = this.sequencerIdProvider.getSequencerId(); @@ -69,6 +66,7 @@ export class IndexerNotifier extends SequencerModule> { const txQueue = await this.taskQueue.getQueue( this.indexPendingTxTask.name ); + // This part seems weird const payload = await txInputSerializer.toJSON(tx); const sequencerId = this.sequencerIdProvider.getSequencerId(); diff --git a/packages/indexer/src/tasks/IndexBlockTask.ts b/packages/indexer/src/tasks/IndexBlockTask.ts index 96d92677c..956ec5840 100644 --- a/packages/indexer/src/tasks/IndexBlockTask.ts +++ b/packages/indexer/src/tasks/IndexBlockTask.ts @@ -1,5 +1,6 @@ import { BlockQueue, + JSONTaskSerializer, Task, TaskSerializer, TaskWorkerModule, @@ -7,10 +8,7 @@ import { import { log } from "@proto-kit/common"; import { inject, injectable } from "tsyringe"; -import { - IndexBlockTaskParameters, - IndexBlockTaskParametersSerializer, -} from "./IndexBlockTaskParameters"; +import { IndexBlockTaskParameters } from "./IndexBlockTaskParameters"; @injectable() export class IndexBlockTask @@ -20,7 +18,6 @@ export class IndexBlockTask public name = "index-block"; public constructor( - public taskSerializer: IndexBlockTaskParametersSerializer, @inject("BlockQueue") public blockStorage: BlockQueue ) { @@ -37,16 +34,15 @@ export class IndexBlockTask await this.blockStorage.pushBlock(input.block); await this.blockStorage.pushResult(input.result); } catch (error) { - log.error("Failed to index block", input.block.height.toBigInt(), error); - return undefined; + log.error("Failed to index block", input.block.height, error); + return; } - log.info(`Block ${input.block.height.toBigInt()} indexed sucessfully`); - return ""; + log.info(`Block ${input.block.height} indexed sucessfully`); } public inputSerializer(): TaskSerializer { - return this.taskSerializer; + return JSONTaskSerializer.fromType(); } public resultSerializer(): TaskSerializer { diff --git a/packages/indexer/src/tasks/IndexPendingTxTask.ts b/packages/indexer/src/tasks/IndexPendingTxTask.ts index db468660d..5022ddf17 100644 --- a/packages/indexer/src/tasks/IndexPendingTxTask.ts +++ b/packages/indexer/src/tasks/IndexPendingTxTask.ts @@ -1,4 +1,5 @@ import { + JSONTaskSerializer, PendingTransaction, Task, TaskSerializer, @@ -8,8 +9,6 @@ import { import { log } from "@proto-kit/common"; import { inject, injectable } from "tsyringe"; -import { IndexPendingTxTaskParametersSerializer } from "./IndexPendingTxTaskParameters"; - @injectable() export class IndexPendingTxTask extends TaskWorkerModule @@ -18,7 +17,6 @@ export class IndexPendingTxTask public name = "index-pending-tx"; public constructor( - public taskSerializer: IndexPendingTxTaskParametersSerializer, @inject("TransactionStorage") public transactionStorage: TransactionStorage ) { @@ -39,7 +37,7 @@ export class IndexPendingTxTask } public inputSerializer(): TaskSerializer { - return this.taskSerializer; + return JSONTaskSerializer.fromType(); } public resultSerializer(): TaskSerializer { diff --git a/packages/indexer/src/tasks/IndexPendingTxTaskParameters.ts b/packages/indexer/src/tasks/IndexPendingTxTaskParameters.ts deleted file mode 100644 index 5c60be517..000000000 --- a/packages/indexer/src/tasks/IndexPendingTxTaskParameters.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { PendingTransaction } from "@proto-kit/sequencer"; -import { TransactionMapper } from "@proto-kit/persistance"; -import { injectable } from "tsyringe"; - -@injectable() -export class IndexPendingTxTaskParametersSerializer { - public constructor(public transactionMapper: TransactionMapper) {} - - public toJSON(parameters: PendingTransaction): string { - return JSON.stringify({ - tx: this.transactionMapper.mapOut(parameters), - }); - } - - public fromJSON(json: string): PendingTransaction { - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - const parsed = JSON.parse(json) as { - tx: ReturnType; - }; - return this.transactionMapper.mapIn(parsed.tx); - } -} diff --git a/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts b/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts index 3ef0ffe06..9f24d049d 100644 --- a/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts +++ b/packages/indexer/test/GeneratedResolverFactoryGraphqlModule.test.ts @@ -8,7 +8,7 @@ import { log } from "@proto-kit/common"; import { jest } from "@jest/globals"; import { Indexer } from "../src/Indexer"; -import { GeneratedResolverFactoryGraphqlModule } from "../src/api/GeneratedResolverFactoryGraphqlModule"; +import { GeneratedResolverFactoryGraphqlModule } from "../src"; log.setLevel("info"); diff --git a/packages/indexer/test/IndexBlockTask.test.ts b/packages/indexer/test/IndexBlockTask.test.ts index b5432e5a3..47213f251 100644 --- a/packages/indexer/test/IndexBlockTask.test.ts +++ b/packages/indexer/test/IndexBlockTask.test.ts @@ -54,8 +54,6 @@ describe("IndexBlockTask", () => { const storage = indexer.resolve("BlockStorage"); const latestBlock = await storage.getLatestBlock(); - expect(latestBlock?.block.hash.toBigInt()).toBe( - block.block.hash.toBigInt() - ); + expect(latestBlock?.block.hash).toBe(block.block.hash); }); }); diff --git a/packages/indexer/test/IndexerNotifier.test.ts b/packages/indexer/test/IndexerNotifier.test.ts index 31ab57210..914ebb3c3 100644 --- a/packages/indexer/test/IndexerNotifier.test.ts +++ b/packages/indexer/test/IndexerNotifier.test.ts @@ -21,13 +21,15 @@ import { TestingAppChain, } from "@proto-kit/sdk"; import { + JSONTaskSerializer, LocalTaskQueue, + PendingTransaction, Sequencer, TaskPayload, VanillaTaskWorkerModules, } from "@proto-kit/sequencer"; -import { IndexerNotifier, IndexBlockTaskParametersSerializer } from "../src"; +import { IndexerNotifier, IndexBlockTaskParameters } from "../src"; class TestBalances extends Balances { @runtimeMethod() @@ -130,7 +132,7 @@ async function sendTransactions( { nonce: i } ); - console.log("tx nonce", tx.transaction?.nonce.toBigInt()); + console.log("tx nonce", (tx.transaction as PendingTransaction).nonce); await tx.sign(); await tx.send(); @@ -141,7 +143,7 @@ async function sendTransactions( const txs = await mempool.getTxs(); console.log( "txs", - txs.map((tx) => tx.nonce.toBigInt()) + txs.map((tx) => tx.nonce) ); return await appChain.produceBlock(); @@ -179,11 +181,13 @@ describe.skip("IndexerNotifier", () => { }, 20000); it("should create a task for every unproven block produced", async () => { - const { block } = container - .resolve(IndexBlockTaskParametersSerializer) - .fromJSON(addTaskSpy.mock.lastCall?.[0].payload!); + const serializer = JSONTaskSerializer.fromType(); - expect(block.height.toBigInt()).toBe(0n); + const { block } = await serializer.fromJSON( + addTaskSpy.mock.lastCall?.[0].payload! + ); + + expect(block.height).toBe(0); expect(block.transactions.length).toBe(2); }); }); diff --git a/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts b/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts index 707d80a4c..351b273fc 100644 --- a/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts +++ b/packages/library/src/hooks/RuntimeFeeAnalyzerService.ts @@ -8,7 +8,7 @@ import { container, inject } from "tsyringe"; import { RuntimeMethodExecutionContext, RuntimeTransaction, - NetworkState, + ProvableNetworkState, } from "@proto-kit/protocol"; import { Field, Poseidon, Struct } from "o1js"; @@ -77,7 +77,7 @@ export class RuntimeFeeAnalyzerService extends ConfigurableModule { const feeConfig = Provable.witness(MethodFeeConfigData, () => this.feeAnalyzer.getFeeConfig( - executionData.transaction.methodId.toBigInt() + executionData.transaction.methodId.toString() ) ); const witness = Provable.witness( RuntimeFeeAnalyzerService.getWitnessType(), () => this.feeAnalyzer.getWitness( - executionData.transaction.methodId.toBigInt() + executionData.transaction.methodId.toString() ) ); @@ -167,7 +167,7 @@ export class TransactionFeeHook extends ProvableTransactionHook { const feeConfig = this.feeAnalyzer.getFeeConfig( - args.transaction.methodId.toBigInt() + args.transaction.methodId.toString() ); const fee = this.getFee(feeConfig); diff --git a/packages/library/test/math/State.test.ts b/packages/library/test/math/State.test.ts index 369fc78b1..e76166761 100644 --- a/packages/library/test/math/State.test.ts +++ b/packages/library/test/math/State.test.ts @@ -4,7 +4,7 @@ import { StateServiceProvider, RuntimeMethodExecutionContext, RuntimeTransaction, - NetworkState, + ProvableNetworkState, } from "@proto-kit/protocol"; import { UInt64, Field } from "o1js"; import { InMemoryStateService } from "@proto-kit/module"; @@ -24,7 +24,7 @@ describe("interop uint <-> state", () => { const context = container.resolve(RuntimeMethodExecutionContext); context.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); const uint = await state.get(); diff --git a/packages/module/src/method/MethodParameterEncoder.ts b/packages/module/src/method/MethodParameterEncoder.ts index 691e0d6b2..83fa21c23 100644 --- a/packages/module/src/method/MethodParameterEncoder.ts +++ b/packages/module/src/method/MethodParameterEncoder.ts @@ -128,7 +128,7 @@ export class MethodParameterEncoder { public constructor(private readonly types: ArgTypeArray) {} - public decode(fields: Field[], auxiliary: string[]): Promise { + public decode(fields: string[], auxiliary: string[]): Promise { if (fields.length < this.fieldSize()) { throw errors.fieldLengthNotMatching(this.fieldSize(), fields.length); } @@ -155,12 +155,8 @@ export class MethodParameterEncoder { const inputFieldSize = MethodParameterEncoder.fieldSize( type.publicInputType )!; - const input = structFields - .slice(0, inputFieldSize) - .map((x) => x.toString()); - const output = structFields - .slice(inputFieldSize) - .map((x) => x.toString()); + const input = structFields.slice(0, inputFieldSize); + const output = structFields.slice(inputFieldSize); // fromJSON has incompatible signature for Proof and DynamicProof if (isProofType(type)) { @@ -180,7 +176,7 @@ export class MethodParameterEncoder { } return (type as FlexibleProvable).fromFields( - structFields, + structFields.map(Field), [] ) as any; }) diff --git a/packages/module/src/runtime/MethodIdResolver.ts b/packages/module/src/runtime/MethodIdResolver.ts index b7233b61e..9e4865da6 100644 --- a/packages/module/src/runtime/MethodIdResolver.ts +++ b/packages/module/src/runtime/MethodIdResolver.ts @@ -29,7 +29,7 @@ export class MethodIdResolver { this.runtime.assertIsValidModuleName(moduleName); runtime.resolve(moduleName).runtimeMethodNames.forEach((methodName) => { - dict[this.getMethodId(moduleName, methodName).toString()] = { + dict[this.getMethodId(moduleName, methodName)] = { moduleName, methodName, }; @@ -83,8 +83,8 @@ export class MethodIdResolver { }, {}); } - public getMethodNameFromId(methodId: bigint): [string, string] | undefined { - const methodPath = this.dictionary[methodId.toString()]; + public getMethodNameFromId(methodId: string): [string, string] | undefined { + const methodPath = this.dictionary[methodId]; if (methodPath === undefined) { return undefined; @@ -97,12 +97,12 @@ export class MethodIdResolver { return [moduleName, methodName]; } - public getMethodId(moduleName: string, methodName: string): bigint { + public getMethodId(moduleName: string, methodName: string): string { this.runtime.assertIsValidModuleName(moduleName); return Poseidon.hash([ stringToField(moduleName), stringToField(methodName), - ]).toBigInt(); + ]).toString(); } } diff --git a/packages/module/src/runtime/Runtime.ts b/packages/module/src/runtime/Runtime.ts index 37bd65e7c..27822b80b 100644 --- a/packages/module/src/runtime/Runtime.ts +++ b/packages/module/src/runtime/Runtime.ts @@ -19,7 +19,7 @@ import { SimpleAsyncStateService, RuntimeMethodExecutionContext, RuntimeTransaction, - NetworkState, + ProvableNetworkState, } from "@proto-kit/protocol"; import { @@ -337,7 +337,7 @@ export class Runtime * Encoding: "stringToField(module.name) << 128 + stringToField(method-name)" */ public getMethodById( - methodId: bigint + methodId: string ): ((...args: unknown[]) => Promise) | undefined { const methodDescriptor = this.methodIdResolver.getMethodNameFromId(methodId); @@ -388,7 +388,7 @@ export class Runtime const context = container.resolve(RuntimeMethodExecutionContext); context.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); return await this.zkProgrammable.compile(registry); } diff --git a/packages/module/src/runtime/RuntimeModule.ts b/packages/module/src/runtime/RuntimeModule.ts index 7267e4c60..d7b4793c9 100644 --- a/packages/module/src/runtime/RuntimeModule.ts +++ b/packages/module/src/runtime/RuntimeModule.ts @@ -1,7 +1,7 @@ import { ConfigurableModule, NoConfig, Presets } from "@proto-kit/common"; import { container, injectable } from "tsyringe"; import { - NetworkState, + ProvableNetworkState, RuntimeTransaction, RuntimeMethodExecutionContext, RuntimeMethodExecutionData, @@ -112,7 +112,7 @@ export class RuntimeModule< return this.getInputs().transaction; } - public get network(): NetworkState { + public get network(): ProvableNetworkState { return this.getInputs().networkState; } } diff --git a/packages/module/test/Runtime.test.ts b/packages/module/test/Runtime.test.ts index 28ba7f24e..58d45dcf2 100644 --- a/packages/module/test/Runtime.test.ts +++ b/packages/module/test/Runtime.test.ts @@ -10,7 +10,7 @@ describe("noop", () => { // import { // RuntimeMethodExecutionContext, // RuntimeTransaction, -// NetworkState, +// ProvableNetworkState, // } from "@proto-kit/protocol"; // // import { MethodIdResolver } from "../src"; @@ -62,7 +62,7 @@ describe("noop", () => { // const context = container.resolve(RuntimeMethodExecutionContext); // context.setup({ // transaction: RuntimeTransaction.dummyTransaction(), -// networkState: NetworkState.empty(), +// networkState: ProvableNetworkState.empty(), // }); // // await runtime.zkProgrammable.zkProgram.analyzeMethods(); diff --git a/packages/module/test/method/MethodParameterEncoder.test.ts b/packages/module/test/method/MethodParameterEncoder.test.ts index 9f4bb5c05..65a8ab938 100644 --- a/packages/module/test/method/MethodParameterEncoder.test.ts +++ b/packages/module/test/method/MethodParameterEncoder.test.ts @@ -1,3 +1,4 @@ +import "reflect-metadata"; import { Struct, Field, @@ -50,7 +51,8 @@ describe("MethodParameterEncoder", () => { expect(fields[0].toString()).toBe("2"); expect(fields[1].toString()).toStrictEqual(Bool(true).toField().toString()); - const decoded = await encoder.decode(fields, auxiliary); + const fieldString = fields.map((field) => field.toString()); + const decoded = await encoder.decode(fieldString, auxiliary); expect(decoded).toHaveLength(1); const decoded1 = decoded[0] as unknown as NonMethods; expect(decoded1.a.toString()).toStrictEqual("2"); @@ -70,8 +72,8 @@ describe("MethodParameterEncoder", () => { expect(fields.map((x) => x.toString())).toStrictEqual( pk.toFields().map((x) => x.toString()) ); - - const decoded = await encoder.decode(fields, auxiliary); + const fieldString = fields.map((field) => field.toString()); + const decoded = await encoder.decode(fieldString, auxiliary); expect(decoded).toHaveLength(1); const decoded1 = decoded[0] as unknown as PublicKey; @@ -105,8 +107,8 @@ describe("MethodParameterEncoder", () => { x.toString() ) ); - - const decoded = await encoder.decode(fields, auxiliary); + const fieldString = fields.map((field) => field.toString()); + const decoded = await encoder.decode(fieldString, auxiliary); expect(decoded).toHaveLength(1); const decoded1 = decoded[0] as unknown as Proof; diff --git a/packages/module/test/modules/Balances.test.ts b/packages/module/test/modules/Balances.test.ts index d61f6a3d9..0706df416 100644 --- a/packages/module/test/modules/Balances.test.ts +++ b/packages/module/test/modules/Balances.test.ts @@ -8,7 +8,7 @@ import { SimpleAsyncStateService, RuntimeMethodExecutionContext, RuntimeTransaction, - NetworkState, + ProvableNetworkState, PROTOKIT_PREFIXES, } from "@proto-kit/protocol"; @@ -74,7 +74,7 @@ describe("balances", () => { const executionContext = container.resolve(RuntimeMethodExecutionContext); executionContext.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); const expectedStateTransitionsHash = @@ -114,7 +114,7 @@ describe("balances", () => { ); executionContext.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); await balances.getTotalSupply(); @@ -177,7 +177,7 @@ describe("balances", () => { ); executionContext.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); await balances.getTotalSupply(); @@ -236,7 +236,7 @@ describe("balances", () => { ); executionContext.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); await balances.setTotalSupply(); @@ -305,7 +305,7 @@ describe("balances", () => { ); executionContext.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); await balances.getBalance(address); diff --git a/packages/module/test/modules/State.test.ts b/packages/module/test/modules/State.test.ts index 8f5f55533..684c1d613 100644 --- a/packages/module/test/modules/State.test.ts +++ b/packages/module/test/modules/State.test.ts @@ -2,7 +2,7 @@ import "reflect-metadata"; import { PublicKey, UInt64 } from "o1js"; import { container } from "tsyringe"; import { - NetworkState, + ProvableNetworkState, Option, RuntimeMethodExecutionContext, RuntimeTransaction, @@ -56,7 +56,7 @@ describe("state", () => { const executionContext = container.resolve(RuntimeMethodExecutionContext); executionContext.setup({ - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), transaction: RuntimeTransaction.dummyTransaction(), }); await balances.transientState(); diff --git a/packages/module/test/runtimeMethod.test.ts b/packages/module/test/runtimeMethod.test.ts index ca895ae31..e83471168 100644 --- a/packages/module/test/runtimeMethod.test.ts +++ b/packages/module/test/runtimeMethod.test.ts @@ -10,7 +10,7 @@ import { } from "o1js"; import { MethodPublicOutput, - NetworkState, + ProvableNetworkState, RuntimeMethodExecutionContext, RuntimeTransaction, } from "@proto-kit/protocol"; @@ -91,12 +91,11 @@ describe("runtimeMethod", () => { expect.assertions(1 + parameters.length); const module = runtime.resolve("Balances"); - - const decoder = MethodParameterEncoder.fromMethod(module, "getBalance"); - const recodedParameters = await decoder.decode( - parameters.flatMap((x) => x.toFields()), - [] + const parametersArray = parameters.flatMap((x) => + x.toFields().map((f) => f.toString()) ); + const decoder = MethodParameterEncoder.fromMethod(module, "getBalance"); + const recodedParameters = await decoder.decode(parametersArray, []); expect(parameters).toHaveLength(recodedParameters.length); @@ -118,7 +117,7 @@ describe("runtimeMethod", () => { context.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); const module = runtime.resolve("Balances"); @@ -126,7 +125,7 @@ describe("runtimeMethod", () => { context.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); await expect(context.current().result.prover!()).rejects.toThrow( @@ -158,7 +157,7 @@ describe("runtimeMethod", () => { methodId: Field(eventMakerMethodId), argsHash: Poseidon.hash([]), }), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); const module = runtime.resolve("EventMaker"); diff --git a/packages/persistance/src/services/prisma/PrismaBlockStorage.ts b/packages/persistance/src/services/prisma/PrismaBlockStorage.ts index f3146642e..74f8ea5b7 100644 --- a/packages/persistance/src/services/prisma/PrismaBlockStorage.ts +++ b/packages/persistance/src/services/prisma/PrismaBlockStorage.ts @@ -80,7 +80,7 @@ export class PrismaBlockStorage implements BlockQueue, BlockStorage { public async pushBlock(block: Block): Promise { log.trace( "Pushing block to DB. Txs:", - block.transactions.map((x) => x.tx.hash().toString()) + block.transactions.map((x) => x.tx.hash) ); const transactions = block.transactions.map( @@ -88,7 +88,7 @@ export class PrismaBlockStorage implements BlockQueue, BlockStorage { const encoded = this.transactionResultMapper.mapOut(tx); return { ...encoded[0], - blockHash: block.hash.toString(), + blockHash: block.hash, }; } ); @@ -191,7 +191,7 @@ export class PrismaBlockStorage implements BlockQueue, BlockStorage { if (result !== undefined) { if (result.result === undefined) { throw new Error( - `Block result for block ${result.block.height.toString()} not found` + `Block result for block ${result.block.height} not found` ); } return { diff --git a/packages/persistance/src/services/prisma/mappers/BlockMapper.ts b/packages/persistance/src/services/prisma/mappers/BlockMapper.ts index bd5ee9b06..3ebe0f4dc 100644 --- a/packages/persistance/src/services/prisma/mappers/BlockMapper.ts +++ b/packages/persistance/src/services/prisma/mappers/BlockMapper.ts @@ -1,8 +1,7 @@ import { singleton } from "tsyringe"; import { Block } from "@proto-kit/sequencer"; -import { Block as PrismaBlock } from "@prisma/client"; +import { Prisma, Block as PrismaBlock } from "@prisma/client"; import { NetworkState } from "@proto-kit/protocol"; -import { Field } from "o1js"; import { ObjectMapper } from "../../../ObjectMapper"; @@ -19,28 +18,22 @@ export class BlockMapper implements ObjectMapper { transactions: [], networkState: { - before: new NetworkState( - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - NetworkState.fromJSON(input.beforeNetworkState as any) - ), - during: new NetworkState( - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - NetworkState.fromJSON(input.duringNetworkState as any) - ), + before: input.beforeNetworkState as NetworkState, + during: input.duringNetworkState as NetworkState, }, - hash: Field(input.hash), - height: Field(input.height), - fromEternalTransactionsHash: Field(input.fromEternalTransactionsHash), - toEternalTransactionsHash: Field(input.toEternalTransactionsHash), - fromBlockHashRoot: Field(input.fromBlockHashRoot), - fromMessagesHash: Field(input.fromMessagesHash), - toMessagesHash: Field(input.toMessagesHash), - fromStateRoot: Field(input.fromStateRoot), + hash: input.hash, + height: input.height, + fromEternalTransactionsHash: input.fromEternalTransactionsHash, + toEternalTransactionsHash: input.toEternalTransactionsHash, + fromBlockHashRoot: input.fromBlockHashRoot, + fromMessagesHash: input.fromMessagesHash, + toMessagesHash: input.toMessagesHash, + fromStateRoot: input.fromStateRoot, - transactionsHash: Field(input.transactionsHash), + transactionsHash: input.transactionsHash, previousBlockHash: - input.parentHash !== null ? Field(input.parentHash) : undefined, + input.parentHash !== null ? input.parentHash : undefined, beforeBlockStateTransitions: this.stArrayMapper.mapIn( input.beforeBlockStateTransitions @@ -50,24 +43,23 @@ export class BlockMapper implements ObjectMapper { public mapOut(input: Block): PrismaBlock { return { - height: Number(input.height.toBigInt()), - beforeNetworkState: NetworkState.toJSON(input.networkState.before), - duringNetworkState: NetworkState.toJSON(input.networkState.during), - fromEternalTransactionsHash: input.fromEternalTransactionsHash.toString(), - toEternalTransactionsHash: input.toEternalTransactionsHash.toString(), - fromBlockHashRoot: input.fromBlockHashRoot.toString(), - fromMessagesHash: input.fromMessagesHash.toString(), - toMessagesHash: input.toMessagesHash.toString(), - fromStateRoot: input.fromStateRoot.toString(), + height: input.height, + beforeNetworkState: input.networkState.before, + duringNetworkState: input.networkState.during, + fromEternalTransactionsHash: input.fromEternalTransactionsHash, + toEternalTransactionsHash: input.toEternalTransactionsHash, + fromBlockHashRoot: input.fromBlockHashRoot, + fromMessagesHash: input.fromMessagesHash, + toMessagesHash: input.toMessagesHash, + fromStateRoot: input.fromStateRoot, - hash: input.hash.toString(), - transactionsHash: input.transactionsHash.toString(), - parentHash: input.previousBlockHash?.toString() ?? null, + hash: input.hash, + transactionsHash: input.transactionsHash, + parentHash: input.previousBlockHash ?? null, batchHeight: null, - beforeBlockStateTransitions: this.stArrayMapper.mapOut( - input.beforeBlockStateTransitions - ), + beforeBlockStateTransitions: + input.beforeBlockStateTransitions as unknown as Prisma.JsonArray, }; } } diff --git a/packages/persistance/src/services/prisma/mappers/BlockResultMapper.ts b/packages/persistance/src/services/prisma/mappers/BlockResultMapper.ts index fd65c6d02..3881e5e3d 100644 --- a/packages/persistance/src/services/prisma/mappers/BlockResultMapper.ts +++ b/packages/persistance/src/services/prisma/mappers/BlockResultMapper.ts @@ -1,7 +1,10 @@ import { singleton } from "tsyringe"; import { BlockResult } from "@proto-kit/sequencer"; -import { BlockResult as DBBlockResult } from "@prisma/client"; -import { BlockHashMerkleTreeWitness, NetworkState } from "@proto-kit/protocol"; +import { BlockResult as DBBlockResult, Prisma } from "@prisma/client"; +import { + BlockHashMerkleTreeWitnessJson, + NetworkState, +} from "@proto-kit/protocol"; import { ObjectMapper } from "../../../ObjectMapper"; @@ -17,23 +20,19 @@ export class BlockResultMapper public mapIn(input: DBBlockResult): BlockResult { return { - afterNetworkState: new NetworkState( - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - NetworkState.fromJSON(input.afterNetworkState as any) - ), + afterNetworkState: input.afterNetworkState as NetworkState, + + stateRoot: input.stateRoot, + blockHashRoot: input.blockHashRoot, + blockHashWitness: + input.blockHashWitness as BlockHashMerkleTreeWitnessJson, - stateRoot: BigInt(input.stateRoot), - blockHashRoot: BigInt(input.blockHashRoot), - blockHashWitness: new BlockHashMerkleTreeWitness( - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - BlockHashMerkleTreeWitness.fromJSON(input.blockHashWitness as any) - ), afterBlockStateTransitions: this.stArrayMapper.mapIn( input.afterBlockStateTransitions ), - blockHash: BigInt(input.blockHash), + blockHash: input.blockHash, - witnessedRoots: [BigInt(input.witnessedRoots[0])], + witnessedRoots: [input.witnessedRoots[0]], }; } @@ -43,13 +42,10 @@ export class BlockResultMapper blockHash: input.blockHash.toString(), blockHashRoot: input.blockHashRoot.toString(), - blockHashWitness: BlockHashMerkleTreeWitness.toJSON( - input.blockHashWitness - ), - afterBlockStateTransitions: this.stArrayMapper.mapOut( - input.afterBlockStateTransitions - ), - afterNetworkState: NetworkState.toJSON(input.afterNetworkState), + blockHashWitness: input.blockHashWitness, + afterBlockStateTransitions: + input.afterBlockStateTransitions as unknown as Prisma.JsonArray, + afterNetworkState: input.afterNetworkState, witnessedRoots: [input.witnessedRoots[0].toString()], }; diff --git a/packages/persistance/src/services/prisma/mappers/EventMapper.ts b/packages/persistance/src/services/prisma/mappers/EventMapper.ts index b56416a87..c80e7f6a6 100644 --- a/packages/persistance/src/services/prisma/mappers/EventMapper.ts +++ b/packages/persistance/src/services/prisma/mappers/EventMapper.ts @@ -1,31 +1,30 @@ import { singleton } from "tsyringe"; import { Prisma } from "@prisma/client"; -import { Field } from "o1js"; import { ObjectMapper } from "../../../ObjectMapper"; -type EventData = { +type EventDataJson = { eventName: string; - data: Field[]; + data: string[]; source: "afterTxHook" | "beforeTxHook" | "runtime"; }; @singleton() -export class EventMapper implements ObjectMapper { - public mapIn(input: Prisma.JsonObject): EventData { +export class EventMapper + implements ObjectMapper +{ + public mapIn(input: Prisma.JsonObject): EventDataJson { return { eventName: input.eventName as string, - data: (input.data as Prisma.JsonArray).map((field) => - Field.fromJSON(field as string) - ), + data: input.data as string[], source: this.sourceConvert(input.source as string), }; } - public mapOut(input: EventData): Prisma.JsonObject { + public mapOut(input: EventDataJson): Prisma.JsonObject { return { eventName: input.eventName, - data: input.data.map((field) => field.toString()), + data: input.data, source: input.source, } as Prisma.JsonObject; } @@ -46,11 +45,11 @@ export class EventMapper implements ObjectMapper { @singleton() export class EventArrayMapper - implements ObjectMapper + implements ObjectMapper { public constructor(private readonly eventMapper: EventMapper) {} - public mapIn(input: Prisma.JsonValue | undefined): EventData[] { + public mapIn(input: Prisma.JsonValue | undefined): EventDataJson[] { if (input === undefined) return []; if (Array.isArray(input)) { @@ -61,7 +60,7 @@ export class EventArrayMapper return []; } - public mapOut(input: EventData[]): Prisma.JsonValue { + public mapOut(input: EventDataJson[]): Prisma.JsonValue { return input.map((event) => this.eventMapper.mapOut(event) ) as Prisma.JsonArray; diff --git a/packages/persistance/src/services/prisma/mappers/TransactionMapper.ts b/packages/persistance/src/services/prisma/mappers/TransactionMapper.ts index e999e9bc2..fdcfd2445 100644 --- a/packages/persistance/src/services/prisma/mappers/TransactionMapper.ts +++ b/packages/persistance/src/services/prisma/mappers/TransactionMapper.ts @@ -1,13 +1,12 @@ import { singleton, injectable } from "tsyringe"; import { - PendingTransaction, TransactionExecutionResult, + PendingTransaction, } from "@proto-kit/sequencer"; import { Transaction as DBTransaction, TransactionExecutionResult as DBTransactionExecutionResult, } from "@prisma/client"; -import { Bool } from "o1js"; import { ObjectMapper } from "../../../ObjectMapper"; @@ -20,8 +19,15 @@ export class TransactionMapper implements ObjectMapper { public mapIn(input: DBTransaction): PendingTransaction { - return PendingTransaction.fromJSON({ - ...input, + return new PendingTransaction({ + hash: input.hash, + methodId: input.methodId, + nonce: input.nonce, + sender: input.sender, + argsFields: input.argsFields, + auxiliaryData: input.auxiliaryData, + isMessage: input.isMessage, + signature: { r: input.signature_r, s: input.signature_s, @@ -30,17 +36,16 @@ export class TransactionMapper } public mapOut(input: PendingTransaction): DBTransaction { - const json = input.toJSON(); return { - methodId: json.methodId, - nonce: json.nonce, - sender: json.sender, - argsFields: json.argsFields, - auxiliaryData: json.auxiliaryData, - isMessage: json.isMessage, - signature_r: json.signature.r, - signature_s: json.signature.s, - hash: input.hash().toString(), + hash: input.hash, + methodId: input.methodId, + nonce: input.nonce, + sender: input.sender, + argsFields: input.argsFields, + auxiliaryData: input.auxiliaryData, + isMessage: input.isMessage, + signature_r: input.signature.r, + signature_s: input.signature.s, }; } } @@ -65,8 +70,8 @@ export class TransactionExecutionResultMapper const executionResult = input[0]; return { tx: this.transactionMapper.mapIn(input[1]), - status: Bool(executionResult.status), - hooksStatus: Bool(executionResult.hooksStatus), + status: executionResult.status, + hooksStatus: executionResult.hooksStatus, statusMessage: executionResult.statusMessage ?? undefined, stateTransitions: this.stBatchMapper.mapIn( executionResult.stateTransitions @@ -80,8 +85,8 @@ export class TransactionExecutionResultMapper ): [Omit, DBTransaction] { const tx = this.transactionMapper.mapOut(input.tx); const executionResult = { - status: input.status.toBoolean(), - hooksStatus: input.hooksStatus.toBoolean(), + status: input.status, + hooksStatus: input.hooksStatus, statusMessage: input.statusMessage ?? null, stateTransitions: this.stBatchMapper.mapOut(input.stateTransitions), events: this.eventArrayMapper.mapOut(input.events), diff --git a/packages/persistance/test-integration/PrismaBlockProduction.test.ts b/packages/persistance/test-integration/PrismaBlockProduction.test.ts index f6299f6b1..75c93c678 100644 --- a/packages/persistance/test-integration/PrismaBlockProduction.test.ts +++ b/packages/persistance/test-integration/PrismaBlockProduction.test.ts @@ -2,9 +2,8 @@ import "reflect-metadata"; import { afterAll, beforeAll, describe, expect } from "@jest/globals"; import { expectDefined, log } from "@proto-kit/common"; import { BalancesKey, TokenId } from "@proto-kit/library"; -import { NetworkState } from "@proto-kit/protocol"; import { AppChainTransaction } from "@proto-kit/sdk"; -import { Block, Batch } from "@proto-kit/sequencer"; +import { Block, Batch, PendingTransaction } from "@proto-kit/sequencer"; import { PrivateKey, PublicKey } from "o1js"; import { container } from "tsyringe"; import { testBlockProduction } from "@proto-kit/sequencer/test/integration/BlockProduction-test"; @@ -97,13 +96,11 @@ describe("prisma integration", () => { // Check that transactions match expect(retrievedBlock.transactions).toHaveLength(1); - expect(retrievedBlock.transactions[0].tx.hash().toString()).toStrictEqual( - block.transactions[0].tx.hash().toString() + expect(retrievedBlock.transactions[0].tx.hash).toStrictEqual( + block.transactions[0].tx.hash ); - expect(retrievedBlock.hash.toString()).toStrictEqual( - block.hash.toString() - ); + expect(retrievedBlock.hash).toStrictEqual(block.hash); // Check that events match expect(retrievedBlock.transactions[0].events).toHaveLength(1); @@ -111,23 +108,11 @@ describe("prisma integration", () => { block.transactions[0].events ); - expect( - NetworkState.toFields(retrievedBlock.networkState.before).map((x) => - x.toString() - ) - ).toStrictEqual( - NetworkState.toFields(block.networkState.before).map((x) => - x.toString() - ) + expect(retrievedBlock.networkState.before).toStrictEqual( + block.networkState.before ); - expect( - NetworkState.toFields(retrievedBlock.networkState.during).map((x) => - x.toString() - ) - ).toStrictEqual( - NetworkState.toFields(block.networkState.during).map((x) => - x.toString() - ) + expect(retrievedBlock.networkState.during).toStrictEqual( + block.networkState.during ); }); @@ -239,10 +224,16 @@ describe("prisma integration", () => { expectDefined(transaction.transaction); + let txHash: string; + + if (transaction.transaction instanceof PendingTransaction) { + txHash = transaction.transaction.hash; + } else { + txHash = transaction.transaction!.hash().toString(); + } + expect(txs).toHaveLength(1); - expect(txs[0].hash().toString()).toStrictEqual( - transaction.transaction.hash().toString() - ); + expect(txs[0].hash).toStrictEqual(txHash); }); it("should resolve transaction from storage as pending", async () => { @@ -255,10 +246,16 @@ describe("prisma integration", () => { expectDefined(transaction.transaction); + let txHash: string; + + if (transaction.transaction instanceof PendingTransaction) { + txHash = transaction.transaction.hash; + } else { + txHash = transaction.transaction!.hash().toString(); + } + expect(txs).toHaveLength(1); - expect(txs[0].hash().toString()).toStrictEqual( - transaction.transaction.hash().toString() - ); + expect(txs[0].hash).toStrictEqual(txHash); }); }); }); diff --git a/packages/processor/src/handlers/HandlersExecutor.ts b/packages/processor/src/handlers/HandlersExecutor.ts index a67612a8a..64d171e77 100644 --- a/packages/processor/src/handlers/HandlersExecutor.ts +++ b/packages/processor/src/handlers/HandlersExecutor.ts @@ -75,7 +75,7 @@ export class HandlersExecutor< ) { await client.block.create({ data: { - height: Number(block.block.height.toBigInt()), + height: Number(block.block.height), }, }); } diff --git a/packages/processor/src/triggers/TimedProcessorTrigger.ts b/packages/processor/src/triggers/TimedProcessorTrigger.ts index 7f3f59454..beee4dfe6 100644 --- a/packages/processor/src/triggers/TimedProcessorTrigger.ts +++ b/packages/processor/src/triggers/TimedProcessorTrigger.ts @@ -40,19 +40,19 @@ export class TimedProcessorTrigger extends ProcessorModule { ) => { // iterate over all transactions for (const tx of block.transactions) { - const methodId = tx.tx.methodId.toBigInt(); + const { methodId } = tx.tx; const methodDescriptor = appChain.runtime.methodIdResolver.getMethodNameFromId(methodId); @@ -87,7 +87,7 @@ describe("HandlersModule", () => { await client.balance.create({ data: { address: from.toBase58(), - height: Number(block.height.toString()), + height: Number(block.height), amount: newFromBalance > 0n ? newFromBalance.toString() : "0", }, }); @@ -109,7 +109,7 @@ describe("HandlersModule", () => { await client.balance.create({ data: { address: to.toBase58(), - height: Number(block.height.toString()), + height: Number(block.height), amount: newToBalance > 0n ? newToBalance.toString() : "0", }, }); diff --git a/packages/protocol/src/hooks/BlockHeightHook.ts b/packages/protocol/src/hooks/BlockHeightHook.ts index d08d48124..08541eac9 100644 --- a/packages/protocol/src/hooks/BlockHeightHook.ts +++ b/packages/protocol/src/hooks/BlockHeightHook.ts @@ -1,9 +1,11 @@ -import { NetworkState } from "../model/network/NetworkState"; +import { ProvableNetworkState } from "../model/network/NetworkState"; import { ProvableBlockHook } from "../protocol/ProvableBlockHook"; export class BlockHeightHook extends ProvableBlockHook> { - public async afterBlock(networkState: NetworkState): Promise { - return new NetworkState({ + public async afterBlock( + networkState: ProvableNetworkState + ): Promise { + return new ProvableNetworkState({ block: { height: networkState.block.height.add(1), }, @@ -11,7 +13,9 @@ export class BlockHeightHook extends ProvableBlockHook> { }); } - public async beforeBlock(networkState: NetworkState): Promise { + public async beforeBlock( + networkState: ProvableNetworkState + ): Promise { return networkState; } } diff --git a/packages/protocol/src/hooks/LastStateRootBlockHook.ts b/packages/protocol/src/hooks/LastStateRootBlockHook.ts index 4c7cf8091..577d6c996 100644 --- a/packages/protocol/src/hooks/LastStateRootBlockHook.ts +++ b/packages/protocol/src/hooks/LastStateRootBlockHook.ts @@ -2,16 +2,16 @@ import { AfterBlockHookArguments, ProvableBlockHook, } from "../protocol/ProvableBlockHook"; -import { NetworkState } from "../model/network/NetworkState"; +import { ProvableNetworkState } from "../model/network/NetworkState"; export class LastStateRootBlockHook extends ProvableBlockHook< Record > { public async afterBlock( - networkState: NetworkState, + networkState: ProvableNetworkState, { stateRoot }: AfterBlockHookArguments - ): Promise { - return new NetworkState({ + ): Promise { + return new ProvableNetworkState({ block: networkState.block, previous: { rootHash: stateRoot, @@ -19,7 +19,9 @@ export class LastStateRootBlockHook extends ProvableBlockHook< }); } - public async beforeBlock(networkState: NetworkState): Promise { + public async beforeBlock( + networkState: ProvableNetworkState + ): Promise { return networkState; } } diff --git a/packages/protocol/src/hooks/NoopBlockHook.ts b/packages/protocol/src/hooks/NoopBlockHook.ts index a836edc81..9c6c4b26a 100644 --- a/packages/protocol/src/hooks/NoopBlockHook.ts +++ b/packages/protocol/src/hooks/NoopBlockHook.ts @@ -5,20 +5,20 @@ import { BeforeBlockHookArguments, ProvableBlockHook, } from "../protocol/ProvableBlockHook"; -import { NetworkState } from "../model/network/NetworkState"; +import { ProvableNetworkState } from "../model/network/NetworkState"; export class NoopBlockHook extends ProvableBlockHook { public async afterBlock( - networkState: NetworkState, + networkState: ProvableNetworkState, state: AfterBlockHookArguments - ): Promise { + ): Promise { return networkState; } public async beforeBlock( - networkState: NetworkState, + networkState: ProvableNetworkState, state: BeforeBlockHookArguments - ): Promise { + ): Promise { return networkState; } } diff --git a/packages/protocol/src/model/RuntimeLike.ts b/packages/protocol/src/model/RuntimeLike.ts index ec636f5d0..733b1620d 100644 --- a/packages/protocol/src/model/RuntimeLike.ts +++ b/packages/protocol/src/model/RuntimeLike.ts @@ -2,7 +2,7 @@ export type RuntimeMethodInvocationType = "INCOMING_MESSAGE" | "SIGNATURE"; export type RuntimeMethodIdMapping = Record< `${string}.${string}`, - { methodId: bigint; type: RuntimeMethodInvocationType } + { methodId: string; type: RuntimeMethodInvocationType } >; export interface RuntimeLike { diff --git a/packages/protocol/src/model/network/NetworkState.ts b/packages/protocol/src/model/network/NetworkState.ts index b0213ac36..ef0ca8e5c 100644 --- a/packages/protocol/src/model/network/NetworkState.ts +++ b/packages/protocol/src/model/network/NetworkState.ts @@ -1,4 +1,4 @@ -import { Field, Poseidon, Struct, UInt64 } from "o1js"; +import { Field, InferJson, Poseidon, Struct, UInt64 } from "o1js"; import { RollupMerkleTree } from "@proto-kit/common"; export class CurrentBlock extends Struct({ @@ -9,7 +9,7 @@ export class PreviousBlock extends Struct({ rootHash: Field, }) {} -export class NetworkState extends Struct({ +export class ProvableNetworkState extends Struct({ block: CurrentBlock, previous: PreviousBlock, }) { @@ -21,7 +21,7 @@ export class NetworkState extends Struct({ } public static empty() { - return new NetworkState({ + return new ProvableNetworkState({ block: { height: UInt64.zero, }, @@ -31,3 +31,5 @@ export class NetworkState extends Struct({ }); } } + +export type NetworkState = InferJson; diff --git a/packages/protocol/src/protocol/ProvableBlockHook.ts b/packages/protocol/src/protocol/ProvableBlockHook.ts index 7ba6dcd32..b6248dbac 100644 --- a/packages/protocol/src/protocol/ProvableBlockHook.ts +++ b/packages/protocol/src/protocol/ProvableBlockHook.ts @@ -1,7 +1,7 @@ import { Field } from "o1js"; import { NoConfig } from "@proto-kit/common"; -import { NetworkState } from "../model/network/NetworkState"; +import { ProvableNetworkState } from "../model/network/NetworkState"; import { BlockProverState, BlockProverPublicInput, @@ -51,12 +51,12 @@ export abstract class ProvableBlockHook< Config = NoConfig, > extends TransitioningProtocolModule { public abstract beforeBlock( - networkState: NetworkState, + networkState: ProvableNetworkState, state: BeforeBlockHookArguments - ): Promise; + ): Promise; public abstract afterBlock( - networkState: NetworkState, + networkState: ProvableNetworkState, state: AfterBlockHookArguments - ): Promise; + ): Promise; } diff --git a/packages/protocol/src/protocol/ProvableTransactionHook.ts b/packages/protocol/src/protocol/ProvableTransactionHook.ts index 68fa3bedf..c6337bc05 100644 --- a/packages/protocol/src/protocol/ProvableTransactionHook.ts +++ b/packages/protocol/src/protocol/ProvableTransactionHook.ts @@ -2,7 +2,7 @@ import { NoConfig } from "@proto-kit/common"; import { Signature } from "o1js"; import { RuntimeTransaction } from "../model/transaction/RuntimeTransaction"; -import { NetworkState } from "../model/network/NetworkState"; +import { ProvableNetworkState } from "../model/network/NetworkState"; import { MethodPublicOutput } from "../model/MethodPublicOutput"; import { TransactionProverPublicInput, @@ -36,7 +36,7 @@ export function toBeforeTransactionHookArgument( TransactionProverTransactionArguments, "verificationKeyAttestation" >, - networkState: NetworkState, + networkState: ProvableNetworkState, state: Parameters[0] ): BeforeTransactionHookArguments { const { transaction, signature } = executionData; @@ -54,7 +54,7 @@ export function toAfterTransactionHookArgument( TransactionProverTransactionArguments, "verificationKeyAttestation" >, - networkState: NetworkState, + networkState: ProvableNetworkState, state: Parameters[0], runtimeResult: MethodPublicOutput ): AfterTransactionHookArguments { @@ -77,7 +77,7 @@ export type TransactionResult = Omit< export interface BeforeTransactionHookArguments { transaction: RuntimeTransaction; signature: Signature; - networkState: NetworkState; + networkState: ProvableNetworkState; prover: ProvableHookTransactionState; } diff --git a/packages/protocol/src/prover/block/BlockProvable.ts b/packages/protocol/src/prover/block/BlockProvable.ts index dbcb311fe..3c90302e1 100644 --- a/packages/protocol/src/prover/block/BlockProvable.ts +++ b/packages/protocol/src/prover/block/BlockProvable.ts @@ -2,7 +2,7 @@ import { Bool, Field, Proof, Struct } from "o1js"; import { CompilableModule, WithZkProgrammable } from "@proto-kit/common"; import { StateTransitionProof } from "../statetransition/StateTransitionProvable"; -import { NetworkState } from "../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../model/network/NetworkState"; import { TransactionHashList } from "../accumulators/TransactionHashList"; import { MinaActionsHashList } from "../../utils/MinaPrefixedProvableHashList"; import { AppliedBatchHashList } from "../accumulators/AppliedBatchHashList"; @@ -34,7 +34,7 @@ export class BlockProverState extends TransactionProverState { constructor(args: { transactionList: TransactionHashList; - networkState: NetworkState; + networkState: ProvableNetworkState; eternalTransactionsList: TransactionHashList; pendingSTBatches: AppliedBatchHashList; incomingMessages: MinaActionsHashList; @@ -60,7 +60,7 @@ export class BlockProverState extends TransactionProverState { public static fromCommitments( publicInput: BlockProverPublicInput, - networkState: NetworkState + networkState: ProvableNetworkState ): BlockProverState { return new BlockProverState({ ...super.fromCommitments(publicInput, networkState), @@ -105,7 +105,7 @@ export interface BlockProvable CompilableModule { proveBlock: ( publicInput: BlockProverPublicInput, - networkState: NetworkState, + networkState: ProvableNetworkState, blockWitness: BlockHashMerkleTreeWitness, stateTransitionProof: StateTransitionProof, deferSTs: Bool, diff --git a/packages/protocol/src/prover/block/BlockProver.ts b/packages/protocol/src/prover/block/BlockProver.ts index ede4ea8c9..acb692276 100644 --- a/packages/protocol/src/prover/block/BlockProver.ts +++ b/packages/protocol/src/prover/block/BlockProver.ts @@ -28,7 +28,7 @@ import { ProvableBlockHook, toProvableHookBlockState, } from "../../protocol/ProvableBlockHook"; -import { NetworkState } from "../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../model/network/NetworkState"; import { assertEqualsIf } from "../../utils/utils"; import { WitnessedRootWitness } from "../accumulators/WitnessedRootHashList"; import { StateServiceProvider } from "../../state/StateServiceProvider"; @@ -99,11 +99,11 @@ export class BlockProverProgrammable extends ZkProgrammable< >( hook: ( module: ProvableBlockHook, - networkState: NetworkState, + networkState: ProvableNetworkState, args: T - ) => Promise, + ) => Promise, hookArguments: T, - inputNetworkState: NetworkState + inputNetworkState: ProvableNetworkState ) { const transaction = RuntimeTransaction.dummyTransaction(); const startingInputs = { @@ -114,7 +114,7 @@ export class BlockProverProgrammable extends ZkProgrammable< return await executeHooks(startingInputs, async () => { const executionContext = container.resolve(RuntimeMethodExecutionContext); - return await this.blockHooks.reduce>( + return await this.blockHooks.reduce>( async (networkStatePromise, blockHook) => { const networkState = await networkStatePromise; @@ -218,7 +218,7 @@ export class BlockProverProgrammable extends ZkProgrammable< @provableMethod() public async proveBlock( publicInput: BlockProverPublicInput, - networkState: NetworkState, + networkState: ProvableNetworkState, blockWitness: BlockHashMerkleTreeWitness, stateTransitionProof: StateTransitionProof, deferSTProof: Bool, @@ -566,7 +566,7 @@ export class BlockProverProgrammable extends ZkProgrammable< methods: { proveBlock: { privateInputs: [ - NetworkState, + ProvableNetworkState, BlockHashMerkleTreeWitness, StateTransitionProofClass, Bool, @@ -575,7 +575,7 @@ export class BlockProverProgrammable extends ZkProgrammable< ], async method( publicInput: BlockProverPublicInput, - networkState: NetworkState, + networkState: ProvableNetworkState, blockWitness: BlockHashMerkleTreeWitness, stateTransitionProof: StateTransitionProof, deferSTs: Bool, @@ -685,7 +685,7 @@ export class BlockProver public proveBlock( publicInput: BlockProverPublicInput, - networkState: NetworkState, + networkState: ProvableNetworkState, blockWitness: BlockHashMerkleTreeWitness, stateTransitionProof: StateTransitionProof, deferSTs: Bool, diff --git a/packages/protocol/src/prover/block/accummulators/BlockHashMerkleTree.ts b/packages/protocol/src/prover/block/accummulators/BlockHashMerkleTree.ts index e80d4b6b8..9011686e4 100644 --- a/packages/protocol/src/prover/block/accummulators/BlockHashMerkleTree.ts +++ b/packages/protocol/src/prover/block/accummulators/BlockHashMerkleTree.ts @@ -1,5 +1,5 @@ import { createMerkleTree } from "@proto-kit/common"; -import { Bool, Field, Poseidon, Struct } from "o1js"; +import { Bool, Field, InferJson, Poseidon, Struct } from "o1js"; export class BlockHashMerkleTree extends createMerkleTree(40) {} export class BlockHashMerkleTreeWitness extends BlockHashMerkleTree.WITNESS {} @@ -22,3 +22,6 @@ export class BlockHashTreeEntry extends Struct({ return Poseidon.hash([blockHash, ...this.closed.toFields()]); } } +export type BlockHashMerkleTreeWitnessJson = InferJson< + typeof BlockHashMerkleTreeWitness +>; diff --git a/packages/protocol/src/prover/transaction/TransactionProvable.ts b/packages/protocol/src/prover/transaction/TransactionProvable.ts index 4180fd906..9c9f68768 100644 --- a/packages/protocol/src/prover/transaction/TransactionProvable.ts +++ b/packages/protocol/src/prover/transaction/TransactionProvable.ts @@ -5,7 +5,7 @@ import { DynamicProof, Field, Proof, Signature, Struct, Void } from "o1js"; import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction"; import { RuntimeVerificationKeyAttestation } from "../block/accummulators/RuntimeVerificationKeyTree"; import { MethodPublicOutput } from "../../model/MethodPublicOutput"; -import { NetworkState } from "../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../model/network/NetworkState"; import { TransactionHashList } from "../accumulators/TransactionHashList"; import { AppliedBatchHashList } from "../accumulators/AppliedBatchHashList"; import { MinaActionsHashList } from "../../utils/MinaPrefixedProvableHashList"; @@ -22,7 +22,7 @@ export class TransactionProverState { * The network state which gives access to values such as blockHeight * This value is the same for the whole batch (L2 block) */ - networkState: NetworkState; + networkState: ProvableNetworkState; /** * A variant of the transactionsHash that is never reset. @@ -39,7 +39,7 @@ export class TransactionProverState { constructor(args: { transactionList: TransactionHashList; - networkState: NetworkState; + networkState: ProvableNetworkState; eternalTransactionsList: TransactionHashList; pendingSTBatches: AppliedBatchHashList; incomingMessages: MinaActionsHashList; @@ -66,7 +66,7 @@ export class TransactionProverState { public static fromCommitments( publicInput: TransactionProverPublicInput, - networkState: NetworkState + networkState: ProvableNetworkState ): TransactionProverState { publicInput.networkStateHash.assertEquals( networkState.hash(), @@ -137,13 +137,13 @@ export class DynamicRuntimeProof extends DynamicProof< export class BlockProverSingleTransactionExecutionData extends Struct({ transaction: TransactionProverTransactionArguments, - networkState: NetworkState, + networkState: ProvableNetworkState, }) {} export class BlockProverMultiTransactionExecutionData extends Struct({ transaction1: TransactionProverTransactionArguments, transaction2: TransactionProverTransactionArguments, - networkState: NetworkState, + networkState: ProvableNetworkState, }) {} export type TransactionProof = Proof< diff --git a/packages/protocol/src/prover/transaction/TransactionProver.ts b/packages/protocol/src/prover/transaction/TransactionProver.ts index 6c686ba17..0d91a7071 100644 --- a/packages/protocol/src/prover/transaction/TransactionProver.ts +++ b/packages/protocol/src/prover/transaction/TransactionProver.ts @@ -11,7 +11,7 @@ import { import { Bool, Field, SelfProof, VerificationKey, ZkProgram } from "o1js"; import { inject, injectable, injectAll } from "tsyringe"; -import { NetworkState } from "../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../model/network/NetworkState"; import { ProtocolModule } from "../../protocol/ProtocolModule"; import { MethodPublicOutput } from "../../model/MethodPublicOutput"; import { @@ -102,7 +102,7 @@ export class TransactionProverZkProgrammable extends ZkProgrammable< fromState: TransactionProverState, runtimeOutput: MethodPublicOutput, executionData: ApplyTransactionArguments, - networkState: NetworkState + networkState: ProvableNetworkState ): Promise { const { transaction, signature } = executionData; diff --git a/packages/protocol/src/settlement/contracts/settlement/BridgingSettlementContract.ts b/packages/protocol/src/settlement/contracts/settlement/BridgingSettlementContract.ts index 4865e4ec5..66e4d845a 100644 --- a/packages/protocol/src/settlement/contracts/settlement/BridgingSettlementContract.ts +++ b/packages/protocol/src/settlement/contracts/settlement/BridgingSettlementContract.ts @@ -19,7 +19,7 @@ import { } from "o1js"; import { container } from "tsyringe"; -import { NetworkState } from "../../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../../model/network/NetworkState"; import { DispatchContractType } from "../DispatchSmartContract"; import { BridgeContractType } from "../BridgeContract"; import { TokenBridgeDeploymentAuth } from "../authorizations/TokenBridgeDeploymentAuth"; @@ -168,8 +168,8 @@ export abstract class BridgingSettlementContractBase blockProof: DynamicBlockProof, signature: Signature, publicKey: PublicKey, - inputNetworkState: NetworkState, - outputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, + outputNetworkState: ProvableNetworkState, newPromisedMessagesHash: Field ) { await super.settleBase( @@ -265,8 +265,8 @@ export class BridgingSettlementContract blockProof: DynamicBlockProof, signature: Signature, publicKey: PublicKey, - inputNetworkState: NetworkState, - outputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, + outputNetworkState: ProvableNetworkState, newPromisedMessagesHash: Field ) { return await this.settleBaseBridging( diff --git a/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts b/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts index cc6401c03..152c6eda0 100644 --- a/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts +++ b/packages/protocol/src/settlement/contracts/settlement/SettlementBase.ts @@ -20,7 +20,7 @@ import { import { container } from "tsyringe"; import { BlockHashMerkleTree } from "../../../prover/block/accummulators/BlockHashMerkleTree"; -import { NetworkState } from "../../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../../model/network/NetworkState"; import { ProvableSettlementHook, SettlementHookInputs, @@ -70,8 +70,8 @@ export interface SettlementContractType { blockProof: DynamicBlockProof, signature: Signature, publicKey: PublicKey, - inputNetworkState: NetworkState, - outputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, + outputNetworkState: ProvableNetworkState, newPromisedMessagesHash: Field ) => Promise; } @@ -111,15 +111,15 @@ export abstract class SettlementBase this.sequencerKey.set(sequencer.x); this.stateRoot.set(LinkedMerkleTree.EMPTY_ROOT); this.blockHashRoot.set(Field(BlockHashMerkleTree.EMPTY_ROOT)); - this.networkStateHash.set(NetworkState.empty().hash()); + this.networkStateHash.set(ProvableNetworkState.empty().hash()); } abstract settle( blockProof: DynamicBlockProof, signature: Signature, publicKey: PublicKey, - inputNetworkState: NetworkState, - outputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, + outputNetworkState: ProvableNetworkState, newPromisedMessagesHash: Field ): Promise; @@ -134,8 +134,8 @@ export abstract class SettlementBase blockProof: DynamicBlockProof, signature: Signature, publicKey: PublicKey, - inputNetworkState: NetworkState, - outputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, + outputNetworkState: ProvableNetworkState, newPromisedMessagesHash: Field ) { const { diff --git a/packages/protocol/src/settlement/contracts/settlement/SettlementContract.ts b/packages/protocol/src/settlement/contracts/settlement/SettlementContract.ts index 95321684f..2fa4a2476 100644 --- a/packages/protocol/src/settlement/contracts/settlement/SettlementContract.ts +++ b/packages/protocol/src/settlement/contracts/settlement/SettlementContract.ts @@ -12,7 +12,7 @@ import { } from "o1js"; import { O1PublicKeyOption } from "@proto-kit/common"; -import { NetworkState } from "../../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../../model/network/NetworkState"; import { DynamicBlockProof, @@ -59,8 +59,8 @@ export class SettlementContract blockProof: DynamicBlockProof, signature: Signature, publicKey: PublicKey, - inputNetworkState: NetworkState, - outputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, + outputNetworkState: ProvableNetworkState, newPromisedMessagesHash: Field ): Promise { await super.settleBase( diff --git a/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts b/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts index 67148bfa1..9b3cd3c33 100644 --- a/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts +++ b/packages/protocol/src/settlement/modularity/ProvableSettlementHook.ts @@ -2,7 +2,7 @@ import { Field, PublicKey, UInt32 } from "o1js"; import { InferProofBase } from "@proto-kit/common"; import { ProtocolModule } from "../../protocol/ProtocolModule"; -import { NetworkState } from "../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../model/network/NetworkState"; import type { BlockProof } from "../../prover/block/BlockProvable"; import type { SettlementContractType } from "../contracts/settlement/SettlementBase"; @@ -19,8 +19,8 @@ export type SettlementStateRecord = { export type SettlementHookInputs = { blockProof: InputBlockProof; - fromNetworkState: NetworkState; - toNetworkState: NetworkState; + fromNetworkState: ProvableNetworkState; + toNetworkState: ProvableNetworkState; newPromisedMessagesHash: Field; contractState: SettlementStateRecord; currentL1BlockHeight: UInt32; diff --git a/packages/protocol/src/state/context/RuntimeMethodExecutionContext.ts b/packages/protocol/src/state/context/RuntimeMethodExecutionContext.ts index a497533c0..cad75f50d 100644 --- a/packages/protocol/src/state/context/RuntimeMethodExecutionContext.ts +++ b/packages/protocol/src/state/context/RuntimeMethodExecutionContext.ts @@ -7,7 +7,7 @@ import { import { StateTransition } from "../../model/StateTransition"; import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction"; -import { NetworkState } from "../../model/network/NetworkState"; +import { ProvableNetworkState } from "../../model/network/NetworkState"; const errors = { setupNotCalled: () => @@ -35,13 +35,13 @@ export class RuntimeProvableMethodExecutionResult extends ProvableMethodExecutio export interface RuntimeMethodExecutionData { transaction: RuntimeTransaction; - networkState: NetworkState; + networkState: ProvableNetworkState; } export class RuntimeMethodExecutionDataStruct extends Struct({ transaction: RuntimeTransaction, - networkState: NetworkState, + networkState: ProvableNetworkState, }) implements RuntimeMethodExecutionData {} diff --git a/packages/protocol/test/BlockProver.test.ts b/packages/protocol/test/BlockProver.test.ts index 44b49dc6b..d52cc235c 100644 --- a/packages/protocol/test/BlockProver.test.ts +++ b/packages/protocol/test/BlockProver.test.ts @@ -9,7 +9,7 @@ import "reflect-metadata"; import { MethodPublicOutput, - NetworkState, + ProvableNetworkState, SignedTransaction, StateTransitionProverPublicInput, StateTransitionProverPublicOutput, @@ -59,7 +59,7 @@ class RuntimeZkProgrammable extends ZkProgrammable< } describe("blockProver", () => { - const networkState = new NetworkState({ + const networkState = new ProvableNetworkState({ block: { height: UInt64.zero, }, @@ -78,7 +78,7 @@ describe("blockProver", () => { protocolHash: Field, tx: SignedTransaction, // eslint-disable-next-line @typescript-eslint/no-shadow - networkState: NetworkState + networkState: ProvableNetworkState ): BlockProverProofPair { const transactionHash = tx.transaction.hash(); const sthash = Field(123); diff --git a/packages/protocol/test/State.test.ts b/packages/protocol/test/State.test.ts index cc51bc5de..e645b3156 100644 --- a/packages/protocol/test/State.test.ts +++ b/packages/protocol/test/State.test.ts @@ -4,7 +4,7 @@ import { Bool, Field, UInt64 } from "o1js"; import { container } from "tsyringe"; import { - NetworkState, + ProvableNetworkState, RuntimeMethodExecutionContext, RuntimeTransaction, State, @@ -18,7 +18,7 @@ describe("state", () => { executionContext.setup({ transaction: undefined as unknown as RuntimeTransaction, - networkState: undefined as unknown as NetworkState, + networkState: undefined as unknown as ProvableNetworkState, }); }); diff --git a/packages/protocol/test/state/assert/assert.test.ts b/packages/protocol/test/state/assert/assert.test.ts index 475959073..18d769a27 100644 --- a/packages/protocol/test/state/assert/assert.test.ts +++ b/packages/protocol/test/state/assert/assert.test.ts @@ -6,7 +6,7 @@ import { container } from "tsyringe"; import { assert } from "../../../src/state/assert/assert"; import { RuntimeMethodExecutionContext } from "../../../src/state/context/RuntimeMethodExecutionContext"; import { RuntimeTransaction } from "../../../src/model/transaction/RuntimeTransaction"; -import { NetworkState } from "../../../src/model/network/NetworkState"; +import { ProvableNetworkState } from "../../../src/model/network/NetworkState"; describe("assert", () => { const defaultStatusMessage = "something went wrong"; @@ -17,7 +17,7 @@ describe("assert", () => { executionContext.setup({ transaction: undefined as unknown as RuntimeTransaction, - networkState: undefined as unknown as NetworkState, + networkState: undefined as unknown as ProvableNetworkState, }); }); diff --git a/packages/sdk/src/client/ClientAppChain.ts b/packages/sdk/src/client/ClientAppChain.ts index e46414d1b..14507050e 100644 --- a/packages/sdk/src/client/ClientAppChain.ts +++ b/packages/sdk/src/client/ClientAppChain.ts @@ -9,7 +9,7 @@ import { } from "@proto-kit/module"; import { MandatoryProtocolModulesRecord, - NetworkState, + ProvableNetworkState, Protocol, ProtocolModule, ProtocolModulesRecord, @@ -112,7 +112,7 @@ export class ClientAppChain< executionContext.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); executionContext.setSimulated(true); diff --git a/packages/sdk/src/graphql/GraphqlBlockExplorerTransportModule.ts b/packages/sdk/src/graphql/GraphqlBlockExplorerTransportModule.ts index 3908ab6cd..d9b13cdde 100644 --- a/packages/sdk/src/graphql/GraphqlBlockExplorerTransportModule.ts +++ b/packages/sdk/src/graphql/GraphqlBlockExplorerTransportModule.ts @@ -7,7 +7,6 @@ import { ClientTransaction, InclusionStatus, } from "@proto-kit/sequencer"; -import { Field } from "o1js"; import { GraphqlClient } from "./GraphqlClient"; @@ -106,14 +105,14 @@ export class GraphqlBlockExplorerTransportModule const previousBlockHash = blockData.previousBlockHash != null && blockData.previousBlockHash !== "" - ? Field(blockData.previousBlockHash) + ? blockData.previousBlockHash : undefined; return { - hash: Field(blockData.hash), - height: Field(blockData.height), + hash: blockData.hash, + height: blockData.height, previousBlockHash, - transactionsHash: Field(blockData.transactionsHash), + transactionsHash: blockData.transactionsHash, transactions: blockData.txs, }; } diff --git a/packages/sdk/src/graphql/GraphqlNetworkStateTransportModule.ts b/packages/sdk/src/graphql/GraphqlNetworkStateTransportModule.ts index eb406a5aa..f140f8371 100644 --- a/packages/sdk/src/graphql/GraphqlNetworkStateTransportModule.ts +++ b/packages/sdk/src/graphql/GraphqlNetworkStateTransportModule.ts @@ -30,7 +30,7 @@ export class GraphqlNetworkStateTransportModule private async retrieveNetworkState(path: string): Promise { const query = gql` - query NetworkState { + query ProvableNetworkState { network { ${path} { block { @@ -57,8 +57,8 @@ export class GraphqlNetworkStateTransportModule } try { - // eslint-disable-next-line @typescript-eslint/no-unsafe-argument - return new NetworkState(NetworkState.fromJSON(json)); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + return json as NetworkState; } catch (e) { if (e instanceof Error) { throw errors.receivedResultMalformed(e.message); diff --git a/packages/sdk/src/graphql/GraphqlTransactionSender.ts b/packages/sdk/src/graphql/GraphqlTransactionSender.ts index 6bf97b774..c22a5ed4e 100644 --- a/packages/sdk/src/graphql/GraphqlTransactionSender.ts +++ b/packages/sdk/src/graphql/GraphqlTransactionSender.ts @@ -1,5 +1,5 @@ import { inject, injectable } from "tsyringe"; -import { PendingTransaction, AppChainModule } from "@proto-kit/sequencer"; +import { AppChainModule, PendingTransaction } from "@proto-kit/sequencer"; import { gql } from "@urql/core"; import { TransactionSender } from "../transaction/InMemoryTransactionSender"; @@ -23,7 +23,7 @@ export class GraphqlTransactionSender submitTx(tx: $tx) } `; - const tx = transaction.toJSON(); + const tx = transaction; const queryResult = await this.graphqlClient.client .mutation(query, { tx }) diff --git a/packages/sdk/src/query/BlockStorageNetworkStateModule.ts b/packages/sdk/src/query/BlockStorageNetworkStateModule.ts index 274037c14..713e5a6a5 100644 --- a/packages/sdk/src/query/BlockStorageNetworkStateModule.ts +++ b/packages/sdk/src/query/BlockStorageNetworkStateModule.ts @@ -71,7 +71,7 @@ export class BlockStorageNetworkStateModule } return block.networkState.during; // TODO Probably metadata.after? } - // TODO Replace by NetworkState.empty() across the whole application + // TODO Replace by ProvableNetworkState.empty() across the whole application return undefined; } } diff --git a/packages/sdk/src/query/InMemoryBlockExplorer.ts b/packages/sdk/src/query/InMemoryBlockExplorer.ts index 0838eb2ae..ae92707ee 100644 --- a/packages/sdk/src/query/InMemoryBlockExplorer.ts +++ b/packages/sdk/src/query/InMemoryBlockExplorer.ts @@ -59,35 +59,21 @@ export class InMemoryBlockExplorer if (block === undefined) { return undefined; } - - // Convert block.transactions to ClientTransaction format const clientTransactions: ClientTransaction[] = block.transactions.map( (txResult) => ({ - tx: { - hash: txResult.tx.hash().toString(), - methodId: txResult.tx.methodId.toString(), - nonce: txResult.tx.nonce.toString(), - sender: txResult.tx.sender.toBase58(), - argsFields: txResult.tx.argsFields.map((f) => f.toString()), - auxiliaryData: txResult.tx.auxiliaryData, - signature: { - r: txResult.tx.signature.r.toString(), - // eslint-disable-next-line @typescript-eslint/no-base-to-string - s: txResult.tx.signature.s.toString(), - }, - isMessage: txResult.tx.isMessage, - }, - status: txResult.status.toBoolean(), + tx: txResult.tx.toJSON(), + status: txResult.status, statusMessage: txResult.statusMessage, }) ); return { - hash: block.hash, - previousBlockHash: block.previousBlockHash, - height: block.height, + ...block, + previousBlockHash: + block.previousBlockHash !== undefined + ? block.previousBlockHash + : undefined, transactions: clientTransactions, - transactionsHash: block.transactionsHash, }; } } diff --git a/packages/sdk/src/transaction/InMemoryTransactionSender.ts b/packages/sdk/src/transaction/InMemoryTransactionSender.ts index b3bb74981..50a76f9b9 100644 --- a/packages/sdk/src/transaction/InMemoryTransactionSender.ts +++ b/packages/sdk/src/transaction/InMemoryTransactionSender.ts @@ -1,7 +1,7 @@ import { PrivateMempool, - PendingTransaction, AppChainModule, + PendingTransaction, } from "@proto-kit/sequencer"; import { inject, injectable } from "tsyringe"; import { ModuleContainerLike } from "@proto-kit/common"; diff --git a/packages/sdk/test/TestingAppChain.test.ts b/packages/sdk/test/TestingAppChain.test.ts index f07a6c21c..2f67764a5 100644 --- a/packages/sdk/test/TestingAppChain.test.ts +++ b/packages/sdk/test/TestingAppChain.test.ts @@ -147,7 +147,7 @@ describe("testing app chain", () => { Provable.log("block", block); - expect(block?.transactions[0].status.toBoolean()).toBe(true); + expect(block?.transactions[0].status).toBe(true); /** * Observe new state after the block has been produced diff --git a/packages/sdk/test/blockProof/blockProof.test.ts b/packages/sdk/test/blockProof/blockProof.test.ts index 2bc920780..b5a711302 100644 --- a/packages/sdk/test/blockProof/blockProof.test.ts +++ b/packages/sdk/test/blockProof/blockProof.test.ts @@ -7,7 +7,7 @@ import { import { Field, PrivateKey, UInt64 as O1UInt64, Signature } from "o1js"; import { BlockProverPublicOutput, - NetworkState, + ProvableNetworkState, ProvableTransactionHook, RuntimeMethodExecutionContext, RuntimeTransaction, @@ -74,7 +74,7 @@ describe.skip("blockProof", () => { context.setup({ transaction: RuntimeTransaction.dummyTransaction(), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), }); const balancesMethodId = appChain.runtime.methodIdResolver.getMethodId( @@ -95,7 +95,7 @@ describe.skip("blockProof", () => { methodId: Field(balancesMethodId), argsHash: Field(0), }), - networkState: NetworkState.empty(), + networkState: ProvableNetworkState.empty(), signature: Signature.create(PrivateKey.random(), [Field(0)]), prover: { incomingMessagesHash: Field(0), @@ -137,7 +137,7 @@ describe.skip("blockProof", () => { }) ); - expect(block?.transactions[0].status.toBoolean()).toBe(true); + expect(block?.transactions[0].status).toBe(true); expect(aliceBalance?.toBigInt()).toBe(1000n); }, 120_000); }); diff --git a/packages/sdk/test/fee-hook-sts-regression.test.ts b/packages/sdk/test/fee-hook-sts-regression.test.ts index 69a47d39d..9c0a837ea 100644 --- a/packages/sdk/test/fee-hook-sts-regression.test.ts +++ b/packages/sdk/test/fee-hook-sts-regression.test.ts @@ -167,7 +167,7 @@ describe("testing app chain", () => { console.log("block2", block2); - expect(block2?.transactions[0].status.toBoolean()).toBe(true); + expect(block2?.transactions[0].status).toBe(true); /** * Observe new state after the block has been produced diff --git a/packages/sdk/test/fees-multi-zkprograms.test.ts b/packages/sdk/test/fees-multi-zkprograms.test.ts index 53d4389f9..9be9884db 100644 --- a/packages/sdk/test/fees-multi-zkprograms.test.ts +++ b/packages/sdk/test/fees-multi-zkprograms.test.ts @@ -227,7 +227,8 @@ describe("check fee analyzer", () => { await tx2.sign(); await tx2.send(); - const methodId2 = tx2.transaction?.methodId.toBigInt(); + + const methodId2 = tx2.transaction?.methodId.toString(); expectDefined(methodId2); const transactionFeeConfig2 = transactionFeeModule.feeAnalyzer.getFeeConfig(methodId2); @@ -244,7 +245,7 @@ describe("check fee analyzer", () => { await tx3.sign(); await tx3.send(); - const methodId3 = tx3.transaction?.methodId.toBigInt(); + const methodId3 = tx3.transaction?.methodId.toString(); expectDefined(methodId3); const transactionFeeConfig3 = transactionFeeModule.feeAnalyzer.getFeeConfig(methodId3); @@ -262,7 +263,7 @@ describe("check fee analyzer", () => { await tx4.sign(); await tx4.send(); - const methodId4 = tx4.transaction?.methodId.toBigInt(); + const methodId4 = tx4.transaction?.methodId.toString(); expectDefined(methodId4); const transactionFeeConfig4 = transactionFeeModule.feeAnalyzer.getFeeConfig(methodId4); @@ -280,7 +281,7 @@ describe("check fee analyzer", () => { await tx5.sign(); await tx5.send(); - const methodId5 = tx5.transaction?.methodId.toBigInt(); + const methodId5 = tx5.transaction?.methodId.toString(); expectDefined(methodId5); const transactionFeeConfig5 = transactionFeeModule.feeAnalyzer.getFeeConfig(methodId5); diff --git a/packages/sdk/test/fees.test.ts b/packages/sdk/test/fees.test.ts index 9adaa126d..168abbc56 100644 --- a/packages/sdk/test/fees.test.ts +++ b/packages/sdk/test/fees.test.ts @@ -135,7 +135,7 @@ describe("fees", () => { await pit.burn(burnAmount); }); - const methodId = tx.transaction?.methodId.toBigInt(); + const methodId = tx.transaction?.methodId.toString(); expectDefined(methodId); const transactionFeeConfig = transactionFeeModule.feeAnalyzer.getFeeConfig(methodId); diff --git a/packages/sdk/test/networkstate/NetworkState.test.ts b/packages/sdk/test/networkstate/NetworkState.test.ts index f2b812a6e..428dba6ab 100644 --- a/packages/sdk/test/networkstate/NetworkState.test.ts +++ b/packages/sdk/test/networkstate/NetworkState.test.ts @@ -121,7 +121,7 @@ describe.skip("block production", () => { expectDefined(block2); expect(block2.transactions).toHaveLength(1); - expect(block2!.transactions[0].status.toBoolean()).toBe(true); + expect(block2!.transactions[0].status).toBe(true); }, 60000); it("should produce a valid block", async () => { @@ -138,7 +138,7 @@ describe.skip("block production", () => { await tx.send(); const [block, batch] = await blockTrigger.produceBlockAndBatch(); - expect(block!.transactions[0].status.toBoolean()).toBe(true); + expect(block!.transactions[0].status).toBe(true); expectDefined(batch); const publicOutput = BlockProverPublicOutput.fromFields( @@ -155,7 +155,7 @@ describe.skip("block production", () => { await tx2.send(); const [block2, batch2] = await blockTrigger.produceBlockAndBatch(); - expect(block2!.transactions[0].status.toBoolean()).toBe(true); + expect(block2!.transactions[0].status).toBe(true); expectDefined(batch2); const publicOutput2 = BlockProverPublicOutput.fromFields( @@ -172,6 +172,6 @@ describe.skip("block production", () => { await tx3.send(); const [block3] = await blockTrigger.produceBlockAndBatch(); - expect(block3!.transactions[0].status.toBoolean()).toBe(false); + expect(block3!.transactions[0].status).toBe(false); }, 60_000); }); diff --git a/packages/sdk/test/parameters.test.ts b/packages/sdk/test/parameters.test.ts index 9212d8420..938999caf 100644 --- a/packages/sdk/test/parameters.test.ts +++ b/packages/sdk/test/parameters.test.ts @@ -146,6 +146,6 @@ describe("parameters", () => { const block = await appChain.produceBlock(); expectDefined(block); - expect(block.transactions[0].status.toBoolean()).toBe(true); + expect(block.transactions[0].status).toBe(true); }, 60_000); }); diff --git a/packages/sequencer/src/helpers/query/BlockExplorerTransportModule.ts b/packages/sequencer/src/helpers/query/BlockExplorerTransportModule.ts index 67e002cb9..b7830d07a 100644 --- a/packages/sequencer/src/helpers/query/BlockExplorerTransportModule.ts +++ b/packages/sequencer/src/helpers/query/BlockExplorerTransportModule.ts @@ -1,5 +1,3 @@ -import { Field } from "o1js"; - export interface ClientTransaction { tx: { hash: string; @@ -19,11 +17,11 @@ export interface ClientTransaction { } export interface ClientBlock { - hash: Field; - previousBlockHash: Field | undefined; - height: Field; + hash: string; + previousBlockHash: string | undefined; + height: number; transactions: ClientTransaction[]; - transactionsHash: Field; + transactionsHash: string; } export interface BlockExplorerTransportModule { diff --git a/packages/sequencer/src/index.ts b/packages/sequencer/src/index.ts index a0fee0179..bce411ef9 100644 --- a/packages/sequencer/src/index.ts +++ b/packages/sequencer/src/index.ts @@ -39,7 +39,6 @@ export * from "./protocol/production/tasks/serializers/ArtifactionRecordSerializ export * from "./protocol/production/tasks/serializers/BlockProofSerializer"; export * from "./protocol/production/tasks/serializers/DecodedStateSerializer"; export * from "./protocol/production/tasks/serializers/NewBlockProvingParametersSerializer"; -export * from "./protocol/production/tasks/serializers/RuntimeProofParametersSerializer"; export * from "./protocol/production/tasks/serializers/RuntimeVerificationKeyAttestationSerializer"; export * from "./protocol/production/tasks/serializers/StateTransitionParametersSerializer"; export * from "./protocol/production/tasks/serializers/TransactionProvingTaskParameterSerializer"; diff --git a/packages/sequencer/src/mempool/PendingTransaction.ts b/packages/sequencer/src/mempool/PendingTransaction.ts index fd1fedfec..36aa511e1 100644 --- a/packages/sequencer/src/mempool/PendingTransaction.ts +++ b/packages/sequencer/src/mempool/PendingTransaction.ts @@ -27,6 +27,106 @@ export type UnsignedTransactionBody = { isMessage: boolean; }; +interface PendingTransactionJSONType { + hash: string; + methodId: string; + nonce: string; + sender: string; + argsFields: string[]; + auxiliaryData: string[]; + signature: { + r: string; + s: string; + }; + isMessage: boolean; +} + +export class PendingTransaction { + public readonly hash: string; + + public readonly methodId: string; + + public readonly nonce: string; + + public readonly sender: string; + + public readonly argsFields: string[]; + + public readonly auxiliaryData: string[]; + + public readonly signature: { r: string; s: string }; + + public readonly isMessage: boolean; + + public static fromJSON( + object: PendingTransactionJSONType + ): PendingTransaction { + return new PendingTransaction({ + hash: object.hash, + methodId: object.methodId, + nonce: object.nonce, + sender: object.sender, + argsFields: object.argsFields.slice(), + auxiliaryData: object.auxiliaryData.slice(), + signature: { r: object.signature.r, s: object.signature.s }, + isMessage: object.isMessage, + }); + } + + public constructor(data: { + hash: string; + methodId: string; + nonce: string; + sender: string; + argsFields: string[]; + auxiliaryData: string[]; + signature: { r: string; s: string }; + isMessage: boolean; + }) { + this.hash = data.hash; + this.methodId = data.methodId; + this.nonce = data.nonce; + this.sender = data.sender; + this.argsFields = data.argsFields; + this.auxiliaryData = data.auxiliaryData; + this.signature = data.signature; + this.isMessage = data.isMessage; + } + + public toJSON(): PendingTransactionJSONType { + return { + hash: this.hash, + methodId: this.methodId, + nonce: this.nonce, + sender: this.sender, + argsFields: this.argsFields.slice(), + auxiliaryData: this.auxiliaryData.slice(), + signature: { r: this.signature.r, s: this.signature.s }, + isMessage: this.isMessage, + }; + } + + public toRuntimeTransaction(): RuntimeTransaction { + const isSome = Bool(!this.isMessage); + return new RuntimeTransaction({ + methodId: Field(this.methodId), + argsHash: Poseidon.hash(this.argsFields.map((f) => Field(f))), + nonce: new UInt64Option({ value: UInt64.from(this.nonce), isSome }), + sender: new PublicKeyOption({ + value: PublicKey.fromBase58(this.sender), + isSome, + }), + }); + } + + public toProtocolTransaction(): SignedTransaction { + return new SignedTransaction({ + transaction: this.toRuntimeTransaction(), + signature: Signature.fromJSON(this.signature), + }); + } +} + export class UnsignedTransaction implements UnsignedTransactionBody { public readonly methodId: Field; @@ -104,92 +204,16 @@ export class UnsignedTransaction implements UnsignedTransactionBody { }); } - public signed(signature: Signature): PendingTransaction { - // eslint-disable-next-line @typescript-eslint/no-use-before-define + public signed(signature: Signature) { return new PendingTransaction({ - methodId: this.methodId, - sender: this.sender, - nonce: this.nonce, - signature, - argsFields: this.argsFields, - auxiliaryData: this.auxiliaryData, - isMessage: this.isMessage, - }); - } -} - -interface PendingTransactionJSONType { - hash: string; - methodId: string; - nonce: string; - sender: string; - argsFields: string[]; - auxiliaryData: string[]; - signature: { - r: string; - s: string; - }; - isMessage: boolean; -} - -export class PendingTransaction extends UnsignedTransaction { - public static fromJSON( - object: PendingTransactionJSONType - ): PendingTransaction { - return new PendingTransaction( - { - methodId: Field.fromJSON(object.methodId), - nonce: UInt64.from(object.nonce), - sender: PublicKey.fromBase58(object.sender), - argsFields: object.argsFields.map((x) => Field.fromJSON(x)), - signature: Signature.fromJSON(object.signature), - auxiliaryData: object.auxiliaryData.slice(), - isMessage: object.isMessage, - }, - Field(object.hash) - ); - } - - public signature: Signature; - - public constructor( - data: { - methodId: Field; - nonce: UInt64; - sender: PublicKey; - signature: Signature; - argsFields: Field[]; - auxiliaryData: string[]; - isMessage: boolean; - }, - memoizedHash?: Field - ) { - super(data, memoizedHash); - this.signature = data.signature; - } - - public toJSON(): PendingTransactionJSONType { - return { hash: this.hash().toString(), - methodId: this.methodId.toJSON(), - nonce: this.nonce.toString(), + methodId: this.methodId.toString(), sender: this.sender.toBase58(), - argsFields: this.argsFields.map((x) => x.toJSON()), - auxiliaryData: this.auxiliaryData.slice(), + nonce: this.nonce.toString(), + signature: { r: signature.r.toJSON(), s: signature.s.toJSON() }, + argsFields: this.argsFields.map((f) => f.toString()), + auxiliaryData: this.auxiliaryData, isMessage: this.isMessage, - - signature: { - r: this.signature.r.toJSON(), - - s: this.signature.s.toJSON(), - }, - }; - } - - public toProtocolTransaction(): SignedTransaction { - return new SignedTransaction({ - transaction: this.toRuntimeTransaction(), - signature: this.signature, }); } } diff --git a/packages/sequencer/src/mempool/private/PrivateMempool.ts b/packages/sequencer/src/mempool/private/PrivateMempool.ts index e750060ea..d4de6f09b 100644 --- a/packages/sequencer/src/mempool/private/PrivateMempool.ts +++ b/packages/sequencer/src/mempool/private/PrivateMempool.ts @@ -9,6 +9,7 @@ import { AccountStateHook, BlockHashMerkleTree, MandatoryProtocolModulesRecord, + ProvableNetworkState, NetworkState, Protocol, ProvableHookBlockState, @@ -19,7 +20,7 @@ import { import { Field } from "o1js"; import type { Mempool, MempoolEvents } from "../Mempool"; -import type { PendingTransaction } from "../PendingTransaction"; +import { PendingTransaction } from "../PendingTransaction"; import { sequencerModule, SequencerModule, @@ -35,7 +36,7 @@ import { trace } from "../../logging/trace"; type MempoolTransactionPaths = { transaction: PendingTransaction; - paths: Field[]; + paths: string[]; }; interface PrivateMempoolConfig { @@ -79,23 +80,21 @@ export class PrivateMempool const success = await this.transactionStorage.pushUserTransaction(tx); if (success) { this.events.emit("mempool-transaction-added", tx); - log.trace(`Transaction added to mempool: ${tx.hash().toString()}`); + log.trace(`Transaction added to mempool: ${tx.hash}`); } else { - log.error( - `Transaction ${tx.hash().toString()} rejected: already exists in mempool` - ); + log.error(`Transaction ${tx.hash} rejected: already exists in mempool`); } return success; } log.error( - `Validation of tx ${tx.hash().toString()} failed:`, + `Validation of tx ${tx.hash} failed:`, `${error ?? "unknown error"}` ); throw new Error( - `Validation of tx ${tx.hash().toString()} failed: ${error ?? "unknown error"}` + `Validation of tx ${tx.hash} failed: ${error ?? "unknown error"}` ); } @@ -122,8 +121,12 @@ export class PrivateMempool const baseCachedStateService = new CachedStateService(this.stateService); + // Should provide ProvableNetworkState to checkTxValid. + const stagedNetworkState = await this.getStagedNetworkState(); + const networkState = - (await this.getStagedNetworkState()) ?? NetworkState.empty(); + stagedNetworkState || + ProvableNetworkState.toJSON(ProvableNetworkState.empty()); const validationEnabled = this.config.validationEnabled ?? false; const sortedTxs = validationEnabled @@ -174,12 +177,17 @@ export class PrivateMempool blockHashRoot: Field( previousBlock?.result.blockHashRoot ?? BlockHashMerkleTree.EMPTY_ROOT ), - eternalTransactionsHash: - previousBlock?.block.toEternalTransactionsHash ?? Field(0), - transactionsHash: previousBlock?.block.transactionsHash ?? Field(0), - incomingMessagesHash: previousBlock?.block.toMessagesHash ?? Field(0), + eternalTransactionsHash: Field( + previousBlock?.block.toEternalTransactionsHash ?? 0 + ), + transactionsHash: Field(previousBlock?.block.transactionsHash ?? 0), + incomingMessagesHash: Field(previousBlock?.block.toMessagesHash ?? 0), }; + const provableNetworkState = new ProvableNetworkState( + ProvableNetworkState.fromJSON(networkState) + ); + while ( queue.length > 0 && sortedTransactions.length < (limit ?? Number.MAX_VALUE) @@ -188,7 +196,7 @@ export class PrivateMempool const txStateService = new CachedStateService(baseService); stateServiceProvider.setCurrentStateService(txStateService); const contextInputs: RuntimeMethodExecutionData = { - networkState: networkState, + networkState: provableNetworkState, transaction: tx.toProtocolTransaction().transaction, }; executionContext.setup(contextInputs); @@ -197,7 +205,7 @@ export class PrivateMempool // eslint-disable-next-line no-await-in-loop await this.accountStateHook.beforeTransaction({ - networkState: networkState, + networkState: provableNetworkState, transaction: signedTransaction.transaction, signature: signedTransaction.signature, prover: proverState, @@ -206,18 +214,18 @@ export class PrivateMempool executionContext.current().result; if (status.toBoolean()) { - log.trace(`Accepted tx ${tx.hash().toString()}`); + log.trace(`Accepted tx ${tx.hash}`); sortedTransactions.push(tx); // eslint-disable-next-line no-await-in-loop await txStateService.applyStateTransitions(stateTransitions); // eslint-disable-next-line no-await-in-loop await txStateService.mergeIntoParent(); - delete skippedTransactions[tx.hash().toString()]; + delete skippedTransactions[tx.hash]; if (Object.entries(skippedTransactions).length > 0) { // eslint-disable-next-line @typescript-eslint/no-loop-func stateTransitions.forEach((st) => { Object.values(skippedTransactions).forEach((value) => { - if (value.paths.some((x) => x.equals(st.path))) { + if (value.paths.some((x) => x === st.path.toString())) { queue.push(value.transaction); } }); @@ -227,33 +235,29 @@ export class PrivateMempool } else { // eslint-disable-next-line no-await-in-loop const removeTxWhen = await this.accountStateHook.removeTransactionWhen({ - networkState: networkState, + networkState: provableNetworkState, transaction: signedTransaction.transaction, signature: signedTransaction.signature, prover: proverState, }); if (removeTxWhen) { // eslint-disable-next-line no-await-in-loop - await this.transactionStorage.removeTx( - [tx.hash().toString()], - "dropped" - ); + await this.transactionStorage.removeTx([tx.hash], "dropped"); log.trace( - `Deleting tx ${tx.hash().toString()} from mempool because removeTransactionWhen condition is satisfied` + `Deleting tx ${tx.hash} from mempool because removeTransactionWhen condition is satisfied` ); // eslint-disable-next-line no-continue continue; } - log.trace( - `Skipped tx ${tx.hash().toString()} because ${statusMessage}` - ); - if (!(tx.hash().toString() in skippedTransactions)) { - skippedTransactions[tx.hash().toString()] = { + log.trace(`Skipped tx ${tx.hash} because ${statusMessage}`); + if (!(tx.hash in skippedTransactions)) { + skippedTransactions[tx.hash] = { transaction: tx, paths: stateTransitions .map((x) => x.path) - .filter((id, idx, arr) => arr.indexOf(id) === idx), + .filter((id, idx, arr) => arr.indexOf(id) === idx) + .map((f) => f.toString()), }; } stateServiceProvider.popCurrentStateService(); diff --git a/packages/sequencer/src/mempool/verification/TransactionValidator.ts b/packages/sequencer/src/mempool/verification/TransactionValidator.ts index c839ecece..aae6fde51 100644 --- a/packages/sequencer/src/mempool/verification/TransactionValidator.ts +++ b/packages/sequencer/src/mempool/verification/TransactionValidator.ts @@ -4,6 +4,7 @@ import { Runtime, RuntimeModulesRecord, } from "@proto-kit/module"; +import { Signature } from "o1js"; import { PendingTransaction } from "../PendingTransaction"; @@ -20,7 +21,7 @@ export class TransactionValidator { // module name validation happens inside getMethodNameFromId // and also in the next step const methodPath = this.runtime.methodIdResolver.getMethodNameFromId( - tx.methodId.toBigInt() + tx.methodId ); if (methodPath === undefined) { @@ -45,10 +46,14 @@ export class TransactionValidator { return [false, methodError]; } - const validSignature = tx.signature.verify( - tx.sender, - tx.getSignatureData() - ); + const signature = Signature.fromJSON(tx.signature); + const runtimeTx = tx.toRuntimeTransaction(); + + const validSignature = signature.verify(runtimeTx.sender.value, [ + runtimeTx.methodId, + ...runtimeTx.nonce.value.value.toFields(), + runtimeTx.argsHash, + ]); if (!validSignature.toBoolean()) { return [false, "Signature provided is not valid"]; diff --git a/packages/sequencer/src/protocol/production/BatchProducerModule.ts b/packages/sequencer/src/protocol/production/BatchProducerModule.ts index 545190624..021c779b1 100644 --- a/packages/sequencer/src/protocol/production/BatchProducerModule.ts +++ b/packages/sequencer/src/protocol/production/BatchProducerModule.ts @@ -4,7 +4,7 @@ import { BlockProverPublicOutput, NetworkState, } from "@proto-kit/protocol"; -import { Field, Proof } from "o1js"; +import { Proof } from "o1js"; import { log, noop } from "@proto-kit/common"; import { @@ -22,7 +22,7 @@ import { BlockProofSerializer } from "./tasks/serializers/BlockProofSerializer"; import { BatchTracingService } from "./tracing/BatchTracingService"; import { BatchFlow } from "./flow/BatchFlow"; -export type StateRecord = Record; +export type StateRecord = Record; interface BatchMetadata { batch: SettleableBatch; @@ -141,7 +141,7 @@ export class BatchProducerModule extends SequencerModule { ): Promise { const batch = await this.computeBatch(blocks, height); - const blockHashes = blocks.map((bundle) => bundle.block.hash.toString()); + const blockHashes = blocks.map((bundle) => bundle.block.hash); const jsonProof = this.blockProofSerializer .getBlockProofSerializer() diff --git a/packages/sequencer/src/protocol/production/flow/TransactionFlow.ts b/packages/sequencer/src/protocol/production/flow/TransactionFlow.ts index d124a352c..728524a3d 100644 --- a/packages/sequencer/src/protocol/production/flow/TransactionFlow.ts +++ b/packages/sequencer/src/protocol/production/flow/TransactionFlow.ts @@ -53,7 +53,7 @@ export class TransactionFlow { public async proveRuntimes( trace: TransactionTrace, - blockHeight: string, + blockHeight: number, txIndex: number, callback: (params: TransactionProvingTaskParameters) => Promise ) { diff --git a/packages/sequencer/src/protocol/production/helpers/UntypedOption.ts b/packages/sequencer/src/protocol/production/helpers/UntypedOption.ts index bad6e485f..b40f087ea 100644 --- a/packages/sequencer/src/protocol/production/helpers/UntypedOption.ts +++ b/packages/sequencer/src/protocol/production/helpers/UntypedOption.ts @@ -1,15 +1,25 @@ -import { Bool, Field } from "o1js"; -import { Option, OptionBase } from "@proto-kit/protocol"; +import { Bool, Field, Poseidon } from "o1js"; +import { Option, ProvableOption } from "@proto-kit/protocol"; + +export class UntypedOption { + public constructor( + public isSome: boolean, + public value: string[], + public isForcedSome: boolean + ) {} + + public get treeValue(): string { + if (this.isSome && !this.isForcedSome) { + return Poseidon.hash(this.encodeValueToFields()).toString(); + } + return "0"; + } -/** - * Option facilitating in-circuit values that may or may not exist. - */ -export class UntypedOption extends OptionBase { public static fromOption(option: Option | Option) { return new UntypedOption( - option.isSome, - option.encodeValueToFields(), - option.isForcedSome + option.isSome.toBoolean(), + option.encodeValueToFields().map((f) => f.toString()), + option.isForcedSome.toBoolean() ); } @@ -22,26 +32,34 @@ export class UntypedOption extends OptionBase { value: string[]; isForcedSome: boolean; }): UntypedOption { - return new UntypedOption( - Bool(isSome), - value.map((fieldString) => Field(fieldString)), - Bool(isForcedSome) - ); + return new UntypedOption(isSome, value, isForcedSome); } - public constructor( - isSome: Bool, - public value: Field[], - enforceEmpty: Bool - ) { - super(isSome, enforceEmpty); + public toJSON() { + return { + isSome: this.isSome, + value: this.value, + isForcedSome: this.isForcedSome, + }; } public clone() { - return new UntypedOption(this.isSome, this.value, this.isForcedSome); + return new UntypedOption(this.isSome, [...this.value], this.isForcedSome); + } + + public forceSome() { + this.isForcedSome = !this.isSome; + this.isSome = true; + } + + public encodeValueToFields(): Field[] { + return this.value.map((fieldString) => Field(fieldString)); } - protected encodeValueToFields(): Field[] { - return this.value; + public toProvable(): ProvableOption { + return new ProvableOption({ + isSome: Bool(this.isSome), + value: Field(this.treeValue), + }); } } diff --git a/packages/sequencer/src/protocol/production/helpers/UntypedStateTransition.ts b/packages/sequencer/src/protocol/production/helpers/UntypedStateTransition.ts index 425f01445..a5d9c9c0b 100644 --- a/packages/sequencer/src/protocol/production/helpers/UntypedStateTransition.ts +++ b/packages/sequencer/src/protocol/production/helpers/UntypedStateTransition.ts @@ -3,14 +3,10 @@ import { ProvableStateTransition, StateTransition } from "@proto-kit/protocol"; import { UntypedOption } from "./UntypedOption"; -/** - * Generic state transition that constraints the current method circuit - * to external state, by providing a state anchor. - */ export class UntypedStateTransition { public static fromStateTransition(st: StateTransition) { return new UntypedStateTransition( - st.path, + st.path.toString(), UntypedOption.fromOption(st.fromValue), UntypedOption.fromOption(st.toValue) ); @@ -26,45 +22,34 @@ export class UntypedStateTransition { to: Parameters[0]; }): UntypedStateTransition { return new UntypedStateTransition( - Field(path), + path, UntypedOption.fromJSON(from), UntypedOption.fromJSON(to) ); } public constructor( - public path: Field, - public fromValue: UntypedOption, - public toValue: UntypedOption + public path: string, + public from: UntypedOption, + public to: UntypedOption ) {} - public get from() { - const from = this.fromValue.clone(); - from.forceSome(); - return from; - } - - public get to() { - return this.toValue.clone(); + public toJSON() { + return { + path: this.path, + from: this.from.toJSON(), + to: this.to.toJSON(), + }; } - /** - * Converts a StateTransition to a ProvableStateTransition, - * while enforcing the 'from' property to be 'Some' in all cases. - */ public toProvable(): ProvableStateTransition { + const from = this.from.clone(); + from.forceSome(); + return new ProvableStateTransition({ - path: this.path, - from: this.from.toProvable(), + path: Field(this.path), + from: from.toProvable(), to: this.to.toProvable(), }); } - - public toJSON() { - return { - path: this.path.toString(), - from: this.fromValue.toJSON(), - to: this.toValue.toJSON(), - }; - } } diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts b/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts index 8f035c338..ffa600922 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockProducerModule.ts @@ -74,7 +74,7 @@ export class BlockProducerModule extends SequencerModule { private prettyPrintBlockContents(block: Block) { block.transactions.forEach((tx, i) => { const methodName = this.methodIdResolver.getMethodNameFromId( - tx.tx.methodId.toBigInt() + tx.tx.methodId ); if (!methodName) return; @@ -86,12 +86,7 @@ export class BlockProducerModule extends SequencerModule { log.info("---------------------------------------"); log.info(`Transaction #${i}`); - log.info( - "Sender:", - tx.tx.sender.toBase58(), - "Nonce:", - tx.tx.nonce.toBigInt() - ); + log.info("Sender:", tx.tx.sender, "Nonce:", tx.tx.nonce); log.info(`Method: ${methodName?.join(".")}`); log.info(); if (log.getLevel() <= log.levels.INFO) { @@ -101,7 +96,7 @@ export class BlockProducerModule extends SequencerModule { ); } log.info( - `Status: ${tx.status.toBoolean()}`, + `Status: ${tx.status ? "true" : "false"}`, tx.statusMessage !== undefined ? `Reason: ${tx.statusMessage}` : "" ); }); @@ -110,10 +105,10 @@ export class BlockProducerModule extends SequencerModule { } } - @trace("block.result", ([block]) => ({ height: block.height.toString() })) + @trace("block.result", ([block]) => ({ height: block.height })) public async generateMetadata(block: Block): Promise { const traceMetadata = { - height: block.height.toString(), + height: block.height, }; const { result, blockHashTreeStore, treeStore, stateService } = @@ -155,7 +150,7 @@ export class BlockProducerModule extends SequencerModule { } log.info( - `Produced block #${block.height.toBigInt()} (${block.transactions.length} txs)` + `Produced block #${block.height} (${block.transactions.length} txs)` ); this.prettyPrintBlockContents(block); @@ -193,7 +188,7 @@ export class BlockProducerModule extends SequencerModule { metadata = BlockWithResult.createEmpty(); } else if (parentBlock.result === undefined) { throw new Error( - `Metadata for block at height ${parentBlock.block.height.toString()} not available` + `Metadata for block at height ${parentBlock.block.height} not available` ); } else { metadata = { @@ -248,7 +243,7 @@ export class BlockProducerModule extends SequencerModule { await this.blockQueue.pushBlock(block); }), { - height: block.height.toString(), + height: block.height, } ); diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts b/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts index 18010fa28..e585b8f27 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockProductionService.ts @@ -3,7 +3,7 @@ import { BeforeBlockHookArguments, MandatoryProtocolModulesRecord, MinaActionsHashList, - NetworkState, + ProvableNetworkState, Protocol, ProtocolModulesRecord, ProvableBlockHook, @@ -14,7 +14,7 @@ import { TransactionHashList, } from "@proto-kit/protocol"; import { Field } from "o1js"; -import { log } from "@proto-kit/common"; +import { log, FieldString } from "@proto-kit/common"; import { match } from "ts-pattern"; import { @@ -63,7 +63,7 @@ export class BlockProductionService { @trace("block.hook.before") public async executeBeforeBlockHook( args: BeforeBlockHookArguments, - inputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, cachedStateService: CachedStateService ) { this.stateServiceProvider.setCurrentStateService(cachedStateService); @@ -76,7 +76,7 @@ export class BlockProductionService { const executionResult = await executeWithExecutionContext( async () => - await this.blockHooks.reduce>( + await this.blockHooks.reduce>( async (networkState, hook) => await hook.beforeBlock(await networkState, args), Promise.resolve(inputNetworkState) @@ -120,16 +120,20 @@ export class BlockProductionService { const blockState: BlockTrackers = { blockHashRoot: Field(lastResult.blockHashRoot), eternalTransactionsList: new TransactionHashList( - lastBlock.toEternalTransactionsHash + Field(lastBlock.toEternalTransactionsHash) ), transactionList: new TransactionHashList(), - incomingMessages: new MinaActionsHashList(lastBlock.toMessagesHash), + incomingMessages: new MinaActionsHashList( + Field(lastBlock.toMessagesHash) + ), }; // Get used networkState by executing beforeBlock() hooks const beforeHookResult = await this.executeBeforeBlockHook( toProvableHookBlockState(blockState), - lastResult.afterNetworkState, + new ProvableNetworkState( + ProvableNetworkState.fromJSON(lastResult.afterNetworkState) + ), stateService ); @@ -149,7 +153,9 @@ export class BlockProductionService { ); const previousBlockHash = - lastResult.blockHash === 0n ? undefined : Field(lastResult.blockHash); + lastResult.blockHash === "0" + ? undefined + : FieldString(lastResult.blockHash); if (executionResults.length === 0 && !allowEmptyBlocks) { log.info( @@ -164,33 +170,32 @@ export class BlockProductionService { const block: Omit = { transactions: includedTransactions, - transactionsHash: newBlockState.transactionList.commitment, + transactionsHash: FieldString(newBlockState.transactionList.commitment), fromEternalTransactionsHash: lastBlock.toEternalTransactionsHash, - toEternalTransactionsHash: - newBlockState.eternalTransactionsList.commitment, - height: - lastBlock.hash.toBigInt() !== 0n ? lastBlock.height.add(1) : Field(0), - fromBlockHashRoot: Field(lastResult.blockHashRoot), + toEternalTransactionsHash: FieldString( + newBlockState.eternalTransactionsList.commitment + ), + height: lastBlock.hash !== "0" ? lastBlock.height + 1 : 0, + fromBlockHashRoot: FieldString(lastResult.blockHashRoot), fromMessagesHash: lastBlock.toMessagesHash, - fromStateRoot: Field(lastResult.stateRoot), - toMessagesHash: newBlockState.incomingMessages.commitment, + fromStateRoot: FieldString(lastResult.stateRoot), + toMessagesHash: FieldString(newBlockState.incomingMessages.commitment), previousBlockHash, networkState: { - before: new NetworkState(lastResult.afterNetworkState), - during: networkState, + before: lastResult.afterNetworkState, + during: ProvableNetworkState.toJSON(networkState), }, - beforeBlockStateTransitions, + beforeBlockStateTransitions: beforeBlockStateTransitions, }; - const hash = Block.hash(block); + const hash = Block.hash(block).toString(); const includedTxs = executionResults.map((x) => { const txHash = match(x) .with({ status: "included" }, ({ result }) => result.tx) - .otherwise(({ tx }) => tx) - .hash() - .toString(); + .otherwise(({ tx }) => tx).hash; + return { hash: txHash, type: x.status, diff --git a/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts b/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts index 5419344bb..2ba26bce5 100644 --- a/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/BlockResultService.ts @@ -1,11 +1,12 @@ import { Bool, Field, Poseidon } from "o1js"; -import { LinkedMerkleTree } from "@proto-kit/common"; +import { LinkedMerkleTree, FieldString } from "@proto-kit/common"; import { AfterBlockHookArguments, BlockHashMerkleTree, + BlockHashMerkleTreeWitness, BlockHashTreeEntry, MandatoryProtocolModulesRecord, - NetworkState, + ProvableNetworkState, Protocol, ProtocolModulesRecord, ProvableBlockHook, @@ -36,15 +37,12 @@ import { executeWithExecutionContext } from "./TransactionExecutionService"; function collectOrderedStateDiff( stateTransitions: UntypedStateTransition[] ): StateRecord { - return stateTransitions.reduce>( - (state, st) => { - if (st.toValue.isSome.toBoolean()) { - state[st.path.toString()] = st.toValue.value; - } - return state; - }, - {} - ); + return stateTransitions.reduce((state, st) => { + if (st.to.isSome) { + state[st.path] = st.to.value; + } + return state; + }, {}); } function createCombinedOrderedStateDiff( @@ -56,7 +54,9 @@ function createCombinedOrderedStateDiff( .map((tx) => { const transitions = tx.stateTransitions .filter(({ applied }) => applied) - .flatMap(({ stateTransitions }) => stateTransitions); + .flatMap(({ stateTransitions }) => + stateTransitions.map((st) => UntypedStateTransition.fromJSON(st)) + ); transitions.push(...blockHookSTs); @@ -88,7 +88,7 @@ export class BlockResultService { @trace("block.hook.after") public async executeAfterBlockHook( args: AfterBlockHookArguments, - inputNetworkState: NetworkState, + inputNetworkState: ProvableNetworkState, asyncStateService: AsyncStateService ) { const cachedStateService = new CachedStateService(asyncStateService); @@ -102,7 +102,7 @@ export class BlockResultService { const executionResult = await executeWithExecutionContext( async () => - await this.blockHooks.reduce>( + await this.blockHooks.reduce>( async (networkState, hook) => await hook.afterBlock(await networkState, args), Promise.resolve(inputNetworkState) @@ -131,21 +131,21 @@ export class BlockResultService { ); // TODO This can be optimized a lot (we are only interested in the root at this step) - await blockHashInMemoryStore.preloadKey(block.height.toBigInt()); + await blockHashInMemoryStore.preloadKey(BigInt(block.height)); const blockHashTree = new BlockHashMerkleTree(blockHashInMemoryStore); blockHashTree.setLeaf( - block.height.toBigInt(), + BigInt(block.height), new BlockHashTreeEntry({ block: { - index: block.height, - transactionListHash: block.transactionsHash, + index: Field(block.height), + transactionListHash: Field(block.transactionsHash), }, closed: Bool(true), }).hash() ); - const blockHashWitness = blockHashTree.getWitness(block.height.toBigInt()); + const blockHashWitness = blockHashTree.getWitness(BigInt(block.height)); const newBlockHashRoot = blockHashTree.getRoot(); return { @@ -171,7 +171,8 @@ export class BlockResultService { const tree = new LinkedMerkleTree(store.treeStore, store); const writes = Object.entries(stateDiff).map(([key, state]) => { - const treeValue = state !== undefined ? Poseidon.hash(state) : Field(0); + const treeValue = + state !== undefined ? Poseidon.hash(state.map(Field)) : Field(0); return { path: BigInt(key), value: treeValue.toBigInt() }; }); tree.setLeaves(writes); @@ -184,7 +185,7 @@ export class BlockResultService { } @trace("block.result.generate", ([block]) => ({ - height: block.height.toString(), + height: block.height, })) public async generateMetadataForNextBlock( block: Block, @@ -218,11 +219,13 @@ export class BlockResultService { { blockHashRoot, stateRoot: witnessedStateRoot, - incomingMessagesHash: block.toMessagesHash, - transactionsHash: block.transactionsHash, - eternalTransactionsHash: block.toEternalTransactionsHash, + incomingMessagesHash: Field(block.toMessagesHash), + transactionsHash: Field(block.transactionsHash), + eternalTransactionsHash: Field(block.toEternalTransactionsHash), }, - block.networkState.during, + new ProvableNetworkState( + ProvableNetworkState.fromJSON(block.networkState.during) + ), stateService ); @@ -240,17 +243,17 @@ export class BlockResultService { return { result: { - afterNetworkState: methodResult, + afterNetworkState: ProvableNetworkState.toJSON(methodResult), // This is the state root after the last tx and the afterBlock hook - stateRoot: stateRoot.toBigInt(), - witnessedRoots: [witnessedStateRoot.toBigInt()], - blockHashRoot: blockHashRoot.toBigInt(), - blockHashWitness, + stateRoot: FieldString(stateRoot), + witnessedRoots: [FieldString(witnessedStateRoot)], + blockHashRoot: FieldString(blockHashRoot), + blockHashWitness: BlockHashMerkleTreeWitness.toJSON(blockHashWitness), afterBlockStateTransitions: stateTransitions.map((st) => UntypedStateTransition.fromStateTransition(st) ), - blockHash: block.hash.toBigInt(), + blockHash: FieldString(block.hash), }, treeStore: inMemoryStore, blockHashTreeStore: cachedBlockHashTreeStore, diff --git a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts index 24dc9852a..b213c8f36 100644 --- a/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts +++ b/packages/sequencer/src/protocol/production/sequencing/TransactionExecutionService.ts @@ -2,7 +2,7 @@ import assert from "node:assert"; import { container, inject, injectable, Lifecycle, scoped } from "tsyringe"; import { - NetworkState, + ProvableNetworkState, Protocol, ProtocolModulesRecord, ProvableTransactionHook, @@ -87,13 +87,13 @@ async function decodeTransaction( module: RuntimeModule; }> { const methodDescriptors = runtime.methodIdResolver.getMethodNameFromId( - tx.methodId.toBigInt() + tx.methodId ); - const method = runtime.getMethodById(tx.methodId.toBigInt()); + const method = runtime.getMethodById(tx.methodId); if (methodDescriptors === undefined || method === undefined) { - throw errors.methodIdNotFound(tx.methodId.toString()); + throw errors.methodIdNotFound(tx.methodId); } const [moduleName, methodName] = methodDescriptors; @@ -326,7 +326,7 @@ export class TransactionExecutionService { public async createExecutionTraces( asyncStateService: CachedStateService, transactions: PendingTransaction[], - networkState: NetworkState, + networkState: ProvableNetworkState, state: BlockTrackers ): Promise<{ blockState: BlockTrackers; @@ -354,10 +354,7 @@ export class TransactionExecutionService { // If the hooks fail AND the tx is not a message (in which case we // have to still execute it), we skip this tx and don't add it to the block - if ( - !executionTrace.hooksStatus.toBoolean() && - !executionTrace.tx.isMessage - ) { + if (!executionTrace.hooksStatus && !executionTrace.tx.isMessage) { const actionMessage = shouldRemove ? "removing as to removeWhen hooks" : "skipping"; @@ -410,10 +407,13 @@ export class TransactionExecutionService { { networkState, hash: networkStateHash, - }: { networkState: NetworkState; hash: Field }, + }: { networkState: ProvableNetworkState; hash: Field }, state: BlockTrackers, newState: BlockTrackers - ): Promise<{ result: TransactionExecutionResult; shouldRemove: boolean }> { + ): Promise<{ + result: TransactionExecutionResult; + shouldRemove: boolean; + }> { // TODO Use RecordingStateService -> async asProver needed const recordingStateService = new CachedStateService(asyncStateService); @@ -485,7 +485,7 @@ export class TransactionExecutionService { status: runtimeResult.status, networkStateHash: networkStateHash, isMessage: Bool(tx.isMessage), - transactionHash: tx.hash(), + transactionHash: Field(tx.hash), eventsHash, stateTransitionsHash, }) @@ -539,15 +539,21 @@ export class TransactionExecutionService { return { result: { tx, - hooksStatus: Bool(txHooksValid), - status: runtimeResult.status, + hooksStatus: txHooksValid, + status: runtimeResult.status.toBoolean(), statusMessage: beforeTxHookResult.statusMessage ?? afterTxHookResult.statusMessage ?? runtimeResult.statusMessage, - stateTransitions, - events: beforeHookEvents.concat(runtimeResultEvents, afterHookEvents), + stateTransitions: stateTransitions, + events: beforeHookEvents + .concat(runtimeResultEvents, afterHookEvents) + .map((e) => ({ + eventName: e.eventName, + data: e.data.map((f) => f.toString()), + source: e.source, + })), }, shouldRemove, }; diff --git a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts index 338ce9514..ab5696211 100644 --- a/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/NewBlockTask.ts @@ -2,7 +2,7 @@ import { inject, injectable, Lifecycle, scoped } from "tsyringe"; import { BlockProvable, BlockProverPublicInput, - NetworkState, + ProvableNetworkState, Protocol, StateTransitionProof, StateTransitionProvable, @@ -23,19 +23,19 @@ import { Task, TaskSerializer } from "../../../worker/flow/Task"; import { ProofTaskSerializer } from "../../../helpers/utils"; import { TaskWorkerModule } from "../../../worker/worker/TaskWorkerModule"; import { PairingDerivedInput } from "../flow/ReductionTaskFlow"; -import type { TaskStateRecord } from "../tracing/BlockTracingService"; import { NewBlockProvingParametersSerializer } from "./serializers/NewBlockProvingParametersSerializer"; import { executeWithPrefilledStateService } from "./TransactionProvingTask"; +import { JSONEncodableState } from "./serializers/DecodedStateSerializer"; export interface NewBlockProverParameters { publicInput: BlockProverPublicInput; - networkState: NetworkState; + networkState: ProvableNetworkState; blockWitness: BlockHashMerkleTreeWitness; deferSTProof: Bool; afterBlockRootWitness: WitnessedRootWitness; - startingStateBeforeHook: TaskStateRecord; - startingStateAfterHook: TaskStateRecord; + startingStateBeforeHook: JSONEncodableState; + startingStateAfterHook: JSONEncodableState; } export type NewBlockProvingParameters = PairingDerivedInput< diff --git a/packages/sequencer/src/protocol/production/tasks/RuntimeProvingTask.ts b/packages/sequencer/src/protocol/production/tasks/RuntimeProvingTask.ts index 3fe0756d3..a444bbc58 100644 --- a/packages/sequencer/src/protocol/production/tasks/RuntimeProvingTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/RuntimeProvingTask.ts @@ -6,6 +6,7 @@ import { } from "@proto-kit/module"; import { MethodPublicOutput, + ProvableNetworkState, NetworkState, RuntimeMethodExecutionContext, } from "@proto-kit/protocol"; @@ -17,16 +18,19 @@ import { ProofTaskSerializer } from "../../../helpers/utils"; import { TaskWorkerModule } from "../../../worker/worker/TaskWorkerModule"; import { PreFilledStateService } from "../../../state/prefilled/PreFilledStateService"; import { PendingTransaction } from "../../../mempool/PendingTransaction"; -import { TaskStateRecord } from "../tracing/BlockTracingService"; +import { JSONTaskSerializer } from "../../../worker/flow/JSONTaskSerializer"; -import { RuntimeProofParametersSerializer } from "./serializers/RuntimeProofParametersSerializer"; +import { + DecodedStateSerializer, + JSONEncodableState, +} from "./serializers/DecodedStateSerializer"; type RuntimeProof = Proof; export interface RuntimeProofParameters { - tx: PendingTransaction; + tx: ReturnType; networkState: NetworkState; - state: TaskStateRecord; + state: JSONEncodableState; } @injectable() @@ -49,7 +53,7 @@ export class RuntimeProvingTask } public inputSerializer(): TaskSerializer { - return new RuntimeProofParametersSerializer(); + return JSONTaskSerializer.fromType(); } public resultSerializer(): TaskSerializer { @@ -57,14 +61,14 @@ export class RuntimeProvingTask } public async compute(input: RuntimeProofParameters): Promise { - const method = this.runtime.getMethodById(input.tx.methodId.toBigInt()); + const method = this.runtime.getMethodById(input.tx.methodId); const methodDescriptors = this.runtime.dependencyContainer .resolve("MethodIdResolver") - .getMethodNameFromId(input.tx.methodId.toBigInt()); + .getMethodNameFromId(input.tx.methodId); if (methodDescriptors === undefined || method === undefined) { - throw new Error(`MethodId not found ${input.tx.methodId.toString()}`); + throw new Error(`MethodId not found ${input.tx.methodId}`); } const [moduleName, methodName] = methodDescriptors; @@ -78,15 +82,21 @@ export class RuntimeProvingTask input.tx.auxiliaryData ); - const prefilledStateService = new PreFilledStateService(input.state); + const prefilledStateService = new PreFilledStateService( + DecodedStateSerializer.fromJSON(input.state) + ); this.runtime.stateServiceProvider.setCurrentStateService( prefilledStateService ); // Set network state and transaction for the runtimemodule to access - const { transaction, signature } = input.tx.toProtocolTransaction(); + const { transaction, signature } = PendingTransaction.fromJSON( + input.tx + ).toProtocolTransaction(); const contextInputs = { - networkState: input.networkState, + networkState: new ProvableNetworkState( + ProvableNetworkState.fromJSON(input.networkState) + ), transaction, signature, }; diff --git a/packages/sequencer/src/protocol/production/tasks/TransactionProvingTask.ts b/packages/sequencer/src/protocol/production/tasks/TransactionProvingTask.ts index de4b80b63..783a22010 100644 --- a/packages/sequencer/src/protocol/production/tasks/TransactionProvingTask.ts +++ b/packages/sequencer/src/protocol/production/tasks/TransactionProvingTask.ts @@ -18,17 +18,20 @@ import { ProofTaskSerializer } from "../../../helpers/utils"; import { TaskSerializer, Task } from "../../../worker/flow/Task"; import { PreFilledStateService } from "../../../state/prefilled/PreFilledStateService"; import { TaskWorkerModule } from "../../../worker/worker/TaskWorkerModule"; -import type { TaskStateRecord } from "../tracing/BlockTracingService"; import { TransactionProvingTaskParameterSerializer } from "./serializers/TransactionProvingTaskParameterSerializer"; import { TransactionProvingTaskParameters, TransactionProvingType, } from "./serializers/types/TransactionProvingTypes"; +import { + DecodedStateSerializer, + JSONEncodableState, +} from "./serializers/DecodedStateSerializer"; export async function executeWithPrefilledStateService( stateServiceProvider: StateServiceProvider, - startingStates: TaskStateRecord[], + startingStates: JSONEncodableState[], callback: () => Promise ): Promise { startingStates @@ -37,7 +40,7 @@ export async function executeWithPrefilledStateService( .forEach((startingState) => { stateServiceProvider.setCurrentStateService( new PreFilledStateService({ - ...startingState, + ...DecodedStateSerializer.fromJSON(startingState), }) ); }); diff --git a/packages/sequencer/src/protocol/production/tasks/serializers/DecodedStateSerializer.ts b/packages/sequencer/src/protocol/production/tasks/serializers/DecodedStateSerializer.ts index 475a223be..14a178ff2 100644 --- a/packages/sequencer/src/protocol/production/tasks/serializers/DecodedStateSerializer.ts +++ b/packages/sequencer/src/protocol/production/tasks/serializers/DecodedStateSerializer.ts @@ -1,7 +1,6 @@ import { Field } from "o1js"; -import type { TaskStateRecord } from "../../tracing/BlockTracingService"; - +export type TaskStateRecord = Record; export type JSONEncodableState = Record; export class DecodedStateSerializer { diff --git a/packages/sequencer/src/protocol/production/tasks/serializers/NewBlockProvingParametersSerializer.ts b/packages/sequencer/src/protocol/production/tasks/serializers/NewBlockProvingParametersSerializer.ts index 58771b1df..4a14c6ecb 100644 --- a/packages/sequencer/src/protocol/production/tasks/serializers/NewBlockProvingParametersSerializer.ts +++ b/packages/sequencer/src/protocol/production/tasks/serializers/NewBlockProvingParametersSerializer.ts @@ -1,7 +1,7 @@ import { BlockHashMerkleTreeWitness, BlockProverPublicInput, - NetworkState, + ProvableNetworkState, ReturnType, StateTransitionProof, StateTransitionProverPublicInput, @@ -18,17 +18,14 @@ import { TaskSerializer } from "../../../../worker/flow/Task"; import { ProofTaskSerializer } from "../../../../helpers/utils"; import { PairingDerivedInput } from "../../flow/ReductionTaskFlow"; -import { - DecodedStateSerializer, - JSONEncodableState, -} from "./DecodedStateSerializer"; +import { JSONEncodableState } from "./DecodedStateSerializer"; interface JsonType { input1: string; input2: string; params: { publicInput: ReturnType; - networkState: ReturnType; + networkState: ReturnType; blockWitness: ReturnType; startingStateBeforeHook: JSONEncodableState; startingStateAfterHook: JSONEncodableState; @@ -65,19 +62,15 @@ export class NewBlockProvingParametersSerializer params: { publicInput: BlockProverPublicInput.toJSON(input.params.publicInput), - networkState: NetworkState.toJSON(input.params.networkState), + networkState: ProvableNetworkState.toJSON(input.params.networkState), blockWitness: BlockHashMerkleTreeWitness.toJSON( input.params.blockWitness ), - startingStateBeforeHook: DecodedStateSerializer.toJSON( - input.params.startingStateBeforeHook - ), + startingStateBeforeHook: input.params.startingStateBeforeHook, - startingStateAfterHook: DecodedStateSerializer.toJSON( - input.params.startingStateAfterHook - ), + startingStateAfterHook: input.params.startingStateAfterHook, deferSTProof: input.params.deferSTProof.toBoolean(), @@ -100,21 +93,17 @@ export class NewBlockProvingParametersSerializer jsonObject.params.publicInput ), - networkState: new NetworkState( - NetworkState.fromJSON(jsonObject.params.networkState) + networkState: new ProvableNetworkState( + ProvableNetworkState.fromJSON(jsonObject.params.networkState) ), blockWitness: new BlockHashMerkleTreeWitness( BlockHashMerkleTreeWitness.fromJSON(jsonObject.params.blockWitness) ), - startingStateBeforeHook: DecodedStateSerializer.fromJSON( - jsonObject.params.startingStateBeforeHook - ), + startingStateBeforeHook: jsonObject.params.startingStateBeforeHook, - startingStateAfterHook: DecodedStateSerializer.fromJSON( - jsonObject.params.startingStateBeforeHook - ), + startingStateAfterHook: jsonObject.params.startingStateAfterHook, deferSTProof: Bool(jsonObject.params.deferSTProof), diff --git a/packages/sequencer/src/protocol/production/tasks/serializers/RuntimeProofParametersSerializer.ts b/packages/sequencer/src/protocol/production/tasks/serializers/RuntimeProofParametersSerializer.ts deleted file mode 100644 index 102d89c09..000000000 --- a/packages/sequencer/src/protocol/production/tasks/serializers/RuntimeProofParametersSerializer.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { NetworkState, ReturnType } from "@proto-kit/protocol"; - -import { TaskSerializer } from "../../../../worker/flow/Task"; -import { PendingTransaction } from "../../../../mempool/PendingTransaction"; -import type { RuntimeProofParameters } from "../RuntimeProvingTask"; - -import { - DecodedStateSerializer, - JSONEncodableState, -} from "./DecodedStateSerializer"; - -export class RuntimeProofParametersSerializer - implements TaskSerializer -{ - public toJSON(parameters: RuntimeProofParameters): string { - const jsonReadyObject = { - tx: parameters.tx.toJSON(), - networkState: NetworkState.toJSON(parameters.networkState), - state: DecodedStateSerializer.toJSON(parameters.state), - }; - return JSON.stringify(jsonReadyObject); - } - - public fromJSON(json: string): RuntimeProofParameters { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const jsonReadyObject: { - tx: ReturnType; - networkState: ReturnType<(typeof NetworkState)["toJSON"]>; - state: JSONEncodableState; - } = JSON.parse(json); - return { - tx: PendingTransaction.fromJSON(jsonReadyObject.tx), - - networkState: new NetworkState( - NetworkState.fromJSON(jsonReadyObject.networkState) - ), - - state: DecodedStateSerializer.fromJSON(jsonReadyObject.state), - }; - } -} diff --git a/packages/sequencer/src/protocol/production/tasks/serializers/TransactionProvingTaskParameterSerializer.ts b/packages/sequencer/src/protocol/production/tasks/serializers/TransactionProvingTaskParameterSerializer.ts index 3e08b804e..a03d7f403 100644 --- a/packages/sequencer/src/protocol/production/tasks/serializers/TransactionProvingTaskParameterSerializer.ts +++ b/packages/sequencer/src/protocol/production/tasks/serializers/TransactionProvingTaskParameterSerializer.ts @@ -1,7 +1,7 @@ import { BlockProverPublicInput, MethodPublicOutput, - NetworkState, + ProvableNetworkState, ReturnType, RuntimeTransaction, TransactionProverTransactionArguments, @@ -15,11 +15,8 @@ import { TransactionProvingTaskParameters, TransactionProvingType, } from "./types/TransactionProvingTypes"; -import { - DecodedStateSerializer, - JSONEncodableState, -} from "./DecodedStateSerializer"; import { RuntimeVerificationKeyAttestationSerializer } from "./RuntimeVerificationKeyAttestationSerializer"; +import { JSONEncodableState } from "./DecodedStateSerializer"; export type TransactionProverTransactionArgumentsJSON = { transaction: ReturnType; @@ -31,13 +28,13 @@ export type TransactionProverTransactionArgumentsJSON = { export type SingleExecutionDataJSON = { transaction: TransactionProverTransactionArgumentsJSON; - networkState: ReturnType; + networkState: ReturnType; }; export type MultiExecutionDataJSON = { transaction1: TransactionProverTransactionArgumentsJSON; transaction2: TransactionProverTransactionArgumentsJSON; - networkState: ReturnType; + networkState: ReturnType; }; export type TransactionProverTaskParametersJSON< @@ -108,9 +105,7 @@ export class TransactionProvingTaskParameterSerializer const partialParameters = { publicInput: BlockProverPublicInput.toJSON(parameters.publicInput), - startingState: parameters.startingState.map((stateRecord) => - DecodedStateSerializer.toJSON(stateRecord) - ), + startingState: parameters.startingState, }; // The reason we can't just use the structs toJSON is that the VerificationKey @@ -119,7 +114,7 @@ export class TransactionProvingTaskParameterSerializer if (type === TransactionProvingType.SINGLE) { const { executionData } = parameters; const executionDataJson: SingleExecutionDataJSON = { - networkState: NetworkState.toJSON(executionData.networkState), + networkState: ProvableNetworkState.toJSON(executionData.networkState), transaction: this.transactionProverArgumentsToJson( executionData.transaction ), @@ -136,7 +131,7 @@ export class TransactionProvingTaskParameterSerializer } else { const { executionData } = parameters; const executionDataJson: MultiExecutionDataJSON = { - networkState: NetworkState.toJSON(executionData.networkState), + networkState: ProvableNetworkState.toJSON(executionData.networkState), transaction1: this.transactionProverArgumentsToJson( executionData.transaction1 ), @@ -171,9 +166,7 @@ export class TransactionProvingTaskParameterSerializer const partialParameters = { publicInput: BlockProverPublicInput.fromJSON(parameters.publicInput), - startingState: parameters.startingState.map((stateRecord) => - DecodedStateSerializer.fromJSON(stateRecord) - ), + startingState: parameters.startingState, }; if (type === TransactionProvingType.SINGLE) { @@ -188,8 +181,10 @@ export class TransactionProvingTaskParameterSerializer transaction: this.transactionProverArgumentsFromJson( parameters.executionData.transaction ), - networkState: new NetworkState( - NetworkState.fromJSON(parameters.executionData.networkState) + networkState: new ProvableNetworkState( + ProvableNetworkState.fromJSON( + parameters.executionData.networkState + ) ), }, }, @@ -213,8 +208,8 @@ export class TransactionProvingTaskParameterSerializer transaction2: this.transactionProverArgumentsFromJson( parameters.executionData.transaction2 ), - networkState: new NetworkState( - NetworkState.fromJSON(parameters.executionData.networkState) + networkState: new ProvableNetworkState( + ProvableNetworkState.fromJSON(parameters.executionData.networkState) ), }, }, diff --git a/packages/sequencer/src/protocol/production/tasks/serializers/types/TransactionProvingTypes.ts b/packages/sequencer/src/protocol/production/tasks/serializers/types/TransactionProvingTypes.ts index b091abdc2..490564a20 100644 --- a/packages/sequencer/src/protocol/production/tasks/serializers/types/TransactionProvingTypes.ts +++ b/packages/sequencer/src/protocol/production/tasks/serializers/types/TransactionProvingTypes.ts @@ -6,7 +6,7 @@ import { } from "@proto-kit/protocol"; import { Proof } from "o1js"; -import type { TaskStateRecord } from "../../../tracing/BlockTracingService"; +import { JSONEncodableState } from "../DecodedStateSerializer"; export type RuntimeProof = Proof; @@ -22,7 +22,7 @@ export interface TransactionProverTaskParameters< > { publicInput: BlockProverPublicInput; executionData: ExecutionData; - startingState: TaskStateRecord[]; + startingState: JSONEncodableState[]; } export type TransactionProvingTaskParameters = diff --git a/packages/sequencer/src/protocol/production/tracing/BatchTracingService.ts b/packages/sequencer/src/protocol/production/tracing/BatchTracingService.ts index f54d52e6f..b489c557f 100644 --- a/packages/sequencer/src/protocol/production/tracing/BatchTracingService.ts +++ b/packages/sequencer/src/protocol/production/tracing/BatchTracingService.ts @@ -2,10 +2,12 @@ import { log, yieldSequential } from "@proto-kit/common"; import { AppliedBatchHashList, MinaActionsHashList, + ProvableNetworkState, TransactionHashList, WitnessedRootHashList, } from "@proto-kit/protocol"; import { inject, injectable } from "tsyringe"; +import { Field } from "o1js"; import { StateTransitionProofParameters } from "../tasks/StateTransitionTask"; import { BlockWithResult } from "../../../storage/model/Block"; @@ -40,12 +42,16 @@ export class BatchTracingService { return { pendingSTBatches: new AppliedBatchHashList(), witnessedRoots: new WitnessedRootHashList(), - stateRoot: block.block.fromStateRoot, + stateRoot: Field(block.block.fromStateRoot), eternalTransactionsList: new TransactionHashList( - block.block.fromEternalTransactionsHash + Field(block.block.fromEternalTransactionsHash) + ), + incomingMessages: new MinaActionsHashList( + Field(block.block.fromMessagesHash) + ), + networkState: new ProvableNetworkState( + ProvableNetworkState.fromJSON(block.block.networkState.before) ), - incomingMessages: new MinaActionsHashList(block.block.fromMessagesHash), - networkState: block.block.networkState.before, }; } diff --git a/packages/sequencer/src/protocol/production/tracing/BlockTracingService.ts b/packages/sequencer/src/protocol/production/tracing/BlockTracingService.ts index 8b6a98bbf..eb20e6597 100644 --- a/packages/sequencer/src/protocol/production/tracing/BlockTracingService.ts +++ b/packages/sequencer/src/protocol/production/tracing/BlockTracingService.ts @@ -1,6 +1,8 @@ import { + BlockHashMerkleTreeWitness, BlockProverPublicInput, BlockProverState, + ProvableNetworkState, WitnessedRootWitness, } from "@proto-kit/protocol"; import { Bool, Field } from "o1js"; @@ -21,8 +23,6 @@ import { TransactionTracingService, } from "./TransactionTracingService"; -export type TaskStateRecord = Record; - export type BlockTracingState = Pick< BlockProverState, | "witnessedRoots" @@ -38,7 +38,7 @@ export type BlockTrace = { blockParams: NewBlockProverParameters; transactions: TransactionTrace[]; // Only for debugging and logging - height: string; + height: number; }; @injectable() @@ -50,7 +50,7 @@ export class BlockTracingService { ) {} @trace("batch.trace.block", ([, block]) => ({ - height: block.block.height.toString(), + height: block.block.height, })) public async traceBlock( state: BlockTracingState, @@ -59,12 +59,14 @@ export class BlockTracingService { ): Promise<[BlockTracingState, BlockTrace]> { const publicInput: BlockProverPublicInput = new BlockProverPublicInput({ stateRoot: state.stateRoot, - blockNumber: block.block.height, - blockHashRoot: block.block.fromBlockHashRoot, - eternalTransactionsHash: block.block.fromEternalTransactionsHash, - incomingMessagesHash: block.block.fromMessagesHash, + blockNumber: Field(block.block.height), + blockHashRoot: Field(block.block.fromBlockHashRoot), + eternalTransactionsHash: Field(block.block.fromEternalTransactionsHash), + incomingMessagesHash: Field(block.block.fromMessagesHash), transactionsHash: Field(0), - networkStateHash: block.block.networkState.before.hash(), + networkStateHash: new ProvableNetworkState( + ProvableNetworkState.fromJSON(block.block.networkState.before) + ).hash(), witnessedRootsHash: state.witnessedRoots.commitment, pendingSTBatchesHash: state.pendingSTBatches.commitment, }); @@ -75,9 +77,13 @@ export class BlockTracingService { const blockTrace = { publicInput, - networkState: block.block.networkState.before, + networkState: new ProvableNetworkState( + ProvableNetworkState.fromJSON(block.block.networkState.before) + ), deferSTProof: Bool(!includeSTProof), - blockWitness: block.result.blockHashWitness, + blockWitness: new BlockHashMerkleTreeWitness( + BlockHashMerkleTreeWitness.fromJSON(block.result.blockHashWitness) + ), startingStateBeforeHook, } satisfies Partial; @@ -87,7 +93,9 @@ export class BlockTracingService { ), applied: Bool(true), }); - state.networkState = block.block.networkState.during; + state.networkState = new ProvableNetworkState( + ProvableNetworkState.fromJSON(block.block.networkState.during) + ); const [afterState, transactionTraces] = await yieldSequential( chunk(block.block.transactions, 2), @@ -133,7 +141,9 @@ export class BlockTracingService { const startingStateAfterHook = collectStartingState( block.result.afterBlockStateTransitions ); - state.networkState = block.result.afterNetworkState; + state.networkState = new ProvableNetworkState( + ProvableNetworkState.fromJSON(block.result.afterNetworkState) + ); return [ afterState, @@ -144,7 +154,7 @@ export class BlockTracingService { afterBlockRootWitness, }, transactions: transactionTraces, - height: block.block.height.toString(), + height: block.block.height, }, ]; } diff --git a/packages/sequencer/src/protocol/production/tracing/StateTransitionTracingService.ts b/packages/sequencer/src/protocol/production/tracing/StateTransitionTracingService.ts index 03621892b..d4afc72c4 100644 --- a/packages/sequencer/src/protocol/production/tracing/StateTransitionTracingService.ts +++ b/packages/sequencer/src/protocol/production/tracing/StateTransitionTracingService.ts @@ -50,7 +50,12 @@ export class StateTransitionTracingService { stateTransitions: block.block.beforeBlockStateTransitions, applied: true, }, - ...block.block.transactions.flatMap((tx) => tx.stateTransitions), + ...block.block.transactions.flatMap((tx) => + tx.stateTransitions.map((batch) => ({ + stateTransitions: batch.stateTransitions.map((st) => st), + applied: batch.applied, + })) + ), ].map((batch) => ({ ...batch, witnessRoot: false })); const batchBeforeWitnessing = previous.concat(batches); diff --git a/packages/sequencer/src/protocol/production/tracing/TransactionTracingService.ts b/packages/sequencer/src/protocol/production/tracing/TransactionTracingService.ts index ee591d282..1901a0a6d 100644 --- a/packages/sequencer/src/protocol/production/tracing/TransactionTracingService.ts +++ b/packages/sequencer/src/protocol/production/tracing/TransactionTracingService.ts @@ -3,10 +3,10 @@ import { BlockProverMultiTransactionExecutionData, BlockProverPublicInput, BlockProverSingleTransactionExecutionData, - NetworkState, + ProvableNetworkState, TransactionProverTransactionArguments, } from "@proto-kit/protocol"; -import { Bool, Field } from "o1js"; +import { Bool, Field, Signature } from "o1js"; import { MAX_FIELD } from "@proto-kit/common"; import { toStateTransitionsHash } from "@proto-kit/module"; import { injectable } from "tsyringe"; @@ -20,8 +20,9 @@ import { } from "../tasks/serializers/types/TransactionProvingTypes"; import { UntypedStateTransition } from "../helpers/UntypedStateTransition"; import { VerificationKeyService } from "../../runtime/RuntimeVerificationKeyService"; +import { JSONEncodableState } from "../tasks/serializers/DecodedStateSerializer"; -import type { BlockTracingState, TaskStateRecord } from "./BlockTracingService"; +import type { BlockTracingState } from "./BlockTracingService"; export type TransactionTrace = | { @@ -37,19 +38,18 @@ export type TransactionTrace = export function collectStartingState( stateTransitions: UntypedStateTransition[] -): TaskStateRecord { +): JSONEncodableState { const stateEntries = stateTransitions // Filter distinct .filter( (st, index, array) => - array.findIndex((st2) => st2.path.toBigInt() === st.path.toBigInt()) === - index + array.findIndex((st2) => st2.path === st.path) === index ) // Filter out STs that have isSome: false as precondition, because this means // "state hasn't been set before" and has to correlate to a precondition on Field(0) // and for that the state has to be undefined - .filter((st) => st.fromValue.isSome.toBoolean()) - .map((st) => [st.path.toString(), st.fromValue.value]); + .filter((st) => st.from.isSome) + .map((st) => [st.path, st.from.value]); return Object.fromEntries(stateEntries); } @@ -64,13 +64,11 @@ export class TransactionTracingService { transaction: PendingTransaction ): Promise { const verificationKeyAttestation = - this.verificationKeyService.getAttestation( - transaction.methodId.toBigInt() - ); + this.verificationKeyService.getAttestation(transaction.methodId); return { transaction: transaction.toRuntimeTransaction(), - signature: transaction.signature, + signature: Signature.fromJSON(transaction.signature), verificationKeyAttestation, }; } @@ -95,14 +93,16 @@ export class TransactionTracingService { previousState: BlockTracingState, transaction: TransactionExecutionResult ) { + const { tx } = transaction; // TODO Remove this call and instead reuse results from sequencing const newState = addTransactionToBundle( previousState, - Bool(transaction.tx.isMessage), - transaction.tx.toRuntimeTransaction() + Bool(tx.isMessage), + tx.toRuntimeTransaction() ); - transaction.stateTransitions.forEach((batch) => { + const stBatches = transaction.stateTransitions; + stBatches.forEach((batch) => { newState.pendingSTBatches.push({ applied: Bool(batch.applied), batchHash: toStateTransitionsHash(batch.stateTransitions), @@ -114,15 +114,14 @@ export class TransactionTracingService { private createRuntimeProofParams( tx: TransactionExecutionResult, - networkState: NetworkState + networkState: ProvableNetworkState ): RuntimeProofParameters { - const startingState = collectStartingState( - tx.stateTransitions[1].stateTransitions - ); + const stBatch = tx.stateTransitions[1]; + const startingState = collectStartingState(stBatch.stateTransitions); return { tx: tx.tx, - networkState, + networkState: ProvableNetworkState.toJSON(networkState), state: startingState, }; } @@ -131,8 +130,10 @@ export class TransactionTracingService { previousState: BlockTracingState, transaction: TransactionExecutionResult ) { + const stBatches = transaction.stateTransitions; + const beforeHookStartingState = collectStartingState( - transaction.stateTransitions[0].stateTransitions.flat() + stBatches[0].stateTransitions.flat() ); const runtimeTrace1 = this.createRuntimeProofParams( @@ -141,7 +142,7 @@ export class TransactionTracingService { ); const afterHookStartingState = collectStartingState( - transaction.stateTransitions[2].stateTransitions.flat() + stBatches[2].stateTransitions.flat() ); const newState = this.appendTransactionToState(previousState, transaction); diff --git a/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts b/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts index 5445d6e63..62717cc4a 100644 --- a/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts +++ b/packages/sequencer/src/protocol/runtime/RuntimeVerificationKeyService.ts @@ -25,7 +25,7 @@ export type VKRecord = { }; export interface WithGetMethodId { - getMethodId: (moduleName: string, methodName: string) => bigint; + getMethodId: (moduleName: string, methodName: string) => string; } export interface WithZkProgrammableAndGetMethodById { @@ -81,10 +81,10 @@ export class VerificationKeyService extends ConfigurableModule<{}> { methodName ); // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - return [ - methodId.toString(), - new VerificationKey(artifact.verificationKey), - ] as [string, VerificationKey]; + return [methodId, new VerificationKey(artifact.verificationKey)] as [ + string, + VerificationKey, + ]; }); } ); @@ -131,8 +131,8 @@ export class VerificationKeyService extends ConfigurableModule<{}> { return this.persistedVKRecord; } - public getAttestation(methodId: bigint) { - const verificationKey = this.getVkRecord()[methodId.toString()]; + public getAttestation(methodId: string) { + const verificationKey = this.getVkRecord()[methodId]; if (verificationKey === undefined) { throw new Error( `MethodId not registered in VerificationKeyService (${methodId})` @@ -147,9 +147,9 @@ export class VerificationKeyService extends ConfigurableModule<{}> { }); } - public getWitness(methodId: bigint) { + public getWitness(methodId: string) { const vkTree = this.getVKTree(); - return vkTree.tree.getWitness(vkTree.indexes[methodId.toString()]); + return vkTree.tree.getWitness(vkTree.indexes[methodId]); } public getRoot(): bigint { diff --git a/packages/sequencer/src/settlement/interactions/bridging/BridgingSettlementInteraction.ts b/packages/sequencer/src/settlement/interactions/bridging/BridgingSettlementInteraction.ts index ee8b74983..0205d1bff 100644 --- a/packages/sequencer/src/settlement/interactions/bridging/BridgingSettlementInteraction.ts +++ b/packages/sequencer/src/settlement/interactions/bridging/BridgingSettlementInteraction.ts @@ -5,6 +5,7 @@ import { BridgingSettlementModulesRecord, DynamicBlockProof, MandatoryProtocolModulesRecord, + ProvableNetworkState, Protocol, SettlementContractModule, } from "@proto-kit/protocol"; @@ -101,8 +102,12 @@ export class BridgingSettlementInteraction implements SettleInteraction { dynamicBlockProof, signature, feepayer, - batch.fromNetworkState, - batch.toNetworkState, + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch.fromNetworkState) + ), + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch.toNetworkState) + ), latestSequenceStateHash ); } diff --git a/packages/sequencer/src/settlement/interactions/vanilla/VanillaSettlementInteraction.ts b/packages/sequencer/src/settlement/interactions/vanilla/VanillaSettlementInteraction.ts index 096438ab5..fc3782af6 100644 --- a/packages/sequencer/src/settlement/interactions/vanilla/VanillaSettlementInteraction.ts +++ b/packages/sequencer/src/settlement/interactions/vanilla/VanillaSettlementInteraction.ts @@ -5,6 +5,7 @@ import { BridgingSettlementModulesRecord, DynamicBlockProof, MandatoryProtocolModulesRecord, + ProvableNetworkState, Protocol, SettlementContractModule, } from "@proto-kit/protocol"; @@ -93,8 +94,12 @@ export class VanillaSettlementInteraction implements SettleInteraction { dynamicBlockProof, signature, feepayer, - batch.fromNetworkState, - batch.toNetworkState, + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch.fromNetworkState) + ), + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch.toNetworkState) + ), latestSequenceStateHash ); } diff --git a/packages/sequencer/src/settlement/messages/MinaIncomingMessageAdapter.ts b/packages/sequencer/src/settlement/messages/MinaIncomingMessageAdapter.ts index 764cfd1ae..a8460e689 100644 --- a/packages/sequencer/src/settlement/messages/MinaIncomingMessageAdapter.ts +++ b/packages/sequencer/src/settlement/messages/MinaIncomingMessageAdapter.ts @@ -66,12 +66,12 @@ export class MinaIncomingMessageAdapter implements IncomingMessageAdapter { private async mapActionToTransactions( tx: RuntimeTransaction, - fieldArgs: Field[] + fieldArgs: string[] ): Promise { const { methodId } = tx; const methodPointer = this.runtime.methodIdResolver.getMethodNameFromId( - methodId.toBigInt() + methodId.toString() ); if (methodPointer === undefined) { @@ -87,13 +87,22 @@ export class MinaIncomingMessageAdapter implements IncomingMessageAdapter { const args = await methodEncoder.decode(fieldArgs, []); const { fields, auxiliary } = methodEncoder.encode(args); + const hash = Poseidon.hash([ + methodId, + ...EMPTY_PUBLICKEY.toFields(), + ...UInt64.zero.toFields(), + Poseidon.hash(fields), + ]).toString(); + + const signature = Signature.create(PrivateKey.random(), [Field(0)]); return new PendingTransaction({ - methodId, - sender: EMPTY_PUBLICKEY, - nonce: UInt64.zero, - signature: Signature.create(PrivateKey.random(), [Field(0)]), - argsFields: fields, + hash, + methodId: methodId.toString(), + sender: EMPTY_PUBLICKEY.toBase58(), + nonce: UInt64.zero.toString(), + signature: { r: signature.r.toString(), s: signature.s.toJSON() }, + argsFields: fields.map((f) => f.toString()), auxiliaryData: auxiliary, isMessage: true, }); @@ -169,7 +178,7 @@ export class MinaIncomingMessageAdapter implements IncomingMessageAdapter { if (correspondingEvent === undefined) { throw new Error("Couldn't find events corresponding to action"); } - const args = correspondingEvent.event.data.map((x) => Field(x)); + const args = correspondingEvent.event.data; return await this.mapActionToTransactions(tx, args); }); diff --git a/packages/sequencer/src/settlement/messages/outgoing/DefaultOutgoingMessageAdapter.ts b/packages/sequencer/src/settlement/messages/outgoing/DefaultOutgoingMessageAdapter.ts index 3653d023d..11f3b0207 100644 --- a/packages/sequencer/src/settlement/messages/outgoing/DefaultOutgoingMessageAdapter.ts +++ b/packages/sequencer/src/settlement/messages/outgoing/DefaultOutgoingMessageAdapter.ts @@ -61,7 +61,7 @@ export class DefaultOutgoingMessageAdapter ) .map((event) => { const type = this.outgoingWithdrawalEvents[event.eventName]; - return type.eventType.fromFields(event.data); + return type.eventType.fromFields(event.data.map((d) => Field(d))); }) ); } diff --git a/packages/sequencer/src/storage/inmemory/InMemoryBlockStorage.ts b/packages/sequencer/src/storage/inmemory/InMemoryBlockStorage.ts index 5c5306e7b..bc0e53cf6 100644 --- a/packages/sequencer/src/storage/inmemory/InMemoryBlockStorage.ts +++ b/packages/sequencer/src/storage/inmemory/InMemoryBlockStorage.ts @@ -47,7 +47,7 @@ export class InMemoryBlockStorage implements BlockStorage, BlockQueue { if (result !== undefined) { if (result.result === undefined) { throw new Error( - `Block result for block ${result.block.height.toString()} not found` + `Block result for block ${result.block.height} not found` ); } return { @@ -65,9 +65,7 @@ export class InMemoryBlockStorage implements BlockStorage, BlockQueue { if (latestBatch !== undefined) { cursor = this.blocks.reduce( (c, block, index) => - latestBatch.blockHashes.includes(block.hash.toString()) - ? index + 1 - : c, + latestBatch.blockHashes.includes(block.hash) ? index + 1 : c, 0 ); } @@ -100,6 +98,6 @@ export class InMemoryBlockStorage implements BlockStorage, BlockQueue { } public async getBlock(hash: string): Promise { - return this.blocks.find((block) => block.hash.toString() === hash); + return this.blocks.find((block) => block.hash === hash); } } diff --git a/packages/sequencer/src/storage/inmemory/InMemoryTransactionStorage.ts b/packages/sequencer/src/storage/inmemory/InMemoryTransactionStorage.ts index df0fe7fd7..44d91d41a 100644 --- a/packages/sequencer/src/storage/inmemory/InMemoryTransactionStorage.ts +++ b/packages/sequencer/src/storage/inmemory/InMemoryTransactionStorage.ts @@ -1,5 +1,4 @@ import { inject, injectable } from "tsyringe"; -import { Field } from "o1js"; import { TransactionStorage } from "../repositories/TransactionStorage"; import { PendingTransaction } from "../../mempool/PendingTransaction"; @@ -22,8 +21,7 @@ export class InMemoryTransactionStorage implements TransactionStorage { public async removeTx(hashes: string[]) { const hashSet = new Set(hashes); this.queue = this.queue.filter((tx) => { - const hash = tx.hash().toString(); - return !hashSet.has(hash); + return !hashSet.has(tx.hash); }); } @@ -37,10 +35,8 @@ export class InMemoryTransactionStorage implements TransactionStorage { // eslint-disable-next-line no-await-in-loop const block = await this.blockStorage.getBlockAt(height); if (block !== undefined) { - const hashes = block.transactions.map((tx) => tx.tx.hash().toString()); - this.queue = this.queue.filter( - (tx) => !hashes.includes(tx.hash().toString()) - ); + const hashes = block.transactions.map((tx) => tx.tx.hash); + this.queue = this.queue.filter((tx) => !hashes.includes(tx.hash)); } } this.latestScannedBlock = nextHeight - 1; @@ -50,9 +46,7 @@ export class InMemoryTransactionStorage implements TransactionStorage { public async pushUserTransaction(tx: PendingTransaction): Promise { const notInQueue = - this.queue.find( - (tx2) => tx2.hash().toString() === tx.hash().toString() - ) === undefined; + this.queue.find((tx2) => tx2.hash === tx.hash) === undefined; if (notInQueue) { this.queue.push(tx); } @@ -84,7 +78,7 @@ export class InMemoryTransactionStorage implements TransactionStorage { | undefined > { const pending = await this.getPendingUserTransactions(); - const pendingResult = pending.find((tx) => tx.hash().toString() === hash); + const pendingResult = pending.find((tx) => tx.hash === hash); if (pendingResult !== undefined) { return { transaction: pendingResult, @@ -92,7 +86,6 @@ export class InMemoryTransactionStorage implements TransactionStorage { } const tipHeight = await this.blockStorage.getCurrentBlockHeight(); - const hashField = Field(hash); for (let height = tipHeight - 1; height >= 0; height--) { // eslint-disable-next-line no-await-in-loop @@ -100,15 +93,13 @@ export class InMemoryTransactionStorage implements TransactionStorage { if (block === undefined) { return undefined; } - const txResult = block.transactions.find((tx) => - tx.tx.hash().equals(hashField).toBoolean() - ); + const txResult = block.transactions.find((tx) => tx.tx.hash === hash); if (txResult !== undefined) { // eslint-disable-next-line no-await-in-loop - const batch = await this.findBatch(block.hash.toString()); + const batch = await this.findBatch(block.hash); return { transaction: txResult.tx, - block: block.transactionsHash.toString(), + block: block.transactionsHash, batch, }; } diff --git a/packages/sequencer/src/storage/model/Block.ts b/packages/sequencer/src/storage/model/Block.ts index da2e44802..b47b69991 100644 --- a/packages/sequencer/src/storage/model/Block.ts +++ b/packages/sequencer/src/storage/model/Block.ts @@ -1,11 +1,13 @@ -import { Bool, Field, Poseidon } from "o1js"; +import { Field, Poseidon } from "o1js"; import { ACTIONS_EMPTY_HASH, BlockHashMerkleTree, BlockHashMerkleTreeWitness, + BlockHashMerkleTreeWitnessJson, + ProvableNetworkState, NetworkState, } from "@proto-kit/protocol"; -import { LinkedMerkleTree } from "@proto-kit/common"; +import { LinkedMerkleTree, FieldString } from "@proto-kit/common"; import { PendingTransaction } from "../../mempool/PendingTransaction"; import { UntypedStateTransition } from "../../protocol/production/helpers/UntypedStateTransition"; @@ -18,36 +20,34 @@ export interface StateTransitionBatch { export interface TransactionExecutionResult { tx: PendingTransaction; stateTransitions: StateTransitionBatch[]; - status: Bool; - hooksStatus: Bool; + status: boolean; + hooksStatus: boolean; statusMessage?: string; events: { eventName: string; - data: Field[]; + data: FieldString[]; source: "afterTxHook" | "beforeTxHook" | "runtime"; }[]; } -// TODO Why is Block using Fields, but BlockResult bigints? Align that towards the best option - export interface Block { - hash: Field; - previousBlockHash: Field | undefined; - height: Field; + hash: FieldString; + previousBlockHash: FieldString | undefined; + height: number; networkState: { before: NetworkState; during: NetworkState; }; transactions: TransactionExecutionResult[]; - transactionsHash: Field; + transactionsHash: FieldString; - fromEternalTransactionsHash: Field; - fromBlockHashRoot: Field; - fromMessagesHash: Field; - fromStateRoot: Field; - toEternalTransactionsHash: Field; - toMessagesHash: Field; + fromEternalTransactionsHash: FieldString; + fromBlockHashRoot: FieldString; + fromMessagesHash: FieldString; + fromStateRoot: FieldString; + toEternalTransactionsHash: FieldString; + toMessagesHash: FieldString; beforeBlockStateTransitions: UntypedStateTransition[]; } @@ -59,18 +59,21 @@ export const Block = { }, hash(block: Omit): Field { - return Block.calculateHash(block.height, block.transactionsHash); + return Block.calculateHash( + Field(block.height), + Field(block.transactionsHash) + ); }, }; export interface BlockResult { - blockHash: bigint; - witnessedRoots: [bigint]; - stateRoot: bigint; - blockHashRoot: bigint; + blockHash: FieldString; + witnessedRoots: [FieldString]; + stateRoot: FieldString; + blockHashRoot: FieldString; afterNetworkState: NetworkState; afterBlockStateTransitions: UntypedStateTransition[]; - blockHashWitness: BlockHashMerkleTreeWitness; + blockHashWitness: BlockHashMerkleTreeWitnessJson; } export interface BlockWithResult { @@ -93,33 +96,37 @@ export const BlockWithResult = { createEmpty: () => ({ block: { - hash: Field(0), + hash: FieldString(0), - height: Field(0), - transactionsHash: Field(0), - fromEternalTransactionsHash: Field(0), - toEternalTransactionsHash: Field(0), + height: 0, + transactionsHash: FieldString(0), + fromEternalTransactionsHash: FieldString(0), + toEternalTransactionsHash: FieldString(0), transactions: [], networkState: { - before: NetworkState.empty(), - during: NetworkState.empty(), + before: ProvableNetworkState.toJSON(ProvableNetworkState.empty()), + during: ProvableNetworkState.toJSON(ProvableNetworkState.empty()), }, - fromBlockHashRoot: Field(BlockHashMerkleTree.EMPTY_ROOT), - fromMessagesHash: Field(0), - fromStateRoot: LinkedMerkleTree.EMPTY_ROOT, - toMessagesHash: ACTIONS_EMPTY_HASH, + fromBlockHashRoot: FieldString(BlockHashMerkleTree.EMPTY_ROOT), + fromMessagesHash: FieldString(0), + fromStateRoot: FieldString(LinkedMerkleTree.EMPTY_ROOT), + toMessagesHash: FieldString(ACTIONS_EMPTY_HASH), beforeBlockStateTransitions: [], previousBlockHash: undefined, }, result: { - afterNetworkState: NetworkState.empty(), - stateRoot: LinkedMerkleTree.EMPTY_ROOT.toBigInt(), - blockHashRoot: BlockHashMerkleTree.EMPTY_ROOT, + afterNetworkState: ProvableNetworkState.toJSON( + ProvableNetworkState.empty() + ), + stateRoot: FieldString(LinkedMerkleTree.EMPTY_ROOT), + blockHashRoot: FieldString(BlockHashMerkleTree.EMPTY_ROOT), afterBlockStateTransitions: [], - blockHashWitness: BlockHashMerkleTree.WITNESS.dummy(), - blockHash: 0n, - witnessedRoots: [LinkedMerkleTree.EMPTY_ROOT.toBigInt()], + blockHashWitness: BlockHashMerkleTreeWitness.toJSON( + BlockHashMerkleTree.WITNESS.dummy() + ), + blockHash: "0", + witnessedRoots: [String(LinkedMerkleTree.EMPTY_ROOT)], }, }) satisfies BlockWithResult, }; diff --git a/packages/sequencer/test-integration/workers/workers-proven.test.ts b/packages/sequencer/test-integration/workers/workers-proven.test.ts index f914473e4..de9de936e 100644 --- a/packages/sequencer/test-integration/workers/workers-proven.test.ts +++ b/packages/sequencer/test-integration/workers/workers-proven.test.ts @@ -120,7 +120,7 @@ describe("worker-proven", () => { expectDefined(block); expect(block.transactions).toHaveLength(1); - expect(block.transactions[0].status.toBoolean()).toBe(true); + expect(block.transactions[0].status).toBe(true); expectDefined(batch); diff --git a/packages/sequencer/test/Mempool.test.ts b/packages/sequencer/test/Mempool.test.ts index d80a00f0f..373625cc4 100644 --- a/packages/sequencer/test/Mempool.test.ts +++ b/packages/sequencer/test/Mempool.test.ts @@ -20,12 +20,14 @@ describe("memPool", () => { }); const data = unsigned.getSignatureData(); - const hash = unsigned.hash(); + const hash = unsigned.hash().toString(); const signed = unsigned.sign(pk); - expect(data).toStrictEqual(signed.getSignatureData()); - expect(hash).toStrictEqual(signed.hash()); + expect(data).toStrictEqual( + signed.toProtocolTransaction().getSignatureData() + ); + expect(hash).toStrictEqual(signed.hash); }); }); diff --git a/packages/sequencer/test/integration/BlockProduction-test.ts b/packages/sequencer/test/integration/BlockProduction-test.ts index 71c4172f9..bc0417f95 100644 --- a/packages/sequencer/test/integration/BlockProduction-test.ts +++ b/packages/sequencer/test/integration/BlockProduction-test.ts @@ -20,6 +20,7 @@ import { Path, Protocol, PROTOKIT_PREFIXES, + ProvableNetworkState, } from "@proto-kit/protocol"; import { Bool, Field, PrivateKey, PublicKey, Struct, UInt64 } from "o1js"; import "reflect-metadata"; @@ -206,7 +207,7 @@ export function testBlockProduction< expect(block).toBeDefined(); expect(block!.transactions).toHaveLength(1); - expect(block!.transactions[0].status.toBoolean()).toBe(true); + expect(block!.transactions[0].status).toBe(true); expect(block!.transactions[0].statusMessage).toBeUndefined(); expect(block!.transactions[0].stateTransitions).toHaveLength(3); @@ -231,8 +232,20 @@ export function testBlockProduction< expectDefined(latestBlockWithResult); expectDefined(latestBlockWithResult.result); expect( - latestBlockWithResult.result.afterNetworkState.hash().toString() - ).toStrictEqual(batch!.toNetworkState.hash().toString()); + new ProvableNetworkState( + ProvableNetworkState.fromJSON( + latestBlockWithResult.result.afterNetworkState + ) + ) + .hash() + .toString() + ).toStrictEqual( + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch!.toNetworkState) + ) + .hash() + .toString() + ); // Check if the batchstorage has received the block const batchStorage = sequencer.resolve("BatchStorage") as BatchStorage; @@ -282,7 +295,7 @@ export function testBlockProduction< expect(block).toBeDefined(); expect(block!.transactions).toHaveLength(1); - expect(block!.transactions[0].status.toBoolean()).toBe(true); + expect(block!.transactions[0].status).toBe(true); expect(block!.transactions[0].statusMessage).toBeUndefined(); expect(batch!.blockHashes).toHaveLength(1); @@ -312,7 +325,7 @@ export function testBlockProduction< const [block] = await test.produceBlockAndBatch(); expect(block?.transactions).toHaveLength(1); - expect(block?.transactions[0].status.toBoolean()).toBe(false); + expect(block?.transactions[0].status).toBe(false); expect(block?.transactions[0].statusMessage).toBe("Condition not met"); const balanceModule = runtime.resolve("Balance"); @@ -352,7 +365,7 @@ export function testBlockProduction< expect(block).toBeDefined(); expect(block!.transactions).toHaveLength(1); - expect(block!.transactions[0].status.toBoolean()).toBe(true); + expect(block!.transactions[0].status).toBe(true); expect(block!.transactions[0].statusMessage).toBeUndefined(); expect( @@ -408,7 +421,7 @@ export function testBlockProduction< expect(block2).toBeDefined(); expect(block2!.transactions).toHaveLength(1); - expect(block2!.transactions[0].status.toBoolean()).toBe(true); + expect(block2!.transactions[0].status).toBe(true); expect(block2!.transactions[0].statusMessage).toBeUndefined(); await expect( @@ -442,17 +455,17 @@ export function testBlockProduction< expect(block!.transactions).toHaveLength(numberTxs); range(0, numberTxs).forEach((index) => { - expect(block!.transactions[index].status.toBoolean()).toBe(true); + expect(block!.transactions[index].status).toBe(true); expect(block!.transactions[index].statusMessage).toBe(undefined); const transitions = block!.transactions[index].stateTransitions[1].stateTransitions; const fromBalance = increment * index; - expect(transitions[0].fromValue.value[0].toBigInt()).toStrictEqual( + expect(BigInt(transitions[0].from.value[0])).toStrictEqual( BigInt(fromBalance) ); - expect(transitions[0].toValue.value[0].toBigInt()).toStrictEqual( + expect(BigInt(transitions[0].to.value[0])).toStrictEqual( BigInt(fromBalance + increment) ); }); @@ -584,7 +597,7 @@ export function testBlockProduction< for (let k = 0; k < txsPerBlock; k++) { expect(block!.transactions).toHaveLength(txsPerBlock); - expect(block!.transactions[0].status.toBoolean()).toBe(true); + expect(block!.transactions[0].status).toBe(true); } } @@ -617,7 +630,7 @@ export function testBlockProduction< expect(block!.transactions).toHaveLength(1); - expect(block!.transactions[0].status.toBoolean()).toBe(true); + expect(block!.transactions[0].status).toBe(true); expect(block!.transactions[0].statusMessage).toBe(undefined); expect(batch!.blockHashes).toHaveLength(1); @@ -664,7 +677,7 @@ export function testBlockProduction< expect(block).toBeDefined(); expect(block!.transactions).toHaveLength(1); - expect(block!.transactions[0].status.toBoolean()).toBe(true); + expect(block!.transactions[0].status).toBe(true); expect(block!.transactions[0].statusMessage).toBeUndefined(); expect( @@ -710,13 +723,17 @@ export function testBlockProduction< }; const firstEventReduced = { eventName: firstExpectedEvent.eventName, - data: firstExpectedEvent.eventType.toFields(firstExpectedEvent.event), + data: firstExpectedEvent.eventType + .toFields(firstExpectedEvent.event) + .map((f) => f.toString()), source: "runtime", }; const secondEventReduced = { eventName: secondExpectedEvent.eventName, - data: secondExpectedEvent.eventType.toFields(secondExpectedEvent.event), + data: secondExpectedEvent.eventType + .toFields(secondExpectedEvent.event) + .map((f) => f.toString()), source: "runtime", }; diff --git a/packages/sequencer/test/integration/Mempool.test.ts b/packages/sequencer/test/integration/Mempool.test.ts index d5aec4037..2054b7f86 100644 --- a/packages/sequencer/test/integration/Mempool.test.ts +++ b/packages/sequencer/test/integration/Mempool.test.ts @@ -134,18 +134,18 @@ describe.each([["InMemory", InMemoryDatabase]])( const txs = await mempool.getTxs(); expect(txs).toHaveLength(6); - expect(txs[0].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[0].sender).toStrictEqual(user1PublicKey); - expect(txs[1].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[1].sender).toStrictEqual(user2PublicKey); - expect(txs[2].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[2].sender).toStrictEqual(user3PublicKey); - expect(txs[3].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[3].sender).toStrictEqual(user1PublicKey); - expect(txs[4].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[4].sender).toStrictEqual(user2PublicKey); - expect(txs[5].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[5].sender).toStrictEqual(user3PublicKey); + expect(txs[0].nonce).toStrictEqual("0"); + expect(txs[0].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[1].nonce).toStrictEqual("0"); + expect(txs[1].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[2].nonce).toStrictEqual("0"); + expect(txs[2].sender).toStrictEqual(user3PublicKey.toBase58()); + expect(txs[3].nonce).toStrictEqual("1"); + expect(txs[3].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[4].nonce).toStrictEqual("1"); + expect(txs[4].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[5].nonce).toStrictEqual("1"); + expect(txs[5].sender).toStrictEqual(user3PublicKey.toBase58()); }); it("transactions are returned in right order - medium", async () => { @@ -163,18 +163,18 @@ describe.each([["InMemory", InMemoryDatabase]])( const txs = await mempool.getTxs(); expect(txs).toHaveLength(6); - expect(txs[0].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[0].sender).toStrictEqual(user1PublicKey); - expect(txs[1].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[1].sender).toStrictEqual(user2PublicKey); - expect(txs[2].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[2].sender).toStrictEqual(user1PublicKey); - expect(txs[3].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[3].sender).toStrictEqual(user2PublicKey); - expect(txs[4].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[4].sender).toStrictEqual(user3PublicKey); - expect(txs[5].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[5].sender).toStrictEqual(user3PublicKey); + expect(txs[0].nonce).toStrictEqual("0"); + expect(txs[0].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[1].nonce).toStrictEqual("0"); + expect(txs[1].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[2].nonce).toStrictEqual("1"); + expect(txs[2].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[3].nonce).toStrictEqual("1"); + expect(txs[3].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[4].nonce).toStrictEqual("0"); + expect(txs[4].sender).toStrictEqual(user3PublicKey.toBase58()); + expect(txs[5].nonce).toStrictEqual("1"); + expect(txs[5].sender).toStrictEqual(user3PublicKey.toBase58()); }); it("transactions are returned in right order - harder", async () => { @@ -190,18 +190,18 @@ describe.each([["InMemory", InMemoryDatabase]])( const txs = await mempool.getTxs(); expect(txs).toHaveLength(6); - expect(txs[0].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[0].sender).toStrictEqual(user1PublicKey); - expect(txs[1].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[1].sender).toStrictEqual(user2PublicKey); - expect(txs[2].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[2].sender).toStrictEqual(user3PublicKey); - expect(txs[3].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[3].sender).toStrictEqual(user1PublicKey); - expect(txs[4].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[4].sender).toStrictEqual(user2PublicKey); - expect(txs[5].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[5].sender).toStrictEqual(user3PublicKey); + expect(txs[0].nonce).toStrictEqual("0"); + expect(txs[0].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[1].nonce).toStrictEqual("0"); + expect(txs[1].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[2].nonce).toStrictEqual("0"); + expect(txs[2].sender).toStrictEqual(user3PublicKey.toBase58()); + expect(txs[3].nonce).toStrictEqual("1"); + expect(txs[3].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[4].nonce).toStrictEqual("1"); + expect(txs[4].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[5].nonce).toStrictEqual("1"); + expect(txs[5].sender).toStrictEqual(user3PublicKey.toBase58()); }); it("transactions are returned in right order - hardest", async () => { @@ -219,18 +219,18 @@ describe.each([["InMemory", InMemoryDatabase]])( const txs = await mempool.getTxs(); expect(txs).toHaveLength(6); - expect(txs[0].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[0].sender).toStrictEqual(user1PublicKey); - expect(txs[1].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[1].sender).toStrictEqual(user2PublicKey); - expect(txs[2].nonce.toBigInt()).toStrictEqual(0n); - expect(txs[2].sender).toStrictEqual(user3PublicKey); - expect(txs[3].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[3].sender).toStrictEqual(user1PublicKey); - expect(txs[4].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[4].sender).toStrictEqual(user2PublicKey); - expect(txs[5].nonce.toBigInt()).toStrictEqual(1n); - expect(txs[5].sender).toStrictEqual(user3PublicKey); + expect(txs[0].nonce).toStrictEqual("0"); + expect(txs[0].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[1].nonce).toStrictEqual("0"); + expect(txs[1].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[2].nonce).toStrictEqual("0"); + expect(txs[2].sender).toStrictEqual(user3PublicKey.toBase58()); + expect(txs[3].nonce).toStrictEqual("1"); + expect(txs[3].sender).toStrictEqual(user1PublicKey.toBase58()); + expect(txs[4].nonce).toStrictEqual("1"); + expect(txs[4].sender).toStrictEqual(user2PublicKey.toBase58()); + expect(txs[5].nonce).toStrictEqual("1"); + expect(txs[5].sender).toStrictEqual(user3PublicKey.toBase58()); }); } ); diff --git a/packages/sequencer/test/integration/Proven.test.ts b/packages/sequencer/test/integration/Proven.test.ts index bca7f53af..e8ea6d024 100644 --- a/packages/sequencer/test/integration/Proven.test.ts +++ b/packages/sequencer/test/integration/Proven.test.ts @@ -211,7 +211,7 @@ describe.skip("Proven", () => { expectDefined(block); expect(block.transactions).toHaveLength(1); - expect(block.transactions[0].status.toBoolean()).toBe(true); + expect(block.transactions[0].status).toBe(true); expectDefined(batch); diff --git a/packages/sequencer/test/integration/StorageIntegration.test.ts b/packages/sequencer/test/integration/StorageIntegration.test.ts index 16f17bbe0..a52f259ee 100644 --- a/packages/sequencer/test/integration/StorageIntegration.test.ts +++ b/packages/sequencer/test/integration/StorageIntegration.test.ts @@ -35,7 +35,10 @@ function checkStateDiffEquality(stateDiff: StateRecord, state: StateEntry[]) { return value === undefined; } if (value !== undefined) { - return entry.value.find((v, i) => v !== value[i]) === undefined; + return ( + entry.value.find((v, i) => !v.equals(value[i]).toBoolean()) === + undefined + ); } } return false; @@ -136,25 +139,19 @@ describe.each([["InMemory", InMemoryDatabase]])( const { block } = blocks[0]; - expect(block.hash.toBigInt()).toStrictEqual( - generatedBlock.hash.toBigInt() - ); + expect(block.hash).toStrictEqual(generatedBlock.hash); const blockStorage = sequencer.resolve("BlockStorage") as BlockStorage; const block2 = await blockStorage.getBlockAt( - Number(blocks[0].block.height.toString()) + Number(blocks[0].block.height) ); expectDefined(block2); - expect(block2.hash.toBigInt()).toStrictEqual( - generatedBlock.hash.toBigInt() - ); - - const stateDiff = collectStateDiff( - block.transactions.flatMap((tx) => - tx.stateTransitions.flatMap((batch) => batch.stateTransitions) - ) + expect(block2.hash).toStrictEqual(generatedBlock.hash); + const input = block.transactions.flatMap((tx) => + tx.stateTransitions.flatMap((batch) => batch.stateTransitions) ); + const stateDiff = collectStateDiff(input); const state = await unprovenState.getMany( Object.keys(stateDiff).map(Field) @@ -203,7 +200,7 @@ describe.each([["InMemory", InMemoryDatabase]])( const txs = await txStorage.getPendingUserTransactions(); expect(txs).toHaveLength(1); - expect(txs[0].hash().toString()).toStrictEqual(tx.hash().toString()); + expect(txs[0].hash).toStrictEqual(tx.hash); await sequencer.resolve("BlockTrigger").produceBlock(); diff --git a/packages/sequencer/test/integration/utils.ts b/packages/sequencer/test/integration/utils.ts index f863cf605..4cdfc4a24 100644 --- a/packages/sequencer/test/integration/utils.ts +++ b/packages/sequencer/test/integration/utils.ts @@ -7,6 +7,7 @@ import { } from "@proto-kit/module"; import { + PendingTransaction, StateRecord, UnsignedTransaction, UntypedStateTransition, @@ -18,7 +19,7 @@ export function createTransaction(spec: { method: [string, string]; args: ArgumentTypes; nonce: number; -}) { +}): PendingTransaction { const methodId = spec.runtime.dependencyContainer .resolve("MethodIdResolver") .getMethodId(spec.method[0], spec.method[1]); @@ -43,11 +44,8 @@ export function createTransaction(spec: { export function collectStateDiff( stateTransitions: UntypedStateTransition[] ): StateRecord { - return stateTransitions.reduce>( - (state, st) => { - state[st.path.toString()] = st.toValue.value; - return state; - }, - {} - ); + return stateTransitions.reduce((state, st) => { + state[st.path] = st.to.value; + return state; + }, {}); } diff --git a/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts b/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts index 6c877194c..b26505cfd 100644 --- a/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts +++ b/packages/sequencer/test/production/tracing/StateTransitionTracingService.test.ts @@ -61,10 +61,10 @@ async function applyBatchesToTree( const tree = new LinkedMerkleTree(cached.treeStore, cached); await mapSequential(sts, async (st) => { - await cached.preloadKey(st.path.toBigInt()); + await cached.preloadKey(BigInt(st.path)); - if (st.to.isSome.toBoolean()) { - tree.setLeaf(st.path.toBigInt(), st.to.treeValue.toBigInt()); + if (st.to.isSome) { + tree.setLeaf(BigInt(st.path), BigInt(st.to.treeValue)); } }); diff --git a/packages/sequencer/test/protocol/production/helpers/UntypedOption.test.ts b/packages/sequencer/test/protocol/production/helpers/UntypedOption.test.ts index e14d343e7..200c543cd 100644 --- a/packages/sequencer/test/protocol/production/helpers/UntypedOption.test.ts +++ b/packages/sequencer/test/protocol/production/helpers/UntypedOption.test.ts @@ -20,12 +20,10 @@ describe("option <-> untypedoption", () => { const untyped = UntypedOption.fromOption(option); - expect(untyped.isSome.toBoolean()).toStrictEqual(option.isSome.toBoolean()); - expect(untyped.isForcedSome.toBoolean()).toStrictEqual( - option.isForcedSome.toBoolean() - ); + expect(untyped.isSome).toStrictEqual(option.isSome.toBoolean()); + expect(untyped.isForcedSome).toStrictEqual(option.isForcedSome.toBoolean()); expect(untyped.value).toStrictEqual( - option.valueType.toFields(option.value) + option.valueType.toFields(option.value).map((f) => f.toString()) ); const provable1 = option.toProvable(); diff --git a/packages/sequencer/test/protocol/production/helpers/UntypedStateTransition.test.ts b/packages/sequencer/test/protocol/production/helpers/UntypedStateTransition.test.ts index 5fc4ae5d4..9ebfe119b 100644 --- a/packages/sequencer/test/protocol/production/helpers/UntypedStateTransition.test.ts +++ b/packages/sequencer/test/protocol/production/helpers/UntypedStateTransition.test.ts @@ -30,29 +30,28 @@ describe("stateTransition", () => { const untyped = UntypedStateTransition.fromStateTransition(st); - expect(untyped.path).toStrictEqual(st.path); + expect(untyped.path).toStrictEqual(st.path.toString()); - expect(untyped.fromValue.value).toStrictEqual( - st.fromValue.valueType.toFields(st.fromValue.value) + expect(untyped.from.value).toStrictEqual( + st.fromValue.valueType + .toFields(st.fromValue.value) + .map((f) => f.toString()) ); - expect(untyped.fromValue.isSome.toBoolean()).toStrictEqual( - st.fromValue.isSome.toBoolean() - ); - expect(untyped.fromValue.isForcedSome.toBoolean()).toStrictEqual( + expect(untyped.from.isSome).toStrictEqual(st.fromValue.isSome.toBoolean()); + expect(untyped.from.isForcedSome).toStrictEqual( st.fromValue.isForcedSome.toBoolean() ); - expect(untyped.toValue.value).toStrictEqual( - st.toValue.valueType.toFields(st.toValue.value) - ); - expect(untyped.toValue.isSome.toBoolean()).toStrictEqual( - st.toValue.isSome.toBoolean() + expect(untyped.to.value).toStrictEqual( + st.toValue.valueType.toFields(st.toValue.value).map((f) => f.toString()) ); - expect(untyped.toValue.isForcedSome.toBoolean()).toStrictEqual( + expect(untyped.to.isSome).toStrictEqual(st.toValue.isSome.toBoolean()); + expect(untyped.to.isForcedSome).toStrictEqual( st.toValue.isForcedSome.toBoolean() ); const provable1 = st.toProvable(); + const provable2 = untyped.toProvable(); expect(provable1).toStrictEqual(provable2); diff --git a/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts b/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts index e34b72af6..1606cb97f 100644 --- a/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts +++ b/packages/sequencer/test/protocol/production/sequencing/atomic-block-production.test.ts @@ -115,6 +115,6 @@ describe("atomic block production", () => { const block = await trigger.produceBlock(); expectDefined(block); - expect(block.height.toString()).toBe("1"); + expect(block.height).toBe(1); }); }); diff --git a/packages/sequencer/test/settlement/Settlement-only.ts b/packages/sequencer/test/settlement/Settlement-only.ts index c894bfbcf..02f63432f 100644 --- a/packages/sequencer/test/settlement/Settlement-only.ts +++ b/packages/sequencer/test/settlement/Settlement-only.ts @@ -12,6 +12,7 @@ import { import { BlockProverPublicInput, ContractArgsRegistry, + ProvableNetworkState, Protocol, SettlementContractModule, } from "@proto-kit/protocol"; @@ -155,6 +156,7 @@ export const settlementOnlyTestFn = ( async function createBatch( withTransactions: boolean, customNonce: number = 0, + // Why is it like this? txs: PendingTransaction[] = [] ) { const mempool = appChain.sequencer.resolve("Mempool") as PrivateMempool; @@ -275,10 +277,14 @@ export const settlementOnlyTestFn = ( address: settlementModule.getSettlementContractAddress(), }); const settlement = settlementModule.getSettlementContract(); + + const afterNetworkState = new ProvableNetworkState( + ProvableNetworkState.fromJSON(lastBlock!.result?.afterNetworkState!) + ); expectDefined(lastBlock); expectDefined(lastBlock.result); expect(settlement.networkStateHash.get().toString()).toStrictEqual( - lastBlock!.result.afterNetworkState.hash().toString() + afterNetworkState.hash().toString() ); expect(settlement.stateRoot.get().toString()).toStrictEqual( lastBlock!.result.stateRoot.toString() diff --git a/packages/sequencer/test/settlement/Settlement.ts b/packages/sequencer/test/settlement/Settlement.ts index 0b89e8871..c0564113d 100644 --- a/packages/sequencer/test/settlement/Settlement.ts +++ b/packages/sequencer/test/settlement/Settlement.ts @@ -11,7 +11,7 @@ import { BridgeContract, ContractArgsRegistry, DispatchSmartContract, - NetworkState, + ProvableNetworkState, Protocol, ReturnType, SettlementContractModule, @@ -43,7 +43,6 @@ import { FungibleToken, FungibleTokenAdmin } from "mina-fungible-token"; import { ManualBlockTrigger, - PendingTransaction, PrivateMempool, BlockQueue, SettlementModule, @@ -56,6 +55,7 @@ import { VanillaTaskWorkerModules, Sequencer, InMemoryMinaSigner, + PendingTransaction, CircuitAnalysisModule, } from "../../src"; import { BlockProofSerializer } from "../../src/protocol/production/tasks/serializers/BlockProofSerializer"; @@ -252,7 +252,7 @@ export const settlementTestFn = ( const [block, batch] = result; console.log( - `block ${block?.height.toString()} ${block?.fromMessagesHash.toString()} -> ${block?.toMessagesHash.toString()}` + `block ${block?.height} ${block?.fromMessagesHash} -> ${block?.toMessagesHash}` ); const proof = await blockSerializer .getBlockProofSerializer() @@ -532,7 +532,11 @@ export const settlementTestFn = ( expectDefined(lastBlock); expectDefined(lastBlock.result); expect(settlement.networkStateHash.get().toString()).toStrictEqual( - lastBlock!.result.afterNetworkState.hash().toString() + new ProvableNetworkState( + ProvableNetworkState.fromJSON(lastBlock!.result.afterNetworkState) + ) + .hash() + .toString() ); expect(settlement.stateRoot.get().toString()).toStrictEqual( lastBlock!.result.stateRoot.toString() @@ -649,13 +653,35 @@ export const settlementTestFn = ( console.log(networkstateHash.zkapp!.appState.map((x) => x.toString())); console.log( - `Empty Network State ${NetworkState.empty().hash().toString()}` + `Empty Network State ${ProvableNetworkState.empty().hash().toString()}` + ); + console.log( + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch!.toNetworkState) + ) + .hash() + .toString() + ); + console.log( + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch2!.fromNetworkState) + ) + .hash() + .toString() ); - console.log(batch!.toNetworkState.hash().toString()); - console.log(batch2!.fromNetworkState.hash().toString()); - expect(batch!.toNetworkState.hash().toString()).toStrictEqual( - batch2!.fromNetworkState.hash().toString() + expect( + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch!.toNetworkState) + ) + .hash() + .toString() + ).toStrictEqual( + new ProvableNetworkState( + ProvableNetworkState.fromJSON(batch2!.fromNetworkState) + ) + .hash() + .toString() ); expect(batch2!.blockHashes).toHaveLength(1); @@ -710,12 +736,12 @@ export const settlementTestFn = ( acc0L2Nonce += 2; expectDefined(block); - expect(block.transactions[0].status.toBoolean()).toBe(true); + expect(block.transactions[0].status).toBe(true); expectDefined(batch); console.log("Test networkstate"); - console.log(NetworkState.toJSON(block.networkState.during)); - console.log(NetworkState.toJSON(batch.toNetworkState)); + console.log(block.networkState.during); + console.log(batch.toNetworkState); const settlementResult = await trigger.settle(batch, { [bridgedTokenId.toString()]: { diff --git a/packages/stack/test/graphql/graphql.test.ts b/packages/stack/test/graphql/graphql.test.ts index 45b29206b..641cc905c 100644 --- a/packages/stack/test/graphql/graphql.test.ts +++ b/packages/stack/test/graphql/graphql.test.ts @@ -14,6 +14,7 @@ import { ManualBlockTrigger, Sequencer, InclusionStatus, + UnsignedTransaction, } from "@proto-kit/sequencer"; import { ClientAppChain, @@ -152,7 +153,7 @@ describe("graphql client test", () => { const state = await appChain.query.network.unproven; expect(state).toBeDefined(); - expect(state!.block.height.toBigInt()).toBeGreaterThanOrEqual(0n); + expect(BigInt(state!.block.height)).toBeGreaterThanOrEqual(0n); }); it("should retrieve merkle witness", async () => { @@ -184,7 +185,10 @@ describe("graphql client test", () => { await tx.sign(); await tx.send(); - const txHash = tx.transaction?.hash().toString()!; + const txHash = + tx.transaction instanceof UnsignedTransaction + ? tx.transaction.hash().toString() + : tx.transaction!.hash; const waitPromise = appChain.query.explorer.fetchTxInclusion(txHash); @@ -217,8 +221,8 @@ describe("graphql client test", () => { await tx.send(); const block = await trigger.produceBlock(); - const hash = block?.hash.toString()!; - const height = Number(block?.height.toBigInt()); + const hash = block?.hash!; + const height = Number(block?.height); const hashResult = await appChain.query.explorer.getBlock({ hash: hash }); const heightResult = await appChain.query.explorer.getBlock({ @@ -227,7 +231,7 @@ describe("graphql client test", () => { const heightParsedTx = heightResult?.transactions!; - const blockTxHash = block?.transactions[0].tx.toJSON().hash; + const blockTxHash = block?.transactions[0].tx.hash; const queryTxHash = heightParsedTx[0]?.tx?.hash; @@ -235,19 +239,19 @@ describe("graphql client test", () => { expect(blockTxHash).toBe(queryTxHash); // Block hashes should match - expect(block?.hash.toBigInt()).toBe(heightResult?.hash.toBigInt()); + expect(block?.hash).toBe(heightResult?.hash.toString()); // Block heights should match - expect(block?.height.toBigInt()).toBe(heightResult?.height.toBigInt()); + expect(block?.height).toBe(heightResult?.height); // Previous block hashes should match - expect(block?.previousBlockHash?.toBigInt()).toBe( - heightResult?.previousBlockHash?.toBigInt() + expect(block?.previousBlockHash).toBe( + heightResult?.previousBlockHash?.toString() ); // Transaction hashes should match - expect(block?.transactionsHash.toBigInt()).toBe( - heightResult?.transactionsHash.toBigInt() + expect(block?.transactionsHash).toBe( + heightResult?.transactionsHash.toString() ); // Both query methods should return the same result