trac-msb 0.2.26 → 0.3.0-beta.2

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 +121 -0
  10. package/rpc/routes/v1.js +12 -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 +1803 -159
  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 +280 -67
  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,226 @@
1
+ import V1EpochProofProposalRequest from "../validators/V1EpochProofProposalRequest.js";
2
+ import V1EpochProofProposalApproval from "../validators/V1EpochProofProposalApproval.js";
3
+ import { getResultCode } from "../V1ConsensusProtocolError.js"
4
+ import { ConsensusResultCode, CustomEventType } from "../../../../../../utils/constants.js";
5
+ import { consensusMessageFactory } from "../../../../../../messages/consensus/v1/consensusMessageFactory.js";
6
+ import { bufferToAddress } from "../../../../../state/utils/address.js"
7
+ import ConnectionOperationHandler from "../../../shared/ConnectionOperationHandler.js";
8
+ import { publicKeyToAddress } from "../../../../../../utils/helpers.js";
9
+
10
+
11
+ class V1EpochProofProposalOperationHandler extends ConnectionOperationHandler {
12
+ #proofProposalRequestValidator;
13
+ #proofProposalApprovalValidator;
14
+ #wallet;
15
+ #state;
16
+ #connectionPolicy;
17
+
18
+ constructor(state, wallet, config, connectionPolicy) {
19
+ super(config)
20
+ this.#state = state;
21
+ this.#wallet = wallet;
22
+ this.#connectionPolicy = connectionPolicy;
23
+ this.#proofProposalRequestValidator = new V1EpochProofProposalRequest(config, state);
24
+ this.#proofProposalApprovalValidator = new V1EpochProofProposalApproval(config, state);
25
+ }
26
+
27
+ /**
28
+ * Handles a leader's consensus v1 epoch proof proposal from the minion side.
29
+ * @param {object} message Decoded consensus v1 message containing `proof_proposal` and `session_id`.
30
+ * @param {object} connection Peer connection context used by the request validator.
31
+ * @param protocolSession Protocol session context used by the request validator.
32
+ * @returns {Promise<void>} Resolves after responding, unless the consensus session is closed or the peer is banned.
33
+ */
34
+ async handleRequest(message, connection, protocolSession) {
35
+ const eventContext = this.#buildRequestEventContext(message, connection);
36
+ this.#emitEvent(CustomEventType.EPOCH_PROPOSAL_RECEIVED, eventContext);
37
+
38
+ let resultCode = ConsensusResultCode.OK;
39
+ let validationError;
40
+ let proofProposal;
41
+ try {
42
+ await this.#proofProposalRequestValidator.validate(message, connection);
43
+ proofProposal = message.proof_proposal;
44
+ this.#emitEvent(CustomEventType.EPOCH_PROPOSAL_VALIDATION_SUCCESS, {
45
+ ...eventContext,
46
+ resultCode,
47
+ proofProposal
48
+ });
49
+ } catch (e) {
50
+ validationError = e;
51
+ resultCode = getResultCode(e);
52
+ this.#emitEvent(CustomEventType.EPOCH_PROPOSAL_VALIDATION_FAILURE, {
53
+ ...eventContext,
54
+ resultCode,
55
+ error: validationError
56
+ });
57
+ }
58
+ finally {
59
+ if (!this.#connectionPolicy.requestPeerBan(connection, validationError)) {
60
+ await this.#sendEpochProofProposalApprovalResponse(
61
+ message?.session_id,
62
+ connection,
63
+ protocolSession,
64
+ message,
65
+ resultCode
66
+ );
67
+ }
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Handles a minion's consensus v1 epoch proof proposal approval from the requester side.
73
+ *
74
+ * Failure events include `error` only for locally detected validation failures;
75
+ * authenticated peer rejections carry their result code without an error.
76
+ *
77
+ * @param {object} message Decoded consensus v1 message containing `proof_proposal_response`.
78
+ * @param {object} connection Peer connection context used by the response validator.
79
+ * @param _protocolSession Protocol session context used by the response validator.
80
+ * @param {object} proofProposal Original proof proposal used by the response validator.
81
+ * @returns {Promise<{resultCode: number, approval?: object}>} Approval handling outcome with a ConsensusResultCode value.
82
+ */
83
+
84
+ async handleApproval(
85
+ message,
86
+ connection,
87
+ _protocolSession,
88
+ proofProposal
89
+ ) {
90
+ const eventContext = this.#buildApprovalEventContext(message, connection, proofProposal);
91
+ this.#emitEvent(CustomEventType.EPOCH_PROPOSAL_APPROVAL_RECEIVED, eventContext); // NOTE: Maybe not needed. Investigate. For now, this will be only a placeholder
92
+
93
+ let result;
94
+ try {
95
+ result = await this.#proofProposalApprovalValidator.validate(message, connection, proofProposal);
96
+ } catch (error) {
97
+ const resultCode = getResultCode(error);
98
+ this.#emitEvent(CustomEventType.EPOCH_PROPOSAL_APPROVAL_FAILURE, {
99
+ ...eventContext,
100
+ resultCode,
101
+ error: error
102
+ });
103
+ this.#connectionPolicy.requestPeerBan(connection, error);
104
+ return { resultCode };
105
+ }
106
+
107
+ const event = result.resultCode === ConsensusResultCode.OK
108
+ ? CustomEventType.EPOCH_PROPOSAL_APPROVAL_SUCCESS
109
+ : CustomEventType.EPOCH_PROPOSAL_APPROVAL_FAILURE;
110
+
111
+ this.#emitEvent(event, {
112
+ ...eventContext,
113
+ ...result
114
+ });
115
+ return result;
116
+ }
117
+
118
+ #buildRequestEventContext(message, connection) {
119
+ const remotePublicKey = connection?.remotePublicKey;
120
+
121
+ return {
122
+ message,
123
+ connection,
124
+ sessionId: message?.session_id,
125
+ remotePublicKey,
126
+ };
127
+ }
128
+
129
+ // TODO: This function is mostly copy-past from the one above. Refactor
130
+ #buildApprovalEventContext(message, connection, proofProposal) {
131
+ const remotePublicKey = connection?.remotePublicKey;
132
+
133
+ return {
134
+ message,
135
+ connection,
136
+ sessionId: message?.session_id,
137
+ remotePublicKey,
138
+ proofProposal
139
+ };
140
+ }
141
+
142
+ #emitEvent(eventName, context) {
143
+ try {
144
+ this.#state.emit(eventName, context);
145
+ } catch (error) {
146
+ this.displayError(`failed to emit ${eventName}`, context?.remotePublicKey, error);
147
+ }
148
+ }
149
+
150
+ async #buildProofProposalApproval(sessionId, proofProposal, resultCode) {
151
+ const proposer = bufferToAddress(proofProposal.proposer, this.config.addressPrefix);
152
+
153
+ // TODO: In here we are basically getting some fields represented as buffers from
154
+ // the received proofProposal, converting them to numbers, just to convert them
155
+ // back to buffers internally. This should be optimized
156
+ return await consensusMessageFactory(this.#wallet, this.config).buildProofProposalResponse(
157
+ sessionId,
158
+ proofProposal.network_id.readUInt16BE(0),
159
+ proofProposal.epoch.readBigUInt64BE(0),
160
+ proofProposal.previous_epoch_record_hash,
161
+ proposer,
162
+ proofProposal.difficulty,
163
+ proofProposal.discriminant_bit_size,
164
+ proofProposal.proof,
165
+ proofProposal.signature,
166
+ resultCode,
167
+ this.#wallet.address
168
+ );
169
+ }
170
+
171
+ async #buildProofProposalRejection(sessionId, resultCode) {
172
+ return await consensusMessageFactory(this.#wallet, this.config).buildProofProposalRejectionResponse(
173
+ sessionId,
174
+ resultCode
175
+ );
176
+ }
177
+
178
+ #isValidResponseSessionId(sessionId) {
179
+ return typeof sessionId === 'string' && sessionId.length > 0 && sessionId.length <= 64;
180
+ }
181
+
182
+ async #sendEpochProofProposalApprovalResponse(
183
+ messageId,
184
+ connection,
185
+ protocolSession,
186
+ message,
187
+ resultCode
188
+ ) {
189
+ try {
190
+ if (protocolSession.closed) return;
191
+ if (!this.#isValidResponseSessionId(messageId)) {
192
+ const sender = publicKeyToAddress(connection.remotePublicKey, this.config);
193
+ this.#connectionPolicy.handleInvalidMessage(protocolSession, `${this.constructor.name}: invalid Consensus V1 message session_id, sender: ${sender}`);
194
+ return;
195
+ }
196
+
197
+ const response = resultCode === ConsensusResultCode.OK
198
+ ? await this.#buildProofProposalApproval(
199
+ messageId,
200
+ message.proof_proposal,
201
+ resultCode,
202
+ )
203
+ : await this.#buildProofProposalRejection(
204
+ messageId,
205
+ resultCode
206
+ );
207
+
208
+ if (!protocolSession.closed) protocolSession.sendAndForget(response);
209
+
210
+ } catch (error) {
211
+ this.displayError(
212
+ "failed to build/send response to sender",
213
+ connection.remotePublicKey,
214
+ error
215
+ );
216
+ }
217
+ }
218
+
219
+ displayError(step, senderPublicKey, error) {
220
+ const sender = publicKeyToAddress(senderPublicKey, this.config);
221
+ this.#connectionPolicy.handleLocalError(`${this.constructor.name}: Consensus V1 message ${step}, sender: ${sender}: ${error?.message ?? 'Unexpected error'}`);
222
+ }
223
+
224
+ }
225
+
226
+ export default V1EpochProofProposalOperationHandler;
@@ -0,0 +1,192 @@
1
+ import Validator from 'fastest-validator';
2
+ import {
3
+ HASH_BYTE_LENGTH,
4
+ PUBLIC_KEY_LENGTH,
5
+ CONSENSUS_REQUEST_ID_MAX_LENGTH,
6
+ CONSENSUS_SESSION_ID_MAX_LENGTH,
7
+ ConsensusOperationType,
8
+ SIGNATURE_BYTE_LENGTH,
9
+ ConsensusResultCode,
10
+ NETWORK_ID_BYTE_LENGTH,
11
+ EPOCH_BYTE_LENGTH,
12
+ VDF_DIFFICULTY_SIZE,
13
+ VDF_DISCRIMINANT_SIZE
14
+ } from '../../../../../../utils/constants.js';
15
+ import { EPOCH_APPENDER_SELECTION_VERSION, EpochAppenderVoteStatus } from '../../../../../consensus/epochAppenderSelection/epochAppenderSelectionState.js';
16
+ import {
17
+ compileBufferRule,
18
+ validateSelectionCounter,
19
+ validateProofProposalLength,
20
+ validateProofProposalApprovalPresence,
21
+ } from './consensusValidationSchemaHelpers.js';
22
+
23
+ const ALLOWED_RESULT_CODES = Object.values(ConsensusResultCode);
24
+
25
+ class ConsensusValidationSchema {
26
+ #config;
27
+ #validator;
28
+ #validateConsensusV1ProofProposalSchema;
29
+ #validateConsensusV1ProposalApprovalSchema;
30
+ #validateEpochAppendRequestSchema;
31
+ #validateEpochAppendReplySchema;
32
+ #epochAppendIntentSchema;
33
+
34
+ constructor(config) {
35
+ this.#config = config;
36
+ this.#validator = new Validator({
37
+ useNewCustomCheckerFunction: true,
38
+ messages: {
39
+ buffer: "The '{field}' field must be a Buffer! Actual: {actual}",
40
+ bufferLength: "The '{field}' field must be a Buffer with length {expected}! Actual: {actual}",
41
+ bufferMinLength: "The '{field}' field must be a Buffer with min length {expected}! Actual: {actual}",
42
+ bufferMaxLength: "The '{field}' field must be a Buffer with max length {expected}! Actual: {actual}",
43
+ nonZeroBuffer: "The '{field}' field must not be an empty or zero-filled Buffer!",
44
+ emptyBuffer: "The '{field}' field must not be an empty Buffer! Actual: {actual}",
45
+ uint64: "The '{field}' field must be an unsigned 64-bit integer! Actual: {actual}",
46
+ },
47
+ });
48
+ this.#validator.add('buffer', compileBufferRule);
49
+ this.#epochAppendIntentSchema = {
50
+ type: 'object',
51
+ strict: true,
52
+ props: {
53
+ network_id: { type: 'buffer', length: NETWORK_ID_BYTE_LENGTH, required: true },
54
+ bootstrap: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true },
55
+ epoch: { type: 'buffer', length: EPOCH_BYTE_LENGTH, required: true },
56
+ parent_hash: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true },
57
+ membership_context: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true },
58
+ config_hash: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true },
59
+ request_id: { type: 'string', min: 1, max: CONSENSUS_REQUEST_ID_MAX_LENGTH, required: true },
60
+ payload_hash: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true },
61
+ logical_counter: { type: 'buffer', length: EPOCH_BYTE_LENGTH, required: true, custom: validateSelectionCounter },
62
+ requester: { type: 'buffer', length: PUBLIC_KEY_LENGTH, required: true },
63
+ selection_version: { type: 'equal', value: EPOCH_APPENDER_SELECTION_VERSION, required: true },
64
+ },
65
+ };
66
+ this.#validateConsensusV1ProofProposalSchema = this.#compileV1EpochProofProposalRequestSchema();
67
+ this.#validateConsensusV1ProposalApprovalSchema = this.#compileConsensusV1ProposalApprovalSchema();
68
+ this.#validateEpochAppendRequestSchema = this.#compileEpochAppendRequestSchema();
69
+ this.#validateEpochAppendReplySchema = this.#compileEpochAppendReplySchema();
70
+ }
71
+
72
+ #compileV1EpochProofProposalRequestSchema() {
73
+ const schema = {
74
+ $$strict: true,
75
+ type: {
76
+ type: 'number',
77
+ integer: true,
78
+ equal: ConsensusOperationType.PROOF_PROPOSAL,
79
+ required: true
80
+ },
81
+ session_id: { type: 'string', min: 1, max: CONSENSUS_SESSION_ID_MAX_LENGTH, required: true },
82
+ timestamp: { type: 'number', integer: true, min: 1, max: Number.MAX_SAFE_INTEGER, required: true },
83
+ proof_proposal: {
84
+ strict: true,
85
+ type: 'object',
86
+ props: {
87
+ network_id: { type: 'buffer', length: NETWORK_ID_BYTE_LENGTH, required: true },
88
+ epoch: { type: 'buffer', length: EPOCH_BYTE_LENGTH, required: true },
89
+ previous_epoch_record_hash: { type: 'buffer', length: HASH_BYTE_LENGTH, required: true },
90
+ proposer: { type: 'buffer', length: this.#config.addressLength, required: true },
91
+ difficulty: { type: 'buffer', length: VDF_DIFFICULTY_SIZE, required: true },
92
+ discriminant_bit_size: { type: 'buffer', length: VDF_DISCRIMINANT_SIZE, required: true },
93
+ proof: { type: 'buffer', required: true },
94
+ signature: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true },
95
+ },
96
+ custom: validateProofProposalLength,
97
+ },
98
+ };
99
+ return this.#validator.compile(schema);
100
+ }
101
+
102
+ validateConsensusV1ProofProposal(operation) {
103
+ return this.#validateConsensusV1ProofProposalSchema(operation) === true;
104
+ }
105
+
106
+ #compileConsensusV1ProposalApprovalSchema() {
107
+ const schema = {
108
+ $$strict: true,
109
+ type: {
110
+ type: 'number',
111
+ integer: true,
112
+ equal: ConsensusOperationType.PROOF_PROPOSAL_APPROVAL,
113
+ required: true
114
+ },
115
+ session_id: { type: 'string', min: 1, max: CONSENSUS_SESSION_ID_MAX_LENGTH, required: true },
116
+ timestamp: { type: 'number', integer: true, min: 1, max: Number.MAX_SAFE_INTEGER, required: true },
117
+ proof_proposal_response: {
118
+ strict: true,
119
+ type: 'object',
120
+ props: {
121
+ result: { type: 'enum', values: ALLOWED_RESULT_CODES, required: true },
122
+ approval: {
123
+ strict: true,
124
+ type: 'object',
125
+ optional: true,
126
+ props: {
127
+ approver: { type: 'buffer', length: this.#config.addressLength, required: true },
128
+ approval_sig: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true },
129
+ }
130
+ },
131
+ response_sig: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true },
132
+ },
133
+ custom: validateProofProposalApprovalPresence,
134
+ },
135
+ };
136
+ return this.#validator.compile(schema);
137
+ }
138
+
139
+ validateV1EpochProofProposalResponse(operation) {
140
+ return this.#validateConsensusV1ProposalApprovalSchema(operation) === true;
141
+ }
142
+
143
+ #compileEpochAppendRequestSchema() {
144
+ const schema = {
145
+ $$strict: true,
146
+ type: { type: 'number', integer: true, equal: ConsensusOperationType.REQUEST, required: true },
147
+ session_id: { type: 'string', min: 1, max: CONSENSUS_SESSION_ID_MAX_LENGTH, required: true },
148
+ timestamp: { type: 'number', integer: true, min: 1, max: Number.MAX_SAFE_INTEGER, required: true },
149
+ request: {
150
+ type: 'object',
151
+ strict: true,
152
+ props: {
153
+ intent: this.#epochAppendIntentSchema,
154
+ signature: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true },
155
+ },
156
+ },
157
+ };
158
+ return this.#validator.compile(schema);
159
+ }
160
+
161
+ validateEpochAppendRequest(operation) {
162
+ return this.#validateEpochAppendRequestSchema(operation) === true;
163
+ }
164
+
165
+ #compileEpochAppendReplySchema() {
166
+ const schema = {
167
+ $$strict: true,
168
+ type: { type: 'number', integer: true, equal: ConsensusOperationType.REPLY, required: true },
169
+ session_id: { type: 'string', min: 1, max: CONSENSUS_SESSION_ID_MAX_LENGTH, required: true },
170
+ timestamp: { type: 'number', integer: true, min: 1, max: Number.MAX_SAFE_INTEGER, required: true },
171
+ reply: {
172
+ type: 'object',
173
+ strict: true,
174
+ props: {
175
+ intent: this.#epochAppendIntentSchema,
176
+ signature: { type: 'buffer', length: SIGNATURE_BYTE_LENGTH, required: true },
177
+ responder: { type: 'buffer', length: PUBLIC_KEY_LENGTH, required: true },
178
+ vote_status: { type: 'enum', values: Object.values(EpochAppenderVoteStatus), required: true },
179
+ observed_counter: { type: 'buffer', length: EPOCH_BYTE_LENGTH, required: true, custom: validateSelectionCounter },
180
+ vote: this.#epochAppendIntentSchema,
181
+ },
182
+ },
183
+ };
184
+ return this.#validator.compile(schema);
185
+ }
186
+
187
+ validateEpochAppendReply(operation) {
188
+ return this.#validateEpochAppendReplySchema(operation) === true;
189
+ }
190
+ }
191
+
192
+ export default ConsensusValidationSchema;