@proto-kit/protocol 0.1.1-develop.1086

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 (251) hide show
  1. package/LICENSE.md +201 -0
  2. package/README.md +45 -0
  3. package/dist/Constants.d.ts +4 -0
  4. package/dist/Constants.d.ts.map +1 -0
  5. package/dist/Constants.js +3 -0
  6. package/dist/hooks/AccountStateHook.d.ts +52 -0
  7. package/dist/hooks/AccountStateHook.d.ts.map +1 -0
  8. package/dist/hooks/AccountStateHook.js +47 -0
  9. package/dist/hooks/BlockHeightHook.d.ts +7 -0
  10. package/dist/hooks/BlockHeightHook.d.ts.map +1 -0
  11. package/dist/hooks/BlockHeightHook.js +15 -0
  12. package/dist/hooks/LastStateRootBlockHook.d.ts +8 -0
  13. package/dist/hooks/LastStateRootBlockHook.d.ts.map +1 -0
  14. package/dist/hooks/LastStateRootBlockHook.js +15 -0
  15. package/dist/hooks/NoopBlockHook.d.ts +9 -0
  16. package/dist/hooks/NoopBlockHook.d.ts.map +1 -0
  17. package/dist/hooks/NoopBlockHook.js +9 -0
  18. package/dist/hooks/NoopSettlementHook.d.ts +6 -0
  19. package/dist/hooks/NoopSettlementHook.d.ts.map +1 -0
  20. package/dist/hooks/NoopSettlementHook.js +17 -0
  21. package/dist/hooks/NoopTransactionHook.d.ts +6 -0
  22. package/dist/hooks/NoopTransactionHook.d.ts.map +1 -0
  23. package/dist/hooks/NoopTransactionHook.js +7 -0
  24. package/dist/index.d.ts +54 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +53 -0
  27. package/dist/model/MethodPublicOutput.d.ts +113 -0
  28. package/dist/model/MethodPublicOutput.d.ts.map +1 -0
  29. package/dist/model/MethodPublicOutput.js +14 -0
  30. package/dist/model/Option.d.ts +122 -0
  31. package/dist/model/Option.d.ts.map +1 -0
  32. package/dist/model/Option.js +110 -0
  33. package/dist/model/Path.d.ts +31 -0
  34. package/dist/model/Path.d.ts.map +1 -0
  35. package/dist/model/Path.js +42 -0
  36. package/dist/model/RuntimeLike.d.ts +11 -0
  37. package/dist/model/RuntimeLike.d.ts.map +1 -0
  38. package/dist/model/RuntimeLike.js +1 -0
  39. package/dist/model/StateTransition.d.ts +135 -0
  40. package/dist/model/StateTransition.d.ts.map +1 -0
  41. package/dist/model/StateTransition.js +68 -0
  42. package/dist/model/StateTransitionProvableBatch.d.ts +172 -0
  43. package/dist/model/StateTransitionProvableBatch.d.ts.map +1 -0
  44. package/dist/model/StateTransitionProvableBatch.js +85 -0
  45. package/dist/model/network/NetworkState.d.ts +160 -0
  46. package/dist/model/network/NetworkState.d.ts.map +1 -0
  47. package/dist/model/network/NetworkState.js +31 -0
  48. package/dist/model/transaction/RuntimeTransaction.d.ts +122 -0
  49. package/dist/model/transaction/RuntimeTransaction.d.ts.map +1 -0
  50. package/dist/model/transaction/RuntimeTransaction.js +86 -0
  51. package/dist/model/transaction/SignedTransaction.d.ts +107 -0
  52. package/dist/model/transaction/SignedTransaction.d.ts.map +1 -0
  53. package/dist/model/transaction/SignedTransaction.js +33 -0
  54. package/dist/model/transaction/ValueOption.d.ts +173 -0
  55. package/dist/model/transaction/ValueOption.d.ts.map +1 -0
  56. package/dist/model/transaction/ValueOption.js +24 -0
  57. package/dist/protocol/Protocol.d.ts +43 -0
  58. package/dist/protocol/Protocol.d.ts.map +1 -0
  59. package/dist/protocol/Protocol.js +95 -0
  60. package/dist/protocol/ProtocolEnvironment.d.ts +9 -0
  61. package/dist/protocol/ProtocolEnvironment.d.ts.map +1 -0
  62. package/dist/protocol/ProtocolEnvironment.js +1 -0
  63. package/dist/protocol/ProtocolModule.d.ts +9 -0
  64. package/dist/protocol/ProtocolModule.d.ts.map +1 -0
  65. package/dist/protocol/ProtocolModule.js +12 -0
  66. package/dist/protocol/ProvableBlockHook.d.ts +8 -0
  67. package/dist/protocol/ProvableBlockHook.d.ts.map +1 -0
  68. package/dist/protocol/ProvableBlockHook.js +4 -0
  69. package/dist/protocol/ProvableTransactionHook.d.ts +7 -0
  70. package/dist/protocol/ProvableTransactionHook.d.ts.map +1 -0
  71. package/dist/protocol/ProvableTransactionHook.js +3 -0
  72. package/dist/protocol/TransitioningProtocolModule.d.ts +10 -0
  73. package/dist/protocol/TransitioningProtocolModule.d.ts.map +1 -0
  74. package/dist/protocol/TransitioningProtocolModule.js +8 -0
  75. package/dist/prover/block/BlockProvable.d.ts +395 -0
  76. package/dist/prover/block/BlockProvable.d.ts.map +1 -0
  77. package/dist/prover/block/BlockProvable.js +45 -0
  78. package/dist/prover/block/BlockProver.d.ts +92 -0
  79. package/dist/prover/block/BlockProver.d.ts.map +1 -0
  80. package/dist/prover/block/BlockProver.js +472 -0
  81. package/dist/prover/block/accummulators/BlockHashMerkleTree.d.ts +64 -0
  82. package/dist/prover/block/accummulators/BlockHashMerkleTree.d.ts.map +1 -0
  83. package/dist/prover/block/accummulators/BlockHashMerkleTree.js +16 -0
  84. package/dist/prover/block/accummulators/RuntimeVerificationKeyTree.d.ts +139 -0
  85. package/dist/prover/block/accummulators/RuntimeVerificationKeyTree.d.ts.map +1 -0
  86. package/dist/prover/block/accummulators/RuntimeVerificationKeyTree.js +20 -0
  87. package/dist/prover/block/services/RuntimeVerificationKeyRootService.d.ts +7 -0
  88. package/dist/prover/block/services/RuntimeVerificationKeyRootService.d.ts.map +1 -0
  89. package/dist/prover/block/services/RuntimeVerificationKeyRootService.js +22 -0
  90. package/dist/prover/statetransition/StateTransitionProvable.d.ts +174 -0
  91. package/dist/prover/statetransition/StateTransitionProvable.d.ts.map +1 -0
  92. package/dist/prover/statetransition/StateTransitionProvable.js +15 -0
  93. package/dist/prover/statetransition/StateTransitionProver.d.ts +51 -0
  94. package/dist/prover/statetransition/StateTransitionProver.d.ts.map +1 -0
  95. package/dist/prover/statetransition/StateTransitionProver.js +188 -0
  96. package/dist/prover/statetransition/StateTransitionWitnessProvider.d.ts +16 -0
  97. package/dist/prover/statetransition/StateTransitionWitnessProvider.d.ts.map +1 -0
  98. package/dist/prover/statetransition/StateTransitionWitnessProvider.js +16 -0
  99. package/dist/prover/statetransition/StateTransitionWitnessProviderReference.d.ts +7 -0
  100. package/dist/prover/statetransition/StateTransitionWitnessProviderReference.d.ts.map +1 -0
  101. package/dist/prover/statetransition/StateTransitionWitnessProviderReference.js +19 -0
  102. package/dist/settlement/ContractModule.d.ts +15 -0
  103. package/dist/settlement/ContractModule.d.ts.map +1 -0
  104. package/dist/settlement/ContractModule.js +11 -0
  105. package/dist/settlement/SettlementContractModule.d.ts +40 -0
  106. package/dist/settlement/SettlementContractModule.d.ts.map +1 -0
  107. package/dist/settlement/SettlementContractModule.js +71 -0
  108. package/dist/settlement/contracts/DispatchContractProtocolModule.d.ts +12 -0
  109. package/dist/settlement/contracts/DispatchContractProtocolModule.d.ts.map +1 -0
  110. package/dist/settlement/contracts/DispatchContractProtocolModule.js +35 -0
  111. package/dist/settlement/contracts/DispatchSmartContract.d.ts +22 -0
  112. package/dist/settlement/contracts/DispatchSmartContract.d.ts.map +1 -0
  113. package/dist/settlement/contracts/DispatchSmartContract.js +110 -0
  114. package/dist/settlement/contracts/SettlementContractProtocolModule.d.ts +19 -0
  115. package/dist/settlement/contracts/SettlementContractProtocolModule.d.ts.map +1 -0
  116. package/dist/settlement/contracts/SettlementContractProtocolModule.js +44 -0
  117. package/dist/settlement/contracts/SettlementSmartContract.d.ts +42 -0
  118. package/dist/settlement/contracts/SettlementSmartContract.d.ts.map +1 -0
  119. package/dist/settlement/contracts/SettlementSmartContract.js +241 -0
  120. package/dist/settlement/messages/Deposit.d.ts +64 -0
  121. package/dist/settlement/messages/Deposit.d.ts.map +1 -0
  122. package/dist/settlement/messages/Deposit.js +6 -0
  123. package/dist/settlement/messages/OutgoingMessageArgument.d.ts +189 -0
  124. package/dist/settlement/messages/OutgoingMessageArgument.d.ts.map +1 -0
  125. package/dist/settlement/messages/OutgoingMessageArgument.js +32 -0
  126. package/dist/settlement/messages/Withdrawal.d.ts +65 -0
  127. package/dist/settlement/messages/Withdrawal.d.ts.map +1 -0
  128. package/dist/settlement/messages/Withdrawal.js +13 -0
  129. package/dist/settlement/modularity/ProvableSettlementHook.d.ts +24 -0
  130. package/dist/settlement/modularity/ProvableSettlementHook.d.ts.map +1 -0
  131. package/dist/settlement/modularity/ProvableSettlementHook.js +3 -0
  132. package/dist/settlement/modules/NetworkStateSettlementModule.d.ts +11 -0
  133. package/dist/settlement/modules/NetworkStateSettlementModule.d.ts.map +1 -0
  134. package/dist/settlement/modules/NetworkStateSettlementModule.js +14 -0
  135. package/dist/state/State.d.ts +68 -0
  136. package/dist/state/State.d.ts.map +1 -0
  137. package/dist/state/State.js +129 -0
  138. package/dist/state/StateMap.d.ts +37 -0
  139. package/dist/state/StateMap.d.ts.map +1 -0
  140. package/dist/state/StateMap.js +55 -0
  141. package/dist/state/StateService.d.ts +6 -0
  142. package/dist/state/StateService.d.ts.map +1 -0
  143. package/dist/state/StateService.js +1 -0
  144. package/dist/state/StateServiceProvider.d.ts +8 -0
  145. package/dist/state/StateServiceProvider.d.ts.map +1 -0
  146. package/dist/state/StateServiceProvider.js +36 -0
  147. package/dist/state/assert/assert.d.ts +12 -0
  148. package/dist/state/assert/assert.d.ts.map +1 -0
  149. package/dist/state/assert/assert.js +30 -0
  150. package/dist/state/context/ProtocolMethodExecutionContext.d.ts +22 -0
  151. package/dist/state/context/ProtocolMethodExecutionContext.d.ts.map +1 -0
  152. package/dist/state/context/ProtocolMethodExecutionContext.js +28 -0
  153. package/dist/state/context/RuntimeMethodExecutionContext.d.ts +193 -0
  154. package/dist/state/context/RuntimeMethodExecutionContext.d.ts.map +1 -0
  155. package/dist/state/context/RuntimeMethodExecutionContext.js +135 -0
  156. package/dist/state/context/TransitionMethodExecutionContext.d.ts +23 -0
  157. package/dist/state/context/TransitionMethodExecutionContext.d.ts.map +1 -0
  158. package/dist/state/context/TransitionMethodExecutionContext.js +5 -0
  159. package/dist/state/protocol/ProtocolState.d.ts +7 -0
  160. package/dist/state/protocol/ProtocolState.d.ts.map +1 -0
  161. package/dist/state/protocol/ProtocolState.js +39 -0
  162. package/dist/utils/MinaPrefixedProvableHashList.d.ts +24 -0
  163. package/dist/utils/MinaPrefixedProvableHashList.d.ts.map +1 -0
  164. package/dist/utils/MinaPrefixedProvableHashList.js +52 -0
  165. package/dist/utils/PrefixedProvableHashList.d.ts +8 -0
  166. package/dist/utils/PrefixedProvableHashList.d.ts.map +1 -0
  167. package/dist/utils/PrefixedProvableHashList.js +12 -0
  168. package/dist/utils/ProvableHashList.d.ts +27 -0
  169. package/dist/utils/ProvableHashList.d.ts.map +1 -0
  170. package/dist/utils/ProvableHashList.js +43 -0
  171. package/dist/utils/ProvableReductionHashList.d.ts +14 -0
  172. package/dist/utils/ProvableReductionHashList.d.ts.map +1 -0
  173. package/dist/utils/ProvableReductionHashList.js +50 -0
  174. package/dist/utils/StateTransitionReductionList.d.ts +11 -0
  175. package/dist/utils/StateTransitionReductionList.d.ts.map +1 -0
  176. package/dist/utils/StateTransitionReductionList.js +60 -0
  177. package/dist/utils/utils.d.ts +11 -0
  178. package/dist/utils/utils.d.ts.map +1 -0
  179. package/dist/utils/utils.js +44 -0
  180. package/jest.config.cjs +1 -0
  181. package/package.json +36 -0
  182. package/src/Constants.ts +3 -0
  183. package/src/hooks/AccountStateHook.ts +48 -0
  184. package/src/hooks/BlockHeightHook.ts +17 -0
  185. package/src/hooks/LastStateRootBlockHook.ts +26 -0
  186. package/src/hooks/NoopBlockHook.ts +21 -0
  187. package/src/hooks/NoopSettlementHook.ts +20 -0
  188. package/src/hooks/NoopTransactionHook.ts +10 -0
  189. package/src/index.ts +53 -0
  190. package/src/model/MethodPublicOutput.ts +14 -0
  191. package/src/model/Option.ts +172 -0
  192. package/src/model/Path.ts +50 -0
  193. package/src/model/RuntimeLike.ts +12 -0
  194. package/src/model/StateTransition.ts +88 -0
  195. package/src/model/StateTransitionProvableBatch.ts +125 -0
  196. package/src/model/Transaction.ts +31 -0
  197. package/src/model/network/NetworkState.ts +33 -0
  198. package/src/model/transaction/RuntimeTransaction.ts +105 -0
  199. package/src/model/transaction/SignedTransaction.ts +47 -0
  200. package/src/model/transaction/ValueOption.ts +28 -0
  201. package/src/protocol/Protocol.ts +197 -0
  202. package/src/protocol/ProtocolEnvironment.ts +10 -0
  203. package/src/protocol/ProtocolModule.ts +27 -0
  204. package/src/protocol/ProvableBlockHook.ts +19 -0
  205. package/src/protocol/ProvableTransactionHook.ts +13 -0
  206. package/src/protocol/TransitioningProtocolModule.ts +12 -0
  207. package/src/prover/block/BlockProvable.ts +99 -0
  208. package/src/prover/block/BlockProver.ts +954 -0
  209. package/src/prover/block/accummulators/BlockHashMerkleTree.ts +16 -0
  210. package/src/prover/block/accummulators/RuntimeVerificationKeyTree.ts +24 -0
  211. package/src/prover/block/services/RuntimeVerificationKeyRootService.ts +20 -0
  212. package/src/prover/statetransition/StateTransitionProvable.ts +44 -0
  213. package/src/prover/statetransition/StateTransitionProver.ts +371 -0
  214. package/src/prover/statetransition/StateTransitionWitnessProvider.ts +23 -0
  215. package/src/prover/statetransition/StateTransitionWitnessProviderReference.ts +17 -0
  216. package/src/settlement/ContractModule.ts +24 -0
  217. package/src/settlement/SettlementContractModule.ts +132 -0
  218. package/src/settlement/contracts/DispatchContractProtocolModule.ts +39 -0
  219. package/src/settlement/contracts/DispatchSmartContract.ts +136 -0
  220. package/src/settlement/contracts/SettlementContractProtocolModule.ts +67 -0
  221. package/src/settlement/contracts/SettlementSmartContract.ts +344 -0
  222. package/src/settlement/messages/Deposit.ts +6 -0
  223. package/src/settlement/messages/OutgoingMessageArgument.ts +42 -0
  224. package/src/settlement/messages/Withdrawal.ts +14 -0
  225. package/src/settlement/modularity/ProvableSettlementHook.ts +33 -0
  226. package/src/settlement/modules/NetworkStateSettlementModule.ts +42 -0
  227. package/src/state/State.ts +175 -0
  228. package/src/state/StateMap.ts +73 -0
  229. package/src/state/StateService.ts +6 -0
  230. package/src/state/StateServiceProvider.ts +37 -0
  231. package/src/state/assert/assert.ts +35 -0
  232. package/src/state/context/RuntimeMethodExecutionContext.ts +174 -0
  233. package/src/state/context/TransitionMethodExecutionContext.ts +26 -0
  234. package/src/state/protocol/ProtocolState.ts +61 -0
  235. package/src/utils/MinaPrefixedProvableHashList.ts +73 -0
  236. package/src/utils/PrefixedProvableHashList.ts +21 -0
  237. package/src/utils/ProvableHashList.ts +50 -0
  238. package/src/utils/ProvableReductionHashList.ts +68 -0
  239. package/src/utils/StateTransitionReductionList.ts +89 -0
  240. package/src/utils/utils.ts +75 -0
  241. package/test/BlockProver.test.ts +211 -0
  242. package/test/Protocol.test.ts +37 -0
  243. package/test/State.test.ts +45 -0
  244. package/test/StateTransition.test.ts +174 -0
  245. package/test/TestingProtocol.ts +47 -0
  246. package/test/model/Option.test.ts +72 -0
  247. package/test/state/assert/assert.test.ts +56 -0
  248. package/test/tsconfig.json +7 -0
  249. package/test/utils/ProvableReductionHashList.test.ts +117 -0
  250. package/test/utils.test.ts +27 -0
  251. package/tsconfig.json +8 -0
@@ -0,0 +1,39 @@
1
+ import { inject, injectable } from "tsyringe";
2
+
3
+ import { RuntimeLike } from "../../model/RuntimeLike";
4
+ import {
5
+ ContractModule,
6
+ SmartContractClassFromInterface,
7
+ } from "../ContractModule";
8
+
9
+ import {
10
+ DispatchSmartContract,
11
+ DispatchContractType,
12
+ } from "./DispatchSmartContract";
13
+
14
+ export type DispatchContractConfig = {
15
+ incomingMessagesMethods: Record<string, `${string}.${string}`>;
16
+ };
17
+
18
+ @injectable()
19
+ export class DispatchContractProtocolModule extends ContractModule<
20
+ DispatchContractType,
21
+ undefined,
22
+ DispatchContractConfig
23
+ > {
24
+ public constructor(@inject("Runtime") private readonly runtime: RuntimeLike) {
25
+ super();
26
+ }
27
+
28
+ public contractFactory(): SmartContractClassFromInterface<DispatchContractType> {
29
+ const { incomingMessagesMethods } = this.config;
30
+ const methodIdMappings = this.runtime.methodIdResolver.methodIdMap();
31
+
32
+ DispatchSmartContract.args = {
33
+ incomingMessagesPaths: incomingMessagesMethods,
34
+ methodIdMappings,
35
+ };
36
+
37
+ return DispatchSmartContract;
38
+ }
39
+ }
@@ -0,0 +1,136 @@
1
+ import {
2
+ AccountUpdate,
3
+ Field,
4
+ method,
5
+ Poseidon,
6
+ ProvableExtended,
7
+ PublicKey,
8
+ Reducer,
9
+ SmartContract,
10
+ State,
11
+ state,
12
+ UInt64,
13
+ } from "o1js";
14
+
15
+ import { RuntimeMethodIdMapping } from "../../model/RuntimeLike";
16
+ import { RuntimeTransaction } from "../../model/transaction/RuntimeTransaction";
17
+ import {
18
+ MinaActions,
19
+ MinaEvents,
20
+ } from "../../utils/MinaPrefixedProvableHashList";
21
+ import { Deposit } from "../messages/Deposit";
22
+
23
+ export const ACTIONS_EMPTY_HASH = Reducer.initialActionState;
24
+
25
+ export interface DispatchContractType {
26
+ updateMessagesHash: (
27
+ executedMessagesHash: Field,
28
+ newPromisedMessagesHash: Field
29
+ ) => Promise<void>;
30
+ initialize: (settlementContract: PublicKey) => Promise<void>;
31
+
32
+ promisedMessagesHash: State<Field>;
33
+ }
34
+
35
+ export class DispatchSmartContract
36
+ extends SmartContract
37
+ implements DispatchContractType
38
+ {
39
+ public static args: {
40
+ methodIdMappings: RuntimeMethodIdMapping;
41
+ incomingMessagesPaths: Record<string, `${string}.${string}`>;
42
+ };
43
+
44
+ @state(Field) public promisedMessagesHash = State<Field>();
45
+
46
+ @state(Field) public honoredMessagesHash = State<Field>();
47
+
48
+ @state(PublicKey) public settlementContract = State<PublicKey>();
49
+
50
+ @method
51
+ public async updateMessagesHash(
52
+ executedMessagesHash: Field,
53
+ newPromisedMessagesHash: Field
54
+ ) {
55
+ const promisedMessagesHash =
56
+ this.promisedMessagesHash.getAndRequireEquals();
57
+ this.honoredMessagesHash.getAndRequireEquals();
58
+
59
+ executedMessagesHash.assertEquals(promisedMessagesHash);
60
+
61
+ this.honoredMessagesHash.set(executedMessagesHash);
62
+
63
+ // Assert and apply new promisedMessagesHash
64
+ this.self.account.actionState.requireEquals(newPromisedMessagesHash);
65
+ this.promisedMessagesHash.set(newPromisedMessagesHash);
66
+ }
67
+
68
+ @method
69
+ public async initialize(settlementContract: PublicKey) {
70
+ this.promisedMessagesHash.getAndRequireEquals().assertEquals(Field(0));
71
+ this.honoredMessagesHash.getAndRequireEquals().assertEquals(Field(0));
72
+ this.settlementContract
73
+ .getAndRequireEquals()
74
+ .assertEquals(PublicKey.empty<typeof PublicKey>());
75
+
76
+ this.promisedMessagesHash.set(ACTIONS_EMPTY_HASH);
77
+ this.honoredMessagesHash.set(ACTIONS_EMPTY_HASH);
78
+ this.settlementContract.set(settlementContract);
79
+ }
80
+
81
+ private dispatchMessage<Type>(
82
+ methodId: Field,
83
+ value: Type,
84
+ valueType: ProvableExtended<Type>
85
+ ) {
86
+ const args = valueType.toFields(value);
87
+ // Should be the same as RuntimeTransaction.hash
88
+ const argsHash = Poseidon.hash(args);
89
+ const runtimeTransaction = RuntimeTransaction.fromMessage({
90
+ methodId,
91
+ argsHash,
92
+ });
93
+
94
+ // Append tx to incomingMessagesHash
95
+ const actionData = runtimeTransaction.hashData();
96
+ const actionHash = MinaActions.actionHash(actionData);
97
+
98
+ this.self.body.actions = {
99
+ hash: actionHash,
100
+ data: [actionData],
101
+ };
102
+
103
+ const eventHash = MinaEvents.eventHash(args);
104
+ this.self.body.events = {
105
+ hash: eventHash,
106
+ data: [args],
107
+ };
108
+ }
109
+
110
+ @method
111
+ public async deposit(amount: UInt64) {
112
+ // Save this, since otherwise it would be a second witness later,
113
+ // which could be a different values than the first
114
+ const sender = this.sender.getUnconstrained();
115
+
116
+ const settlementContract = this.settlementContract.getAndRequireEquals();
117
+
118
+ // Credit the amount to the settlement contract
119
+ const balanceAU = AccountUpdate.create(settlementContract);
120
+ balanceAU.balance.addInPlace(amount);
121
+ this.self.approve(balanceAU);
122
+
123
+ const action = new Deposit({
124
+ address: sender,
125
+ amount,
126
+ });
127
+
128
+ const { methodIdMappings, incomingMessagesPaths } =
129
+ DispatchSmartContract.args;
130
+
131
+ const methodId = Field(
132
+ methodIdMappings[incomingMessagesPaths.deposit].methodId
133
+ ).toConstant();
134
+ this.dispatchMessage(methodId.toConstant(), action, Deposit);
135
+ }
136
+ }
@@ -0,0 +1,67 @@
1
+ import { TypedClass } from "@proto-kit/common";
2
+ import { SmartContract } from "o1js";
3
+ import { inject, injectable, injectAll } from "tsyringe";
4
+
5
+ import { BlockProvable } from "../../prover/block/BlockProvable";
6
+ import {
7
+ ContractModule,
8
+ SmartContractClassFromInterface,
9
+ } from "../ContractModule";
10
+ import { ProvableSettlementHook } from "../modularity/ProvableSettlementHook";
11
+
12
+ import { DispatchContractType } from "./DispatchSmartContract";
13
+ import {
14
+ LazyBlockProof,
15
+ SettlementContractType,
16
+ SettlementSmartContract,
17
+ } from "./SettlementSmartContract";
18
+
19
+ export type SettlementContractConfig = {
20
+ escapeHatchSlotsInterval?: number;
21
+ withdrawalStatePath: `${string}.${string}`;
22
+ withdrawalMethodPath: `${string}.${string}`;
23
+ };
24
+
25
+ // 24 hours
26
+ const DEFAULT_ESCAPE_HATCH = (60 / 3) * 24;
27
+
28
+ @injectable()
29
+ export class SettlementContractProtocolModule extends ContractModule<
30
+ SettlementContractType,
31
+ TypedClass<DispatchContractType & SmartContract>,
32
+ SettlementContractConfig
33
+ > {
34
+ public constructor(
35
+ @injectAll("ProvableSettlementHook")
36
+ private readonly hooks: ProvableSettlementHook<unknown>[],
37
+ @inject("BlockProver")
38
+ private readonly blockProver: BlockProvable
39
+ ) {
40
+ LazyBlockProof.tag = blockProver.zkProgrammable.zkProgram[0].Proof.tag;
41
+ super();
42
+ }
43
+
44
+ public contractFactory(
45
+ dispatchContract: TypedClass<DispatchContractType & SmartContract>
46
+ ): SmartContractClassFromInterface<SettlementContractType> {
47
+ const { hooks, config } = this;
48
+
49
+ // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
50
+ const withdrawalStatePathSplit = config.withdrawalStatePath.split(".") as [
51
+ string,
52
+ string,
53
+ ];
54
+
55
+ const escapeHatchSlotsInterval =
56
+ config.escapeHatchSlotsInterval ?? DEFAULT_ESCAPE_HATCH;
57
+
58
+ SettlementSmartContract.args = {
59
+ DispatchContract: dispatchContract,
60
+ hooks,
61
+ withdrawalStatePath: withdrawalStatePathSplit,
62
+ escapeHatchSlotsInterval,
63
+ };
64
+
65
+ return SettlementSmartContract;
66
+ }
67
+ }
@@ -0,0 +1,344 @@
1
+ import {
2
+ prefixToField,
3
+ RollupMerkleTree,
4
+ TypedClass,
5
+ mapSequential,
6
+ } from "@proto-kit/common";
7
+ import {
8
+ AccountUpdate,
9
+ Bool,
10
+ Field,
11
+ method,
12
+ Mina,
13
+ Poseidon,
14
+ Proof,
15
+ Provable,
16
+ PublicKey,
17
+ Signature,
18
+ SmartContract,
19
+ State,
20
+ state,
21
+ TokenId,
22
+ UInt32,
23
+ UInt64,
24
+ TokenContract,
25
+ AccountUpdateForest,
26
+ } from "o1js";
27
+
28
+ import { NetworkState } from "../../model/network/NetworkState";
29
+ import { Path } from "../../model/Path";
30
+ import { BlockHashMerkleTree } from "../../prover/block/accummulators/BlockHashMerkleTree";
31
+ import {
32
+ BlockProverPublicInput,
33
+ BlockProverPublicOutput,
34
+ } from "../../prover/block/BlockProvable";
35
+ import {
36
+ OUTGOING_MESSAGE_BATCH_SIZE,
37
+ OutgoingMessageArgumentBatch,
38
+ } from "../messages/OutgoingMessageArgument";
39
+ import { Withdrawal } from "../messages/Withdrawal";
40
+ import {
41
+ ProvableSettlementHook,
42
+ SettlementHookInputs,
43
+ SettlementStateRecord,
44
+ } from "../modularity/ProvableSettlementHook";
45
+
46
+ import { DispatchContractType } from "./DispatchSmartContract";
47
+
48
+ /* eslint-disable @typescript-eslint/lines-between-class-members */
49
+
50
+ export class LazyBlockProof extends Proof<
51
+ BlockProverPublicInput,
52
+ BlockProverPublicOutput
53
+ > {
54
+ public static publicInputType = BlockProverPublicInput;
55
+
56
+ public static publicOutputType = BlockProverPublicOutput;
57
+
58
+ public static tag: () => { name: string } = () => {
59
+ throw new Error("Tag not initialized yet");
60
+ };
61
+ }
62
+
63
+ export interface SettlementContractType {
64
+ initialize: (
65
+ sequencer: PublicKey,
66
+ dispatchContract: PublicKey
67
+ ) => Promise<void>;
68
+ settle: (
69
+ blockProof: LazyBlockProof,
70
+ signature: Signature,
71
+ dispatchContractAddress: PublicKey,
72
+ publicKey: PublicKey,
73
+ inputNetworkState: NetworkState,
74
+ outputNetworkState: NetworkState,
75
+ newPromisedMessagesHash: Field
76
+ ) => Promise<void>;
77
+ rollupOutgoingMessages: (
78
+ batch: OutgoingMessageArgumentBatch
79
+ ) => Promise<void>;
80
+ redeem: (additionUpdate: AccountUpdate) => Promise<void>;
81
+ }
82
+
83
+ // Some random prefix for the sequencer signature
84
+ export const BATCH_SIGNATURE_PREFIX = prefixToField("pk-batchSignature");
85
+
86
+ export class SettlementSmartContract
87
+ extends TokenContract
88
+ implements SettlementContractType
89
+ {
90
+ // This pattern of injecting args into a smartcontract is currently the only
91
+ // viable solution that works given the inheritance issues of o1js
92
+ public static args: {
93
+ DispatchContract: TypedClass<DispatchContractType & SmartContract>;
94
+ hooks: ProvableSettlementHook<unknown>[];
95
+ withdrawalStatePath: [string, string];
96
+ escapeHatchSlotsInterval: number;
97
+ };
98
+
99
+ @state(Field) public sequencerKey = State<Field>();
100
+ @state(UInt32) public lastSettlementL1BlockHeight = State<UInt32>();
101
+
102
+ @state(Field) public stateRoot = State<Field>();
103
+ @state(Field) public networkStateHash = State<Field>();
104
+ @state(Field) public blockHashRoot = State<Field>();
105
+
106
+ @state(Field) public dispatchContractAddressX = State<Field>();
107
+
108
+ @state(Field) public outgoingMessageCursor = State<Field>();
109
+
110
+ @method async approveBase(forest: AccountUpdateForest) {
111
+ this.checkZeroBalanceChange(forest);
112
+ }
113
+
114
+ @method
115
+ public async initialize(sequencer: PublicKey, dispatchContract: PublicKey) {
116
+ this.sequencerKey.getAndRequireEquals().assertEquals(Field(0));
117
+ this.stateRoot.getAndRequireEquals().assertEquals(Field(0));
118
+ this.blockHashRoot.getAndRequireEquals().assertEquals(Field(0));
119
+ this.networkStateHash.getAndRequireEquals().assertEquals(Field(0));
120
+ this.dispatchContractAddressX.getAndRequireEquals().assertEquals(Field(0));
121
+
122
+ this.sequencerKey.set(sequencer.x);
123
+ this.stateRoot.set(Field(RollupMerkleTree.EMPTY_ROOT));
124
+ this.blockHashRoot.set(Field(BlockHashMerkleTree.EMPTY_ROOT));
125
+ this.networkStateHash.set(NetworkState.empty().hash());
126
+ this.dispatchContractAddressX.set(dispatchContract.x);
127
+
128
+ const { DispatchContract } = SettlementSmartContract.args;
129
+ const contractInstance = new DispatchContract(dispatchContract);
130
+ await contractInstance.initialize(this.address);
131
+ }
132
+
133
+ @method
134
+ public async settle(
135
+ blockProof: LazyBlockProof,
136
+ signature: Signature,
137
+ dispatchContractAddress: PublicKey,
138
+ publicKey: PublicKey,
139
+ inputNetworkState: NetworkState,
140
+ outputNetworkState: NetworkState,
141
+ newPromisedMessagesHash: Field
142
+ ) {
143
+ // Verify the blockproof
144
+ blockProof.verify();
145
+
146
+ // Get and assert on-chain values
147
+ const stateRoot = this.stateRoot.getAndRequireEquals();
148
+ const networkStateHash = this.networkStateHash.getAndRequireEquals();
149
+ const blockHashRoot = this.blockHashRoot.getAndRequireEquals();
150
+ const sequencerKey = this.sequencerKey.getAndRequireEquals();
151
+ const lastSettlementL1BlockHeight =
152
+ this.lastSettlementL1BlockHeight.getAndRequireEquals();
153
+ const onChainDispatchContractAddressX =
154
+ this.dispatchContractAddressX.getAndRequireEquals();
155
+
156
+ onChainDispatchContractAddressX.assertEquals(
157
+ dispatchContractAddress.x,
158
+ "DispatchContract address not provided correctly"
159
+ );
160
+
161
+ const { DispatchContract, escapeHatchSlotsInterval, hooks } =
162
+ SettlementSmartContract.args;
163
+
164
+ // Get dispatch contract values
165
+ // These values are witnesses but will be checked later on the AU
166
+ // call to the dispatch contract via .updateMessagesHash()
167
+ const dispatchContract = new DispatchContract(dispatchContractAddress);
168
+ const promisedMessagesHash = dispatchContract.promisedMessagesHash.get();
169
+
170
+ // Get block height and use the lower bound for all ops
171
+ const minBlockHeightIncluded = this.network.blockchainLength.get();
172
+ this.network.blockchainLength.requireBetween(
173
+ minBlockHeightIncluded,
174
+ // 5 because that is the length the newPromisedMessagesHash will be valid
175
+ minBlockHeightIncluded.add(4)
176
+ );
177
+
178
+ // Check signature/escape catch
179
+ publicKey.x.assertEquals(
180
+ sequencerKey,
181
+ "Sequencer public key witness not matching"
182
+ );
183
+ const signatureValid = signature.verify(publicKey, [
184
+ BATCH_SIGNATURE_PREFIX,
185
+ lastSettlementL1BlockHeight.value,
186
+ ]);
187
+ const escapeHatchActivated = lastSettlementL1BlockHeight
188
+ .add(UInt32.from(escapeHatchSlotsInterval))
189
+ .lessThan(minBlockHeightIncluded);
190
+ signatureValid
191
+ .or(escapeHatchActivated)
192
+ .assertTrue(
193
+ "Sequencer signature not valid and escape hatch not activated"
194
+ );
195
+
196
+ // Assert correctness of networkState witness
197
+ inputNetworkState
198
+ .hash()
199
+ .assertEquals(networkStateHash, "InputNetworkState witness not valid");
200
+ outputNetworkState
201
+ .hash()
202
+ .assertEquals(
203
+ blockProof.publicOutput.networkStateHash,
204
+ "OutputNetworkState witness not valid"
205
+ );
206
+
207
+ blockProof.publicOutput.closed.assertEquals(
208
+ Bool(true),
209
+ "Supplied proof is not a closed BlockProof"
210
+ );
211
+
212
+ // Execute onSettlementHooks for additional checks
213
+ const stateRecord: SettlementStateRecord = {
214
+ blockHashRoot,
215
+ stateRoot,
216
+ networkStateHash,
217
+ lastSettlementL1BlockHeight,
218
+ sequencerKey: publicKey,
219
+ };
220
+ const inputs: SettlementHookInputs = {
221
+ blockProof,
222
+ contractState: stateRecord,
223
+ newPromisedMessagesHash,
224
+ fromNetworkState: inputNetworkState,
225
+ toNetworkState: outputNetworkState,
226
+ currentL1BlockHeight: minBlockHeightIncluded,
227
+ };
228
+ await mapSequential(hooks, async (hook) => {
229
+ await hook.beforeSettlement(this, inputs);
230
+ });
231
+
232
+ // Apply blockProof
233
+ stateRoot.assertEquals(
234
+ blockProof.publicInput.stateRoot,
235
+ "Input state root not matching"
236
+ );
237
+
238
+ networkStateHash.assertEquals(
239
+ blockProof.publicInput.networkStateHash,
240
+ "Input networkStateHash not matching"
241
+ );
242
+ blockHashRoot.assertEquals(
243
+ blockProof.publicInput.blockHashRoot,
244
+ "Input blockHashRoot not matching"
245
+ );
246
+ this.stateRoot.set(blockProof.publicOutput.stateRoot);
247
+ this.networkStateHash.set(blockProof.publicOutput.networkStateHash);
248
+ this.blockHashRoot.set(blockProof.publicOutput.blockHashRoot);
249
+
250
+ // Assert and apply deposit commitments
251
+ promisedMessagesHash.assertEquals(
252
+ blockProof.publicOutput.incomingMessagesHash,
253
+ "Promised messages not honored"
254
+ );
255
+
256
+ // Call DispatchContract
257
+ // This call checks that the promisedMessagesHash, which is already proven
258
+ // to be the blockProofs publicoutput, is actually the current on-chain
259
+ // promisedMessageHash. It also checks the newPromisedMessagesHash to be
260
+ // a current sequencestate value
261
+ await dispatchContract.updateMessagesHash(
262
+ promisedMessagesHash,
263
+ newPromisedMessagesHash
264
+ );
265
+
266
+ this.lastSettlementL1BlockHeight.set(minBlockHeightIncluded);
267
+ }
268
+
269
+ @method
270
+ public async rollupOutgoingMessages(batch: OutgoingMessageArgumentBatch) {
271
+ let counter = this.outgoingMessageCursor.getAndRequireEquals();
272
+ const stateRoot = this.stateRoot.getAndRequireEquals();
273
+
274
+ const [withdrawalModule, withdrawalStateName] =
275
+ SettlementSmartContract.args.withdrawalStatePath;
276
+ const mapPath = Path.fromProperty(withdrawalModule, withdrawalStateName);
277
+
278
+ let accountCreationFeePaid = Field(0);
279
+
280
+ for (let i = 0; i < OUTGOING_MESSAGE_BATCH_SIZE; i++) {
281
+ const args = batch.arguments[i];
282
+
283
+ // Check witness
284
+ const path = Path.fromKey(mapPath, Field, counter);
285
+
286
+ args.witness
287
+ .checkMembership(
288
+ stateRoot,
289
+ path,
290
+ Poseidon.hash(Withdrawal.toFields(args.value))
291
+ )
292
+ .assertTrue("Provided Withdrawal witness not valid");
293
+
294
+ // Process message
295
+ const { address, amount } = args.value;
296
+ const isDummy = address.equals(this.address);
297
+
298
+ const tokenAu = this.internal.mint({ address, amount });
299
+ const isNewAccount = tokenAu.account.isNew.getAndRequireEquals();
300
+ tokenAu.body.balanceChange.magnitude =
301
+ tokenAu.body.balanceChange.magnitude.sub(
302
+ Provable.if(
303
+ isNewAccount,
304
+ Mina.getNetworkConstants().accountCreationFee.toConstant(),
305
+ UInt64.zero
306
+ )
307
+ );
308
+
309
+ accountCreationFeePaid = accountCreationFeePaid.add(
310
+ Provable.if(isNewAccount, Field(1e9), Field(0))
311
+ );
312
+
313
+ counter = counter.add(Provable.if(isDummy, Field(0), Field(1)));
314
+ }
315
+
316
+ this.balance.subInPlace(UInt64.Unsafe.fromField(accountCreationFeePaid));
317
+
318
+ this.outgoingMessageCursor.set(counter);
319
+ }
320
+
321
+ @method
322
+ public async redeem(additionUpdate: AccountUpdate) {
323
+ additionUpdate.body.tokenId.assertEquals(
324
+ TokenId.default,
325
+ "Tokenid not default token"
326
+ );
327
+ additionUpdate.body.balanceChange.sgn
328
+ .isPositive()
329
+ .assertTrue("Sign not correct");
330
+ const amount = additionUpdate.body.balanceChange.magnitude;
331
+
332
+ // Burn tokens
333
+ this.internal.burn({
334
+ address: additionUpdate.publicKey,
335
+ amount,
336
+ });
337
+
338
+ // Send mina
339
+ this.approve(additionUpdate);
340
+ this.balance.subInPlace(amount);
341
+ }
342
+ }
343
+
344
+ /* eslint-enable @typescript-eslint/lines-between-class-members */
@@ -0,0 +1,6 @@
1
+ import { PublicKey, Struct, UInt64 } from "o1js";
2
+
3
+ export class Deposit extends Struct({
4
+ address: PublicKey,
5
+ amount: UInt64,
6
+ }) {}
@@ -0,0 +1,42 @@
1
+ import { Bool, Provable, Struct } from "o1js";
2
+ import { RollupMerkleTreeWitness } from "@proto-kit/common";
3
+
4
+ import { Withdrawal } from "./Withdrawal";
5
+
6
+ export const OUTGOING_MESSAGE_BATCH_SIZE = 1;
7
+
8
+ export class OutgoingMessageArgument extends Struct({
9
+ witness: RollupMerkleTreeWitness,
10
+ value: Withdrawal,
11
+ }) {
12
+ public static dummy(): OutgoingMessageArgument {
13
+ return new OutgoingMessageArgument({
14
+ witness: RollupMerkleTreeWitness.dummy(),
15
+ value: Withdrawal.dummy(),
16
+ });
17
+ }
18
+ }
19
+
20
+ export class OutgoingMessageArgumentBatch extends Struct({
21
+ arguments: Provable.Array(
22
+ OutgoingMessageArgument,
23
+ OUTGOING_MESSAGE_BATCH_SIZE
24
+ ),
25
+
26
+ isDummys: Provable.Array(Bool, OUTGOING_MESSAGE_BATCH_SIZE),
27
+ }) {
28
+ public static fromMessages(providedArguments: OutgoingMessageArgument[]) {
29
+ const batch = providedArguments.slice();
30
+ const isDummys = batch.map(() => Bool(false));
31
+
32
+ while (batch.length < OUTGOING_MESSAGE_BATCH_SIZE) {
33
+ batch.push(OutgoingMessageArgument.dummy());
34
+ isDummys.push(Bool(true));
35
+ }
36
+
37
+ return new OutgoingMessageArgumentBatch({
38
+ arguments: batch,
39
+ isDummys,
40
+ });
41
+ }
42
+ }
@@ -0,0 +1,14 @@
1
+ import { PublicKey, Struct, UInt64 } from "o1js";
2
+ import { EMPTY_PUBLICKEY } from "@proto-kit/common";
3
+
4
+ export class Withdrawal extends Struct({
5
+ address: PublicKey,
6
+ amount: UInt64,
7
+ }) {
8
+ public static dummy() {
9
+ return new Withdrawal({
10
+ address: EMPTY_PUBLICKEY,
11
+ amount: UInt64.from(0),
12
+ });
13
+ }
14
+ }
@@ -0,0 +1,33 @@
1
+ import { Field, PublicKey, UInt32 } from "o1js";
2
+
3
+ import { ProtocolModule } from "../../protocol/ProtocolModule";
4
+ import { NetworkState } from "../../model/network/NetworkState";
5
+ import type { BlockProof } from "../../prover/block/BlockProver";
6
+ import type { SettlementSmartContract } from "../contracts/SettlementSmartContract";
7
+
8
+ export type SettlementStateRecord = {
9
+ sequencerKey: PublicKey;
10
+ lastSettlementL1BlockHeight: UInt32;
11
+
12
+ stateRoot: Field;
13
+ networkStateHash: Field;
14
+ blockHashRoot: Field;
15
+ };
16
+
17
+ export type SettlementHookInputs = {
18
+ blockProof: BlockProof;
19
+ fromNetworkState: NetworkState;
20
+ toNetworkState: NetworkState;
21
+ newPromisedMessagesHash: Field;
22
+ contractState: SettlementStateRecord;
23
+ currentL1BlockHeight: UInt32;
24
+ };
25
+
26
+ export abstract class ProvableSettlementHook<
27
+ Config,
28
+ > extends ProtocolModule<Config> {
29
+ public abstract beforeSettlement(
30
+ smartContract: SettlementSmartContract,
31
+ inputs: SettlementHookInputs
32
+ ): Promise<void>;
33
+ }