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.
- package/SECURITY.md +2 -2
- package/cli/commandHandler.js +317 -20
- package/cli/handlers.js +9 -1
- package/cli/interactive.js +4 -3
- package/cli/tokenSupplyAudit.js +90 -0
- package/msb.mjs +1 -0
- package/package.json +15 -6
- package/rpc/create_server.js +12 -3
- package/rpc/handlers.js +103 -0
- package/rpc/routes/v1.js +8 -0
- package/src/codecs/apply/applyOperationCodec.js +334 -0
- package/src/codecs/apply/applyOperations.generated.cjs +6380 -0
- package/src/codecs/consensus/v1/consensusV1.generated.cjs +3508 -0
- package/src/codecs/consensus/v1/consensusV1OperationCodec.js +161 -0
- package/src/codecs/consensus/v1/vdfConfigCodec.js +83 -0
- package/src/{utils/protobuf → codecs/network/v1}/networkV1.generated.cjs +664 -393
- package/src/codecs/network/v1/networkV1OperationCodec.js +25 -0
- package/src/codecs/protobufRuntime.cjs +95 -0
- package/src/codecs/state/escrowEntryCodec.js +45 -0
- package/src/codecs/state/state.generated.cjs +659 -0
- package/src/config/args.js +0 -1
- package/src/config/config.js +41 -7
- package/src/config/env.js +33 -9
- package/src/core/consensus/epochAppenderSelection/EpochAppenderSelectionError.js +55 -0
- package/src/core/consensus/epochAppenderSelection/EpochAppenderSelectionOperations.js +118 -0
- package/src/core/consensus/epochAppenderSelection/EpochAppenderSelector.js +1042 -0
- package/src/core/consensus/epochAppenderSelection/createEpochAppenderSelector.js +23 -0
- package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionLedgerReader.js +274 -0
- package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionState.js +488 -0
- package/src/core/consensus/epochAppenderSelection/epochAppenderSelectionStorage.js +93 -0
- package/src/core/consensus/quorum.js +11 -0
- package/src/core/consensus/services/EpochCoordinationRound.js +839 -0
- package/src/core/consensus/services/EpochCoordinatorOperations.js +211 -0
- package/src/core/consensus/services/EpochCoordinatorService.js +335 -0
- package/src/core/consensus/services/EpochRoundListeners.js +116 -0
- package/src/core/consensus/services/EpochStateMachine.js +141 -0
- package/src/core/consensus/services/VDFBare.js +291 -0
- package/src/core/consensus/services/VDFNode.js +111 -0
- package/src/core/consensus/services/VDFProgressWatchdog.js +79 -0
- package/src/core/consensus/services/VDFService.js +87 -0
- package/src/core/consensus/services/VDFServiceManager.js +147 -0
- package/src/core/consensus/services/createVDFService.js +16 -0
- package/src/core/consensus/services/vdf-guardian.js +32 -0
- package/src/core/consensus/services/vdf-worker.js +90 -0
- package/src/core/network/Network.js +327 -238
- package/src/core/network/protocols/consensus/IndexerMessages.js +72 -0
- package/src/core/network/protocols/consensus/v1/ConsensusV1ConnectionPolicy.js +57 -0
- package/src/core/network/protocols/consensus/v1/ConsensusV1MessageRouter.js +147 -0
- package/src/core/network/protocols/consensus/v1/ConsensusV1Protocol.js +72 -0
- package/src/core/network/protocols/consensus/v1/IndexerPendingRequestService.js +108 -0
- package/src/core/network/protocols/consensus/v1/V1ConsensusProtocolError.js +29 -0
- package/src/core/network/protocols/consensus/v1/handlers/V1EpochAppendOperationHandler.js +68 -0
- package/src/core/network/protocols/consensus/v1/handlers/V1EpochProofProposalOperationHandler.js +226 -0
- package/src/core/network/protocols/consensus/v1/validators/ConsensusValidationSchema.js +192 -0
- package/src/core/network/protocols/consensus/v1/validators/V1BaseConsensusOperation.js +428 -0
- package/src/core/network/protocols/consensus/v1/validators/V1EpochAppendReply.js +47 -0
- package/src/core/network/protocols/consensus/v1/validators/V1EpochAppendRequest.js +17 -0
- package/src/core/network/protocols/consensus/v1/validators/V1EpochProofProposalApproval.js +116 -0
- package/src/core/network/protocols/consensus/v1/validators/V1EpochProofProposalRequest.js +152 -0
- package/src/core/network/protocols/consensus/v1/validators/consensusValidationSchemaHelpers.js +145 -0
- package/src/core/network/protocols/shared/ConnectionOperationHandler.js +27 -0
- package/src/core/network/protocols/{NetworkMessages.js → validators/ValidatorMessages.js} +24 -14
- package/src/core/network/protocols/{ProtocolSession.js → validators/ValidatorProtocolSession.js} +22 -25
- package/src/core/network/protocols/{legacy/NetworkMessageRouter.js → validators/legacy/ValidatorLegacyMessageRouter.js} +6 -6
- package/src/core/network/protocols/{LegacyProtocol.js → validators/legacy/ValidatorLegacyProtocol.js} +9 -7
- package/src/core/network/protocols/{legacy → validators/legacy}/handlers/BaseStateOperationHandler.js +1 -1
- package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyGetRequestHandler.js +5 -5
- package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyRoleOperationHandler.js +5 -5
- package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacySubnetworkOperationHandler.js +5 -5
- package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyTransferOperationHandler.js +5 -5
- package/src/core/network/protocols/{ProtocolInterface.js → validators/shared/ValidatorProtocolInterface.js} +5 -5
- package/src/core/network/protocols/{shared → validators/shared}/validators/PartialBootstrapDeploymentValidator.js +1 -1
- package/src/core/network/protocols/validators/shared/validators/PartialHtlcValidator.js +325 -0
- package/src/core/network/protocols/{shared → validators/shared}/validators/PartialOperationValidator.js +44 -21
- package/src/core/network/protocols/{shared → validators/shared}/validators/PartialRoleAccessValidator.js +3 -3
- package/src/core/network/protocols/{shared → validators/shared}/validators/PartialTransactionValidator.js +3 -3
- package/src/core/network/protocols/{shared → validators/shared}/validators/PartialTransferValidator.js +4 -4
- package/src/core/network/protocols/{v1 → validators/v1}/V1ProtocolError.js +1 -1
- package/src/core/network/{services/PendingRequestService.js → protocols/validators/v1/ValidatorPendingRequestService.js} +19 -82
- package/src/core/network/protocols/{v1/NetworkMessageRouter.js → validators/v1/ValidatorV1MessageRouter.js} +9 -9
- package/src/core/network/protocols/{V1Protocol.js → validators/v1/ValidatorV1Protocol.js} +10 -8
- package/src/core/network/protocols/{connectionPolicies.js → validators/v1/connectionPolicies.js} +1 -1
- package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1BaseOperationHandler.js +6 -23
- package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1BroadcastTransactionOperationHandler.js +14 -9
- package/src/core/network/protocols/{v1 → validators/v1}/handlers/V1LivenessOperationHandler.js +5 -4
- package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionErrorMapper.js +3 -3
- package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionOperationStrategies.js +44 -1
- package/src/core/network/protocols/{v1 → validators/v1}/handlers/broadcastTransaction/BroadcastTransactionPayloadUtils.js +1 -1
- package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BaseOperation.js +19 -15
- package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BroadcastTransactionRequest.js +2 -2
- package/src/core/network/protocols/{v1 → validators/v1}/validators/V1BroadcastTransactionResponse.js +34 -18
- package/src/core/network/protocols/{v1 → validators/v1}/validators/V1ValidationSchema.js +3 -3
- package/src/core/network/services/IndexerConnectionManager.js +88 -0
- package/src/core/network/services/TransactionPoolService.js +11 -18
- package/src/core/network/services/TransactionRateLimiterService.js +1 -1
- package/src/core/network/services/ValidatorConnectionManager.js +163 -0
- package/src/core/network/services/{MessageOrchestrator.js → ValidatorMessageOrchestrator.js} +34 -42
- package/src/core/network/services/ValidatorObserverService.js +21 -36
- package/src/core/network/shared/BasePendingRequestService.js +67 -0
- package/src/core/network/shared/PeerConnectionManager.js +185 -0
- package/src/core/state/State.js +1789 -173
- package/src/core/state/StateEventQueue.js +69 -0
- package/src/core/state/utils/address.js +10 -6
- package/src/core/state/utils/epochProof.js +109 -0
- package/src/core/state/utils/escrowEntry.js +178 -0
- package/src/core/state/validators/StateValidationSchema.js +757 -0
- package/src/core/state/validators/stateValidationRules.js +312 -0
- package/src/index.js +255 -65
- package/src/messages/consensus/v1/ConsensusMessageBuilder.js +368 -0
- package/src/messages/consensus/v1/ConsensusMessageDirector.js +142 -0
- package/src/messages/consensus/v1/consensusMessageFactory.js +12 -0
- package/src/messages/consensus/v1/epochAppendMessage.js +58 -0
- package/src/messages/network/v1/NetworkMessageBuilder.js +15 -7
- package/src/messages/state/ApplyStateMessageBuilder.js +499 -13
- package/src/messages/state/ApplyStateMessageDirector.js +261 -2
- package/src/utils/StateMachine.js +125 -0
- package/src/utils/applyOperations.js +45 -2
- package/src/utils/buffer.js +239 -59
- package/src/utils/consensusConfig.js +76 -0
- package/src/utils/constants.js +174 -73
- package/src/utils/helpers.js +0 -25
- package/src/utils/htlcLock.js +122 -0
- package/src/utils/logger.js +10 -4
- package/src/utils/migrationUtils.js +2 -1
- package/src/utils/normalizers.js +113 -0
- package/src/utils/scheduler/SchedulableService.js +107 -0
- package/src/utils/{Scheduler.js → scheduler/Scheduler.js} +56 -17
- package/src/core/network/services/ConnectionManager.js +0 -406
- package/src/utils/check.js +0 -525
- package/src/utils/protobuf/applyOperations.cjs +0 -1373
- package/src/utils/protobuf/operationHelpers.js +0 -81
- /package/src/core/network/protocols/{legacy → validators/legacy}/handlers/LegacyResponseHandler.js +0 -0
- /package/src/core/network/protocols/{legacy → validators/legacy}/validators/ValidatorResponse.js +0 -0
- /package/src/core/network/protocols/{legacy → validators/legacy}/validators/base/BaseResponse.js +0 -0
- /package/src/core/network/protocols/{v1 → validators/v1}/validators/V1LivenessRequest.js +0 -0
- /package/src/core/network/protocols/{v1 → validators/v1}/validators/V1LivenessResponse.js +0 -0
package/src/utils/buffer.js
CHANGED
|
@@ -5,110 +5,290 @@ export const ZERO_WK = b4a.alloc(32, 0); // 32 bytes of zeroes, used as a placeh
|
|
|
5
5
|
export const NULL_BUFFER = b4a.alloc(0) // null buffer (single byte of 0)
|
|
6
6
|
|
|
7
7
|
const isUInt32 = (n) => { return Number.isInteger(n) && n >= 1 && n <= 0xFFFFFFFF; }
|
|
8
|
+
const MAX_UINT64 = 0xFFFFFFFFFFFFFFFFn;
|
|
8
9
|
|
|
9
10
|
export function isBufferValid(key, size) {
|
|
10
11
|
return b4a.isBuffer(key) && key.length === size;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
export const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
export const bigIntToBuffer = bigIntTo16ByteBuffer
|
|
15
|
+
|
|
16
|
+
export function deepCopyBuffer(buffer) {
|
|
17
|
+
if (!buffer) return null;
|
|
18
|
+
const copy = b4a.alloc(buffer.length);
|
|
19
|
+
buffer.copy(copy);
|
|
20
|
+
return copy;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function timestampToBuffer(timestamp) {
|
|
24
|
+
return uint64ToBuffer(timestamp);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function idToBuffer(id) {
|
|
28
|
+
if (typeof id !== 'string') {
|
|
29
|
+
throw new Error('id must be a string');
|
|
20
30
|
}
|
|
31
|
+
return b4a.from(id, 'utf8');
|
|
21
32
|
}
|
|
22
33
|
|
|
23
|
-
export const createMessage = (...args) => {
|
|
24
34
|
|
|
25
|
-
|
|
35
|
+
export function encodeCapabilities(capabilities) {
|
|
36
|
+
if (!Array.isArray(capabilities)) {
|
|
37
|
+
throw new Error('Capabilities must be an array');
|
|
38
|
+
}
|
|
39
|
+
const validCapabilities = capabilities.map((capability) => {
|
|
40
|
+
if (typeof capability !== 'string') {
|
|
41
|
+
throw new Error('Capabilities array must contain only strings');
|
|
42
|
+
}
|
|
43
|
+
return capability;
|
|
44
|
+
});
|
|
26
45
|
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
46
|
+
const parts = [];
|
|
47
|
+
for (const capability of validCapabilities.slice().sort()) {
|
|
48
|
+
const capabilityBuffer = b4a.from(capability, 'utf8');
|
|
49
|
+
const bufferLen = b4a.allocUnsafe(2);
|
|
50
|
+
bufferLen.writeUInt16BE(capabilityBuffer.length, 0);
|
|
51
|
+
parts.push(bufferLen, capabilityBuffer);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return parts.length ? b4a.concat(parts) : NULL_BUFFER;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function toHex(publicKey) {
|
|
58
|
+
return b4a.isBuffer(publicKey) ? b4a.toString(publicKey, 'hex') : publicKey;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function uint8ToBuffer(value, offset = 0) {
|
|
62
|
+
if (!Number.isInteger(value) || value < 0 || value > 0xFF) {
|
|
63
|
+
throw new Error(`Value must be an unsigned 8-bit integer.`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const buf = b4a.alloc(1);
|
|
67
|
+
buf.writeUInt8(value, offset);
|
|
68
|
+
return buf;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const safeUint8ToBuffer = (value, offset = 0) => {
|
|
72
|
+
try {
|
|
73
|
+
return uint8ToBuffer(value, offset);
|
|
74
|
+
} catch {
|
|
75
|
+
return NULL_BUFFER;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const safeReadUint8 = (buffer, offset = 0) => {
|
|
80
|
+
try {
|
|
81
|
+
if (!b4a.isBuffer(buffer) || buffer.length < offset + 1) {
|
|
82
|
+
return null;
|
|
32
83
|
}
|
|
33
|
-
|
|
84
|
+
return buffer.readUInt8(offset);
|
|
85
|
+
} catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
34
89
|
|
|
35
|
-
|
|
36
|
-
|
|
90
|
+
export function uint16ToBuffer(value, offset = 0) {
|
|
91
|
+
if (!Number.isInteger(value) || value < 0 || value > 0xFFFF) {
|
|
92
|
+
throw new Error(`Value must be an unsigned 16-bit integer.`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const buf = b4a.alloc(2);
|
|
96
|
+
buf.writeUInt16BE(value, offset);
|
|
97
|
+
return buf;
|
|
37
98
|
}
|
|
38
99
|
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
return
|
|
100
|
+
export const safeUint16ToBuffer = (value, offset = 0) => {
|
|
101
|
+
try {
|
|
102
|
+
return uint16ToBuffer(value, offset);
|
|
42
103
|
}
|
|
104
|
+
catch {
|
|
105
|
+
return NULL_BUFFER;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
43
108
|
|
|
44
|
-
|
|
45
|
-
|
|
109
|
+
export const safeReadUint16BE = (buffer, offset = 0) => {
|
|
110
|
+
try {
|
|
111
|
+
if (!b4a.isBuffer(buffer) || buffer.length < offset + 2) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return buffer.readUInt16BE(offset)
|
|
46
115
|
}
|
|
116
|
+
catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
47
120
|
|
|
48
|
-
|
|
49
|
-
|
|
121
|
+
export function uint32ToBuffer(value, offset = 0) {
|
|
122
|
+
if (!Number.isInteger(value) || value < 0 || value > 0xFFFFFFFF) {
|
|
123
|
+
throw new Error(`Value must be an unsigned 32-bit integer.`);
|
|
50
124
|
}
|
|
51
125
|
|
|
52
|
-
|
|
126
|
+
const buf = b4a.alloc(4);
|
|
127
|
+
buf.writeUInt32BE(value, offset);
|
|
128
|
+
return buf;
|
|
53
129
|
}
|
|
54
130
|
|
|
55
|
-
export const
|
|
131
|
+
export const safeWriteUInt32BE = (value, offset = 0) => {
|
|
132
|
+
try {
|
|
133
|
+
return uint32ToBuffer(value, offset);
|
|
134
|
+
} catch {
|
|
135
|
+
return NULL_BUFFER;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
56
138
|
|
|
57
|
-
export
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
139
|
+
export const safeReadUint32BE = (buffer, offset = 0) => {
|
|
140
|
+
try {
|
|
141
|
+
if (!b4a.isBuffer(buffer) || buffer.length < offset + 4) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return buffer.readUInt32BE(offset)
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
62
149
|
}
|
|
63
150
|
|
|
64
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Use BigInt because uint64 values can be larger than Number.MAX_SAFE_INTEGER.
|
|
153
|
+
*/
|
|
154
|
+
// ATTENTION: It was decided to not use BigInt inside the apply function, so we can have more
|
|
155
|
+
// control over the calculations. This function should not be used inside apply(). Use buffer
|
|
156
|
+
// arithmetic (further down this file) instead.
|
|
157
|
+
export function uint64ToBuffer(value) {
|
|
65
158
|
if (typeof value === 'number') {
|
|
66
159
|
if (!Number.isSafeInteger(value) || value < 0) {
|
|
67
|
-
throw new Error(
|
|
160
|
+
throw new Error(`Value must be a non-negative safe integer`);
|
|
68
161
|
}
|
|
69
|
-
value = BigInt(value);
|
|
70
162
|
} else if (typeof value !== 'bigint') {
|
|
71
|
-
throw new Error(
|
|
163
|
+
throw new Error(`Value must be a number or bigint`);
|
|
72
164
|
}
|
|
73
|
-
|
|
74
|
-
|
|
165
|
+
|
|
166
|
+
const uint64Value = typeof value === 'bigint' ? value : BigInt(value);
|
|
167
|
+
|
|
168
|
+
if (uint64Value < 0n) {
|
|
169
|
+
throw new Error(`Value must be a non-negative integer`);
|
|
170
|
+
}
|
|
171
|
+
if (uint64Value > MAX_UINT64) {
|
|
172
|
+
throw new Error(`Value must be an unsigned 64-bit integer`);
|
|
75
173
|
}
|
|
76
174
|
|
|
77
175
|
const buf = b4a.alloc(8);
|
|
78
|
-
buf.writeBigUInt64BE(
|
|
176
|
+
buf.writeBigUInt64BE(uint64Value);
|
|
79
177
|
return buf;
|
|
80
178
|
}
|
|
81
179
|
|
|
82
|
-
|
|
83
|
-
|
|
180
|
+
|
|
181
|
+
export const createMessage = (...args) => {
|
|
182
|
+
|
|
183
|
+
if (args.length === 0) return NULL_BUFFER;
|
|
184
|
+
|
|
185
|
+
const buffers = args.map(arg => {
|
|
186
|
+
if (b4a.isBuffer(arg)) {
|
|
187
|
+
return arg;
|
|
188
|
+
} else if (typeof arg === 'number' && isUInt32(arg)) {
|
|
189
|
+
return safeWriteUInt32BE(arg);
|
|
190
|
+
}
|
|
191
|
+
}).filter(buf => b4a.isBuffer(buf));
|
|
192
|
+
|
|
193
|
+
if (buffers.length === 0) return NULL_BUFFER;
|
|
194
|
+
return b4a.concat(buffers);
|
|
84
195
|
}
|
|
85
196
|
|
|
86
|
-
export function
|
|
87
|
-
if (
|
|
88
|
-
|
|
197
|
+
export function isZeroBuffer(buffer) {
|
|
198
|
+
if (!b4a.isBuffer(buffer)) {
|
|
199
|
+
return false;
|
|
89
200
|
}
|
|
90
|
-
return
|
|
201
|
+
return buffer.every(byte => byte === 0);
|
|
91
202
|
}
|
|
92
203
|
|
|
204
|
+
// Buffer Arithmetic
|
|
93
205
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
206
|
+
/**
|
|
207
|
+
* Increments a fixed-width big-endian unsigned integer buffer by one.
|
|
208
|
+
* The input must contain between 1 and 16 bytes and is not mutated.
|
|
209
|
+
* When enforceLength is provided, the input must contain exactly that
|
|
210
|
+
* number of bytes. Returns null for invalid input, a length mismatch,
|
|
211
|
+
* or an increment that would overflow the buffer's fixed width.
|
|
212
|
+
*
|
|
213
|
+
* @param {Buffer} buffer - The unsigned integer to increment.
|
|
214
|
+
* @param {number|null} [enforceLength=null] - Required input length in bytes.
|
|
215
|
+
* @returns {Buffer|null} A new incremented buffer, or null on failure.
|
|
216
|
+
*/
|
|
217
|
+
export function incrementBuffer(buffer, enforceLength = null) {
|
|
218
|
+
if (!b4a.isBuffer(buffer) ||
|
|
219
|
+
(enforceLength !== null && buffer.length !== enforceLength) ||
|
|
220
|
+
buffer.length === 0 ||
|
|
221
|
+
buffer.length > 16) {
|
|
222
|
+
return null;
|
|
97
223
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
224
|
+
|
|
225
|
+
const result = b4a.from(buffer);
|
|
226
|
+
for (let i = result.length - 1; i >= 0; i--) {
|
|
227
|
+
if (result[i] === 0xFF) {
|
|
228
|
+
result[i] = 0;
|
|
229
|
+
continue;
|
|
101
230
|
}
|
|
102
|
-
return capability;
|
|
103
|
-
});
|
|
104
231
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const capabilityBuffer = b4a.from(capability, 'utf8');
|
|
108
|
-
const bufferLen = b4a.allocUnsafe(2);
|
|
109
|
-
bufferLen.writeUInt16BE(capabilityBuffer.length, 0);
|
|
110
|
-
parts.push(bufferLen, capabilityBuffer);
|
|
232
|
+
result[i]++;
|
|
233
|
+
return result;
|
|
111
234
|
}
|
|
112
235
|
|
|
113
|
-
return
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Converts a big-endian unsigned integer buffer to a numeric string.
|
|
241
|
+
* The input must contain between 1 and 16 bytes.
|
|
242
|
+
*
|
|
243
|
+
* @param {Buffer} buffer - The unsigned integer to convert.
|
|
244
|
+
* @param {'decimal'|'hex'} [encoding='decimal'] - Output encoding.
|
|
245
|
+
* @returns {string} The normalized numeric string.
|
|
246
|
+
* @throws {TypeError} When the input or encoding is invalid.
|
|
247
|
+
*/
|
|
248
|
+
export function toUIntString(buffer, encoding = 'decimal') {
|
|
249
|
+
if (!b4a.isBuffer(buffer) || buffer.length === 0 || buffer.length > 16) {
|
|
250
|
+
throw new TypeError('Input must contain between 1 and 16 bytes.');
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
switch (encoding) {
|
|
254
|
+
case 'hex':
|
|
255
|
+
return buffer.toString('hex').replace(/^0+/, '') || '0';
|
|
256
|
+
case 'decimal': {
|
|
257
|
+
const digits = [0];
|
|
258
|
+
for (const byte of buffer) {
|
|
259
|
+
let carry = byte;
|
|
260
|
+
|
|
261
|
+
for (let i = 0; i < digits.length; i++) {
|
|
262
|
+
const value = digits[i] * 256 + carry;
|
|
263
|
+
digits[i] = value % 10;
|
|
264
|
+
carry = Math.floor(value / 10);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
while (carry > 0) {
|
|
268
|
+
digits.push(carry % 10);
|
|
269
|
+
carry = Math.floor(carry / 10);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return digits.reverse().join('');
|
|
274
|
+
}
|
|
275
|
+
default:
|
|
276
|
+
throw new TypeError("Unsupported encoding. Use 'hex' or 'decimal'.");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Safely converts a big-endian unsigned integer buffer to a numeric string.
|
|
282
|
+
*
|
|
283
|
+
* @param {Buffer} buffer - The unsigned integer to convert.
|
|
284
|
+
* @param {'decimal'|'hex'} [encoding='decimal'] - Output encoding.
|
|
285
|
+
* @returns {string|null} The normalized numeric string, or null for invalid input.
|
|
286
|
+
*/
|
|
287
|
+
export function safeToUIntString(buffer, encoding = 'decimal') {
|
|
288
|
+
try {
|
|
289
|
+
return toUIntString(buffer, encoding);
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
114
294
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { decodeConsensusConfig } from '../codecs/apply/applyOperationCodec.js';
|
|
2
|
+
import { decodeVdfConfig, safeDecodeVdfConfig } from '../codecs/consensus/v1/vdfConfigCodec.js';
|
|
3
|
+
import {
|
|
4
|
+
CONSENSUS_CONFIG_SCHEMA_VERSION_BYTE_LENGTH,
|
|
5
|
+
ConsensusVersion,
|
|
6
|
+
VDF_PROOF_BYTE_LENGTHS,
|
|
7
|
+
} from './constants.js';
|
|
8
|
+
import { isBufferValid, isZeroBuffer, safeReadUint8 } from './buffer.js';
|
|
9
|
+
|
|
10
|
+
// Off-chain helpers. Do not use these in apply or delegate to state/utils:
|
|
11
|
+
// changes here must not change historical state replay.
|
|
12
|
+
|
|
13
|
+
const decodeVdfV1ConfigData = (encodedConfigData) => {
|
|
14
|
+
const decodedConfigData = decodeVdfConfig(encodedConfigData);
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
difficulty: decodedConfigData.difficulty.readUInt32BE(0),
|
|
18
|
+
discriminantBitSize: decodedConfigData.discriminantBitSize.readUInt16BE(0),
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const CONSENSUS_CONFIG_DECODERS = Object.freeze({
|
|
23
|
+
[ConsensusVersion.VDF_V1]: decodeVdfV1ConfigData,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const validateConsensusConfig = (consensusConfig) => {
|
|
27
|
+
if (!isBufferValid(consensusConfig?.sv, CONSENSUS_CONFIG_SCHEMA_VERSION_BYTE_LENGTH)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
switch (safeReadUint8(consensusConfig.sv)) {
|
|
32
|
+
case ConsensusVersion.VDF_V1: {
|
|
33
|
+
const configData = safeDecodeVdfConfig(consensusConfig.cd);
|
|
34
|
+
if (configData === null) return false;
|
|
35
|
+
|
|
36
|
+
return !isZeroBuffer(configData.difficulty) &&
|
|
37
|
+
Object.hasOwn(VDF_PROOF_BYTE_LENGTHS, configData.discriminantBitSize.readUInt16BE(0));
|
|
38
|
+
}
|
|
39
|
+
default:
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Decodes a stored consensus config for off-chain consumers.
|
|
46
|
+
*
|
|
47
|
+
* @param {Buffer} encodedConsensusConfig Encoded consensus config envelope.
|
|
48
|
+
* @returns {{schemaVersion: number, configData: object}} Decoded domain config.
|
|
49
|
+
* @throws {Error} When the envelope, version, or config data is invalid.
|
|
50
|
+
*/
|
|
51
|
+
export const decodeVersionedConsensusConfig = (encodedConsensusConfig) => {
|
|
52
|
+
const consensusConfig = decodeConsensusConfig(encodedConsensusConfig);
|
|
53
|
+
const schemaVersion = consensusConfig.sv.readUInt8(0);
|
|
54
|
+
const decodeConfigData = CONSENSUS_CONFIG_DECODERS[schemaVersion];
|
|
55
|
+
|
|
56
|
+
if (typeof decodeConfigData !== 'function') {
|
|
57
|
+
throw new Error(`Unsupported consensus config schema version: ${schemaVersion}.`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
schemaVersion,
|
|
62
|
+
configData: decodeConfigData(consensusConfig.cd),
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @param {*} encodedConsensusConfig Value expected to contain an encoded config.
|
|
68
|
+
* @returns {{schemaVersion: number, configData: object}|null} Decoded config or null.
|
|
69
|
+
*/
|
|
70
|
+
export const safeDecodeVersionedConsensusConfig = (encodedConsensusConfig) => {
|
|
71
|
+
try {
|
|
72
|
+
return decodeVersionedConsensusConfig(encodedConsensusConfig);
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
};
|