@proto-kit/protocol 0.1.1-develop.457 → 0.1.1-develop.600

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/dist/blockmodules/AccountStateModule.d.ts.map +1 -1
  2. package/dist/blockmodules/AccountStateModule.js +10 -3
  3. package/dist/blockmodules/BlockHeightHook.d.ts +3 -3
  4. package/dist/blockmodules/BlockHeightHook.d.ts.map +1 -1
  5. package/dist/blockmodules/BlockHeightHook.js +5 -4
  6. package/dist/blockmodules/LastStateRootBlockHook.d.ts +8 -0
  7. package/dist/blockmodules/LastStateRootBlockHook.d.ts.map +1 -0
  8. package/dist/blockmodules/LastStateRootBlockHook.js +15 -0
  9. package/dist/blockmodules/NoopBlockHook.d.ts +6 -4
  10. package/dist/blockmodules/NoopBlockHook.d.ts.map +1 -1
  11. package/dist/blockmodules/NoopBlockHook.js +4 -4
  12. package/dist/blockmodules/NoopSettlementHook.d.ts +6 -0
  13. package/dist/blockmodules/NoopSettlementHook.d.ts.map +1 -0
  14. package/dist/blockmodules/NoopSettlementHook.js +18 -0
  15. package/dist/hooks/AccountStateHook.d.ts.map +1 -1
  16. package/dist/hooks/AccountStateHook.js +7 -2
  17. package/dist/hooks/BlockHeightHook.d.ts.map +1 -1
  18. package/dist/index.d.ts +9 -3
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +9 -3
  21. package/dist/model/MethodPublicOutput.d.ts +8 -0
  22. package/dist/model/MethodPublicOutput.d.ts.map +1 -1
  23. package/dist/model/MethodPublicOutput.js +1 -0
  24. package/dist/model/network/NetworkState.d.ts +40 -0
  25. package/dist/model/network/NetworkState.d.ts.map +1 -1
  26. package/dist/model/network/NetworkState.js +14 -2
  27. package/dist/model/transaction/RuntimeTransaction.d.ts +45 -20
  28. package/dist/model/transaction/RuntimeTransaction.d.ts.map +1 -1
  29. package/dist/model/transaction/RuntimeTransaction.js +68 -11
  30. package/dist/model/transaction/SignedTransaction.d.ts +71 -0
  31. package/dist/model/transaction/SignedTransaction.d.ts.map +1 -0
  32. package/dist/model/transaction/SignedTransaction.js +33 -0
  33. package/dist/model/transaction/ValueOption.d.ts +119 -0
  34. package/dist/model/transaction/ValueOption.d.ts.map +1 -0
  35. package/dist/model/transaction/ValueOption.js +24 -0
  36. package/dist/protocol/Protocol.d.ts +7 -3
  37. package/dist/protocol/Protocol.d.ts.map +1 -1
  38. package/dist/protocol/Protocol.js +26 -16
  39. package/dist/protocol/ProvableBlockHook.d.ts +2 -10
  40. package/dist/protocol/ProvableBlockHook.d.ts.map +1 -1
  41. package/dist/protocol/ProvableBlockHook.js +1 -1
  42. package/dist/protocol/ProvableTransactionHook.d.ts +1 -1
  43. package/dist/protocol/ProvableTransactionHook.d.ts.map +1 -1
  44. package/dist/protocol/TransitioningProtocolModule.d.ts +3 -2
  45. package/dist/protocol/TransitioningProtocolModule.d.ts.map +1 -1
  46. package/dist/protocol/TransitioningProtocolModule.js +3 -2
  47. package/dist/prover/block/BlockProvable.d.ts +106 -28
  48. package/dist/prover/block/BlockProvable.d.ts.map +1 -1
  49. package/dist/prover/block/BlockProvable.js +23 -5
  50. package/dist/prover/block/BlockProver.d.ts +29 -8
  51. package/dist/prover/block/BlockProver.d.ts.map +1 -1
  52. package/dist/prover/block/BlockProver.js +241 -77
  53. package/dist/prover/block/accummulators/BlockHashMerkleTree.d.ts +45 -0
  54. package/dist/prover/block/accummulators/BlockHashMerkleTree.d.ts.map +1 -0
  55. package/dist/prover/block/accummulators/BlockHashMerkleTree.js +16 -0
  56. package/dist/settlement/ProvableSettlementHook.d.ts +26 -0
  57. package/dist/settlement/ProvableSettlementHook.d.ts.map +1 -0
  58. package/dist/settlement/ProvableSettlementHook.js +3 -0
  59. package/dist/settlement/SettlementContract.d.ts +230 -0
  60. package/dist/settlement/SettlementContract.d.ts.map +1 -0
  61. package/dist/settlement/SettlementContract.js +346 -0
  62. package/dist/settlement/modules/NetworkStateSettlementModule.d.ts +11 -0
  63. package/dist/settlement/modules/NetworkStateSettlementModule.d.ts.map +1 -0
  64. package/dist/settlement/modules/NetworkStateSettlementModule.js +12 -0
  65. package/dist/state/context/RuntimeMethodExecutionContext.d.ts +75 -1
  66. package/dist/state/context/RuntimeMethodExecutionContext.d.ts.map +1 -1
  67. package/dist/state/context/RuntimeMethodExecutionContext.js +19 -1
  68. package/dist/utils/MinaPrefixedProvableHashList.d.ts +24 -0
  69. package/dist/utils/MinaPrefixedProvableHashList.d.ts.map +1 -0
  70. package/dist/utils/MinaPrefixedProvableHashList.js +51 -0
  71. package/package.json +2 -2
  72. package/src/blockmodules/AccountStateModule.ts +17 -6
  73. package/src/blockmodules/BlockHeightHook.ts +5 -8
  74. package/src/blockmodules/LastStateRootBlockHook.ts +26 -0
  75. package/src/blockmodules/NoopBlockHook.ts +15 -11
  76. package/src/blockmodules/NoopSettlementHook.ts +21 -0
  77. package/src/blockmodules/SequenceStateTransactionModule.ts +25 -0
  78. package/src/index.ts +9 -3
  79. package/src/model/MethodPublicOutput.ts +3 -2
  80. package/src/model/network/NetworkState.ts +15 -3
  81. package/src/model/transaction/RuntimeTransaction.ts +90 -16
  82. package/src/model/transaction/SignedTransaction.ts +54 -0
  83. package/src/model/transaction/ValueOption.ts +28 -0
  84. package/src/protocol/Protocol.ts +49 -31
  85. package/src/protocol/ProvableBlockHook.ts +10 -13
  86. package/src/protocol/ProvableTransactionHook.ts +2 -1
  87. package/src/protocol/TransitioningProtocolModule.ts +3 -2
  88. package/src/prover/block/BlockProvable.ts +39 -6
  89. package/src/prover/block/BlockProver.ts +473 -143
  90. package/src/prover/block/accummulators/BlockHashMerkleTree.ts +16 -0
  91. package/src/settlement/ProvableSettlementHook.ts +37 -0
  92. package/src/settlement/SettlementContract.ts +444 -0
  93. package/src/settlement/modules/NetworkStateSettlementModule.ts +39 -0
  94. package/src/state/context/RuntimeMethodExecutionContext.ts +18 -1
  95. package/src/utils/MinaPrefixedProvableHashList.ts +72 -0
  96. package/test/BlockProver.test.ts +2 -3
  97. package/src/model/transaction/ProtocolTransaction.ts +0 -25
  98. package/src/prover/block/BlockTransactionPosition.ts +0 -34
@@ -11,24 +11,31 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
13
  /* eslint-disable max-lines */
14
- import { Experimental, Field, Provable, SelfProof, } from "o1js";
14
+ import { Bool, Experimental, Field, Poseidon, Provable, SelfProof } from "o1js";
15
15
  import { container, inject, injectable, injectAll } from "tsyringe";
16
16
  import { provableMethod, ZkProgrammable, } from "@proto-kit/common";
17
17
  import { DefaultProvableHashList } from "../../utils/ProvableHashList";
18
18
  import { ProtocolModule } from "../../protocol/ProtocolModule";
19
19
  import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
20
- import { BlockProverExecutionData, BlockProverPublicInput, BlockProverPublicOutput, } from "./BlockProvable";
21
- import { ProvableStateTransition } from "../../model/StateTransition";
20
+ import { ProvableStateTransition, } from "../../model/StateTransition";
22
21
  import { RuntimeMethodExecutionContext } from "../../state/context/RuntimeMethodExecutionContext";
23
22
  import { NetworkState } from "../../model/network/NetworkState";
24
- import { BlockTransactionPosition } from "./BlockTransactionPosition";
23
+ import { SignedTransaction } from "../../model/transaction/SignedTransaction";
24
+ import { MinaActions, MinaActionsHashList } from "../../utils/MinaPrefixedProvableHashList";
25
+ import { BlockProverExecutionData, BlockProverPublicInput, BlockProverPublicOutput, } from "./BlockProvable";
26
+ import { BlockHashMerkleTreeWitness, BlockHashTreeEntry, } from "./accummulators/BlockHashMerkleTree";
25
27
  const errors = {
26
28
  stateProofNotStartingAtZero: () => "StateProof not starting ST-commitment at zero",
27
29
  stateTransitionsHashNotEqual: () => "StateTransition list commitments are not equal",
30
+ propertyNotMatchingStep: (propertyName, step) => `${propertyName} not matching: ${step}`,
28
31
  propertyNotMatching: (propertyName) => `${propertyName} not matching`,
29
- stateRootNotMatching: (step) => `StateRoots not matching ${step}`,
30
- transactionsHashNotMatching: (step) => `transactions hash not matching ${step}`,
32
+ stateRootNotMatching: (step) => errors.propertyNotMatchingStep("StateRoots", step),
33
+ transactionsHashNotMatching: (step) => errors.propertyNotMatchingStep("Transactions hash", step),
34
+ networkStateHashNotMatching: (step) => errors.propertyNotMatchingStep("Network state hash", step),
31
35
  };
36
+ function maxField() {
37
+ return Field(Field.ORDER - 1n);
38
+ }
32
39
  export class BlockProverProgrammable extends ZkProgrammable {
33
40
  constructor(
34
41
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
@@ -49,47 +56,56 @@ export class BlockProverProgrammable extends ZkProgrammable {
49
56
  *
50
57
  * @param state The from-state of the BlockProver
51
58
  * @param stateTransitionProof
52
- * @param appProof
59
+ * @param runtimeProof
53
60
  * @param executionData
54
61
  * @returns The new BlockProver-state to be used as public output
55
62
  */
56
- applyTransaction(state, stateTransitionProof, appProof, executionData) {
57
- const { transaction, networkState } = executionData;
58
- appProof.verify();
63
+ applyTransaction(state, stateTransitionProof, runtimeProof, executionData) {
64
+ const { transaction, networkState, signature } = executionData;
65
+ const isMessage = runtimeProof.publicOutput.isMessage;
66
+ runtimeProof.verify();
59
67
  stateTransitionProof.verify();
60
68
  const stateTo = { ...state };
61
69
  // Checks for the stateTransitionProof and appProof matching
62
70
  stateTransitionProof.publicInput.stateTransitionsHash.assertEquals(Field(0), errors.stateProofNotStartingAtZero());
63
- appProof.publicOutput.stateTransitionsHash.assertEquals(stateTransitionProof.publicOutput.stateTransitionsHash, errors.stateTransitionsHashNotEqual());
71
+ stateTransitionProof.publicInput.protocolTransitionsHash.assertEquals(Field(0), errors.stateProofNotStartingAtZero());
72
+ runtimeProof.publicOutput.stateTransitionsHash.assertEquals(stateTransitionProof.publicOutput.stateTransitionsHash, errors.stateTransitionsHashNotEqual());
64
73
  // Assert from state roots
65
74
  state.stateRoot.assertEquals(stateTransitionProof.publicInput.stateRoot, errors.propertyNotMatching("from state root"));
66
75
  state.stateRoot.assertEquals(stateTransitionProof.publicInput.protocolStateRoot, errors.propertyNotMatching("from protocol state root"));
67
- // Apply state if status success
68
- stateTo.stateRoot = Provable.if(appProof.publicOutput.status, stateTransitionProof.publicOutput.stateRoot, stateTransitionProof.publicOutput.protocolStateRoot);
69
76
  // Apply protocol state transitions
70
- this.assertProtocolTransitions(stateTransitionProof, executionData);
77
+ this.assertProtocolTransitions(stateTransitionProof, executionData, runtimeProof);
78
+ // Apply state if status success
79
+ stateTo.stateRoot = Provable.if(runtimeProof.publicOutput.status, stateTransitionProof.publicOutput.stateRoot, stateTransitionProof.publicOutput.protocolStateRoot);
80
+ // Check transaction integrity against appProof
81
+ const blockTransactionHash = transaction.hash();
82
+ blockTransactionHash.assertEquals(runtimeProof.publicOutput.transactionHash, "Transactions provided in AppProof and BlockProof do not match");
71
83
  // Check transaction signature
72
- transaction
84
+ new SignedTransaction({
85
+ transaction,
86
+ signature,
87
+ })
73
88
  .validateSignature()
89
+ .or(isMessage)
74
90
  .assertTrue("Transaction signature not valid");
75
- // Check transaction integrity against appProof
76
- const blockTransactionHash = RuntimeTransaction.fromProtocolTransaction(transaction).hash();
77
- blockTransactionHash.assertEquals(appProof.publicOutput.transactionHash, "Transactions provided in AppProof and BlockProof do not match");
91
+ // Validate layout of transaction witness
92
+ transaction.assertTransactionType(isMessage);
78
93
  // Check network state integrity against appProof
79
- state.networkStateHash.assertEquals(appProof.publicOutput.networkStateHash, "Network state does not match state used in AppProof");
94
+ state.networkStateHash.assertEquals(runtimeProof.publicOutput.networkStateHash, "Network state does not match state used in AppProof");
80
95
  state.networkStateHash.assertEquals(networkState.hash(), "Network state provided to BlockProver does not match the publicInput");
81
96
  return stateTo;
82
97
  }
83
98
  // eslint-disable-next-line no-warning-comments, max-len
84
99
  // TODO How does this interact with the RuntimeMethodExecutionContext when executing runtimemethods?
85
- assertProtocolTransitions(stateTransitionProof, executionData) {
100
+ assertProtocolTransitions(stateTransitionProof, executionData, runtimeProof) {
86
101
  const executionContext = container.resolve(RuntimeMethodExecutionContext);
87
102
  executionContext.clear();
88
103
  // Setup context for potential calls to runtime methods.
89
104
  // This way they can use this.transaction etc. while still having provable
90
105
  // integrity between data
91
106
  executionContext.setup({
92
- transaction: RuntimeTransaction.fromProtocolTransaction(executionData.transaction),
107
+ // That is why we should probably hide it from the transaction context inputs
108
+ transaction: executionData.transaction,
93
109
  networkState: executionData.networkState,
94
110
  });
95
111
  executionContext.beforeMethod("", "", []);
@@ -106,68 +122,153 @@ export class BlockProverProgrammable extends ZkProgrammable {
106
122
  });
107
123
  stateTransitionProof.publicOutput.protocolTransitionsHash.assertEquals(hashList.commitment, "ProtocolTransitionsHash not matching the generated protocol transitions");
108
124
  }
109
- getBeforeBlockNetworkState(state, networkState) {
110
- return this.blockHooks.reduce((networkState, blockHook) => {
111
- return blockHook.beforeBlock({
112
- state,
113
- networkState,
114
- });
115
- }, networkState);
116
- }
117
- getAfterBlockNetworkState(state, networkState) {
118
- return this.blockHooks.reduce((networkState, blockHook) => {
119
- return blockHook.afterBlock({
120
- state,
125
+ executeBlockHooks(state, inputNetworkState, type) {
126
+ const executionContext = container.resolve(RuntimeMethodExecutionContext);
127
+ executionContext.clear();
128
+ executionContext.beforeMethod("", "", []);
129
+ const resultingNetworkState = this.blockHooks.reduce((networkState, blockHook) => {
130
+ // Setup context for potential calls to runtime methods.
131
+ // With the special case that we set the new networkstate for every hook
132
+ // We also have to put in a dummy transaction for network.transaction
133
+ executionContext.setup({
134
+ transaction: RuntimeTransaction.dummyTransaction(),
121
135
  networkState,
122
136
  });
123
- }, networkState);
137
+ if (type === "beforeBlock") {
138
+ return blockHook.beforeBlock(networkState, state);
139
+ }
140
+ else if (type === "afterBlock") {
141
+ return blockHook.afterBlock(networkState, state);
142
+ }
143
+ else {
144
+ throw new Error("Unreachable");
145
+ }
146
+ }, inputNetworkState);
147
+ executionContext.afterMethod();
148
+ const { stateTransitions, status, statusMessage } = executionContext.current().result;
149
+ status.assertTrue(`Block hook call failed: ${statusMessage ?? "-"}`);
150
+ return {
151
+ networkState: resultingNetworkState,
152
+ stateTransitions,
153
+ };
124
154
  }
125
- addTransactionToBundle(state, stateTransitionProof, appProof, executionData) {
126
- const { transactionPosition, networkState } = executionData;
155
+ addTransactionToBundle(state, isMessage, transaction) {
127
156
  const stateTo = {
128
157
  ...state,
129
158
  };
130
- // Execute beforeBlook hooks and apply if it is the first tx of the bundle
131
- const beforeHookResult = this.getBeforeBlockNetworkState(state, networkState);
132
- const bundleOpened = transactionPosition.equals(BlockTransactionPosition.fromPositionType("FIRST"));
133
- const resultingNetworkState = new NetworkState(Provable.if(bundleOpened, NetworkState, beforeHookResult, networkState));
134
- stateTo.networkStateHash = resultingNetworkState.hash();
135
- // TODO Modify bundle merkle tree as per specs
159
+ const transactionHash = transaction.hash();
136
160
  // Append tx to transaction list
137
161
  const transactionList = new DefaultProvableHashList(Field, state.transactionsHash);
138
- const { transactionHash } = appProof.publicOutput;
139
- transactionList.push(transactionHash);
162
+ transactionList.pushIf(transactionHash, isMessage.not());
140
163
  stateTo.transactionsHash = transactionList.commitment;
141
- return {
142
- state: stateTo,
143
- networkState: resultingNetworkState,
144
- bundleOpened,
145
- bundleClosed: transactionPosition.equals(BlockTransactionPosition.fromPositionType("LAST")),
164
+ // Append tx to eternal transaction list
165
+ // eslint-disable-next-line no-warning-comments
166
+ // TODO Change that to the a sequence-state compatible transaction struct
167
+ const eternalTransactionList = new DefaultProvableHashList(Field, state.eternalTransactionsHash);
168
+ eternalTransactionList.pushIf(transactionHash, isMessage.not());
169
+ stateTo.eternalTransactionsHash = eternalTransactionList.commitment;
170
+ // Append tx to incomingMessagesHash
171
+ const actionHash = MinaActions.actionHash(transaction.hashData());
172
+ const incomingMessagesList = new MinaActionsHashList(state.incomingMessagesHash);
173
+ incomingMessagesList.pushIf(actionHash, isMessage);
174
+ stateTo.incomingMessagesHash = incomingMessagesList.commitment;
175
+ return stateTo;
176
+ }
177
+ proveTransaction(publicInput, stateProof, runtimeProof, executionData) {
178
+ const state = {
179
+ ...publicInput,
146
180
  };
181
+ state.networkStateHash.assertEquals(executionData.networkState.hash(), "ExecutionData Networkstate doesn't equal public input hash");
182
+ const bundleInclusionState = this.addTransactionToBundle(state, runtimeProof.publicOutput.isMessage, executionData.transaction);
183
+ const stateTo = this.applyTransaction(bundleInclusionState, stateProof, runtimeProof, executionData);
184
+ return new BlockProverPublicOutput({
185
+ ...stateTo,
186
+ blockNumber: maxField(),
187
+ closed: Bool(false),
188
+ });
147
189
  }
148
- proveTransaction(publicInput, stateProof, appProof, executionData) {
190
+ assertSTProofInput(stateTransitionProof, stateRoot) {
191
+ stateTransitionProof.publicInput.stateTransitionsHash.assertEquals(Field(0), errors.stateProofNotStartingAtZero());
192
+ stateTransitionProof.publicInput.protocolTransitionsHash.assertEquals(Field(0), errors.stateProofNotStartingAtZero());
193
+ // Assert from state roots
194
+ stateRoot.assertEquals(stateTransitionProof.publicInput.stateRoot, errors.propertyNotMatching("from state root"));
195
+ }
196
+ proveBlock(publicInput, networkState, blockWitness, stateTransitionProof, transactionProof) {
149
197
  const state = {
150
- transactionsHash: publicInput.transactionsHash,
151
- stateRoot: publicInput.stateRoot,
152
- networkStateHash: publicInput.networkStateHash,
198
+ ...publicInput,
153
199
  };
154
- const bundleInclusionResult = this.addTransactionToBundle(state, stateProof, appProof, executionData);
155
- const stateTo = this.applyTransaction(bundleInclusionResult.state, stateProof, appProof, {
156
- transaction: executionData.transaction,
157
- transactionPosition: executionData.transactionPosition,
158
- networkState: bundleInclusionResult.networkState,
200
+ // 1. Make assertions about the inputs
201
+ publicInput.transactionsHash.assertEquals(Field(0), "Transactionshash has to start at 0");
202
+ publicInput.networkStateHash.assertEquals(networkState.hash(), "Wrong NetworkState supplied");
203
+ transactionProof.publicInput.transactionsHash.assertEquals(Field(0), "TransactionProof transactionshash has to start at 0");
204
+ transactionProof.publicInput.blockHashRoot.assertEquals(Field(0), "TransactionProof cannot carry the blockHashRoot - publicInput");
205
+ transactionProof.publicOutput.blockHashRoot.assertEquals(Field(0), "TransactionProof cannot carry the blockHashRoot - publicOutput");
206
+ transactionProof.publicInput.networkStateHash.assertEquals(transactionProof.publicOutput.networkStateHash, "TransactionProof cannot alter the network state");
207
+ transactionProof.publicInput.eternalTransactionsHash.assertEquals(state.eternalTransactionsHash, "TransactionProof starting eternalTransactionHash not matching");
208
+ transactionProof.publicInput.incomingMessagesHash.assertEquals(state.incomingMessagesHash, "TransactionProof starting incomingMessagesHash not matching");
209
+ // Verify ST Proof only if STs have been emitted,
210
+ // otherwise we can input a dummy proof
211
+ const stsEmitted = stateTransitionProof.publicOutput.stateTransitionsHash
212
+ .equals(0)
213
+ .and(stateTransitionProof.publicOutput.protocolTransitionsHash.equals(0))
214
+ .not();
215
+ stateTransitionProof.verifyIf(stsEmitted);
216
+ // Verify Transaction proof if it has at least 1 tx
217
+ // We have to compare the whole input and output because we can make no
218
+ // assumptions about the values, since it can be an arbitrary dummy-proof
219
+ const txProofOutput = transactionProof.publicOutput;
220
+ const verifyTransactionProof = txProofOutput.equals(transactionProof.publicInput, txProofOutput.closed, txProofOutput.blockNumber);
221
+ transactionProof.verifyIf(verifyTransactionProof);
222
+ // 2. Execute beforeBlock hooks
223
+ const beforeBlockResult = this.executeBlockHooks(state, networkState, "beforeBlock");
224
+ const beforeBlockHashList = new DefaultProvableHashList(ProvableStateTransition);
225
+ beforeBlockResult.stateTransitions.forEach((st) => {
226
+ beforeBlockHashList.push(st.toProvable());
159
227
  });
160
- // Apply afterBlock hooks
161
- const afterBlockNetworkState = this.getAfterBlockNetworkState(stateTo, bundleInclusionResult.networkState);
162
- const bundleClosed = executionData.transactionPosition.equals(BlockTransactionPosition.fromPositionType("LAST"));
163
- // We only need the hash here since this computed networkstate
164
- // is only used as an input in the next bundle
165
- const resultingNetworkStateHash = Provable.if(bundleClosed, afterBlockNetworkState.hash(), stateTo.networkStateHash);
228
+ // We are reusing protocolSTs here as beforeBlock STs
229
+ // TODO Not possible atm bcs we can't have a seperation between protocol/runtime state roots,
230
+ // which we would for both before and after to be able to emit STs
231
+ // stateTransitionProof.publicInput.protocolTransitionsHash.assertEquals(
232
+ // beforeBlockHashList.commitment
233
+ // );
234
+ // state.stateRoot = stateTransitionProof.publicInput.protocolStateRoot;
235
+ // TODO Only for now
236
+ beforeBlockHashList.commitment.assertEquals(Field(0), "beforeBlock() cannot emit state transitions yet");
237
+ // 4. Apply TX-type BlockProof
238
+ transactionProof.publicInput.networkStateHash.assertEquals(beforeBlockResult.networkState.hash(), "TransactionProof networkstate hash not matching beforeBlock hook result");
239
+ transactionProof.publicInput.stateRoot.assertEquals(state.stateRoot, "TransactionProof input state root not matching blockprover state root");
240
+ state.stateRoot = transactionProof.publicOutput.stateRoot;
241
+ state.transactionsHash = transactionProof.publicOutput.transactionsHash;
242
+ state.eternalTransactionsHash =
243
+ transactionProof.publicOutput.eternalTransactionsHash;
244
+ state.incomingMessagesHash =
245
+ transactionProof.publicOutput.incomingMessagesHash;
246
+ // 5. Execute afterBlock hooks
247
+ this.assertSTProofInput(stateTransitionProof, state.stateRoot);
248
+ const afterBlockResult = this.executeBlockHooks(state, beforeBlockResult.networkState, "afterBlock");
249
+ const afterBlockHashList = new DefaultProvableHashList(ProvableStateTransition);
250
+ afterBlockResult.stateTransitions.forEach((st) => {
251
+ afterBlockHashList.push(st.toProvable());
252
+ });
253
+ state.networkStateHash = afterBlockResult.networkState.hash();
254
+ // We are reusing runtime STs here as afterBlock STs
255
+ stateTransitionProof.publicInput.stateTransitionsHash.assertEquals(afterBlockHashList.commitment, "STProof from-ST-hash not matching generated ST-hash from afterBlock hooks");
256
+ state.stateRoot = stateTransitionProof.publicInput.stateRoot;
257
+ // 6. Close block
258
+ // Calculate the new block index
259
+ const blockIndex = blockWitness.calculateIndex();
260
+ blockWitness
261
+ .calculateRoot(Field(0))
262
+ .assertEquals(publicInput.blockHashRoot, "Supplied block hash witness not matching state root");
263
+ state.blockHashRoot = blockWitness.calculateRoot(new BlockHashTreeEntry({
264
+ // Mirroring UnprovenBlock.hash()
265
+ blockHash: Poseidon.hash([blockIndex, state.transactionsHash]),
266
+ closed: Bool(true),
267
+ }).hash());
166
268
  return new BlockProverPublicOutput({
167
- stateRoot: stateTo.stateRoot,
168
- transactionsHash: stateTo.transactionsHash,
169
- // eslint-disable-next-line putout/putout
170
- networkStateHash: resultingNetworkStateHash,
269
+ ...state,
270
+ blockNumber: blockIndex,
271
+ closed: Bool(true),
171
272
  });
172
273
  }
173
274
  merge(publicInput, proof1, proof2) {
@@ -176,16 +277,68 @@ export class BlockProverProgrammable extends ZkProgrammable {
176
277
  // Check state
177
278
  publicInput.stateRoot.assertEquals(proof1.publicInput.stateRoot, errors.stateRootNotMatching("publicInput.from -> proof1.from"));
178
279
  proof1.publicOutput.stateRoot.assertEquals(proof2.publicInput.stateRoot, errors.stateRootNotMatching("proof1.to -> proof2.from"));
179
- // Check transaction list
180
- publicInput.transactionsHash.assertEquals(proof1.publicInput.transactionsHash, errors.transactionsHashNotMatching("publicInput.from -> proof1.from"));
181
- proof1.publicOutput.transactionsHash.assertEquals(proof2.publicInput.transactionsHash, errors.transactionsHashNotMatching("proof1.to -> proof2.from"));
280
+ // Check transaction list hash.
281
+ // Only assert them if these are tx proofs, skip for closed proofs
282
+ publicInput.transactionsHash
283
+ .equals(proof1.publicInput.transactionsHash)
284
+ .or(proof1.publicOutput.closed)
285
+ .assertTrue(errors.transactionsHashNotMatching("publicInput.from -> proof1.from"));
286
+ proof1.publicOutput.transactionsHash
287
+ .equals(proof2.publicInput.transactionsHash)
288
+ .or(proof1.publicOutput.closed)
289
+ .assertTrue(errors.transactionsHashNotMatching("proof1.to -> proof2.from"));
182
290
  // Check networkhash
183
- publicInput.networkStateHash.assertEquals(proof1.publicInput.networkStateHash, errors.transactionsHashNotMatching("publicInput.from -> proof1.from"));
184
- proof1.publicOutput.networkStateHash.assertEquals(proof2.publicInput.networkStateHash, errors.transactionsHashNotMatching("proof1.to -> proof2.from"));
291
+ publicInput.networkStateHash.assertEquals(proof1.publicInput.networkStateHash, errors.networkStateHashNotMatching("publicInput.from -> proof1.from"));
292
+ proof1.publicOutput.networkStateHash.assertEquals(proof2.publicInput.networkStateHash, errors.networkStateHashNotMatching("proof1.to -> proof2.from"));
293
+ // Check blockHashRoot
294
+ publicInput.blockHashRoot.assertEquals(proof1.publicInput.blockHashRoot, errors.transactionsHashNotMatching("publicInput.from -> proof1.from"));
295
+ proof1.publicOutput.blockHashRoot.assertEquals(proof2.publicInput.blockHashRoot, errors.transactionsHashNotMatching("proof1.to -> proof2.from"));
296
+ // Check eternalTransactionsHash
297
+ publicInput.eternalTransactionsHash.assertEquals(proof1.publicInput.eternalTransactionsHash, errors.transactionsHashNotMatching("publicInput.from -> proof1.from"));
298
+ proof1.publicOutput.eternalTransactionsHash.assertEquals(proof2.publicInput.eternalTransactionsHash, errors.transactionsHashNotMatching("proof1.to -> proof2.from"));
299
+ // Check incomingMessagesHash
300
+ publicInput.incomingMessagesHash.assertEquals(proof1.publicInput.incomingMessagesHash, errors.propertyNotMatchingStep("IncomingMessagesHash", "publicInput.from -> proof1.from"));
301
+ proof1.publicOutput.incomingMessagesHash.assertEquals(proof2.publicInput.incomingMessagesHash, errors.propertyNotMatchingStep("IncomingMessagesHash", "proof1.to -> proof2.from"));
302
+ // Assert closed indicator matches
303
+ // (i.e. we can only merge TX-Type and Block-Type with each other)
304
+ proof1.publicOutput.closed.assertEquals(proof2.publicOutput.closed, "Closed indicators not matching");
305
+ // Either
306
+ // blockNumbers are unset and proofs are unclosed or
307
+ // both blocks are closed, then they have to increment or
308
+ // one block is closed, then height has to be the same
309
+ // Imperative algo would look like
310
+ // if(proof1.height == MAX && proof2.height == MAX){
311
+ // assert !proof1.closed && !proof2.closed;
312
+ // }else if(proof1.closed && proof2.closed){
313
+ // assert proof1.height + 1 == proof2.height
314
+ // // next one is omitted for now
315
+ // }else if(proof1.closed || proof2.closed{
316
+ // assert proof1.height == proof2.height
317
+ // }
318
+ const proof1Height = proof1.publicOutput.blockNumber;
319
+ const proof1Closed = proof1.publicOutput.closed;
320
+ const proof2Height = proof2.publicOutput.blockNumber;
321
+ const proof2Closed = proof2.publicOutput.closed;
322
+ const isValidTransactionMerge = proof1Height
323
+ .equals(maxField())
324
+ .and(proof2Height.equals(proof1Height))
325
+ .and(proof1Closed.or(proof2Closed).not());
326
+ const isValidClosedMerge = proof1Closed
327
+ .and(proof2Closed)
328
+ .and(proof1Height.add(1).equals(proof2Height));
329
+ isValidTransactionMerge
330
+ .or(isValidClosedMerge)
331
+ .assertTrue("Invalid BlockProof merge");
185
332
  return new BlockProverPublicOutput({
186
333
  stateRoot: proof2.publicOutput.stateRoot,
187
334
  transactionsHash: proof2.publicOutput.transactionsHash,
188
335
  networkStateHash: proof2.publicOutput.networkStateHash,
336
+ blockHashRoot: proof2.publicOutput.blockHashRoot,
337
+ eternalTransactionsHash: proof2.publicOutput.eternalTransactionsHash,
338
+ incomingMessagesHash: proof2.publicOutput.incomingMessagesHash,
339
+ // Provable.if(isValidClosedMerge, Bool(true), Bool(false));
340
+ closed: isValidClosedMerge,
341
+ blockNumber: proof2Height,
189
342
  });
190
343
  }
191
344
  /**
@@ -240,9 +393,17 @@ export class BlockProverProgrammable extends ZkProgrammable {
240
393
  __decorate([
241
394
  provableMethod(),
242
395
  __metadata("design:type", Function),
243
- __metadata("design:paramtypes", [BlockProverPublicInput, Object, Function, BlockProverExecutionData]),
396
+ __metadata("design:paramtypes", [BlockProverPublicInput, Object, Object, BlockProverExecutionData]),
244
397
  __metadata("design:returntype", BlockProverPublicOutput)
245
398
  ], BlockProverProgrammable.prototype, "proveTransaction", null);
399
+ __decorate([
400
+ provableMethod(),
401
+ __metadata("design:type", Function),
402
+ __metadata("design:paramtypes", [BlockProverPublicInput,
403
+ NetworkState,
404
+ BlockHashMerkleTreeWitness, Object, Object]),
405
+ __metadata("design:returntype", BlockProverPublicOutput)
406
+ ], BlockProverProgrammable.prototype, "proveBlock", null);
246
407
  __decorate([
247
408
  provableMethod(),
248
409
  __metadata("design:type", Function),
@@ -261,12 +422,15 @@ let BlockProver = class BlockProver extends ProtocolModule {
261
422
  this.runtime = runtime;
262
423
  this.zkProgrammable = new BlockProverProgrammable(this, stateTransitionProver.zkProgrammable, runtime.zkProgrammable, transactionHooks, blockHooks);
263
424
  }
264
- merge(publicInput, proof1, proof2) {
265
- return this.zkProgrammable.merge(publicInput, proof1, proof2);
266
- }
267
425
  proveTransaction(publicInput, stateProof, appProof, executionData) {
268
426
  return this.zkProgrammable.proveTransaction(publicInput, stateProof, appProof, executionData);
269
427
  }
428
+ proveBlock(publicInput, networkState, blockWitness, stateTransitionProof, transactionProof) {
429
+ return this.zkProgrammable.proveBlock(publicInput, networkState, blockWitness, stateTransitionProof, transactionProof);
430
+ }
431
+ merge(publicInput, proof1, proof2) {
432
+ return this.zkProgrammable.merge(publicInput, proof1, proof2);
433
+ }
270
434
  };
271
435
  BlockProver = __decorate([
272
436
  injectable(),
@@ -0,0 +1,45 @@
1
+ import { Field } from "o1js";
2
+ declare const BlockHashMerkleTree_base: import("@proto-kit/common").AbstractMerkleTreeClass;
3
+ export declare class BlockHashMerkleTree extends BlockHashMerkleTree_base {
4
+ }
5
+ export declare class BlockHashMerkleTreeWitness extends BlockHashMerkleTree.WITNESS {
6
+ }
7
+ declare const BlockHashTreeEntry_base: (new (value: {
8
+ blockHash: import("o1js/dist/node/lib/field").Field;
9
+ closed: import("o1js/dist/node/lib/bool").Bool;
10
+ }) => {
11
+ blockHash: import("o1js/dist/node/lib/field").Field;
12
+ closed: import("o1js/dist/node/lib/bool").Bool;
13
+ }) & {
14
+ _isStruct: true;
15
+ } & import("o1js/dist/node/snarky").ProvablePure<{
16
+ blockHash: import("o1js/dist/node/lib/field").Field;
17
+ closed: import("o1js/dist/node/lib/bool").Bool;
18
+ }> & {
19
+ toInput: (x: {
20
+ blockHash: import("o1js/dist/node/lib/field").Field;
21
+ closed: import("o1js/dist/node/lib/bool").Bool;
22
+ }) => {
23
+ fields?: import("o1js/dist/node/lib/field").Field[] | undefined;
24
+ packed?: [import("o1js/dist/node/lib/field").Field, number][] | undefined;
25
+ };
26
+ toJSON: (x: {
27
+ blockHash: import("o1js/dist/node/lib/field").Field;
28
+ closed: import("o1js/dist/node/lib/bool").Bool;
29
+ }) => {
30
+ blockHash: string;
31
+ closed: boolean;
32
+ };
33
+ fromJSON: (x: {
34
+ blockHash: string;
35
+ closed: boolean;
36
+ }) => {
37
+ blockHash: import("o1js/dist/node/lib/field").Field;
38
+ closed: import("o1js/dist/node/lib/bool").Bool;
39
+ };
40
+ };
41
+ export declare class BlockHashTreeEntry extends BlockHashTreeEntry_base {
42
+ hash(): Field;
43
+ }
44
+ export {};
45
+ //# sourceMappingURL=BlockHashMerkleTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BlockHashMerkleTree.d.ts","sourceRoot":"","sources":["../../../../src/prover/block/accummulators/BlockHashMerkleTree.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,EAA8B,MAAM,MAAM,CAAC;;AAE/D,qBAAa,mBAAoB,SAAQ,wBAAoB;CAAG;AAChE,qBAAa,0BAA2B,SAAQ,mBAAmB,CAAC,OAAO;CAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE9E,qBAAa,kBAAmB,SAAQ,uBAKtC;IACO,IAAI,IAAI,KAAK;CAGrB"}
@@ -0,0 +1,16 @@
1
+ import { createMerkleTree } from "@proto-kit/common";
2
+ import { Bool, Field, Poseidon, Struct } from "o1js";
3
+ export class BlockHashMerkleTree extends createMerkleTree(16) {
4
+ }
5
+ export class BlockHashMerkleTreeWitness extends BlockHashMerkleTree.WITNESS {
6
+ }
7
+ export class BlockHashTreeEntry extends Struct({
8
+ blockHash: Field,
9
+ closed: Bool,
10
+ // TODO We could add startingEternalTransactionsHash here to offer
11
+ // a more trivial connection to the sequence state
12
+ }) {
13
+ hash() {
14
+ return Poseidon.hash([this.blockHash, ...this.closed.toFields()]);
15
+ }
16
+ }
@@ -0,0 +1,26 @@
1
+ import { Field, UInt32 } from "o1js";
2
+ import type { BlockProof } from "../prover/block/BlockProver";
3
+ import { ProtocolModule } from "../protocol/ProtocolModule";
4
+ import { NetworkState } from "../model/network/NetworkState";
5
+ import type { SettlementContract } from "./SettlementContract";
6
+ export type SettlementStateRecord = {
7
+ sequencerKey: Field;
8
+ lastSettlementL1Block: UInt32;
9
+ stateRoot: Field;
10
+ networkStateHash: Field;
11
+ blockHashRoot: Field;
12
+ promisedMessagesHash: Field;
13
+ honoredMessagesHash: Field;
14
+ };
15
+ export type SettlementHookInputs = {
16
+ blockProof: BlockProof;
17
+ fromNetworkState: NetworkState;
18
+ toNetworkState: NetworkState;
19
+ newPromisedMessagesHash: Field;
20
+ contractState: SettlementStateRecord;
21
+ currentL1Block: UInt32;
22
+ };
23
+ export declare abstract class ProvableSettlementHook<Config> extends ProtocolModule<Config> {
24
+ abstract beforeSettlement(smartContract: SettlementContract, inputs: SettlementHookInputs): void;
25
+ }
26
+ //# sourceMappingURL=ProvableSettlementHook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProvableSettlementHook.d.ts","sourceRoot":"","sources":["../../src/settlement/ProvableSettlementHook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAErC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,EAAE,KAAK,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAE9B,SAAS,EAAE,KAAK,CAAC;IACjB,gBAAgB,EAAE,KAAK,CAAC;IACxB,aAAa,EAAE,KAAK,CAAC;IAErB,oBAAoB,EAAE,KAAK,CAAC;IAC5B,mBAAmB,EAAE,KAAK,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,UAAU,EAAE,UAAU,CAAC;IACvB,gBAAgB,EAAE,YAAY,CAAC;IAC/B,cAAc,EAAE,YAAY,CAAC;IAC7B,uBAAuB,EAAE,KAAK,CAAC;IAC/B,aAAa,EAAE,qBAAqB,CAAC;IACrC,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,8BAAsB,sBAAsB,CAC1C,MAAM,CACN,SAAQ,cAAc,CAAC,MAAM,CAAC;aACd,gBAAgB,CAC9B,aAAa,EAAE,kBAAkB,EACjC,MAAM,EAAE,oBAAoB,GAC3B,IAAI;CACR"}
@@ -0,0 +1,3 @@
1
+ import { ProtocolModule } from "../protocol/ProtocolModule";
2
+ export class ProvableSettlementHook extends ProtocolModule {
3
+ }