trac-msb 0.2.12 → 0.2.13
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/package.json +9 -4
- package/proto/network/v1/enums/message_type.proto +16 -0
- package/proto/network/v1/enums/result_code.proto +84 -0
- package/proto/network/v1/messages/broadcast_transaction_request.proto +9 -0
- package/proto/network/v1/messages/broadcast_transaction_response.proto +13 -0
- package/proto/network/v1/messages/liveness_request.proto +8 -0
- package/proto/network/v1/messages/liveness_response.proto +11 -0
- package/proto/network/v1/network_message.proto +22 -0
- package/rpc/rpc_services.js +22 -4
- package/scripts/generate-protobufs.js +37 -12
- package/src/config/config.js +26 -5
- package/src/config/env.js +25 -11
- package/src/core/network/Network.js +73 -36
- package/src/core/network/protocols/LegacyProtocol.js +21 -11
- package/src/core/network/protocols/NetworkMessages.js +38 -17
- package/src/core/network/protocols/ProtocolInterface.js +14 -2
- package/src/core/network/protocols/ProtocolSession.js +144 -17
- package/src/core/network/protocols/V1Protocol.js +37 -18
- package/src/core/network/protocols/connectionPolicies.js +88 -0
- package/src/core/network/protocols/legacy/NetworkMessageRouter.js +25 -19
- package/src/core/network/protocols/{shared/handlers/base/BaseOperationHandler.js → legacy/handlers/BaseStateOperationHandler.js} +23 -12
- package/src/core/network/protocols/legacy/handlers/{GetRequestHandler.js → LegacyGetRequestHandler.js} +6 -6
- package/src/core/network/protocols/legacy/handlers/LegacyResponseHandler.js +23 -0
- package/src/core/network/protocols/{shared/handlers/RoleOperationHandler.js → legacy/handlers/LegacyRoleOperationHandler.js} +18 -11
- package/src/core/network/protocols/{shared/handlers/SubnetworkOperationHandler.js → legacy/handlers/LegacySubnetworkOperationHandler.js} +28 -17
- package/src/core/network/protocols/{shared/handlers/TransferOperationHandler.js → legacy/handlers/LegacyTransferOperationHandler.js} +17 -11
- package/src/core/network/protocols/shared/errors/SharedValidatorRejectionError.js +27 -0
- package/src/core/network/protocols/shared/validators/{PartialBootstrapDeployment.js → PartialBootstrapDeploymentValidator.js} +9 -4
- package/src/core/network/protocols/shared/validators/{base/PartialOperation.js → PartialOperationValidator.js} +47 -25
- package/src/core/network/protocols/shared/validators/{PartialRoleAccess.js → PartialRoleAccessValidator.js} +51 -17
- package/src/core/network/protocols/shared/validators/{PartialTransaction.js → PartialTransactionValidator.js} +21 -7
- package/src/core/network/protocols/shared/validators/{PartialTransfer.js → PartialTransferValidator.js} +26 -9
- package/src/core/network/protocols/v1/NetworkMessageRouter.js +91 -7
- package/src/core/network/protocols/v1/V1ProtocolError.js +91 -0
- package/src/core/network/protocols/v1/handlers/V1BaseOperationHandler.js +65 -0
- package/src/core/network/protocols/v1/handlers/V1BroadcastTransactionOperationHandler.js +389 -0
- package/src/core/network/protocols/v1/handlers/V1LivenessOperationHandler.js +87 -0
- package/src/core/network/protocols/v1/validators/V1BaseOperation.js +211 -0
- package/src/core/network/protocols/v1/validators/V1BroadcastTransactionRequest.js +26 -0
- package/src/core/network/protocols/v1/validators/V1BroadcastTransactionResponse.js +276 -0
- package/src/core/network/protocols/v1/validators/V1LivenessRequest.js +15 -0
- package/src/core/network/protocols/v1/validators/V1LivenessResponse.js +17 -0
- package/src/core/network/protocols/v1/validators/V1ValidationSchema.js +210 -0
- package/src/core/network/services/ConnectionManager.js +146 -94
- package/src/core/network/services/MessageOrchestrator.js +151 -27
- package/src/core/network/services/PendingRequestService.js +172 -0
- package/src/core/network/services/TransactionCommitService.js +149 -0
- package/src/core/network/services/TransactionPoolService.js +129 -18
- package/src/core/network/services/TransactionRateLimiterService.js +52 -34
- package/src/core/network/services/ValidatorHealthCheckService.js +127 -0
- package/src/core/network/services/ValidatorObserverService.js +18 -26
- package/src/core/state/State.js +70 -19
- package/src/index.js +5 -4
- package/src/messages/network/v1/NetworkMessageBuilder.js +59 -79
- package/src/messages/network/v1/NetworkMessageDirector.js +16 -50
- package/src/utils/Scheduler.js +0 -8
- package/src/utils/constants.js +71 -5
- package/src/utils/deepEqualApplyPayload.js +40 -0
- package/src/utils/helpers.js +10 -1
- package/src/utils/logger.js +25 -0
- package/src/utils/normalizers.js +38 -0
- package/src/utils/protobuf/networkV1.generated.cjs +2460 -0
- package/src/utils/protobuf/operationHelpers.js +24 -3
- package/tests/acceptance/v1/account/account.test.mjs +8 -2
- package/tests/acceptance/v1/tx/tx.test.mjs +23 -1
- package/tests/acceptance/v1/tx-details/tx-details.test.mjs +34 -6
- package/tests/fixtures/networkV1.fixtures.js +2 -28
- package/tests/helpers/transactionPayloads.mjs +2 -2
- package/tests/unit/messages/network/NetworkMessageBuilder.test.js +239 -79
- package/tests/unit/messages/network/NetworkMessageDirector.test.js +223 -77
- package/tests/unit/network/LegacyNetworkMessageRouter.test.js +54 -0
- package/tests/unit/network/ProtocolSession.test.js +127 -0
- package/tests/unit/network/networkModule.test.js +4 -1
- package/tests/unit/network/services/ConnectionManager.test.js +450 -0
- package/tests/unit/network/services/MessageOrchestrator.test.js +445 -0
- package/tests/unit/network/services/PendingRequestService.test.js +431 -0
- package/tests/unit/network/services/TransactionCommitService.test.js +246 -0
- package/tests/unit/network/services/TransactionPoolService.test.js +489 -0
- package/tests/unit/network/services/TransactionRateLimiterService.test.js +139 -0
- package/tests/unit/network/services/ValidatorHealthCheckService.test.js +115 -0
- package/tests/unit/network/services/services.test.js +17 -0
- package/tests/unit/network/utils/v1TestUtils.js +153 -0
- package/tests/unit/network/v1/NetworkMessageRouterV1.test.js +151 -0
- package/tests/unit/network/v1/V1BaseOperation.test.js +356 -0
- package/tests/unit/network/v1/V1BroadcastTransactionOperationHandler.test.js +129 -0
- package/tests/unit/network/v1/V1BroadcastTransactionRequest.test.js +53 -0
- package/tests/unit/network/v1/V1BroadcastTransactionResponse.test.js +512 -0
- package/tests/unit/network/v1/V1LivenessRequest.test.js +32 -0
- package/tests/unit/network/v1/V1LivenessResponse.test.js +45 -0
- package/tests/unit/network/v1/V1ResultCode.test.js +84 -0
- package/tests/unit/network/v1/V1ValidationSchema.test.js +13 -0
- package/tests/unit/network/v1/connectionPolicies.test.js +49 -0
- package/tests/unit/network/v1/handlers/V1BaseOperationHandler.test.js +284 -0
- package/tests/unit/network/v1/handlers/V1BroadcastTransactionOperationHandler.test.js +794 -0
- package/tests/unit/network/v1/handlers/V1LivenessOperationHandler.test.js +193 -0
- package/tests/unit/network/v1/v1.handlers.test.js +15 -0
- package/tests/unit/network/v1/v1.test.js +19 -0
- package/tests/unit/network/v1/v1ValidationSchema/broadcastTransactionRequest.test.js +119 -0
- package/tests/unit/network/v1/v1ValidationSchema/broadcastTransactionResponse.test.js +136 -0
- package/tests/unit/network/v1/v1ValidationSchema/common.test.js +308 -0
- package/tests/unit/network/v1/v1ValidationSchema/livenessRequest.test.js +90 -0
- package/tests/unit/network/v1/v1ValidationSchema/livenessResponse.test.js +133 -0
- package/tests/unit/unit.test.js +2 -2
- package/tests/unit/utils/deepEqualApplyPayload/deepEqualApplyPayload.test.js +102 -0
- package/tests/unit/utils/protobuf/operationHelpers.test.js +2 -4
- package/tests/unit/utils/utils.test.js +1 -0
- package/.github/workflows/acceptance-tests.yml +0 -38
- package/.github/workflows/lint-pr-title.yml +0 -26
- package/.github/workflows/publish.yml +0 -33
- package/.github/workflows/unit-tests.yml +0 -34
- package/proto/network.proto +0 -74
- package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +0 -37
- package/src/utils/protobuf/network.cjs +0 -840
- package/tests/unit/network/ConnectionManager.test.js +0 -191
package/src/core/state/State.js
CHANGED
|
@@ -40,13 +40,15 @@ import { safeWriteUInt32BE } from '../../utils/buffer.js';
|
|
|
40
40
|
import deploymentEntryUtils from './utils/deploymentEntry.js';
|
|
41
41
|
import { deepCopyBuffer } from '../../utils/buffer.js';
|
|
42
42
|
import { Status } from './utils/transaction.js';
|
|
43
|
-
import
|
|
43
|
+
import remote from 'hypercore/lib/fully-remote-proof.js'
|
|
44
|
+
import PQueue from 'p-queue';
|
|
44
45
|
|
|
45
46
|
const OVERSIZED_BATCH_PENALTY_MULTIPLIER = BATCH_SIZE;
|
|
46
47
|
|
|
47
48
|
// TODO: #addWriter, #removeWriter, #transfer, #transferFeeTxOperation need to be refactored to get in arguments actor's nodeEntries in buffer format.
|
|
48
49
|
|
|
49
50
|
class State extends ReadyResource {
|
|
51
|
+
#writeQueue = new PQueue({ concurrency: 1 });
|
|
50
52
|
#base;
|
|
51
53
|
#bee;
|
|
52
54
|
#store;
|
|
@@ -187,18 +189,6 @@ class State extends ReadyResource {
|
|
|
187
189
|
return !!nodeEntry.isWhitelisted;
|
|
188
190
|
}
|
|
189
191
|
|
|
190
|
-
async isAddressWriter(address) {
|
|
191
|
-
const nodeEntry = await this.getNodeEntry(address);
|
|
192
|
-
if (nodeEntry === null) return false;
|
|
193
|
-
return !!nodeEntry.isWriter;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
async isAddressIndexer(address) {
|
|
197
|
-
const nodeEntry = await this.getNodeEntry(address);
|
|
198
|
-
if (nodeEntry === null) return false;
|
|
199
|
-
return !!nodeEntry.isIndexer;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
192
|
async getIndexersEntry() {
|
|
203
193
|
return Object.values(this.#base.system.indexers);
|
|
204
194
|
}
|
|
@@ -243,7 +233,67 @@ class State extends ReadyResource {
|
|
|
243
233
|
}
|
|
244
234
|
|
|
245
235
|
async append(payload) {
|
|
246
|
-
|
|
236
|
+
return this.#writeQueue.add(() => this.#base.append(payload));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async appendWithProofOfPublication(batch, batchTxHashes) {
|
|
240
|
+
return this.#writeQueue.add(async () => {
|
|
241
|
+
|
|
242
|
+
const core = this.#base.local;
|
|
243
|
+
const end = await this.#base.append(batch);
|
|
244
|
+
const start = end - batch.length;
|
|
245
|
+
const timestamp = new Date();
|
|
246
|
+
const snapshot = core.snapshot(); // consistent view while generating proofs.
|
|
247
|
+
await snapshot.ready();
|
|
248
|
+
// TODO: check state if specific tx has been appened THEN generate a proof.
|
|
249
|
+
try {
|
|
250
|
+
const receipts = [];
|
|
251
|
+
let failedProofs = 0;
|
|
252
|
+
for (let i = 0; i < batch.length; i++) {
|
|
253
|
+
const blockNumber = start + i;
|
|
254
|
+
const completeTx = batch[i];
|
|
255
|
+
const txHash = batchTxHashes[i];
|
|
256
|
+
|
|
257
|
+
let proof = null;
|
|
258
|
+
let proofError = null;
|
|
259
|
+
|
|
260
|
+
// wait:false makes get fail fast (null) instead of waiting for missing data/replication.
|
|
261
|
+
const rawBlock = await snapshot.get(blockNumber, { raw: true, wait: false });
|
|
262
|
+
if (!rawBlock) {
|
|
263
|
+
proofError = `Missing raw block after append (block=${blockNumber}, start=${start}, end=${end})`;
|
|
264
|
+
failedProofs++;
|
|
265
|
+
} else {
|
|
266
|
+
try {
|
|
267
|
+
proof = await remote.proof(snapshot, { index: blockNumber, block: rawBlock });
|
|
268
|
+
} catch (error) {
|
|
269
|
+
proofError = `Proof generation failed (block=${blockNumber}, start=${start}, end=${end}): ${error?.message ?? 'unknown error'}`;
|
|
270
|
+
failedProofs++;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
receipts.push({
|
|
274
|
+
txHash,
|
|
275
|
+
completeTx,
|
|
276
|
+
proof,
|
|
277
|
+
proofError,
|
|
278
|
+
timestamp,
|
|
279
|
+
blockNumber
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
if (failedProofs > 0) {
|
|
283
|
+
console.error(`appendWithProof completed with ${failedProofs} proof failures (batch=${batch.length})`);
|
|
284
|
+
}
|
|
285
|
+
return receipts;
|
|
286
|
+
} finally {
|
|
287
|
+
await snapshot.close();
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async verifyProofOfPublication(proof) {
|
|
293
|
+
// Valid concern. We currently rely on Hypercore’s internal fully-remote-proof helper, which requires low-level storage access
|
|
294
|
+
const out = await remote.verify(this.#store.storage, proof);
|
|
295
|
+
if (!out) throw new Error('Proof of publication verification failed');
|
|
296
|
+
return out;
|
|
247
297
|
}
|
|
248
298
|
|
|
249
299
|
async getIndexerSequenceState() {
|
|
@@ -264,6 +314,7 @@ class State extends ReadyResource {
|
|
|
264
314
|
return b4a.equals(initialization, safeWriteUInt32BE(0, 0))
|
|
265
315
|
}
|
|
266
316
|
}
|
|
317
|
+
|
|
267
318
|
async getTransactionConfirmedLength(hash) {
|
|
268
319
|
if (!isHexString(hash) || hash.length !== 64) {
|
|
269
320
|
throw new Error("Invalid hash format");
|
|
@@ -1793,9 +1844,9 @@ class State extends ReadyResource {
|
|
|
1793
1844
|
};
|
|
1794
1845
|
|
|
1795
1846
|
/**
|
|
1796
|
-
* Ensure that:
|
|
1797
|
-
* 1) writer key exists in registry (we can not unregister something that was not registered),
|
|
1798
|
-
* 2) matches the one in node entry ,
|
|
1847
|
+
* Ensure that:
|
|
1848
|
+
* 1) writer key exists in registry (we can not unregister something that was not registered),
|
|
1849
|
+
* 2) matches the one in node entry ,
|
|
1799
1850
|
* 3) belongs to the requester - this prevents unauthorized key removal
|
|
1800
1851
|
*/
|
|
1801
1852
|
const writerKeyHasBeenRegistered = await this.#getRegisteredWriterKeyApply(batch, op.rao.iw.toString('hex'))
|
|
@@ -2930,7 +2981,7 @@ class State extends ReadyResource {
|
|
|
2930
2981
|
batch,
|
|
2931
2982
|
node
|
|
2932
2983
|
);
|
|
2933
|
-
|
|
2984
|
+
|
|
2934
2985
|
// TODO: cover next 4 guards below with tests
|
|
2935
2986
|
if (transferFeeTxOperationResult === null) {
|
|
2936
2987
|
this.#safeLogApply(OperationType.TX, "Fee transfer operation failed completely.", node.from.key);
|
|
@@ -3388,7 +3439,7 @@ class State extends ReadyResource {
|
|
|
3388
3439
|
|
|
3389
3440
|
/**
|
|
3390
3441
|
* Retrieves the address assigned to a given writing key from the registry.
|
|
3391
|
-
*
|
|
3442
|
+
*
|
|
3392
3443
|
* @param {Object} batch - The current Hyperbee batch instance used for reading state.
|
|
3393
3444
|
* @param {string} writingKey - The writing key in hex string format.
|
|
3394
3445
|
* @returns {Buffer|null} The address buffer assigned to the writing key, or null if not registered.
|
package/src/index.js
CHANGED
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
getLicenseCountCommand
|
|
45
45
|
} from "./utils/cliCommands.js";
|
|
46
46
|
import {safeEncodeApplyOperation} from "./utils/protobuf/operationHelpers.js";
|
|
47
|
+
import {Config} from "./config/config.js";
|
|
47
48
|
|
|
48
49
|
export class MainSettlementBus extends ReadyResource {
|
|
49
50
|
#store;
|
|
@@ -303,7 +304,7 @@ export class MainSettlementBus extends ReadyResource {
|
|
|
303
304
|
const success = await this.broadcastPartialTransaction(adminRecoveryMessage);
|
|
304
305
|
|
|
305
306
|
if (!success) {
|
|
306
|
-
throw new Error("Failed to broadcast transaction
|
|
307
|
+
throw new Error("Failed to broadcast transaction. Try again later.");
|
|
307
308
|
}
|
|
308
309
|
|
|
309
310
|
console.info(`Transaction hash: ${adminRecoveryMessage.rao.tx}`);
|
|
@@ -424,7 +425,7 @@ export class MainSettlementBus extends ReadyResource {
|
|
|
424
425
|
const success = await this.broadcastPartialTransaction(assembledMessage);
|
|
425
426
|
|
|
426
427
|
if (!success) {
|
|
427
|
-
throw new Error("Failed to broadcast transaction
|
|
428
|
+
throw new Error("Failed to broadcast transaction. Try again later.");
|
|
428
429
|
}
|
|
429
430
|
|
|
430
431
|
console.info(`Transaction hash: ${assembledMessage.rao.tx}`);
|
|
@@ -458,7 +459,7 @@ export class MainSettlementBus extends ReadyResource {
|
|
|
458
459
|
const success = await this.broadcastPartialTransaction(assembledMessage);
|
|
459
460
|
|
|
460
461
|
if (!success) {
|
|
461
|
-
throw new Error("Failed to broadcast transaction
|
|
462
|
+
throw new Error("Failed to broadcast transaction. Try again later.");
|
|
462
463
|
}
|
|
463
464
|
|
|
464
465
|
console.info(`Transaction hash: ${assembledMessage.rao.tx}`);
|
|
@@ -682,7 +683,7 @@ export class MainSettlementBus extends ReadyResource {
|
|
|
682
683
|
const success = await this.broadcastPartialTransaction(payload);
|
|
683
684
|
|
|
684
685
|
if (!success) {
|
|
685
|
-
throw new Error("Failed to broadcast transaction
|
|
686
|
+
throw new Error("Failed to broadcast transaction. Try again later.");
|
|
686
687
|
}
|
|
687
688
|
|
|
688
689
|
console.info(`Transaction hash: ${payload.bdo.tx}`);
|
|
@@ -19,6 +19,8 @@ class NetworkMessageBuilder {
|
|
|
19
19
|
#issuerAddress;
|
|
20
20
|
#resultCode;
|
|
21
21
|
#data;
|
|
22
|
+
#proof;
|
|
23
|
+
#timestamp_ledger;
|
|
22
24
|
#header;
|
|
23
25
|
#payloadKey;
|
|
24
26
|
#body;
|
|
@@ -85,6 +87,9 @@ class NetworkMessageBuilder {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
setData(data) {
|
|
90
|
+
// case when response have to be empty.
|
|
91
|
+
if (data === undefined || data === null) data = b4a.alloc(0);
|
|
92
|
+
|
|
88
93
|
if (!b4a.isBuffer(data)) {
|
|
89
94
|
throw new Error(`Data must be a buffer.`);
|
|
90
95
|
}
|
|
@@ -92,6 +97,30 @@ class NetworkMessageBuilder {
|
|
|
92
97
|
return this;
|
|
93
98
|
}
|
|
94
99
|
|
|
100
|
+
setProof(proof) {
|
|
101
|
+
if (proof === undefined || proof === null) proof = b4a.alloc(0);
|
|
102
|
+
if (!b4a.isBuffer(proof)) {
|
|
103
|
+
throw new Error(`Proof must be a buffer.`);
|
|
104
|
+
}
|
|
105
|
+
this.#proof = proof;
|
|
106
|
+
return this;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
setTimestampLedger(timestamp) {
|
|
110
|
+
if (timestamp === undefined || timestamp === null) {
|
|
111
|
+
this.#timestamp_ledger = null;
|
|
112
|
+
return this;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const value = timestamp instanceof Date ? timestamp.getTime() : timestamp;
|
|
116
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
117
|
+
throw new Error('timestamp must be a non-negative safe integer or Date.');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.#timestamp_ledger = value;
|
|
121
|
+
return this;
|
|
122
|
+
}
|
|
123
|
+
|
|
95
124
|
#setHeader() {
|
|
96
125
|
if (!this.#type) throw new Error('Header requires type to be set');
|
|
97
126
|
if (!this.#id) throw new Error('Header requires id to be set');
|
|
@@ -107,76 +136,6 @@ class NetworkMessageBuilder {
|
|
|
107
136
|
return this;
|
|
108
137
|
}
|
|
109
138
|
|
|
110
|
-
async #buildValidatorConnectionRequestPayload() {
|
|
111
|
-
const issuer = this.#issuerAddress
|
|
112
|
-
if (!isAddressValid(issuer, this.#config.addressPrefix)) {
|
|
113
|
-
throw new Error('Issuer address must be a valid TRAC address');
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (this.#issuerAddress !== this.#wallet.address) {
|
|
117
|
-
throw new Error('Issuer address must be the signer address');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const nonce = PeerWallet.generateNonce();
|
|
121
|
-
const tsBuf = timestampToBuffer(this.#timestamp);
|
|
122
|
-
const idBuf = idToBuffer(this.#id);
|
|
123
|
-
const message = createMessage(
|
|
124
|
-
this.#type,
|
|
125
|
-
idBuf,
|
|
126
|
-
tsBuf,
|
|
127
|
-
addressToBuffer(issuer, this.#config.addressPrefix),
|
|
128
|
-
nonce,
|
|
129
|
-
encodeCapabilities(this.#capabilities),
|
|
130
|
-
);
|
|
131
|
-
const hash = await PeerWallet.blake3(message);
|
|
132
|
-
const signature = this.#wallet.sign(hash);
|
|
133
|
-
|
|
134
|
-
this.#payloadKey = 'validator_connection_request';
|
|
135
|
-
this.#body = {
|
|
136
|
-
issuer_address: issuer,
|
|
137
|
-
nonce,
|
|
138
|
-
signature
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async #buildValidatorConnectionResponsePayload() {
|
|
143
|
-
const issuer = this.#issuerAddress
|
|
144
|
-
if (!isAddressValid(issuer, this.#config.addressPrefix)) {
|
|
145
|
-
throw new Error('Issuer address must be a valid TRAC address');
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (this.#issuerAddress === this.#wallet.address) {
|
|
149
|
-
throw new Error('Issuer address must be the different than the signer address');
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (this.#resultCode === null || this.#resultCode === undefined) {
|
|
153
|
-
throw new Error('Result code must be set before building validator connection response');
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const nonce = PeerWallet.generateNonce();
|
|
157
|
-
const tsBuf = timestampToBuffer(this.#timestamp);
|
|
158
|
-
const idBuf = idToBuffer(this.#id);
|
|
159
|
-
const message = createMessage(
|
|
160
|
-
this.#type,
|
|
161
|
-
idBuf,
|
|
162
|
-
tsBuf,
|
|
163
|
-
addressToBuffer(issuer, this.#config.addressPrefix),
|
|
164
|
-
nonce,
|
|
165
|
-
safeWriteUInt32BE(this.#resultCode, 0),
|
|
166
|
-
encodeCapabilities(this.#capabilities),
|
|
167
|
-
);
|
|
168
|
-
const hash = await PeerWallet.blake3(message);
|
|
169
|
-
const signature = this.#wallet.sign(hash);
|
|
170
|
-
|
|
171
|
-
this.#payloadKey = 'validator_connection_response';
|
|
172
|
-
this.#body = {
|
|
173
|
-
issuer_address: issuer,
|
|
174
|
-
nonce,
|
|
175
|
-
signature,
|
|
176
|
-
result: this.#resultCode
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
139
|
async #buildLivenessRequestPayload() {
|
|
181
140
|
const nonce = PeerWallet.generateNonce();
|
|
182
141
|
const tsBuf = timestampToBuffer(this.#timestamp);
|
|
@@ -258,21 +217,50 @@ class NetworkMessageBuilder {
|
|
|
258
217
|
const nonce = PeerWallet.generateNonce();
|
|
259
218
|
const tsBuf = timestampToBuffer(this.#timestamp);
|
|
260
219
|
const idBuf = idToBuffer(this.#id);
|
|
220
|
+
const proof = b4a.isBuffer(this.#proof) ? this.#proof : b4a.alloc(0);
|
|
221
|
+
const hasProof = proof.length > 0;
|
|
222
|
+
const timestamp = Number.isSafeInteger(this.#timestamp_ledger) ? this.#timestamp_ledger : 0;
|
|
223
|
+
const hasTimestamp = timestamp > 0;
|
|
224
|
+
|
|
225
|
+
if (this.#resultCode === ResultCode.OK) {
|
|
226
|
+
if (!hasProof || !hasTimestamp) {
|
|
227
|
+
throw new Error('Result code OK requires non-empty proof and timestamp > 0.');
|
|
228
|
+
}
|
|
229
|
+
} else if (this.#resultCode === ResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE) {
|
|
230
|
+
if (hasProof) {
|
|
231
|
+
throw new Error('Result code TX_ACCEPTED_PROOF_UNAVAILABLE requires empty proof.');
|
|
232
|
+
}
|
|
233
|
+
if (!hasTimestamp) {
|
|
234
|
+
throw new Error('Result code TX_ACCEPTED_PROOF_UNAVAILABLE requires timestamp > 0.');
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
if (hasProof) {
|
|
238
|
+
throw new Error('Non-OK result code requires empty proof.');
|
|
239
|
+
}
|
|
240
|
+
if (timestamp !== 0) {
|
|
241
|
+
throw new Error('Non-OK result code requires timestamp to be 0, except TX_ACCEPTED_PROOF_UNAVAILABLE.');
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
261
245
|
const message = createMessage(
|
|
262
246
|
this.#type,
|
|
263
247
|
idBuf,
|
|
264
248
|
tsBuf,
|
|
265
249
|
nonce,
|
|
250
|
+
proof,
|
|
251
|
+
timestampToBuffer(timestamp),
|
|
266
252
|
safeWriteUInt32BE(this.#resultCode, 0),
|
|
267
253
|
encodeCapabilities(this.#capabilities),
|
|
268
254
|
);
|
|
255
|
+
|
|
269
256
|
const hash = await PeerWallet.blake3(message);
|
|
270
257
|
const signature = this.#wallet.sign(hash);
|
|
271
|
-
|
|
272
258
|
this.#payloadKey = 'broadcast_transaction_response';
|
|
273
259
|
this.#body = {
|
|
274
260
|
nonce,
|
|
275
261
|
signature,
|
|
262
|
+
proof,
|
|
263
|
+
timestamp: timestamp,
|
|
276
264
|
result: this.#resultCode
|
|
277
265
|
};
|
|
278
266
|
}
|
|
@@ -281,14 +269,6 @@ class NetworkMessageBuilder {
|
|
|
281
269
|
this.#setHeader();
|
|
282
270
|
|
|
283
271
|
switch (this.#type) {
|
|
284
|
-
case NetworkOperationType.VALIDATOR_CONNECTION_REQUEST: {
|
|
285
|
-
await this.#buildValidatorConnectionRequestPayload();
|
|
286
|
-
break;
|
|
287
|
-
}
|
|
288
|
-
case NetworkOperationType.VALIDATOR_CONNECTION_RESPONSE: {
|
|
289
|
-
await this.#buildValidatorConnectionResponsePayload();
|
|
290
|
-
break;
|
|
291
|
-
}
|
|
292
272
|
case NetworkOperationType.LIVENESS_REQUEST: {
|
|
293
273
|
await this.#buildLivenessRequestPayload();
|
|
294
274
|
break;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {NetworkOperationType} from '../../../utils/constants.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Director for v1 internal network protocol messages.
|
|
@@ -13,47 +13,6 @@ class NetworkMessageDirector {
|
|
|
13
13
|
this.#builder = builderInstance;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* Build a validator connection request message.
|
|
18
|
-
* @param {string} id
|
|
19
|
-
* @param {string} issuerAddress
|
|
20
|
-
* @param {string[]} capabilities
|
|
21
|
-
* @returns {Promise<object>}
|
|
22
|
-
*/
|
|
23
|
-
async buildValidatorConnectionRequest(id, issuerAddress, capabilities) {
|
|
24
|
-
await this.#builder
|
|
25
|
-
.setType(NetworkOperationType.VALIDATOR_CONNECTION_REQUEST)
|
|
26
|
-
.setId(id)
|
|
27
|
-
.setTimestamp()
|
|
28
|
-
.setIssuerAddress(issuerAddress)
|
|
29
|
-
.setCapabilities(capabilities)
|
|
30
|
-
.buildPayload()
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
return this.#builder.getResult();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Build a validator connection response message.
|
|
38
|
-
* @param {string} id
|
|
39
|
-
* @param {string} issuerAddress
|
|
40
|
-
* @param {string[]} capabilities
|
|
41
|
-
* @param {number} statusCode
|
|
42
|
-
* @returns {Promise<object>}
|
|
43
|
-
*/
|
|
44
|
-
async buildValidatorConnectionResponse(id, issuerAddress, capabilities, statusCode) {
|
|
45
|
-
await this.#builder
|
|
46
|
-
.setType(NetworkOperationType.VALIDATOR_CONNECTION_RESPONSE)
|
|
47
|
-
.setId(id)
|
|
48
|
-
.setTimestamp()
|
|
49
|
-
.setIssuerAddress(issuerAddress)
|
|
50
|
-
.setCapabilities(capabilities)
|
|
51
|
-
.setResultCode(statusCode)
|
|
52
|
-
.buildPayload()
|
|
53
|
-
|
|
54
|
-
return this.#builder.getResult();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
16
|
/**
|
|
58
17
|
* Build a liveness request message.
|
|
59
18
|
* @param {string} id
|
|
@@ -61,12 +20,11 @@ class NetworkMessageDirector {
|
|
|
61
20
|
* @param {string[]} capabilities
|
|
62
21
|
* @returns {Promise<object>}
|
|
63
22
|
*/
|
|
64
|
-
async buildLivenessRequest(id,
|
|
23
|
+
async buildLivenessRequest(id, capabilities) {
|
|
65
24
|
await this.#builder
|
|
66
25
|
.setType(NetworkOperationType.LIVENESS_REQUEST)
|
|
67
26
|
.setId(id)
|
|
68
27
|
.setTimestamp()
|
|
69
|
-
.setData(data)
|
|
70
28
|
.setCapabilities(capabilities)
|
|
71
29
|
.buildPayload();
|
|
72
30
|
|
|
@@ -76,17 +34,15 @@ class NetworkMessageDirector {
|
|
|
76
34
|
/**
|
|
77
35
|
* Build a liveness response message.
|
|
78
36
|
* @param {string} id
|
|
79
|
-
* @param {Buffer} data
|
|
80
37
|
* @param {string[]} capabilities
|
|
81
38
|
* @param {number} statusCode
|
|
82
39
|
* @returns {Promise<object>}
|
|
83
40
|
*/
|
|
84
|
-
async buildLivenessResponse(id,
|
|
41
|
+
async buildLivenessResponse(id, capabilities, statusCode) {
|
|
85
42
|
await this.#builder
|
|
86
43
|
.setType(NetworkOperationType.LIVENESS_RESPONSE)
|
|
87
44
|
.setId(id)
|
|
88
45
|
.setTimestamp()
|
|
89
|
-
.setData(data)
|
|
90
46
|
.setCapabilities(capabilities)
|
|
91
47
|
.setResultCode(statusCode)
|
|
92
48
|
.buildPayload();
|
|
@@ -115,18 +71,28 @@ class NetworkMessageDirector {
|
|
|
115
71
|
|
|
116
72
|
/**
|
|
117
73
|
* Build a broadcast transaction response message.
|
|
74
|
+
*
|
|
75
|
+
* Allowed payload variants:
|
|
76
|
+
* 1) resultCode === OK - proof must be non-empty and timestamp must be > 0.
|
|
77
|
+
* 2) resultCode === TX_ACCEPTED_PROOF_UNAVAILABLE - proof must be empty and timestamp must be > 0.
|
|
78
|
+
* 3) resultCode !== OK and resultCode !== TX_ACCEPTED_PROOF_UNAVAILABLE - proof must be empty and timestamp must be 0.
|
|
79
|
+
*
|
|
118
80
|
* @param {string} id
|
|
119
81
|
* @param {string[]} capabilities
|
|
120
|
-
* @param {number}
|
|
82
|
+
* @param {number} resultCode
|
|
83
|
+
* @param {Buffer|null|undefined} proof
|
|
84
|
+
* @param {number|Date|null|undefined} timestamp - When transaction has been appended by the validator
|
|
121
85
|
* @returns {Promise<object>}
|
|
122
86
|
*/
|
|
123
|
-
async buildBroadcastTransactionResponse(id, capabilities,
|
|
87
|
+
async buildBroadcastTransactionResponse(id, capabilities, resultCode, proof = null, timestamp = null) {
|
|
124
88
|
await this.#builder
|
|
125
89
|
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
126
90
|
.setId(id)
|
|
127
91
|
.setTimestamp()
|
|
128
92
|
.setCapabilities(capabilities)
|
|
129
|
-
.
|
|
93
|
+
.setProof(proof)
|
|
94
|
+
.setTimestampLedger(timestamp)
|
|
95
|
+
.setResultCode(resultCode)
|
|
130
96
|
.buildPayload();
|
|
131
97
|
|
|
132
98
|
return this.#builder.getResult();
|
package/src/utils/Scheduler.js
CHANGED
|
@@ -42,14 +42,6 @@ class Scheduler {
|
|
|
42
42
|
return this.#defaultInterval;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
get timer() {
|
|
46
|
-
return this.#timer;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
get currentWorkerRun() {
|
|
50
|
-
return this.#currentWorkerRun;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
45
|
static #validateDelay(delayMs, scope = 'delayMs') {
|
|
54
46
|
const ms = Number(delayMs);
|
|
55
47
|
if (!Number.isFinite(ms) || ms < 0) {
|
package/src/utils/constants.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { OperationType as ApplyOperationType } from './protobuf/applyOperations.cjs';
|
|
2
|
-
import
|
|
2
|
+
import networkV1Generated from './protobuf/networkV1.generated.cjs';
|
|
3
3
|
import b4a from 'b4a'
|
|
4
4
|
// TODO: We are going to have a lot of contstants. It would be good, to separate them into different files.
|
|
5
5
|
|
|
6
|
+
const { MessageType: NetworkMessageType, ResultCode: NetworkResultCode } = networkV1Generated.network.v1;
|
|
7
|
+
|
|
6
8
|
//ATTENTION - THIS IS USED IN THE APPLY FUNCTION!
|
|
7
9
|
export const EntryType = Object.freeze({
|
|
8
10
|
ADMIN: 'admin',
|
|
@@ -34,8 +36,6 @@ export const OperationType = Object.freeze({
|
|
|
34
36
|
});
|
|
35
37
|
|
|
36
38
|
export const NetworkOperationType = Object.freeze({
|
|
37
|
-
VALIDATOR_CONNECTION_REQUEST: NetworkMessageType.MESSAGE_TYPE_VALIDATOR_CONNECTION_REQUEST,
|
|
38
|
-
VALIDATOR_CONNECTION_RESPONSE: NetworkMessageType.MESSAGE_TYPE_VALIDATOR_CONNECTION_RESPONSE,
|
|
39
39
|
LIVENESS_REQUEST: NetworkMessageType.MESSAGE_TYPE_LIVENESS_REQUEST,
|
|
40
40
|
LIVENESS_RESPONSE: NetworkMessageType.MESSAGE_TYPE_LIVENESS_RESPONSE,
|
|
41
41
|
BROADCAST_TRANSACTION_REQUEST: NetworkMessageType.MESSAGE_TYPE_BROADCAST_TRANSACTION_REQUEST,
|
|
@@ -43,12 +43,68 @@ export const NetworkOperationType = Object.freeze({
|
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
export const ResultCode = Object.freeze({
|
|
46
|
+
UNSPECIFIED: NetworkResultCode.RESULT_CODE_UNSPECIFIED,
|
|
46
47
|
OK: NetworkResultCode.RESULT_CODE_OK,
|
|
47
48
|
INVALID_PAYLOAD: NetworkResultCode.RESULT_CODE_INVALID_PAYLOAD,
|
|
48
|
-
UNSUPPORTED_VERSION: NetworkResultCode.RESULT_CODE_UNSUPPORTED_VERSION,
|
|
49
49
|
RATE_LIMITED: NetworkResultCode.RESULT_CODE_RATE_LIMITED,
|
|
50
|
-
TIMEOUT: NetworkResultCode.RESULT_CODE_TIMEOUT,
|
|
51
50
|
SIGNATURE_INVALID: NetworkResultCode.RESULT_CODE_SIGNATURE_INVALID,
|
|
51
|
+
UNEXPECTED_ERROR: NetworkResultCode.RESULT_CODE_UNEXPECTED_ERROR,
|
|
52
|
+
TIMEOUT: NetworkResultCode.RESULT_CODE_TIMEOUT,
|
|
53
|
+
NODE_HAS_NO_WRITE_ACCESS: NetworkResultCode.RESULT_CODE_NODE_HAS_NO_WRITE_ACCESS,
|
|
54
|
+
TX_ACCEPTED_PROOF_UNAVAILABLE: NetworkResultCode.RESULT_CODE_TX_ACCEPTED_PROOF_UNAVAILABLE,
|
|
55
|
+
NODE_OVERLOADED: NetworkResultCode.RESULT_CODE_NODE_OVERLOADED,
|
|
56
|
+
TX_ALREADY_PENDING: NetworkResultCode.RESULT_CODE_TX_ALREADY_PENDING,
|
|
57
|
+
OPERATION_TYPE_UNKNOWN: NetworkResultCode.RESULT_CODE_OPERATION_TYPE_UNKNOWN,
|
|
58
|
+
SCHEMA_VALIDATION_FAILED: NetworkResultCode.RESULT_CODE_SCHEMA_VALIDATION_FAILED,
|
|
59
|
+
REQUESTER_ADDRESS_INVALID: NetworkResultCode.RESULT_CODE_REQUESTER_ADDRESS_INVALID,
|
|
60
|
+
REQUESTER_PUBLIC_KEY_INVALID: NetworkResultCode.RESULT_CODE_REQUESTER_PUBLIC_KEY_INVALID,
|
|
61
|
+
TX_HASH_MISMATCH: NetworkResultCode.RESULT_CODE_TX_HASH_MISMATCH,
|
|
62
|
+
TX_SIGNATURE_INVALID: NetworkResultCode.RESULT_CODE_TX_SIGNATURE_INVALID,
|
|
63
|
+
TX_EXPIRED: NetworkResultCode.RESULT_CODE_TX_EXPIRED,
|
|
64
|
+
TX_ALREADY_EXISTS: NetworkResultCode.RESULT_CODE_TX_ALREADY_EXISTS,
|
|
65
|
+
OPERATION_ALREADY_COMPLETED: NetworkResultCode.RESULT_CODE_OPERATION_ALREADY_COMPLETED,
|
|
66
|
+
REQUESTER_NOT_FOUND: NetworkResultCode.RESULT_CODE_REQUESTER_NOT_FOUND,
|
|
67
|
+
INSUFFICIENT_FEE_BALANCE: NetworkResultCode.RESULT_CODE_INSUFFICIENT_FEE_BALANCE,
|
|
68
|
+
EXTERNAL_BOOTSTRAP_EQUALS_MSB_BOOTSTRAP: NetworkResultCode.RESULT_CODE_EXTERNAL_BOOTSTRAP_EQUALS_MSB_BOOTSTRAP,
|
|
69
|
+
SELF_VALIDATION_FORBIDDEN: NetworkResultCode.RESULT_CODE_SELF_VALIDATION_FORBIDDEN,
|
|
70
|
+
ROLE_NODE_ENTRY_NOT_FOUND: NetworkResultCode.RESULT_CODE_ROLE_NODE_ENTRY_NOT_FOUND,
|
|
71
|
+
ROLE_NODE_ALREADY_WRITER: NetworkResultCode.RESULT_CODE_ROLE_NODE_ALREADY_WRITER,
|
|
72
|
+
ROLE_NODE_NOT_WHITELISTED: NetworkResultCode.RESULT_CODE_ROLE_NODE_NOT_WHITELISTED,
|
|
73
|
+
ROLE_NODE_NOT_WRITER: NetworkResultCode.RESULT_CODE_ROLE_NODE_NOT_WRITER,
|
|
74
|
+
ROLE_NODE_IS_INDEXER: NetworkResultCode.RESULT_CODE_ROLE_NODE_IS_INDEXER,
|
|
75
|
+
ROLE_ADMIN_ENTRY_MISSING: NetworkResultCode.RESULT_CODE_ROLE_ADMIN_ENTRY_MISSING,
|
|
76
|
+
ROLE_INVALID_RECOVERY_CASE: NetworkResultCode.RESULT_CODE_ROLE_INVALID_RECOVERY_CASE,
|
|
77
|
+
ROLE_UNKNOWN_OPERATION: NetworkResultCode.RESULT_CODE_ROLE_UNKNOWN_OPERATION,
|
|
78
|
+
ROLE_INVALID_WRITER_KEY: NetworkResultCode.RESULT_CODE_ROLE_INVALID_WRITER_KEY,
|
|
79
|
+
ROLE_INSUFFICIENT_FEE_BALANCE: NetworkResultCode.RESULT_CODE_ROLE_INSUFFICIENT_FEE_BALANCE,
|
|
80
|
+
MSB_BOOTSTRAP_MISMATCH: NetworkResultCode.RESULT_CODE_MSB_BOOTSTRAP_MISMATCH,
|
|
81
|
+
EXTERNAL_BOOTSTRAP_NOT_DEPLOYED: NetworkResultCode.RESULT_CODE_EXTERNAL_BOOTSTRAP_NOT_DEPLOYED,
|
|
82
|
+
EXTERNAL_BOOTSTRAP_TX_MISSING: NetworkResultCode.RESULT_CODE_EXTERNAL_BOOTSTRAP_TX_MISSING,
|
|
83
|
+
EXTERNAL_BOOTSTRAP_MISMATCH: NetworkResultCode.RESULT_CODE_EXTERNAL_BOOTSTRAP_MISMATCH,
|
|
84
|
+
BOOTSTRAP_ALREADY_EXISTS: NetworkResultCode.RESULT_CODE_BOOTSTRAP_ALREADY_EXISTS,
|
|
85
|
+
TRANSFER_RECIPIENT_ADDRESS_INVALID: NetworkResultCode.RESULT_CODE_TRANSFER_RECIPIENT_ADDRESS_INVALID,
|
|
86
|
+
TRANSFER_RECIPIENT_PUBLIC_KEY_INVALID: NetworkResultCode.RESULT_CODE_TRANSFER_RECIPIENT_PUBLIC_KEY_INVALID,
|
|
87
|
+
TRANSFER_AMOUNT_TOO_LARGE: NetworkResultCode.RESULT_CODE_TRANSFER_AMOUNT_TOO_LARGE,
|
|
88
|
+
TRANSFER_SENDER_NOT_FOUND: NetworkResultCode.RESULT_CODE_TRANSFER_SENDER_NOT_FOUND,
|
|
89
|
+
TRANSFER_INSUFFICIENT_BALANCE: NetworkResultCode.RESULT_CODE_TRANSFER_INSUFFICIENT_BALANCE,
|
|
90
|
+
TRANSFER_RECIPIENT_BALANCE_OVERFLOW: NetworkResultCode.RESULT_CODE_TRANSFER_RECIPIENT_BALANCE_OVERFLOW,
|
|
91
|
+
TX_HASH_INVALID_FORMAT: NetworkResultCode.RESULT_CODE_TX_HASH_INVALID_FORMAT,
|
|
92
|
+
INTERNAL_ENQUEUE_VALIDATION_FAILED: NetworkResultCode.RESULT_CODE_INTERNAL_ENQUEUE_VALIDATION_FAILED,
|
|
93
|
+
TX_COMMITTED_RECEIPT_MISSING: NetworkResultCode.RESULT_CODE_TX_COMMITTED_RECEIPT_MISSING,
|
|
94
|
+
VALIDATOR_RESPONSE_TX_TYPE_INVALID: NetworkResultCode.RESULT_CODE_VALIDATOR_RESPONSE_TX_TYPE_INVALID,
|
|
95
|
+
VALIDATOR_RESPONSE_TX_TYPE_UNKNOWN: NetworkResultCode.RESULT_CODE_VALIDATOR_RESPONSE_TX_TYPE_UNKNOWN,
|
|
96
|
+
VALIDATOR_RESPONSE_TX_TYPE_UNSUPPORTED: NetworkResultCode.RESULT_CODE_VALIDATOR_RESPONSE_TX_TYPE_UNSUPPORTED,
|
|
97
|
+
VALIDATOR_RESPONSE_SCHEMA_INVALID: NetworkResultCode.RESULT_CODE_VALIDATOR_RESPONSE_SCHEMA_INVALID,
|
|
98
|
+
PENDING_REQUEST_MISSING_TX_DATA: NetworkResultCode.RESULT_CODE_PENDING_REQUEST_MISSING_TX_DATA,
|
|
99
|
+
PROOF_PAYLOAD_MISMATCH: NetworkResultCode.RESULT_CODE_PROOF_PAYLOAD_MISMATCH,
|
|
100
|
+
VALIDATOR_WRITER_KEY_NOT_REGISTERED: NetworkResultCode.RESULT_CODE_VALIDATOR_WRITER_KEY_NOT_REGISTERED,
|
|
101
|
+
VALIDATOR_ADDRESS_MISMATCH: NetworkResultCode.RESULT_CODE_VALIDATOR_ADDRESS_MISMATCH,
|
|
102
|
+
VALIDATOR_NODE_ENTRY_NOT_FOUND: NetworkResultCode.RESULT_CODE_VALIDATOR_NODE_ENTRY_NOT_FOUND,
|
|
103
|
+
VALIDATOR_NODE_NOT_WRITER: NetworkResultCode.RESULT_CODE_VALIDATOR_NODE_NOT_WRITER,
|
|
104
|
+
VALIDATOR_WRITER_KEY_MISMATCH: NetworkResultCode.RESULT_CODE_VALIDATOR_WRITER_KEY_MISMATCH,
|
|
105
|
+
VALIDATOR_TX_OBJECT_INVALID: NetworkResultCode.RESULT_CODE_VALIDATOR_TX_OBJECT_INVALID,
|
|
106
|
+
VALIDATOR_VA_MISSING: NetworkResultCode.RESULT_CODE_VALIDATOR_VA_MISSING,
|
|
107
|
+
TX_INVALID_PAYLOAD: NetworkResultCode.RESULT_CODE_TX_INVALID_PAYLOAD
|
|
52
108
|
});
|
|
53
109
|
|
|
54
110
|
// Role managment constants
|
|
@@ -61,6 +117,7 @@ export const EventType = Object.freeze({
|
|
|
61
117
|
WARNING: 'warning',
|
|
62
118
|
VALIDATOR_CONNECTION_READY: 'validator-connection-ready',
|
|
63
119
|
VALIDATOR_CONNECTION_TIMEOUT: 'validator-connection-timeout',
|
|
120
|
+
VALIDATOR_HEALTH_CHECK: 'validator-health-check',
|
|
64
121
|
});
|
|
65
122
|
|
|
66
123
|
// Role managment constants
|
|
@@ -109,6 +166,13 @@ export const BOOTSTRAP_HEXSTRING_LENGTH = 64;
|
|
|
109
166
|
// Pool constants
|
|
110
167
|
export const BATCH_SIZE = 10;
|
|
111
168
|
|
|
169
|
+
// Operation handler constants
|
|
170
|
+
export const MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE = 3072;
|
|
171
|
+
export const V1_PROTOCOL_PAYLOAD_MAX_SIZE = 4096;
|
|
172
|
+
|
|
173
|
+
// Transaction Commit Service
|
|
174
|
+
export const TRANSACTION_COMMIT_SERVICE_BUFFER_SIZE = 1500;
|
|
175
|
+
|
|
112
176
|
// Network message constants
|
|
113
177
|
export const NETWORK_MESSAGE_TYPES = Object.freeze({
|
|
114
178
|
GET: {
|
|
@@ -123,3 +187,5 @@ export const NETWORK_MESSAGE_TYPES = Object.freeze({
|
|
|
123
187
|
NODE: 'nodeResponse'
|
|
124
188
|
},
|
|
125
189
|
});
|
|
190
|
+
|
|
191
|
+
export const NETWORK_CAPABILITIES = Object.freeze(["protocols:v1:legacy"]);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import b4a from 'b4a';
|
|
2
|
+
import _ from 'lodash';
|
|
3
|
+
|
|
4
|
+
export const isDeepEqualApplyPayload = (left, right) => {
|
|
5
|
+
if (left === right) return true;
|
|
6
|
+
|
|
7
|
+
const leftIsBuffer = b4a.isBuffer(left);
|
|
8
|
+
const rightIsBuffer = b4a.isBuffer(right);
|
|
9
|
+
|
|
10
|
+
if (leftIsBuffer || rightIsBuffer) {
|
|
11
|
+
return leftIsBuffer && rightIsBuffer && b4a.equals(left, right);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const leftIsArray = Array.isArray(left);
|
|
15
|
+
const rightIsArray = Array.isArray(right);
|
|
16
|
+
|
|
17
|
+
if (leftIsArray || rightIsArray) {
|
|
18
|
+
if (!leftIsArray || !rightIsArray) return false;
|
|
19
|
+
if (left.length !== right.length) return false;
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < left.length; i++) {
|
|
22
|
+
if (!isDeepEqualApplyPayload(left[i], right[i])) return false;
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!_.isObject(left) || !_.isObject(right)) return false;
|
|
28
|
+
|
|
29
|
+
const leftKeys = Object.keys(left);
|
|
30
|
+
const rightKeys = Object.keys(right);
|
|
31
|
+
|
|
32
|
+
if (leftKeys.length !== rightKeys.length) return false;
|
|
33
|
+
|
|
34
|
+
for (const key of leftKeys) {
|
|
35
|
+
if (!Object.prototype.hasOwnProperty.call(right, key)) return false;
|
|
36
|
+
if (!isDeepEqualApplyPayload(left[key], right[key])) return false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return true;
|
|
40
|
+
};
|