@aztec/txe 5.0.0-private.20260319 → 5.0.0-rc.1

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 (154) hide show
  1. package/dest/AuthRegistry-CPGFQR26.js +3 -0
  2. package/dest/AuthRegistry-CPGFQR26.js.map +7 -0
  3. package/dest/ContractClassRegistry-EHVIHGEK.js +3 -0
  4. package/dest/ContractClassRegistry-EHVIHGEK.js.map +7 -0
  5. package/dest/ContractInstanceRegistry-DWZDXHRG.js +3 -0
  6. package/dest/ContractInstanceRegistry-DWZDXHRG.js.map +7 -0
  7. package/dest/FeeJuice-MI32ZO7B.js +3 -0
  8. package/dest/FeeJuice-MI32ZO7B.js.map +7 -0
  9. package/dest/HandshakeRegistry-3KSP3ITH.js +3 -0
  10. package/dest/HandshakeRegistry-3KSP3ITH.js.map +7 -0
  11. package/dest/MultiCallEntrypoint-IU7HYFYE.js +3 -0
  12. package/dest/MultiCallEntrypoint-IU7HYFYE.js.map +7 -0
  13. package/dest/SchnorrAccount-6TUE7JX4.js +3 -0
  14. package/dest/SchnorrAccount-6TUE7JX4.js.map +7 -0
  15. package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js +3 -0
  16. package/dest/SchnorrInitializerlessAccount-S3DU2DJK.js.map +7 -0
  17. package/dest/bin/check_txe_oracle_version.d.ts +2 -0
  18. package/dest/bin/check_txe_oracle_version.d.ts.map +1 -0
  19. package/dest/bin/check_txe_oracle_version.js +61 -0
  20. package/dest/bin/index.js +3 -30
  21. package/dest/bin/index.js.map +7 -0
  22. package/dest/bin/oracle_test_server.d.ts +3 -0
  23. package/dest/bin/oracle_test_server.d.ts.map +1 -0
  24. package/dest/bin/oracle_test_server.js +41 -0
  25. package/dest/chunk-5U25VAFR.js +265 -0
  26. package/dest/chunk-5U25VAFR.js.map +7 -0
  27. package/dest/chunk-BJVAAXNA.js +3 -0
  28. package/dest/chunk-BJVAAXNA.js.map +7 -0
  29. package/dest/chunk-UPW55EJX.js +304 -0
  30. package/dest/chunk-UPW55EJX.js.map +7 -0
  31. package/dest/constants.d.ts +5 -1
  32. package/dest/constants.d.ts.map +1 -1
  33. package/dest/constants.js +8 -0
  34. package/dest/dispatcher_pool.d.ts +67 -0
  35. package/dest/dispatcher_pool.d.ts.map +1 -0
  36. package/dest/dispatcher_pool.js +286 -0
  37. package/dest/index.d.ts +51 -7
  38. package/dest/index.d.ts.map +1 -1
  39. package/dest/index.js +70 -190
  40. package/dest/metafile.json +38829 -0
  41. package/dest/msgpackr_fr_extension.d.ts +2 -0
  42. package/dest/msgpackr_fr_extension.d.ts.map +1 -0
  43. package/dest/msgpackr_fr_extension.js +21 -0
  44. package/dest/oracle/interfaces.d.ts +33 -8
  45. package/dest/oracle/interfaces.d.ts.map +1 -1
  46. package/dest/oracle/test-resolver/fixtures.d.ts +43 -0
  47. package/dest/oracle/test-resolver/fixtures.d.ts.map +1 -0
  48. package/dest/oracle/test-resolver/fixtures.js +39 -0
  49. package/dest/oracle/test-resolver/index.d.ts +9 -0
  50. package/dest/oracle/test-resolver/index.d.ts.map +1 -0
  51. package/dest/oracle/test-resolver/index.js +33 -0
  52. package/dest/oracle/test-resolver/resolver.d.ts +34 -0
  53. package/dest/oracle/test-resolver/resolver.d.ts.map +1 -0
  54. package/dest/oracle/test-resolver/resolver.js +114 -0
  55. package/dest/oracle/txe_oracle_public_context.d.ts +26 -2
  56. package/dest/oracle/txe_oracle_public_context.d.ts.map +1 -1
  57. package/dest/oracle/txe_oracle_public_context.js +43 -1
  58. package/dest/oracle/txe_oracle_registry.d.ts +14 -0
  59. package/dest/oracle/txe_oracle_registry.d.ts.map +1 -0
  60. package/dest/oracle/txe_oracle_registry.js +562 -0
  61. package/dest/oracle/txe_oracle_top_level_context.d.ts +33 -20
  62. package/dest/oracle/txe_oracle_top_level_context.d.ts.map +1 -1
  63. package/dest/oracle/txe_oracle_top_level_context.js +151 -58
  64. package/dest/oracle/txe_oracle_version.d.ts +17 -0
  65. package/dest/oracle/txe_oracle_version.d.ts.map +1 -0
  66. package/dest/oracle/txe_oracle_version.js +14 -0
  67. package/dest/oracle/txe_private_execution_oracle.d.ts +17 -0
  68. package/dest/oracle/txe_private_execution_oracle.d.ts.map +1 -0
  69. package/dest/oracle/txe_private_execution_oracle.js +15 -0
  70. package/dest/rpc_server.d.ts +14 -0
  71. package/dest/rpc_server.d.ts.map +1 -0
  72. package/dest/rpc_server.js +78 -0
  73. package/dest/rpc_translator.d.ts +103 -233
  74. package/dest/rpc_translator.d.ts.map +1 -1
  75. package/dest/rpc_translator.js +695 -636
  76. package/dest/server.bundle.js +3 -0
  77. package/dest/server.bundle.js.map +7 -0
  78. package/dest/state_machine/archiver.d.ts +4 -3
  79. package/dest/state_machine/archiver.d.ts.map +1 -1
  80. package/dest/state_machine/archiver.js +26 -15
  81. package/dest/state_machine/dummy_p2p_client.d.ts +14 -7
  82. package/dest/state_machine/dummy_p2p_client.d.ts.map +1 -1
  83. package/dest/state_machine/dummy_p2p_client.js +19 -4
  84. package/dest/state_machine/global_variable_builder.d.ts +9 -4
  85. package/dest/state_machine/global_variable_builder.d.ts.map +1 -1
  86. package/dest/state_machine/global_variable_builder.js +9 -3
  87. package/dest/state_machine/index.d.ts +4 -2
  88. package/dest/state_machine/index.d.ts.map +1 -1
  89. package/dest/state_machine/index.js +11 -3
  90. package/dest/state_machine/mock_epoch_cache.d.ts +1 -2
  91. package/dest/state_machine/mock_epoch_cache.d.ts.map +1 -1
  92. package/dest/state_machine/mock_epoch_cache.js +0 -3
  93. package/dest/state_machine/synchronizer.js +1 -1
  94. package/dest/txe_session.d.ts +86 -19
  95. package/dest/txe_session.d.ts.map +1 -1
  96. package/dest/txe_session.js +244 -45
  97. package/dest/utils/encoding.d.ts +191 -0
  98. package/dest/utils/encoding.d.ts.map +1 -0
  99. package/dest/{util → utils}/encoding.js +7 -2
  100. package/dest/{util → utils}/expected_failure_error.d.ts +1 -1
  101. package/dest/utils/expected_failure_error.d.ts.map +1 -0
  102. package/dest/{util → utils}/txe_account_store.d.ts +1 -1
  103. package/dest/utils/txe_account_store.d.ts.map +1 -0
  104. package/dest/utils/txe_artifact_resolver.d.ts +37 -0
  105. package/dest/utils/txe_artifact_resolver.d.ts.map +1 -0
  106. package/dest/utils/txe_artifact_resolver.js +161 -0
  107. package/dest/utils/txe_public_contract_data_source.d.ts +20 -0
  108. package/dest/utils/txe_public_contract_data_source.d.ts.map +1 -0
  109. package/dest/{util → utils}/txe_public_contract_data_source.js +1 -3
  110. package/dest/worker.bundle.js +3 -0
  111. package/dest/worker.bundle.js.map +7 -0
  112. package/dest/worker.d.ts +2 -0
  113. package/dest/worker.d.ts.map +1 -0
  114. package/dest/worker.js +92 -0
  115. package/package.json +38 -21
  116. package/src/bin/check_txe_oracle_version.ts +70 -0
  117. package/src/bin/index.ts +11 -2
  118. package/src/bin/oracle_test_server.ts +51 -0
  119. package/src/constants.ts +10 -0
  120. package/src/dispatcher_pool.ts +317 -0
  121. package/src/index.ts +97 -227
  122. package/src/msgpackr_fr_extension.ts +23 -0
  123. package/src/oracle/interfaces.ts +29 -7
  124. package/src/oracle/test-resolver/fixtures.ts +84 -0
  125. package/src/oracle/test-resolver/index.ts +45 -0
  126. package/src/oracle/test-resolver/resolver.ts +165 -0
  127. package/src/oracle/txe_oracle_public_context.ts +60 -0
  128. package/src/oracle/txe_oracle_registry.ts +401 -0
  129. package/src/oracle/txe_oracle_top_level_context.ts +185 -67
  130. package/src/oracle/txe_oracle_version.ts +17 -0
  131. package/src/oracle/txe_private_execution_oracle.ts +30 -0
  132. package/src/rpc_server.ts +87 -0
  133. package/src/rpc_translator.ts +765 -913
  134. package/src/state_machine/archiver.ts +38 -16
  135. package/src/state_machine/dummy_p2p_client.ts +35 -11
  136. package/src/state_machine/global_variable_builder.ts +18 -3
  137. package/src/state_machine/index.ts +17 -5
  138. package/src/state_machine/mock_epoch_cache.ts +0 -4
  139. package/src/state_machine/synchronizer.ts +1 -1
  140. package/src/txe_session.ts +434 -57
  141. package/src/{util → utils}/encoding.ts +8 -2
  142. package/src/utils/txe_artifact_resolver.ts +217 -0
  143. package/src/{util → utils}/txe_public_contract_data_source.ts +0 -2
  144. package/src/worker.ts +98 -0
  145. package/dest/util/encoding.d.ts +0 -720
  146. package/dest/util/encoding.d.ts.map +0 -1
  147. package/dest/util/expected_failure_error.d.ts.map +0 -1
  148. package/dest/util/txe_account_store.d.ts.map +0 -1
  149. package/dest/util/txe_public_contract_data_source.d.ts +0 -20
  150. package/dest/util/txe_public_contract_data_source.d.ts.map +0 -1
  151. /package/dest/{util → utils}/expected_failure_error.js +0 -0
  152. /package/dest/{util → utils}/txe_account_store.js +0 -0
  153. /package/src/{util → utils}/expected_failure_error.ts +0 -0
  154. /package/src/{util → utils}/txe_account_store.ts +0 -0
@@ -1,3 +1,7 @@
1
1
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
2
2
  export declare const DEFAULT_ADDRESS: AztecAddress;
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUUzRCxlQUFPLE1BQU0sZUFBZSxjQUE4QixDQUFDIn0=
3
+ export declare const MAX_PRIVATE_EVENT_LEN = 10;
4
+ export declare const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
5
+ export declare const MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY = 64;
6
+ export declare const MAX_OFFCHAIN_EFFECT_LEN: number;
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUUzRCxlQUFPLE1BQU0sZUFBZSxjQUE4QixDQUFDO0FBRzNELGVBQU8sTUFBTSxxQkFBcUIsS0FBSyxDQUFDO0FBQ3hDLGVBQU8sTUFBTSxnQ0FBZ0MsSUFBSSxDQUFDO0FBR2xELGVBQU8sTUFBTSxrQ0FBa0MsS0FBSyxDQUFDO0FBRXJELGVBQU8sTUFBTSx1QkFBdUIsUUFBaUMsQ0FBQyJ9
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,eAAO,MAAM,eAAe,cAA8B,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAE3D,eAAO,MAAM,eAAe,cAA8B,CAAC;AAG3D,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,gCAAgC,IAAI,CAAC;AAGlD,eAAO,MAAM,kCAAkC,KAAK,CAAC;AAErD,eAAO,MAAM,uBAAuB,QAAiC,CAAC"}
package/dest/constants.js CHANGED
@@ -1,2 +1,10 @@
1
+ import { PRIVATE_LOG_CIPHERTEXT_LEN } from '@aztec/constants';
1
2
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
2
3
  export const DEFAULT_ADDRESS = AztecAddress.fromNumber(42);
4
+ // This is MAX_MESSAGE_CONTENT_LEN - PRIVATE_EVENT_MSG_PLAINTEXT_RESERVED_FIELDS_LEN
5
+ export const MAX_PRIVATE_EVENT_LEN = 10;
6
+ export const MAX_PRIVATE_EVENTS_PER_TXE_QUERY = 5;
7
+ // Arbitrarily set at 64 because we need a bound. Nothing inherent about it.
8
+ export const MAX_OFFCHAIN_EFFECTS_PER_TXE_QUERY = 64;
9
+ // Must match MAX_OFFCHAIN_EFFECT_LEN in noir-projects/aztec-nr/aztec/src/test/helpers/txe_oracles.nr.
10
+ export const MAX_OFFCHAIN_EFFECT_LEN = 2 + PRIVATE_LOG_CIPHERTEXT_LEN;
@@ -0,0 +1,67 @@
1
+ import type { Logger } from '@aztec/foundation/log';
2
+ import type { TXEForeignCallInput } from './index.js';
3
+ import type { ForeignCallResult } from './utils/encoding.js';
4
+ /**
5
+ * Opens a fresh LMDB in a tmp dir and writes the protocol contracts in
6
+ * {@link TXE_REQUIRED_PROTOCOL_CONTRACTS} plus the standard AuthRegistry, HandshakeRegistry, and the SchnorrAccount artifact,
7
+ * returning the directory path and the SchnorrAccount class id (hex). The store handle is intentionally kept
8
+ * alive: closing it would trigger the ephemeral-store cleanup hook and remove the tmp
9
+ * directory, so any worker that has not yet cloned would find it missing.
10
+ */
11
+ export declare function buildSharedContractStore(): Promise<{
12
+ dataDir: string;
13
+ schnorrClassId: string;
14
+ }>;
15
+ export interface TXEDispatcherPoolOptions {
16
+ /** Number of worker threads */
17
+ workers?: number;
18
+ }
19
+ /**
20
+ * Main-thread router that owns a pool of TXE worker threads. Each worker runs its own
21
+ * {@link TXEDispatcher} and handles foreign-call requests for the sessions assigned to it.
22
+ *
23
+ * Routing is sticky by `session_id`: new sessions go to a freshly spawned worker (up to
24
+ * `maxWorkers`) or, once the cap is reached, to the existing worker with the fewest sessions.
25
+ * Each session's state — TXESession, native world state, KV stores — stays single-threaded
26
+ * within its worker; different sessions run in parallel across workers.
27
+ *
28
+ * The main thread builds a shared protocol-contracts LMDB once and passes its path via
29
+ * `workerData`. Workers clone the data file on demand instead of re-registering the contracts.
30
+ */
31
+ export declare class TXEDispatcherPool {
32
+ private readonly logger;
33
+ private readonly workers;
34
+ private readonly sessionToWorker;
35
+ private readonly pending;
36
+ private nextRequestId;
37
+ private readonly maxWorkers;
38
+ private readonly readyPromise;
39
+ private contractStoreSourceDir?;
40
+ private schnorrClassId?;
41
+ private workerPath?;
42
+ constructor(logger: Logger, opts?: TXEDispatcherPoolOptions);
43
+ /** Resolves once the shared protocol-contracts store is built. Workers spawn lazily on demand. */
44
+ ready(): Promise<void>;
45
+ private init;
46
+ /**
47
+ * Spawns a fresh worker and returns its index in `this.workers`. Caller must have awaited
48
+ * `init()` so the shared contract store path is set. Messages posted before the worker has
49
+ * finished loading are queued by Node's worker_threads transport.
50
+ */
51
+ private spawnWorker;
52
+ /** Routes a session-dispose request to the worker that owns the session. Fire-and-forget. */
53
+ disposeSession(sessionId: number): void;
54
+ resolve_foreign_call(callData: TXEForeignCallInput): Promise<ForeignCallResult>;
55
+ /** Terminates all workers. Used by tests; production TXE exits the process directly. */
56
+ shutdown(): Promise<void>;
57
+ /**
58
+ * Returns the index of the worker that should handle a new session. Spawns a fresh worker if
59
+ * the pool hasn't reached its cap; otherwise picks the existing worker with the fewest
60
+ * assigned sessions. Always returns a valid index into `this.workers`.
61
+ */
62
+ private pickOrSpawnWorker;
63
+ private handleMessage;
64
+ private handleResult;
65
+ private handleWorkerError;
66
+ }
67
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGF0Y2hlcl9wb29sLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZGlzcGF0Y2hlcl9wb29sLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBY3BELE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3RELE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFLN0Q7Ozs7OztHQU1HO0FBQ0gsd0JBQXNCLHdCQUF3QixJQUFJLE9BQU8sQ0FBQztJQUFFLE9BQU8sRUFBRSxNQUFNLENBQUM7SUFBQyxjQUFjLEVBQUUsTUFBTSxDQUFBO0NBQUUsQ0FBQyxDQW1Cckc7QUEwREQsTUFBTSxXQUFXLHdCQUF3QjtJQUN2QywrQkFBK0I7SUFDL0IsT0FBTyxDQUFDLEVBQUUsTUFBTSxDQUFDO0NBQ2xCO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxxQkFBYSxpQkFBaUI7SUFZMUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNO0lBWHpCLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFvQjtJQUM1QyxPQUFPLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBNkI7SUFDN0QsT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQXFDO0lBQzdELE9BQU8sQ0FBQyxhQUFhLENBQUs7SUFDMUIsT0FBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQVM7SUFDcEMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQWdCO0lBQzdDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFTO0lBQ3hDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBUztJQUNoQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQU07SUFFekIsWUFDbUIsTUFBTSxFQUFFLE1BQU0sRUFDL0IsSUFBSSxHQUFFLHdCQUE2QixFQUtwQztJQUVELGtHQUFrRztJQUMzRixLQUFLLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUU1QjtZQUVhLElBQUk7SUFhbEI7Ozs7T0FJRztJQUNILE9BQU8sQ0FBQyxXQUFXO0lBeUJuQiw2RkFBNkY7SUFDN0YsY0FBYyxDQUFDLFNBQVMsRUFBRSxNQUFNLEdBQUcsSUFBSSxDQVl0QztJQUdLLG9CQUFvQixDQUFDLFFBQVEsRUFBRSxtQkFBbUIsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FtQnBGO0lBRUQsd0ZBQXdGO0lBQ2xGLFFBQVEsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLENBTzlCO0lBRUQ7Ozs7T0FJRztJQUNILE9BQU8sQ0FBQyxpQkFBaUI7SUFnQnpCLE9BQU8sQ0FBQyxhQUFhO0lBbUJyQixPQUFPLENBQUMsWUFBWTtJQWtCcEIsT0FBTyxDQUFDLGlCQUFpQjtDQW9CMUIifQ==
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatcher_pool.d.ts","sourceRoot":"","sources":["../src/dispatcher_pool.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAcpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAK7D;;;;;;GAMG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC,CAmBrG;AA0DD,MAAM,WAAW,wBAAwB;IACvC,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,iBAAiB;IAY1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAXzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAA6B;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,sBAAsB,CAAC,CAAS;IACxC,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,UAAU,CAAC,CAAM;IAEzB,YACmB,MAAM,EAAE,MAAM,EAC/B,IAAI,GAAE,wBAA6B,EAKpC;IAED,kGAAkG;IAC3F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5B;YAEa,IAAI;IAalB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAyBnB,6FAA6F;IAC7F,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAYtC;IAGK,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmBpF;IAED,wFAAwF;IAClF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAO9B;IAED;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,iBAAiB;CAoB1B"}
@@ -0,0 +1,286 @@
1
+ import { getSchnorrAccountContractArtifact } from '@aztec/accounts/schnorr/lazy';
2
+ import { BackendType, Barretenberg, BarretenbergSync } from '@aztec/bb.js';
3
+ import { openEphemeralStore } from '@aztec/kv-store/lmdb-v2';
4
+ import { LazyProtocolContractsProvider } from '@aztec/protocol-contracts/providers/lazy';
5
+ import { ContractStore } from '@aztec/pxe/client/lazy';
6
+ import { getStandardAuthRegistry } from '@aztec/standard-contracts/auth-registry/lazy';
7
+ import { getStandardHandshakeRegistry } from '@aztec/standard-contracts/handshake-registry/lazy';
8
+ import { getContractClassFromArtifact } from '@aztec/stdlib/contract';
9
+ import { existsSync } from 'node:fs';
10
+ import { cpus } from 'node:os';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { Worker } from 'node:worker_threads';
13
+ import { TXE_REQUIRED_PROTOCOL_CONTRACTS } from './index.js';
14
+ void Barretenberg.initSingleton({
15
+ backend: BackendType.Wasm,
16
+ skipSrsInit: true,
17
+ threads: 1
18
+ });
19
+ void BarretenbergSync.initSingleton({
20
+ backend: BackendType.Wasm
21
+ });
22
+ /**
23
+ * Opens a fresh LMDB in a tmp dir and writes the protocol contracts in
24
+ * {@link TXE_REQUIRED_PROTOCOL_CONTRACTS} plus the standard AuthRegistry, HandshakeRegistry, and the SchnorrAccount artifact,
25
+ * returning the directory path and the SchnorrAccount class id (hex). The store handle is intentionally kept
26
+ * alive: closing it would trigger the ephemeral-store cleanup hook and remove the tmp
27
+ * directory, so any worker that has not yet cloned would find it missing.
28
+ */ export async function buildSharedContractStore() {
29
+ const kvStore = await openEphemeralStore('txe-shared-contracts', undefined, 2);
30
+ const dataDir = kvStore.dataDirectory;
31
+ const contractStore = new ContractStore(kvStore);
32
+ const provider = new LazyProtocolContractsProvider();
33
+ const [protocolContracts, standardContracts, schnorrArtifact] = await Promise.all([
34
+ Promise.all(TXE_REQUIRED_PROTOCOL_CONTRACTS.map((name)=>provider.getProtocolContractArtifact(name))),
35
+ Promise.all([
36
+ getStandardAuthRegistry(),
37
+ getStandardHandshakeRegistry()
38
+ ]),
39
+ getSchnorrAccountContractArtifact()
40
+ ]);
41
+ const schnorrClass = await getContractClassFromArtifact(schnorrArtifact);
42
+ await Promise.all([
43
+ ...[
44
+ ...protocolContracts,
45
+ ...standardContracts
46
+ ].flatMap(({ instance, artifact, contractClass })=>[
47
+ contractStore.addContractArtifact(artifact, contractClass),
48
+ contractStore.addContractInstance(instance)
49
+ ]),
50
+ contractStore.addContractArtifact(schnorrArtifact, schnorrClass)
51
+ ]);
52
+ return {
53
+ dataDir,
54
+ schnorrClassId: schnorrClass.id.toString()
55
+ };
56
+ }
57
+ /**
58
+ * Resolves `worker.bundle.js` whether this code is running unbundled (next to dispatcher_pool.js
59
+ * inside `dest/`) or bundled into `dest/bin/index.js` (one directory deeper). `import.meta.url`
60
+ * refers to whichever module the calling code actually lives in; we try both relative locations
61
+ * and use whichever exists.
62
+ */ function resolveWorkerBundlePath() {
63
+ const candidates = [
64
+ new URL('./worker.bundle.js', import.meta.url),
65
+ new URL('../worker.bundle.js', import.meta.url)
66
+ ];
67
+ return candidates.find((u)=>existsSync(fileURLToPath(u))) ?? candidates[0];
68
+ }
69
+ function deserializeError(payload) {
70
+ if (!payload) {
71
+ return new Error('Worker returned an error with no payload');
72
+ }
73
+ const err = new Error(payload.message);
74
+ if (payload.name) {
75
+ err.name = payload.name;
76
+ }
77
+ if (payload.stack) {
78
+ err.stack = payload.stack;
79
+ }
80
+ return err;
81
+ }
82
+ /**
83
+ * Main-thread router that owns a pool of TXE worker threads. Each worker runs its own
84
+ * {@link TXEDispatcher} and handles foreign-call requests for the sessions assigned to it.
85
+ *
86
+ * Routing is sticky by `session_id`: new sessions go to a freshly spawned worker (up to
87
+ * `maxWorkers`) or, once the cap is reached, to the existing worker with the fewest sessions.
88
+ * Each session's state — TXESession, native world state, KV stores — stays single-threaded
89
+ * within its worker; different sessions run in parallel across workers.
90
+ *
91
+ * The main thread builds a shared protocol-contracts LMDB once and passes its path via
92
+ * `workerData`. Workers clone the data file on demand instead of re-registering the contracts.
93
+ */ export class TXEDispatcherPool {
94
+ logger;
95
+ workers;
96
+ sessionToWorker;
97
+ pending;
98
+ nextRequestId;
99
+ maxWorkers;
100
+ readyPromise;
101
+ contractStoreSourceDir;
102
+ schnorrClassId;
103
+ workerPath;
104
+ constructor(logger, opts = {}){
105
+ this.logger = logger;
106
+ this.workers = [];
107
+ this.sessionToWorker = new Map();
108
+ this.pending = new Map();
109
+ this.nextRequestId = 0;
110
+ // TXE still doesn't scale well beyond 16 workers due to contention
111
+ this.maxWorkers = Math.max(1, opts.workers ?? Math.min(cpus().length, 16));
112
+ this.readyPromise = this.init();
113
+ }
114
+ /** Resolves once the shared protocol-contracts store is built. Workers spawn lazily on demand. */ ready() {
115
+ return this.readyPromise;
116
+ }
117
+ async init() {
118
+ const t0 = Date.now();
119
+ const { dataDir, schnorrClassId } = await buildSharedContractStore();
120
+ this.contractStoreSourceDir = dataDir;
121
+ this.schnorrClassId = schnorrClassId;
122
+ this.workerPath = resolveWorkerBundlePath();
123
+ this.logger.debug(`TXE dispatcher pool ready (lazy spawn, cap=${this.maxWorkers})`, {
124
+ contractStoreSourceDir: dataDir,
125
+ schnorrClassId,
126
+ ms: Date.now() - t0
127
+ });
128
+ }
129
+ /**
130
+ * Spawns a fresh worker and returns its index in `this.workers`. Caller must have awaited
131
+ * `init()` so the shared contract store path is set. Messages posted before the worker has
132
+ * finished loading are queued by Node's worker_threads transport.
133
+ */ spawnWorker() {
134
+ const workerIdx = this.workers.length;
135
+ const w = new Worker(this.workerPath, {
136
+ workerData: {
137
+ contractStoreSourceDir: this.contractStoreSourceDir,
138
+ schnorrClassId: this.schnorrClassId
139
+ }
140
+ });
141
+ const slot = {
142
+ worker: w,
143
+ sessions: new Set(),
144
+ inFlightRequestIds: new Set()
145
+ };
146
+ this.workers.push(slot);
147
+ w.on('message', (msg)=>this.handleMessage(workerIdx, msg));
148
+ w.on('error', (err)=>this.handleWorkerError(workerIdx, err));
149
+ w.on('exit', (code)=>{
150
+ if (code !== 0) {
151
+ this.handleWorkerError(workerIdx, new Error(`Worker ${workerIdx} exited with code ${code}`));
152
+ }
153
+ });
154
+ this.logger.debug(`Spawning TXE worker ${workerIdx} on demand`, {
155
+ cap: this.maxWorkers,
156
+ poolSize: this.workers.length
157
+ });
158
+ return workerIdx;
159
+ }
160
+ /** Routes a session-dispose request to the worker that owns the session. Fire-and-forget. */ disposeSession(sessionId) {
161
+ const workerIdx = this.sessionToWorker.get(sessionId);
162
+ if (workerIdx === undefined) {
163
+ throw new Error(`disposeSession: no worker mapped for session ${sessionId}`);
164
+ }
165
+ this.sessionToWorker.delete(sessionId);
166
+ const slot = this.workers[workerIdx];
167
+ if (!slot) {
168
+ throw new Error(`disposeSession: worker ${workerIdx} (session ${sessionId}) missing from pool`);
169
+ }
170
+ slot.sessions.delete(sessionId);
171
+ slot.worker.postMessage({
172
+ type: 'dispose-session',
173
+ sessionId
174
+ });
175
+ }
176
+ // eslint-disable-next-line camelcase
177
+ async resolve_foreign_call(callData) {
178
+ // Make sure the shared contract store + worker bundle path are in place before we spawn.
179
+ await this.readyPromise;
180
+ const sessionId = callData.session_id;
181
+ let workerIdx = this.sessionToWorker.get(sessionId);
182
+ if (workerIdx === undefined) {
183
+ workerIdx = this.pickOrSpawnWorker();
184
+ this.sessionToWorker.set(sessionId, workerIdx);
185
+ this.workers[workerIdx].sessions.add(sessionId);
186
+ this.logger.debug(`Routing new session ${sessionId} to worker ${workerIdx}`);
187
+ }
188
+ const slot = this.workers[workerIdx];
189
+ const requestId = this.nextRequestId++;
190
+ return new Promise((resolve, reject)=>{
191
+ this.pending.set(requestId, {
192
+ resolve,
193
+ reject,
194
+ workerIdx: workerIdx
195
+ });
196
+ slot.inFlightRequestIds.add(requestId);
197
+ slot.worker.postMessage({
198
+ type: 'foreign-call',
199
+ requestId,
200
+ callData
201
+ });
202
+ });
203
+ }
204
+ /** Terminates all workers. Used by tests; production TXE exits the process directly. */ async shutdown() {
205
+ const slots = this.workers.splice(0, this.workers.length);
206
+ await Promise.all(slots.map((s)=>s.worker.terminate()));
207
+ for (const [requestId, pending] of this.pending){
208
+ pending.reject(new Error('TXE dispatcher pool was shut down'));
209
+ this.pending.delete(requestId);
210
+ }
211
+ }
212
+ /**
213
+ * Returns the index of the worker that should handle a new session. Spawns a fresh worker if
214
+ * the pool hasn't reached its cap; otherwise picks the existing worker with the fewest
215
+ * assigned sessions. Always returns a valid index into `this.workers`.
216
+ */ pickOrSpawnWorker() {
217
+ if (this.workers.length < this.maxWorkers) {
218
+ return this.spawnWorker();
219
+ }
220
+ let minIdx = 0;
221
+ let minCount = this.workers[0].sessions.size;
222
+ for(let i = 1; i < this.workers.length; i++){
223
+ const count = this.workers[i].sessions.size;
224
+ if (count < minCount) {
225
+ minIdx = i;
226
+ minCount = count;
227
+ }
228
+ }
229
+ return minIdx;
230
+ }
231
+ handleMessage(workerIdx, msg) {
232
+ switch(msg.type){
233
+ case 'result':
234
+ this.handleResult(workerIdx, msg);
235
+ return;
236
+ case 'memstat':
237
+ this.logger.debug(`worker ${workerIdx} memstat`, {
238
+ worker: workerIdx,
239
+ sessions: msg.sessions,
240
+ rssMiB: Math.round(msg.rss / 1024 / 1024),
241
+ heapTotalMiB: Math.round(msg.heapTotal / 1024 / 1024),
242
+ heapUsedMiB: Math.round(msg.heapUsed / 1024 / 1024),
243
+ externalMiB: Math.round(msg.external / 1024 / 1024),
244
+ arrayBuffersMiB: Math.round(msg.arrayBuffers / 1024 / 1024)
245
+ });
246
+ return;
247
+ }
248
+ }
249
+ handleResult(workerIdx, msg) {
250
+ const pending = this.pending.get(msg.requestId);
251
+ if (!pending) {
252
+ throw new Error(`handleResult: request ${msg.requestId} (worker ${workerIdx}) not in pending map`);
253
+ }
254
+ this.pending.delete(msg.requestId);
255
+ const slot = this.workers[workerIdx];
256
+ if (!slot) {
257
+ throw new Error(`handleResult: worker ${workerIdx} (request ${msg.requestId}) missing from pool`);
258
+ }
259
+ slot.inFlightRequestIds.delete(msg.requestId);
260
+ if (msg.ok) {
261
+ pending.resolve(msg.value);
262
+ } else {
263
+ pending.reject(deserializeError(msg.error));
264
+ }
265
+ }
266
+ handleWorkerError(workerIdx, err) {
267
+ this.logger.error(`TXE worker ${workerIdx} crashed; sessions assigned to it will fail`, err);
268
+ const slot = this.workers[workerIdx];
269
+ if (!slot) {
270
+ throw new Error(`handleWorkerError: worker ${workerIdx} missing from pool (orig err: ${err.message})`);
271
+ }
272
+ for (const requestId of slot.inFlightRequestIds){
273
+ const pending = this.pending.get(requestId);
274
+ if (!pending) {
275
+ throw new Error(`handleWorkerError: in-flight request ${requestId} (worker ${workerIdx}) not in pending map`);
276
+ }
277
+ pending.reject(err);
278
+ this.pending.delete(requestId);
279
+ }
280
+ slot.inFlightRequestIds.clear();
281
+ for (const sessionId of slot.sessions){
282
+ this.sessionToWorker.delete(sessionId);
283
+ }
284
+ slot.sessions.clear();
285
+ }
286
+ }
package/dest/index.d.ts CHANGED
@@ -1,8 +1,52 @@
1
1
  import type { Logger } from '@aztec/foundation/log';
2
- /**
3
- * Creates an RPC server that forwards calls to the TXE.
4
- * @param logger - Logger to output to
5
- * @returns A TXE RPC server.
6
- */
7
- export declare function createTXERpcServer(logger: Logger): import("@aztec/foundation/json-rpc/server").SafeJsonRpcServer;
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFVQSxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQXFRcEQ7Ozs7R0FJRztBQUNILHdCQUFnQixrQkFBa0IsQ0FBQyxNQUFNLEVBQUUsTUFBTSxpRUFJaEQifQ==
2
+ import type { ProtocolContractName } from '@aztec/protocol-contracts';
3
+ import type { ApiSchemaFor } from '@aztec/stdlib/schemas';
4
+ import { z } from 'zod';
5
+ import './msgpackr_fr_extension.js';
6
+ import { type TXEOracleFunctionName } from './txe_session.js';
7
+ import { type ForeignCallArgs, type ForeignCallResult } from './utils/encoding.js';
8
+ export declare const TXE_REQUIRED_PROTOCOL_CONTRACTS: ProtocolContractName[];
9
+ export type TXEForeignCallInput = {
10
+ session_id: number;
11
+ function: TXEOracleFunctionName;
12
+ root_path: string;
13
+ package_name: string;
14
+ inputs: ForeignCallArgs;
15
+ };
16
+ export declare const TXEForeignCallInputSchema: z.ZodType<TXEForeignCallInput>;
17
+ export interface TXEDispatcherOptions {
18
+ /**
19
+ * Path to an LMDB directory holding the required protocol contracts (see
20
+ * {@link TXE_REQUIRED_PROTOCOL_CONTRACTS}) and the SchnorrAccount artifact. When set, the
21
+ * dispatcher clones this directory into a fresh tmpdir on first use instead of registering
22
+ * the contracts itself.
23
+ */
24
+ contractStoreSourceDir: string;
25
+ /**
26
+ * Class id (hex) of the SchnorrAccount artifact pre-registered in the shared LMDB. The
27
+ * {@link TXEArtifactResolver} looks the artifact up from the cloned store via this class id
28
+ * instead of recomputing it via `getSchnorrAccountContractArtifact()` + `computeArtifactHash()`.
29
+ */
30
+ schnorrClassId: string;
31
+ }
32
+ export declare class TXEDispatcher {
33
+ private logger;
34
+ private contractStore;
35
+ private artifactResolver;
36
+ private readonly contractStoreSourceDir;
37
+ private readonly schnorrClassId;
38
+ constructor(logger: Logger, opts: TXEDispatcherOptions);
39
+ private warmUp;
40
+ resolve_foreign_call(callData: TXEForeignCallInput): Promise<ForeignCallResult>;
41
+ /**
42
+ * Releases a session and its resources (per-session LMDB + `NativeWorldStateService`).
43
+ * Called by the dispatcher pool when nargo closes its TCP connection for a test (see
44
+ * `rpc_server.ts`'s socket tracker). No-op if the session was never created — that happens
45
+ * when nargo opens a connection but errors before sending a request.
46
+ */
47
+ disposeSession(sessionId: number): Promise<void>;
48
+ }
49
+ /** Diagnostic-only: number of sessions currently held by this worker. */
50
+ export declare function activeSessionCount(): number;
51
+ export declare const TXEDispatcherApiSchema: ApiSchemaFor<TXEDispatcher>;
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUVwRCxPQUFPLEtBQUssRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRXRFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBSTFELE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFJeEIsT0FBTyw0QkFBNEIsQ0FBQztBQUNwQyxPQUFPLEVBQUUsS0FBSyxxQkFBcUIsRUFBYyxNQUFNLGtCQUFrQixDQUFDO0FBQzFFLE9BQU8sRUFDTCxLQUFLLGVBQWUsRUFFcEIsS0FBSyxpQkFBaUIsRUFFdkIsTUFBTSxxQkFBcUIsQ0FBQztBQUs3QixlQUFPLE1BQU0sK0JBQStCLEVBQUUsb0JBQW9CLEVBQU8sQ0FBQztBQUkxRSxNQUFNLE1BQU0sbUJBQW1CLEdBQUc7SUFDaEMsVUFBVSxFQUFFLE1BQU0sQ0FBQztJQUNuQixRQUFRLEVBQUUscUJBQXFCLENBQUM7SUFDaEMsU0FBUyxFQUFFLE1BQU0sQ0FBQztJQUNsQixZQUFZLEVBQUUsTUFBTSxDQUFDO0lBQ3JCLE1BQU0sRUFBRSxlQUFlLENBQUM7Q0FDekIsQ0FBQztBQUVGLGVBQU8sTUFBTSx5QkFBeUIsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQWNwRSxDQUFDO0FBRUYsTUFBTSxXQUFXLG9CQUFvQjtJQUNuQzs7Ozs7T0FLRztJQUNILHNCQUFzQixFQUFFLE1BQU0sQ0FBQztJQUMvQjs7OztPQUlHO0lBQ0gsY0FBYyxFQUFFLE1BQU0sQ0FBQztDQUN4QjtBQUVELHFCQUFhLGFBQWE7SUFPdEIsT0FBTyxDQUFDLE1BQU07SUFOaEIsT0FBTyxDQUFDLGFBQWEsQ0FBaUI7SUFDdEMsT0FBTyxDQUFDLGdCQUFnQixDQUF1QjtJQUMvQyxPQUFPLENBQUMsUUFBUSxDQUFDLHNCQUFzQixDQUFTO0lBQ2hELE9BQU8sQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFLO0lBRXBDLFlBQ1UsTUFBTSxFQUFFLE1BQU0sRUFDdEIsSUFBSSxFQUFFLG9CQUFvQixFQUkzQjtZQU9hLE1BQU07SUFpQmQsb0JBQW9CLENBQUMsUUFBUSxFQUFFLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQWlCcEY7SUFFRDs7Ozs7T0FLRztJQUNHLGNBQWMsQ0FBQyxTQUFTLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FPckQ7Q0FDRjtBQUVELHlFQUF5RTtBQUN6RSx3QkFBZ0Isa0JBQWtCLElBQUksTUFBTSxDQUUzQztBQUVELGVBQU8sTUFBTSxzQkFBc0IsRUFBRSxZQUFZLENBQUMsYUFBYSxDQUs5RCxDQUFDIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAqQpD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,iEAIhD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1D,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,4BAA4B,CAAC;AACpC,OAAO,EAAE,KAAK,qBAAqB,EAAc,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,iBAAiB,EAEvB,MAAM,qBAAqB,CAAC;AAK7B,eAAO,MAAM,+BAA+B,EAAE,oBAAoB,EAAO,CAAC;AAI1E,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,CAcpE,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,sBAAsB,EAAE,MAAM,CAAC;IAC/B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,aAAa;IAOtB,OAAO,CAAC,MAAM;IANhB,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAS;IAChD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAK;IAEpC,YACU,MAAM,EAAE,MAAM,EACtB,IAAI,EAAE,oBAAoB,EAI3B;YAOa,MAAM;IAiBd,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAiBpF;IAED;;;;;OAKG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrD;CACF;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,eAAO,MAAM,sBAAsB,EAAE,YAAY,CAAC,aAAa,CAK9D,CAAC"}