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.
- 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 +121 -0
- package/rpc/routes/v1.js +12 -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 +1803 -159
- 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 +280 -67
- 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/config/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import b4a from 'b4a'
|
|
2
2
|
import { isDefined } from '../utils/type.js'
|
|
3
3
|
import _ from 'lodash'
|
|
4
|
+
import { BOOTSTRAP_BYTE_LENGTH, CHANNEL_BYTE_LENGTH } from '../utils/constants.js'
|
|
4
5
|
|
|
5
6
|
export class Config {
|
|
6
7
|
#options
|
|
@@ -59,6 +60,11 @@ export class Config {
|
|
|
59
60
|
return !!this.#config.enableErrorApplyLogs
|
|
60
61
|
}
|
|
61
62
|
|
|
63
|
+
get enableLogTimestamp() {
|
|
64
|
+
if (this.#isOverriden('enableLogTimestamp')) return !!this.#options.enableLogTimestamp
|
|
65
|
+
return !!this.#config.enableLogTimestamp
|
|
66
|
+
}
|
|
67
|
+
|
|
62
68
|
get enableInteractiveMode() {
|
|
63
69
|
if (this.#isOverriden('enableInteractiveMode')) return this.#options.enableInteractiveMode !== false
|
|
64
70
|
return !!this.#config.enableInteractiveMode
|
|
@@ -69,11 +75,6 @@ export class Config {
|
|
|
69
75
|
return !!this.#config.enableRoleRequester
|
|
70
76
|
}
|
|
71
77
|
|
|
72
|
-
get enableValidatorObserver() {
|
|
73
|
-
if (this.#isOverriden('enableValidatorObserver')) return !!this.#options.enableValidatorObserver
|
|
74
|
-
return !!this.#config.enableValidatorObserver
|
|
75
|
-
}
|
|
76
|
-
|
|
77
78
|
get enableTxApplyLogs() {
|
|
78
79
|
if (this.#isOverriden('enableTxApplyLogs')) return !!this.#options.enableTxApplyLogs
|
|
79
80
|
return !!this.#config.enableTxApplyLogs
|
|
@@ -201,6 +202,10 @@ export class Config {
|
|
|
201
202
|
return this.#config.pendingRequestTimeout
|
|
202
203
|
}
|
|
203
204
|
|
|
205
|
+
get indexerPendingRequestTimeout() {
|
|
206
|
+
return this.#config.indexerPendingRequestTimeout
|
|
207
|
+
}
|
|
208
|
+
|
|
204
209
|
get txCommitTimeout() {
|
|
205
210
|
return this.#config.txCommitTimeout
|
|
206
211
|
}
|
|
@@ -214,6 +219,26 @@ export class Config {
|
|
|
214
219
|
return this.#config.validatorHealthCheckInterval
|
|
215
220
|
}
|
|
216
221
|
|
|
222
|
+
get epochInterval() {
|
|
223
|
+
return this.#config.epochInterval
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
get epochBackoffDelay() {
|
|
227
|
+
return this.#config.epochBackoffDelay
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
get epochSignatureTimeout() {
|
|
231
|
+
return this.#config.epochSignatureTimeout
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
get epochRemoteProposalTimeout() {
|
|
235
|
+
return this.#config.epochRemoteProposalTimeout
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
get epochAppendTimeout() {
|
|
239
|
+
return this.#config.epochAppendTimeout
|
|
240
|
+
}
|
|
241
|
+
|
|
217
242
|
get validatorHealthCheckFailureThreshold() {
|
|
218
243
|
if (this.#isOverriden('validatorHealthCheckFailureThreshold')) return this.#options.validatorHealthCheckFailureThreshold
|
|
219
244
|
return this.#config.validatorHealthCheckFailureThreshold
|
|
@@ -228,6 +253,10 @@ export class Config {
|
|
|
228
253
|
return this.#config.maxPendingRequestsInPendingRequestsService
|
|
229
254
|
}
|
|
230
255
|
|
|
256
|
+
get maxPendingConnections() {
|
|
257
|
+
return this.#config.maxPendingConnections
|
|
258
|
+
}
|
|
259
|
+
|
|
231
260
|
get debug() {
|
|
232
261
|
return this.#config.debug
|
|
233
262
|
}
|
|
@@ -251,6 +280,10 @@ export class Config {
|
|
|
251
280
|
return this.#config.bootstrapTimeout
|
|
252
281
|
}
|
|
253
282
|
|
|
283
|
+
get connectTimeoutMs() {
|
|
284
|
+
return this.#config.connectTimeoutMs
|
|
285
|
+
}
|
|
286
|
+
|
|
254
287
|
get writersShortCacheTTL() {
|
|
255
288
|
if (this.#isOverriden('writersShortCacheTTL')) return this.#options.writersShortCacheTTL
|
|
256
289
|
return this.#config.writersShortCacheTTL
|
|
@@ -279,7 +312,7 @@ export class Config {
|
|
|
279
312
|
}
|
|
280
313
|
|
|
281
314
|
#normalizeChannel(channel) {
|
|
282
|
-
return b4a.alloc(
|
|
315
|
+
return b4a.alloc(CHANNEL_BYTE_LENGTH).fill(channel)
|
|
283
316
|
}
|
|
284
317
|
|
|
285
318
|
#validateStringOverride(field, value) {
|
|
@@ -296,7 +329,7 @@ export class Config {
|
|
|
296
329
|
|
|
297
330
|
#validateBootstrapOverride(bootstrap) {
|
|
298
331
|
if (b4a.isBuffer(bootstrap)) {
|
|
299
|
-
if (bootstrap.length !==
|
|
332
|
+
if (bootstrap.length !== BOOTSTRAP_BYTE_LENGTH) {
|
|
300
333
|
throw new Error('MainSettlementBus Config: bootstrap must be a 32-byte hex string or Buffer.');
|
|
301
334
|
}
|
|
302
335
|
return;
|
|
@@ -370,4 +403,5 @@ export class Config {
|
|
|
370
403
|
this.#validateDhtBootstrapOverride(options.dhtBootstrap);
|
|
371
404
|
}
|
|
372
405
|
}
|
|
406
|
+
|
|
373
407
|
}
|
package/src/config/env.js
CHANGED
|
@@ -17,20 +17,22 @@ const configData = {
|
|
|
17
17
|
addressPrefixLength: TRAC_NETWORK_MSB_TESTNET1_PREFIX.length,
|
|
18
18
|
bech32mHrpLength: TRAC_NETWORK_MSB_TESTNET1_PREFIX.length + 1, // len(addressPrefix + separator)
|
|
19
19
|
bootstrap: 'c184f4ad8e9cf5e911f9415b60e7dcfb30aed73ebd8a402ef68e1b154624f5ef',
|
|
20
|
-
channel: '
|
|
20
|
+
channel: '2222trac2network2msb2testnet2222',
|
|
21
21
|
dhtBootstrap: ['116.202.214.149:10001','157.180.12.214:10001','node1.hyperdht.org:49737','node2.hyperdht.org:49737','node3.hyperdht.org:49737'], // these are used to peer discovery
|
|
22
22
|
derivationPath: address.TESNET_DERIVATION_PATH,
|
|
23
|
-
enableValidatorObserver: true,
|
|
24
23
|
pollInterval: 500, // Validator observer poll interval
|
|
25
24
|
adminCacheTTL: 10_000, // Admin cache TTL ms
|
|
26
25
|
validatorConnectionAttemptDelay: 5, // Delay between validator connection attempts (ms)
|
|
26
|
+
connectTimeoutMs: 5_000,
|
|
27
27
|
bootstrapTimeout: 60_000, // time used (ms) to connect to new validators at bootstrap
|
|
28
28
|
writersShortCacheTTL: 10_000, // short TTL during bootstrap
|
|
29
29
|
writersLongCacheTTL: 120_000, // long TTL after bootstrap
|
|
30
30
|
maxValidators: 50,
|
|
31
|
+
maxPendingConnections: 50,
|
|
31
32
|
maxWritersForAdminIndexerConnection: 10, // Connectivity constants
|
|
32
33
|
disableRateLimit: false,
|
|
33
34
|
enableErrorApplyLogs: true,
|
|
35
|
+
enableLogTimestamp: false,
|
|
34
36
|
enableInteractiveMode: true,
|
|
35
37
|
enableRoleRequester: false,
|
|
36
38
|
enableTxApplyLogs: true,
|
|
@@ -53,11 +55,17 @@ const configData = {
|
|
|
53
55
|
rateLimitMaxTransactionsPerSecond: 50, // Rate limiting constants
|
|
54
56
|
maxPendingRequestsInPendingRequestsService: 50_000, // Maximum number of pending requests in PendingRequestService (This value should not exceed 256MB)
|
|
55
57
|
pendingRequestTimeout: 10_000, // Deadline for a pending V1 response (ms), including health checks
|
|
58
|
+
indexerPendingRequestTimeout: 20000, // constant after which time the transaction will be considered invalid
|
|
56
59
|
txCommitTimeout: 5_000, // Wait for local append and publication proof (ms); shorter than the response deadline
|
|
57
60
|
txPoolSize: 1000, // size of transaction pool
|
|
58
61
|
validatorHealthCheckInterval: 5 * 60 * 1000, // How often to check validator health (ms)
|
|
59
62
|
validatorHealthCheckFailureThreshold: 3, // Consecutive failed health checks before a validator is removed
|
|
60
|
-
confirmationStallTimeout: 120_000, // Force a fast-forward when
|
|
63
|
+
confirmationStallTimeout: 120_000, // Force a fast-forward when confirmations stall with unconfirmed entries (ms, 0 = off)
|
|
64
|
+
epochInterval: 3 * 60 * 1000, // How often to trigger epoch proof proposal (ms)
|
|
65
|
+
epochBackoffDelay: 30_000, // Delay before retrying epoch coordination after a failed attempt (ms)
|
|
66
|
+
epochSignatureTimeout: 20_000, // Max time delay an indexer have to sign a proposal
|
|
67
|
+
epochAppendTimeout: 2_000, // Max time a proposer has to append the new epoch in the log
|
|
68
|
+
epochRemoteProposalTimeout: 20_000, // Max time to wait for a competing proposal to land before broadcasting our own
|
|
61
69
|
storesDirectory: 'stores/',
|
|
62
70
|
storeName: 'testnet',
|
|
63
71
|
},
|
|
@@ -71,17 +79,19 @@ const configData = {
|
|
|
71
79
|
channel: '0000trac0network0msb0mainnet0000',
|
|
72
80
|
dhtBootstrap: ['116.202.214.149:10001','157.180.12.214:10001','node1.hyperdht.org:49737','node2.hyperdht.org:49737','node3.hyperdht.org:49737'],
|
|
73
81
|
derivationPath: address.MAINNET_DERIVATION_PATH,
|
|
74
|
-
enableValidatorObserver: true,
|
|
75
82
|
pollInterval: 500, // Validator observer poll interval
|
|
76
83
|
adminCacheTTL: 3_600_000, // Admin cache TTL ms
|
|
77
84
|
validatorConnectionAttemptDelay: 5, // Delay between validator connection attempts (ms)
|
|
85
|
+
connectTimeoutMs: 5_000,
|
|
78
86
|
bootstrapTimeout: 120_000, // time used (ms) to connect to new validators at bootstrap
|
|
79
87
|
writersShortCacheTTL: 2_000, // short TTL during bootstrap
|
|
80
88
|
writersLongCacheTTL: 120_000, // long TTL after bootstrap
|
|
81
89
|
maxValidators: 50,
|
|
90
|
+
maxPendingConnections: 50,
|
|
82
91
|
maxWritersForAdminIndexerConnection: 10, // Connectivity constants
|
|
83
92
|
disableRateLimit: false,
|
|
84
93
|
enableErrorApplyLogs: false,
|
|
94
|
+
enableLogTimestamp: false,
|
|
85
95
|
enableInteractiveMode: true,
|
|
86
96
|
enableRoleRequester: false,
|
|
87
97
|
enableTxApplyLogs: false,
|
|
@@ -104,11 +114,17 @@ const configData = {
|
|
|
104
114
|
rateLimitMaxTransactionsPerSecond: 50, // Rate limiting constants
|
|
105
115
|
maxPendingRequestsInPendingRequestsService: 50_000, // Maximum number of pending requests in PendingRequestService (This value should not exceed 256MB)
|
|
106
116
|
pendingRequestTimeout: 10_000, // Deadline for a pending V1 response (ms), including health checks
|
|
117
|
+
indexerPendingRequestTimeout: 20000, // constant after which time the transaction will be considered invalid
|
|
107
118
|
txCommitTimeout: 5_000, // Wait for local append and publication proof (ms); shorter than the response deadline
|
|
108
119
|
txPoolSize: 1000, // size of transaction pool
|
|
109
120
|
validatorHealthCheckInterval: 5 * 60 * 1000, // How often to check validator health (ms)
|
|
110
121
|
validatorHealthCheckFailureThreshold: 3, // Consecutive failed health checks before a validator is removed
|
|
111
|
-
confirmationStallTimeout: 120_000, // Force a fast-forward when
|
|
122
|
+
confirmationStallTimeout: 120_000, // Force a fast-forward when confirmations stall with unconfirmed entries (ms, 0 = off)
|
|
123
|
+
epochInterval: 3 * 60 * 1000, // How often to trigger epoch proof proposal (ms)
|
|
124
|
+
epochBackoffDelay: 30_000, // Delay before retrying epoch coordination after a failed attempt (ms)
|
|
125
|
+
epochSignatureTimeout: 20_000, // Max time delay an indexer have to sign a proposal
|
|
126
|
+
epochAppendTimeout: 2_000, // Max time a proposer has to append the new epoch in the log
|
|
127
|
+
epochRemoteProposalTimeout: 20_000, // Max time to wait for a competing proposal to land before broadcasting our own
|
|
112
128
|
storesDirectory: 'stores/',
|
|
113
129
|
storeName: 'mainnet',
|
|
114
130
|
},
|
|
@@ -118,21 +134,23 @@ const configData = {
|
|
|
118
134
|
addressPrefix: TRAC_NETWORK_MSB_MAINNET_PREFIX,
|
|
119
135
|
addressPrefixLength: TRAC_NETWORK_MSB_MAINNET_PREFIX.length,
|
|
120
136
|
bech32mHrpLength: TRAC_NETWORK_MSB_MAINNET_PREFIX.length + 1, // len(addressPrefix + separator)
|
|
121
|
-
bootstrap: '
|
|
122
|
-
channel: '
|
|
137
|
+
bootstrap: 'e81a23d67224e794a7df923843591880c24a4fd4de1795a80108035a7fcdfcbd',
|
|
138
|
+
channel: '123123131231233',
|
|
123
139
|
dhtBootstrap: ['116.202.214.149:10001','157.180.12.214:10001','node1.hyperdht.org:49737','node2.hyperdht.org:49737','node3.hyperdht.org:49737'],
|
|
124
140
|
derivationPath: address.MAINNET_DERIVATION_PATH,
|
|
125
|
-
enableValidatorObserver: true,
|
|
126
141
|
pollInterval: 500, // Validator observer poll interval
|
|
127
142
|
adminCacheTTL: 60_000, // Admin cache TTL ms
|
|
128
143
|
validatorConnectionAttemptDelay: 5, // Delay between validator connection attempts (ms)
|
|
144
|
+
connectTimeoutMs: 5_000,
|
|
129
145
|
bootstrapTimeout: 30_000, // time used (ms) to connect to new validators at bootstrap
|
|
130
146
|
writersShortCacheTTL: 1_000, // short TTL during bootstrap
|
|
131
147
|
writersLongCacheTTL: 2_000, // long TTL after bootstrap
|
|
132
148
|
maxValidators: 10,
|
|
149
|
+
maxPendingConnections: 50,
|
|
133
150
|
maxWritersForAdminIndexerConnection: 10, // Connectivity constants
|
|
134
151
|
disableRateLimit: false,
|
|
135
152
|
enableErrorApplyLogs: true,
|
|
153
|
+
enableLogTimestamp: true,
|
|
136
154
|
enableInteractiveMode: true,
|
|
137
155
|
enableRoleRequester: false,
|
|
138
156
|
enableTxApplyLogs: true,
|
|
@@ -155,11 +173,17 @@ const configData = {
|
|
|
155
173
|
rateLimitMaxTransactionsPerSecond: 50, // Rate limiting constants
|
|
156
174
|
maxPendingRequestsInPendingRequestsService: 50_000, // Maximum number of pending requests in PendingRequestService (This value should not exceed 256MB)
|
|
157
175
|
pendingRequestTimeout: 10_000, // Deadline for a pending V1 response (ms), including health checks
|
|
176
|
+
indexerPendingRequestTimeout: 20000, // constant after which time the transaction will be considered invalid
|
|
158
177
|
txCommitTimeout: 5_000, // Wait for local append and publication proof (ms); shorter than the response deadline
|
|
159
178
|
txPoolSize: 1000, // size of transaction pool
|
|
160
179
|
validatorHealthCheckInterval: 1_000, // How often to check validator health (ms)
|
|
161
180
|
validatorHealthCheckFailureThreshold: 3, // Consecutive failed health checks before a validator is removed
|
|
162
|
-
confirmationStallTimeout: 120_000, // Force a fast-forward when
|
|
181
|
+
confirmationStallTimeout: 120_000, // Force a fast-forward when confirmations stall with unconfirmed entries (ms, 0 = off)
|
|
182
|
+
epochInterval: 30 * 1000, // How often to trigger epoch proof proposal (ms)
|
|
183
|
+
epochBackoffDelay: 30_000, // Delay before retrying epoch coordination after a failed attempt (ms)
|
|
184
|
+
epochSignatureTimeout: 40_000, // Max time delay an indexer have to sign a proposal
|
|
185
|
+
epochAppendTimeout: 10_000, // Max time a proposer has to append the new epoch in the log
|
|
186
|
+
epochRemoteProposalTimeout: 40_000, // Max time to wait for a competing proposal to land before broadcasting our own
|
|
163
187
|
storesDirectory: 'stores/',
|
|
164
188
|
storeName: 'development',
|
|
165
189
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** Error codes used when handling election failures and building protocol replies. */
|
|
2
|
+
export const EpochAppenderSelectionErrorCode = Object.freeze({
|
|
3
|
+
SELECTION_STATE_INVALID: 'SELECTION_STATE_INVALID',
|
|
4
|
+
RESERVATION_INVALID: 'RESERVATION_INVALID',
|
|
5
|
+
PUBLICATION_MARKER_INVALID: 'PUBLICATION_MARKER_INVALID',
|
|
6
|
+
PERSISTENCE_FAILED: 'PERSISTENCE_FAILED',
|
|
7
|
+
SELECTOR_CLOSED: 'SELECTOR_CLOSED',
|
|
8
|
+
SELECTOR_UNAVAILABLE: 'SELECTOR_UNAVAILABLE',
|
|
9
|
+
REQUEST_STALE: 'REQUEST_STALE',
|
|
10
|
+
REQUEST_CANCELLED: 'REQUEST_CANCELLED',
|
|
11
|
+
ELECTION_SUPERSEDED: 'ELECTION_SUPERSEDED',
|
|
12
|
+
ELECTION_BUSY: 'ELECTION_BUSY',
|
|
13
|
+
ALREADY_WAITING: 'ALREADY_WAITING',
|
|
14
|
+
PUBLICATION_UNRESOLVED: 'PUBLICATION_UNRESOLVED',
|
|
15
|
+
REPLIES_INCOMPLETE: 'REPLIES_INCOMPLETE',
|
|
16
|
+
REPLY_TIMEOUT: 'REPLY_TIMEOUT',
|
|
17
|
+
CONTEXT_CHANGED: 'CONTEXT_CHANGED',
|
|
18
|
+
NOT_IN_COHORT: 'NOT_IN_COHORT',
|
|
19
|
+
UNEXPECTED_PEER: 'UNEXPECTED_PEER',
|
|
20
|
+
LOGICAL_COUNTER_INVALID: 'LOGICAL_COUNTER_INVALID',
|
|
21
|
+
LOGICAL_CLOCK_EXHAUSTED: 'LOGICAL_CLOCK_EXHAUSTED',
|
|
22
|
+
SIGNED_CHECKPOINT_UNAVAILABLE: 'SIGNED_CHECKPOINT_UNAVAILABLE',
|
|
23
|
+
SIGNED_VIEW_INVALID: 'SIGNED_VIEW_INVALID',
|
|
24
|
+
EPOCH_NOT_INITIALIZED: 'EPOCH_NOT_INITIALIZED',
|
|
25
|
+
PARENT_MISSING: 'PARENT_MISSING',
|
|
26
|
+
MEMBER_IDENTITY_MISSING: 'MEMBER_IDENTITY_MISSING',
|
|
27
|
+
MEMBERSHIP_INVALID: 'MEMBERSHIP_INVALID',
|
|
28
|
+
CONFIG_MISSING: 'CONFIG_MISSING',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Describes an appender selection error. Callers use the code to decide what to do next. The message
|
|
33
|
+
* and details help explain the failure in logs. Protocol handlers convert these errors to protocol
|
|
34
|
+
* result codes.
|
|
35
|
+
*/
|
|
36
|
+
export class EpochAppenderSelectionError extends Error {
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} code One of EpochAppenderSelectionErrorCode.
|
|
39
|
+
* @param {string} message Message shown in logs. Callers use the code to handle the error.
|
|
40
|
+
* @param {object} [options] Extra details and the original error.
|
|
41
|
+
* @param {object} [options.details] Request ID and other details about the failure.
|
|
42
|
+
* @param {Error} [options.cause] Original error that caused this failure.
|
|
43
|
+
*/
|
|
44
|
+
constructor(code, message, { details, cause } = {}) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = this.constructor.name;
|
|
47
|
+
this.code = code;
|
|
48
|
+
if (details !== undefined) {
|
|
49
|
+
this.details = details;
|
|
50
|
+
}
|
|
51
|
+
if (cause !== undefined) {
|
|
52
|
+
this.cause = cause;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { generateUUID } from '../../../utils/helpers.js';
|
|
2
|
+
import { consensusMessageFactory } from '../../../messages/consensus/v1/consensusMessageFactory.js';
|
|
3
|
+
import { EpochAppenderSelectionError, EpochAppenderSelectionErrorCode } from './EpochAppenderSelectionError.js';
|
|
4
|
+
import { loadSelectionState, saveSelectionState } from './epochAppenderSelectionStorage.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Provides local storage, signed ledger reads and network requests for the selector. The selector uses
|
|
8
|
+
* these methods to collect votes. The round handles the epoch append.
|
|
9
|
+
*/
|
|
10
|
+
export class EpochAppenderSelectionOperations {
|
|
11
|
+
#state;
|
|
12
|
+
#wallet;
|
|
13
|
+
#config;
|
|
14
|
+
#getIndexerConnectionManager;
|
|
15
|
+
#logger;
|
|
16
|
+
#pendingRequestService;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Sets up the services used by the selector. The connection manager is read through a callback
|
|
20
|
+
* because Network creates it after the selector.
|
|
21
|
+
*
|
|
22
|
+
* @param {import('../../state/State.js').default} state Access to signed ledger data and local storage.
|
|
23
|
+
* @param {object} wallet Wallet used to sign REQUEST messages.
|
|
24
|
+
* @param {object} config Network and message encoding config.
|
|
25
|
+
* @param {function(): import('../../network/services/IndexerConnectionManager.js').default} getIndexerConnectionManager Returns the connection manager once it is ready.
|
|
26
|
+
* @param {object} [logger] Logger for operation errors.
|
|
27
|
+
* @param {object} [pendingRequestService] Tracks pending requests and cancels them when needed.
|
|
28
|
+
*/
|
|
29
|
+
constructor(state, wallet, config, getIndexerConnectionManager, logger, pendingRequestService) {
|
|
30
|
+
this.#state = state;
|
|
31
|
+
this.#wallet = wallet;
|
|
32
|
+
this.#config = config;
|
|
33
|
+
this.#getIndexerConnectionManager = getIndexerConnectionManager;
|
|
34
|
+
this.#logger = logger;
|
|
35
|
+
this.#pendingRequestService = pendingRequestService;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Loads the election state saved on this node.
|
|
40
|
+
*
|
|
41
|
+
* @returns {Promise<import('./epochAppenderSelectionState.js').EpochAppenderSelectionState|null>}
|
|
42
|
+
*/
|
|
43
|
+
load() {
|
|
44
|
+
return loadSelectionState(this.#state.base);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Saves a copy of the election state on this node.
|
|
49
|
+
*
|
|
50
|
+
* @param {import('./epochAppenderSelectionState.js').EpochAppenderSelectionState} selectionState Election state to save locally.
|
|
51
|
+
* @returns {Promise<void>}
|
|
52
|
+
*/
|
|
53
|
+
save(selectionState) {
|
|
54
|
+
return saveSelectionState(this.#state.base, selectionState);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Reads the epoch, consensus config and indexers from the same signed checkpoint.
|
|
59
|
+
*
|
|
60
|
+
* @returns {Promise<import('./epochAppenderSelectionState.js').EpochAppenderSelectionContext>}
|
|
61
|
+
*/
|
|
62
|
+
readContext() {
|
|
63
|
+
return this.#state.getEpochAppenderSelectionContext();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Checks whether the signed ledger has processed this append.
|
|
68
|
+
*
|
|
69
|
+
* @param {import('./epochAppenderSelectionState.js').EpochAppendPublication} publication Saved writer position and payload hash for this append.
|
|
70
|
+
* @returns {Promise<import('./epochAppenderSelectionState.js').EpochAppendOutcomeResult>}
|
|
71
|
+
*/
|
|
72
|
+
readOutcome(publication) {
|
|
73
|
+
return this.#state.getEpochAppendOutcome(publication);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Connects to the current indexers through the existing session manager.
|
|
78
|
+
*
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
connect() {
|
|
82
|
+
return this.#getIndexerConnectionManager().connect();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Signs and sends a REQUEST for an appender vote. Registers a callback so the election can cancel
|
|
87
|
+
* the pending request. If cancellation happens during signing, nothing is sent.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} peerPublicKey Target wallet key, encoded as hex.
|
|
90
|
+
* @param {import('./epochAppenderSelectionState.js').EpochAppendRequest} selectionRequest Request containing the candidate, election term and payload hash.
|
|
91
|
+
* @param {import('./epochAppenderSelectionState.js').EpochSelectionRequestLifecycle} requestLifecycle Callbacks that check whether the request is active and register cancellation.
|
|
92
|
+
* @returns {Promise<import('./epochAppenderSelectionState.js').EpochAppendReply|null>} Validated reply, or null after cancellation.
|
|
93
|
+
*/
|
|
94
|
+
async sendRequest(peerPublicKey, selectionRequest, requestLifecycle) {
|
|
95
|
+
const requestMessage = await consensusMessageFactory(this.#wallet, this.#config).buildRequest(generateUUID(), selectionRequest);
|
|
96
|
+
if (!requestLifecycle.isActive()) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
requestLifecycle.onPending(() => {
|
|
100
|
+
const error = new EpochAppenderSelectionError(
|
|
101
|
+
EpochAppenderSelectionErrorCode.REQUEST_CANCELLED,
|
|
102
|
+
'Epoch append request no longer waiting',
|
|
103
|
+
{ details: { requestId: selectionRequest.requestId, sessionId: requestMessage.session_id } }
|
|
104
|
+
);
|
|
105
|
+
this.#pendingRequestService?.rejectPendingRequest(requestMessage.session_id, error);
|
|
106
|
+
});
|
|
107
|
+
return this.#getIndexerConnectionManager().send(peerPublicKey, requestMessage);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Logs an error from a background operation. This does not change the election state.
|
|
112
|
+
*
|
|
113
|
+
* @param {Error} error Error from storage, signed context reads or a peer request.
|
|
114
|
+
*/
|
|
115
|
+
onError(error) {
|
|
116
|
+
this.#logger?.debug?.(`[EpochAppenderSelector] ${error.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|