trac-msb 0.2.26 → 0.3.0-beta.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 (136) hide show
  1. package/SECURITY.md +2 -2
  2. package/cli/commandHandler.js +317 -20
  3. package/cli/handlers.js +9 -1
  4. package/cli/interactive.js +4 -3
  5. package/cli/tokenSupplyAudit.js +90 -0
  6. package/msb.mjs +1 -0
  7. package/package.json +15 -6
  8. package/rpc/create_server.js +12 -3
  9. package/rpc/handlers.js +103 -0
  10. package/rpc/routes/v1.js +8 -0
  11. package/src/codecs/apply/applyOperationCodec.js +334 -0
  12. package/src/codecs/apply/applyOperations.generated.cjs +6380 -0
  13. package/src/codecs/consensus/v1/consensusV1.generated.cjs +3508 -0
  14. package/src/codecs/consensus/v1/consensusV1OperationCodec.js +161 -0
  15. package/src/codecs/consensus/v1/vdfConfigCodec.js +83 -0
  16. package/src/{utils/protobuf → codecs/network/v1}/networkV1.generated.cjs +664 -393
  17. package/src/codecs/network/v1/networkV1OperationCodec.js +25 -0
  18. package/src/codecs/protobufRuntime.cjs +95 -0
  19. package/src/codecs/state/escrowEntryCodec.js +45 -0
  20. package/src/codecs/state/state.generated.cjs +659 -0
  21. package/src/config/args.js +0 -1
  22. package/src/config/config.js +41 -7
  23. package/src/config/env.js +33 -9
  24. package/src/core/consensus/epochAppenderSelection/EpochAppenderSelectionError.js +55 -0
  25. package/src/core/consensus/epochAppenderSelection/EpochAppenderSelectionOperations.js +118 -0
  26. package/src/core/consensus/epochAppenderSelection/EpochAppenderSelector.js +1042 -0
  27. package/src/core/consensus/epochAppenderSelection/createEpochAppenderSelector.js +23 -0
  28. package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionLedgerReader.js +274 -0
  29. package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionState.js +488 -0
  30. package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionStorage.js +93 -0
  31. package/src/core/consensus/quorum.js +11 -0
  32. package/src/core/consensus/services/EpochCoordinationRound.js +839 -0
  33. package/src/core/consensus/services/EpochCoordinatorOperations.js +211 -0
  34. package/src/core/consensus/services/EpochCoordinatorService.js +335 -0
  35. package/src/core/consensus/services/EpochRoundListeners.js +116 -0
  36. package/src/core/consensus/services/EpochStateMachine.js +141 -0
  37. package/src/core/consensus/services/VDFBare.js +291 -0
  38. package/src/core/consensus/services/VDFNode.js +111 -0
  39. package/src/core/consensus/services/VDFProgressWatchdog.js +79 -0
  40. package/src/core/consensus/services/VDFService.js +87 -0
  41. package/src/core/consensus/services/VDFServiceManager.js +147 -0
  42. package/src/core/consensus/services/createVDFService.js +16 -0
  43. package/src/core/consensus/services/vdf-guardian.js +32 -0
  44. package/src/core/consensus/services/vdf-worker.js +90 -0
  45. package/src/core/network/Network.js +327 -238
  46. package/src/core/network/protocols/consensus/IndexerMessages.js +72 -0
  47. package/src/core/network/protocols/consensus/v1/ConsensusV1ConnectionPolicy.js +57 -0
  48. package/src/core/network/protocols/consensus/v1/ConsensusV1MessageRouter.js +147 -0
  49. package/src/core/network/protocols/consensus/v1/ConsensusV1Protocol.js +72 -0
  50. package/src/core/network/protocols/consensus/v1/IndexerPendingRequestService.js +108 -0
  51. package/src/core/network/protocols/consensus/v1/V1ConsensusProtocolError.js +29 -0
  52. package/src/core/network/protocols/consensus/v1/handlers/V1EpochAppendOperationHandler.js +68 -0
  53. package/src/core/network/protocols/consensus/v1/handlers/V1EpochProofProposalOperationHandler.js +226 -0
  54. package/src/core/network/protocols/consensus/v1/validators/ConsensusValidationSchema.js +192 -0
  55. package/src/core/network/protocols/consensus/v1/validators/V1BaseConsensusOperation.js +428 -0
  56. package/src/core/network/protocols/consensus/v1/validators/V1EpochAppendReply.js +47 -0
  57. package/src/core/network/protocols/consensus/v1/validators/V1EpochAppendRequest.js +17 -0
  58. package/src/core/network/protocols/consensus/v1/validators/V1EpochProofProposalApproval.js +116 -0
  59. package/src/core/network/protocols/consensus/v1/validators/V1EpochProofProposalRequest.js +152 -0
  60. package/src/core/network/protocols/consensus/v1/validators/consensusValidationSchemaHelpers.js +145 -0
  61. package/src/core/network/protocols/shared/ConnectionOperationHandler.js +27 -0
  62. package/src/core/network/protocols/{NetworkMessages.js → validators/ValidatorMessages.js} +24 -14
  63. package/src/core/network/protocols/{ProtocolSession.js → validators/ValidatorProtocolSession.js} +22 -25
  64. package/src/core/network/protocols/{legacy/NetworkMessageRouter.js → validators/legacy/ValidatorLegacyMessageRouter.js} +6 -6
  65. package/src/core/network/protocols/{LegacyProtocol.js → validators/legacy/ValidatorLegacyProtocol.js} +9 -7
  66. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/BaseStateOperationHandler.js +1 -1
  67. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyGetRequestHandler.js +5 -5
  68. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyRoleOperationHandler.js +5 -5
  69. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacySubnetworkOperationHandler.js +5 -5
  70. package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyTransferOperationHandler.js +5 -5
  71. package/src/core/network/protocols/{ProtocolInterface.js → validators/shared/ValidatorProtocolInterface.js} +5 -5
  72. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialBootstrapDeploymentValidator.js +1 -1
  73. package/src/core/network/protocols/validators/shared/validators/PartialHtlcValidator.js +325 -0
  74. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialOperationValidator.js +44 -21
  75. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialRoleAccessValidator.js +3 -3
  76. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialTransactionValidator.js +3 -3
  77. package/src/core/network/protocols/{shared → validators/shared}/validators/PartialTransferValidator.js +4 -4
  78. package/src/core/network/protocols/{v1 → validators/v1}/V1ProtocolError.js +1 -1
  79. package/src/core/network/{services/PendingRequestService.js → protocols/validators/v1/ValidatorPendingRequestService.js} +19 -82
  80. package/src/core/network/protocols/{v1/NetworkMessageRouter.js → validators/v1/ValidatorV1MessageRouter.js} +9 -9
  81. package/src/core/network/protocols/{V1Protocol.js → validators/v1/ValidatorV1Protocol.js} +10 -8
  82. package/src/core/network/protocols/{connectionPolicies.js → validators/v1/connectionPolicies.js} +1 -1
  83. package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1BaseOperationHandler.js +6 -23
  84. package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1BroadcastTransactionOperationHandler.js +14 -9
  85. package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1LivenessOperationHandler.js +5 -4
  86. package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionErrorMapper.js +3 -3
  87. package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionOperationStrategies.js +44 -1
  88. package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionPayloadUtils.js +1 -1
  89. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BaseOperation.js +19 -15
  90. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BroadcastTransactionRequest.js +2 -2
  91. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BroadcastTransactionResponse.js +34 -18
  92. package/src/core/network/protocols/{v1 → validators/v1}/validators/V1ValidationSchema.js +3 -3
  93. package/src/core/network/services/IndexerConnectionManager.js +88 -0
  94. package/src/core/network/services/TransactionPoolService.js +11 -18
  95. package/src/core/network/services/TransactionRateLimiterService.js +1 -1
  96. package/src/core/network/services/ValidatorConnectionManager.js +163 -0
  97. package/src/core/network/services/{MessageOrchestrator.js → ValidatorMessageOrchestrator.js} +34 -42
  98. package/src/core/network/services/ValidatorObserverService.js +21 -36
  99. package/src/core/network/shared/BasePendingRequestService.js +67 -0
  100. package/src/core/network/shared/PeerConnectionManager.js +185 -0
  101. package/src/core/state/State.js +1789 -173
  102. package/src/core/state/StateEventQueue.js +69 -0
  103. package/src/core/state/utils/address.js +10 -6
  104. package/src/core/state/utils/epochProof.js +109 -0
  105. package/src/core/state/utils/escrowEntry.js +178 -0
  106. package/src/core/state/validators/StateValidationSchema.js +757 -0
  107. package/src/core/state/validators/stateValidationRules.js +312 -0
  108. package/src/index.js +255 -65
  109. package/src/messages/consensus/v1/ConsensusMessageBuilder.js +368 -0
  110. package/src/messages/consensus/v1/ConsensusMessageDirector.js +142 -0
  111. package/src/messages/consensus/v1/consensusMessageFactory.js +12 -0
  112. package/src/messages/consensus/v1/epochAppendMessage.js +58 -0
  113. package/src/messages/network/v1/NetworkMessageBuilder.js +15 -7
  114. package/src/messages/state/ApplyStateMessageBuilder.js +499 -13
  115. package/src/messages/state/ApplyStateMessageDirector.js +261 -2
  116. package/src/utils/StateMachine.js +125 -0
  117. package/src/utils/applyOperations.js +45 -2
  118. package/src/utils/buffer.js +239 -59
  119. package/src/utils/consensusConfig.js +76 -0
  120. package/src/utils/constants.js +174 -73
  121. package/src/utils/helpers.js +0 -25
  122. package/src/utils/htlcLock.js +122 -0
  123. package/src/utils/logger.js +10 -4
  124. package/src/utils/migrationUtils.js +2 -1
  125. package/src/utils/normalizers.js +113 -0
  126. package/src/utils/scheduler/SchedulableService.js +107 -0
  127. package/src/utils/{Scheduler.js → scheduler/Scheduler.js} +56 -17
  128. package/src/core/network/services/ConnectionManager.js +0 -406
  129. package/src/utils/check.js +0 -525
  130. package/src/utils/protobuf/applyOperations.cjs +0 -1373
  131. package/src/utils/protobuf/operationHelpers.js +0 -81
  132. /package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyResponseHandler.js +0 -0
  133. /package/src/core/network/protocols/{legacy → validators/legacy}/validators/ValidatorResponse.js +0 -0
  134. /package/src/core/network/protocols/{legacy → validators/legacy}/validators/base/BaseResponse.js +0 -0
  135. /package/src/core/network/protocols/{v1 → validators/v1}/validators/V1LivenessRequest.js +0 -0
  136. /package/src/core/network/protocols/{v1 → validators/v1}/validators/V1LivenessResponse.js +0 -0
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @typedef {object} VdfWorkerResponse
3
+ * @property {{challenge: Buffer, difficulty: number, discriminantSizeBits: number, solution: Buffer}} [result] Successful calculation.
4
+ * @property {Error|string} [error] Error from the worker, connection or cancellation.
5
+ *
6
+ * @typedef {object} VdfWorkerPort
7
+ * @property {function({challenge: Buffer, difficulty: number, discriminantSizeBits: number}): Promise<void>} write Start a calculation.
8
+ * @property {function(): Promise<VdfWorkerResponse>} read Wait for that calculation's response.
9
+ * @property {function(Error): Promise<void>} close Cancels pending reads and closes the worker port.
10
+ */
11
+ import ReadyResource from 'ready-resource';
12
+
13
+ /**
14
+ * Runs VDF calculations one at a time through the worker port. The Node and Bare services manage their
15
+ * workers. This class queues calculations and returns results and errors in the same format.
16
+ */
17
+ export class VDFService extends ReadyResource {
18
+ #workerPort = null;
19
+ #calculationQueue = Promise.resolve();
20
+
21
+ /**
22
+ * Sets the worker port opened by the Node or Bare service.
23
+ *
24
+ * @param {VdfWorkerPort} workerPort Worker port used by this service.
25
+ * @protected
26
+ */
27
+ _setPort(workerPort) {
28
+ this.#workerPort = workerPort;
29
+ }
30
+
31
+ /**
32
+ * Closes the worker port and waits for queued calculations to finish.
33
+ *
34
+ * @returns {Promise<void>}
35
+ * @protected
36
+ */
37
+ async _close() {
38
+ const workerPort = this.#workerPort;
39
+ this.#workerPort = null;
40
+
41
+ const [closeResult] = await Promise.allSettled([
42
+ workerPort?.close(new Error('VDF service closed')),
43
+ this.#calculationQueue,
44
+ ]);
45
+
46
+ if (closeResult.status === 'rejected') throw closeResult.reason;
47
+ }
48
+
49
+ /**
50
+ * Queues a calculation with the signed VDF parameters. Requests made after shutdown return an
51
+ * error without reaching the worker.
52
+ *
53
+ * @param {Buffer} challenge Encoded epoch challenge.
54
+ * @param {number} difficulty VDF iteration count.
55
+ * @param {number} discriminantSizeBits Discriminant size in bits.
56
+ * @returns {Promise<VdfWorkerResponse>} Response containing the result or an error.
57
+ */
58
+ async calculateVDF(challenge, difficulty, discriminantSizeBits) {
59
+ if (this.closing !== null || this.closed) {
60
+ return { error: new Error('VDF service is closed') };
61
+ }
62
+
63
+ const calculationPromise = this.#calculationQueue.then(() => this.#calculateWithWorker(challenge, difficulty, discriminantSizeBits));
64
+ this.#calculationQueue = calculationPromise.catch(() => {});
65
+ return calculationPromise;
66
+ }
67
+
68
+ /**
69
+ * Sends one calculation to the worker. Returns connection failures as response errors.
70
+ *
71
+ * @param {Buffer} challenge Encoded epoch challenge.
72
+ * @param {number} difficulty VDF iteration count.
73
+ * @param {number} discriminantSizeBits Discriminant size in bits.
74
+ * @returns {Promise<VdfWorkerResponse>} Response containing the result or an error.
75
+ */
76
+ async #calculateWithWorker(challenge, difficulty, discriminantSizeBits) {
77
+ const workerPort = this.#workerPort;
78
+ if (!workerPort) return { error: new Error('VDF service is not ready') };
79
+
80
+ try {
81
+ await workerPort.write({ challenge, difficulty, discriminantSizeBits });
82
+ return await workerPort.read();
83
+ } catch (error) {
84
+ return { error };
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,147 @@
1
+ import { createVDFService } from './createVDFService.js';
2
+ import { EpochCoordinatorOperations } from './EpochCoordinatorOperations.js';
3
+
4
+ /**
5
+ * Manages the VDF worker and the epoch operations that use it. Opens, replaces and closes workers one
6
+ * at a time so config changes cannot start overlapping workers.
7
+ */
8
+ export class VDFServiceManager {
9
+ #state;
10
+ #wallet;
11
+ #config;
12
+ #vdfService = null;
13
+ #operations = null;
14
+ #lifecycleQueue = Promise.resolve();
15
+
16
+ /**
17
+ * Creates the manager. open() starts the first VDF service.
18
+ *
19
+ * @param {import('../../state/State.js').default} state Ledger access used by epoch operations.
20
+ * @param {object} wallet Local proof signing identity.
21
+ * @param {object} config Message and network configuration.
22
+ */
23
+ constructor(state, wallet, config) {
24
+ this.#state = state;
25
+ this.#wallet = wallet;
26
+ this.#config = config;
27
+ }
28
+
29
+ /** @returns {EpochCoordinatorOperations|null} operations using the current VDF service */
30
+ get operations() {
31
+ return this.#operations;
32
+ }
33
+
34
+ /**
35
+ * Returns operations for the current VDF service. Starts a service if needed.
36
+ *
37
+ * @returns {Promise<EpochCoordinatorOperations>}
38
+ */
39
+ open() {
40
+ return this.#enqueueLifecycleChange(() => this.#openVdfService());
41
+ }
42
+
43
+ /**
44
+ * Closes the current VDF service and starts a new one.
45
+ *
46
+ * @returns {Promise<EpochCoordinatorOperations>}
47
+ */
48
+ replace() {
49
+ return this.#enqueueLifecycleChange(async () => {
50
+ await this.#closeVdfService();
51
+ return this.#openVdfService();
52
+ });
53
+ }
54
+
55
+ /**
56
+ * Closes the current VDF service. The manager can be opened again later.
57
+ *
58
+ * @returns {Promise<void>}
59
+ */
60
+ close() {
61
+ return this.#enqueueLifecycleChange(() => this.#closeVdfService());
62
+ }
63
+
64
+ /**
65
+ * Starts a VDF service and creates the operations that use it. If startup fails, closes the
66
+ * service before returning the error.
67
+ *
68
+ * @returns {Promise<EpochCoordinatorOperations>}
69
+ */
70
+ async #openVdfService() {
71
+ if (this.#operations) return this.#operations;
72
+ if (this.#vdfService) throw new Error('Previous VDF service is still open');
73
+
74
+ const vdfService = await createVDFService();
75
+
76
+ try {
77
+ await vdfService.ready();
78
+ const epochOperations = new EpochCoordinatorOperations(
79
+ this.#state,
80
+ vdfService,
81
+ this.#wallet,
82
+ this.#config,
83
+ );
84
+
85
+ this.#vdfService = vdfService;
86
+ this.#operations = epochOperations;
87
+ return epochOperations;
88
+ } catch (error) {
89
+ await this.#closeUnusedService(vdfService);
90
+ throw error;
91
+ }
92
+ }
93
+
94
+ /**
95
+ * Closes the current VDF service. If closing fails, keeps it registered so another worker cannot
96
+ * start while it may still be running.
97
+ *
98
+ * @returns {Promise<void>}
99
+ */
100
+ async #closeVdfService() {
101
+ const vdfService = this.#vdfService;
102
+ if (!vdfService) return;
103
+
104
+ this.#operations = null;
105
+
106
+ try {
107
+ await vdfService.close();
108
+ } catch {
109
+ throw new Error('Failed to close VDF service');
110
+ }
111
+
112
+ if (this.#vdfService === vdfService) this.#vdfService = null;
113
+ }
114
+
115
+ /**
116
+ * Closes a service that failed during startup. If closing also fails, keeps the service registered
117
+ * because its worker may still be running.
118
+ *
119
+ * @param {import('./VDFService.js').VDFService} vdfService Service whose startup failed.
120
+ * @returns {Promise<void>}
121
+ */
122
+ async #closeUnusedService(vdfService) {
123
+ try {
124
+ await vdfService.close();
125
+ } catch {
126
+ this.#vdfService = vdfService;
127
+ this.#operations = null;
128
+ throw new Error('Failed to close VDF service');
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Runs worker startup, replacement and shutdown one at a time. An error does not block the next
134
+ * operation in the queue.
135
+ *
136
+ * @param {() => Promise<unknown>} lifecycleChange Worker startup, replacement or shutdown to queue.
137
+ * @returns {Promise<unknown>}
138
+ */
139
+ #enqueueLifecycleChange(lifecycleChange) {
140
+ const lifecyclePromise = this.#lifecycleQueue.then(lifecycleChange);
141
+
142
+ // Keep the internal queue usable after a failed operation.
143
+ this.#lifecycleQueue = lifecyclePromise.catch(() => {});
144
+
145
+ return lifecyclePromise;
146
+ }
147
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Creates the VDF service for the current runtime. Bare and Pear use separate processes. Node uses a
3
+ * worker thread. The caller waits for ready() before use and calls close() when the service is no
4
+ * longer needed.
5
+ *
6
+ * @returns {Promise<import('./VDFService.js').VDFService>} VDF service ready to be opened.
7
+ */
8
+ export async function createVDFService() {
9
+ if (typeof globalThis.Bare !== 'undefined') {
10
+ const { VDFBare } = await import('./VDFBare.js');
11
+ return new VDFBare();
12
+ } else {
13
+ const { VDFNode } = await import('./VDFNode.js');
14
+ return new VDFNode();
15
+ }
16
+ }
@@ -0,0 +1,32 @@
1
+ import Pipe from 'bare-pipe';
2
+ import { kill, pid } from 'bare-os';
3
+ import { self } from 'bare-thread';
4
+ import { VDF_PROGRESS_PHASES } from './VDFProgressWatchdog.js';
5
+
6
+ // This thread never executes WASM: its event loop remains responsive while the
7
+ // solver blocks the subprocess's main thread. EOF also works after parent SIGKILL.
8
+ const owner = new Pipe(3);
9
+ const die = () => kill(pid(), 'SIGKILL');
10
+ owner.on('end', die);
11
+ owner.on('close', die);
12
+ owner.on('error', die);
13
+ owner.resume();
14
+
15
+ const ready = new Int32Array(self.data, 0, 1);
16
+ const counters = new BigUint64Array(self.data, 8, VDF_PROGRESS_PHASES.length);
17
+ let previous = VDF_PROGRESS_PHASES.map(() => '0');
18
+ let writable = true;
19
+ owner.on('drain', () => { writable = true; });
20
+
21
+ setInterval(() => {
22
+ if (!writable) return;
23
+ const progress = previous.map((_, i) => Atomics.load(counters, i).toString());
24
+ if (progress.every((count, i) => count === previous[i])) return;
25
+ previous = progress;
26
+ writable = owner.write(JSON.stringify({ progress }) + '\n');
27
+ }, 100);
28
+
29
+ // Arm ownership monitoring before the main thread enters the native solver.
30
+ owner.write(JSON.stringify({ ready: true }) + '\n');
31
+ Atomics.store(ready, 0, 1);
32
+ Atomics.notify(ready, 0);
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Receives calculations and returns their results. Node uses workerData.port to pass binary messages.
3
+ * Bare reads one JSON request per line from standard input and writes the response to standard output.
4
+ * Solver errors are included in the response.
5
+ */
6
+ import { VDF_PROGRESS_PHASES } from './VDFProgressWatchdog.js';
7
+ const { solveWesolowski } = await import('@tracsystems/trac-vdf');
8
+
9
+ /**
10
+ * Runs the Wesolowski solver and returns the proof with its input parameters.
11
+ *
12
+ * @param {Buffer} challenge Encoded epoch challenge.
13
+ * @param {number} difficulty VDF iteration count.
14
+ * @param {number} discriminantSizeBits Discriminant size in bits.
15
+ * @param {function({phase: string, completed: bigint}): void} [onProgress] Native progress observer.
16
+ * @returns {Promise<import('./VDFService.js').VdfWorkerResponse>}
17
+ */
18
+ async function solveVdfChallenge(challenge, difficulty, discriminantSizeBits, onProgress) {
19
+ try {
20
+ const solution = await solveWesolowski(challenge, difficulty, discriminantSizeBits, { onProgress });
21
+ return { result: { challenge, difficulty, discriminantSizeBits, solution } };
22
+ } catch (error) {
23
+ return { error: error.message };
24
+ }
25
+ }
26
+
27
+ if (typeof globalThis.Bare !== 'undefined') {
28
+ // Runs as a standalone OS subprocess (spawned via bare-subprocess by VDFBare), not a
29
+ // Bare.Thread: a real solveWesolowski() call leaves native/WASM state that crashes
30
+ // Bare.Thread's teardown (V8's internal WASM compiler threads never rejoin cleanly), so
31
+ // each computation gets its own disposable process instead - see VDFBare.js.
32
+ const { default: Pipe } = await import('bare-pipe');
33
+ const { default: Thread } = await import('bare-thread');
34
+ const shared = new SharedArrayBuffer(8 + VDF_PROGRESS_PHASES.length * 8);
35
+ const ready = new Int32Array(shared, 0, 1);
36
+ const counters = new BigUint64Array(shared, 8, VDF_PROGRESS_PHASES.length);
37
+ // Keep the guardian alive for the whole disposable process. It owns fd 3.
38
+ const guardian = new Thread(new URL('./vdf-guardian.js', import.meta.url).href, { data: shared });
39
+ while (Atomics.load(ready, 0) === 0) Atomics.wait(ready, 0, 0);
40
+ if (guardian.joined) throw new Error('VDF guardian exited before calculation');
41
+ const onProgress = ({ phase, completed }) => {
42
+ const index = VDF_PROGRESS_PHASES.indexOf(phase);
43
+ if (index === -1) throw new Error(`Unknown VDF progress phase: ${phase}`);
44
+ Atomics.store(counters, index, completed);
45
+ };
46
+ const stdin = new Pipe(0);
47
+ const stdout = new Pipe(1);
48
+
49
+ let requestBuffer = '';
50
+ stdin.on('data', async (chunk) => {
51
+ requestBuffer += chunk.toString();
52
+ const newlineIndex = requestBuffer.indexOf('\n');
53
+ if (newlineIndex === -1) return;
54
+ stdin.pause();
55
+ const calculationRequest = JSON.parse(requestBuffer.slice(0, newlineIndex));
56
+ const calculationResponse = await solveVdfChallenge(
57
+ Buffer.from(calculationRequest.challenge, 'hex'),
58
+ calculationRequest.difficulty,
59
+ calculationRequest.discriminantSizeBits,
60
+ onProgress
61
+ );
62
+ stdout.write(JSON.stringify(encodeWorkerResponse(calculationResponse)) + '\n');
63
+ });
64
+
65
+ /**
66
+ * Converts buffers to hex so the Bare worker can send the response as JSON.
67
+ *
68
+ * @param {import('./VDFService.js').VdfWorkerResponse} calculationResponse Worker result.
69
+ * @returns {object} Response that can be encoded as JSON.
70
+ */
71
+ function encodeWorkerResponse(calculationResponse) {
72
+ if (calculationResponse.error) return { error: calculationResponse.error };
73
+ const { challenge, difficulty, discriminantSizeBits, solution } = calculationResponse.result;
74
+ return {
75
+ result: {
76
+ challenge: challenge.toString('hex'),
77
+ difficulty,
78
+ discriminantSizeBits,
79
+ solution: solution.toString('hex')
80
+ }
81
+ };
82
+ }
83
+ } else {
84
+ const { workerData } = await import('worker_threads');
85
+ const workerPort = workerData.port;
86
+
87
+ workerPort.on('message', async (calculationRequest) => {
88
+ workerPort.postMessage(await solveVdfChallenge(calculationRequest.challenge, calculationRequest.difficulty, calculationRequest.discriminantSizeBits));
89
+ });
90
+ }