trac-msb 0.2.6 → 0.2.8
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/.github/workflows/publish.yml +9 -16
- package/docs/networking-dualstack-plan.md +75 -0
- package/docs/networking-layer-redesign.md +155 -0
- package/msb.mjs +11 -23
- package/package.json +2 -3
- package/rpc/{create_server.mjs → create_server.js} +2 -2
- package/rpc/{handlers.mjs → handlers.js} +5 -5
- package/rpc/routes/{index.mjs → index.js} +1 -1
- package/rpc/routes/{v1.mjs → v1.js} +1 -1
- package/rpc/{rpc_server.mjs → rpc_server.js} +1 -1
- package/rpc/rpc_services.js +4 -4
- package/src/config/config.js +137 -0
- package/src/config/env.js +61 -0
- package/src/core/network/Network.js +131 -72
- package/src/core/network/identity/NetworkWalletFactory.js +3 -4
- package/src/core/network/messaging/NetworkMessages.js +12 -11
- package/src/core/network/messaging/handlers/GetRequestHandler.js +5 -4
- package/src/core/network/messaging/handlers/ResponseHandler.js +4 -5
- package/src/core/network/messaging/handlers/RoleOperationHandler.js +17 -19
- package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +44 -38
- package/src/core/network/messaging/handlers/TransferOperationHandler.js +29 -25
- package/src/core/network/messaging/handlers/base/BaseOperationHandler.js +20 -21
- package/src/core/network/messaging/routes/NetworkMessageRouter.js +24 -20
- package/src/core/network/messaging/validators/AdminResponse.js +2 -2
- package/src/core/network/messaging/validators/CustomNodeResponse.js +2 -2
- package/src/core/network/messaging/validators/PartialBootstrapDeployment.js +3 -3
- package/src/core/network/messaging/validators/PartialRoleAccess.js +15 -12
- package/src/core/network/messaging/validators/PartialTransaction.js +9 -10
- package/src/core/network/messaging/validators/PartialTransfer.js +10 -7
- package/src/core/network/messaging/validators/ValidatorResponse.js +2 -2
- package/src/core/network/messaging/validators/base/BaseResponse.js +13 -5
- package/src/core/network/messaging/validators/base/PartialOperation.js +37 -21
- package/src/core/network/services/ConnectionManager.js +248 -62
- package/src/core/network/services/MessageOrchestrator.js +83 -0
- package/src/core/network/services/TransactionPoolService.js +9 -8
- package/src/core/network/services/ValidatorObserverService.js +95 -34
- package/src/core/state/State.js +136 -139
- package/src/core/state/utils/address.js +18 -16
- package/src/core/state/utils/adminEntry.js +17 -16
- package/src/core/state/utils/deploymentEntry.js +15 -15
- package/src/core/state/utils/transaction.js +3 -95
- package/src/index.js +153 -201
- package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +36 -32
- package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +39 -42
- package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +20 -20
- package/src/messages/partialStateMessages/PartialStateMessageOperations.js +29 -22
- package/src/utils/check.js +21 -17
- package/src/utils/cliCommands.js +11 -11
- package/src/utils/constants.js +2 -9
- package/src/utils/fileUtils.js +1 -4
- package/src/utils/helpers.js +9 -20
- package/src/utils/migrationUtils.js +2 -2
- package/src/utils/normalizers.js +10 -9
- package/tests/acceptance/v1/account/account.test.mjs +2 -2
- package/tests/acceptance/v1/balance/balance.test.mjs +1 -1
- package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +11 -2
- package/tests/acceptance/v1/rpc.test.mjs +9 -9
- package/tests/acceptance/v1/tx/tx.test.mjs +4 -2
- package/tests/acceptance/v1/tx-details/tx-details.test.mjs +7 -3
- package/tests/fixtures/check.fixtures.js +42 -42
- package/tests/fixtures/protobuf.fixtures.js +27 -26
- package/tests/helpers/StateNetworkFactory.js +3 -5
- package/tests/helpers/autobaseTestHelpers.js +48 -2
- package/tests/helpers/config.js +3 -0
- package/tests/helpers/setupApplyTests.js +89 -82
- package/tests/helpers/transactionPayloads.mjs +26 -12
- package/tests/integration/apply/addAdmin/addAdminBasic.test.js +10 -9
- package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +20 -19
- package/tests/integration/apply/addIndexer.test.js +23 -21
- package/tests/integration/apply/addWhitelist.test.js +9 -9
- package/tests/integration/apply/addWriter.test.js +33 -32
- package/tests/integration/apply/banValidator.test.js +16 -9
- package/tests/integration/apply/postTx/invalidSubValues.test.js +4 -4
- package/tests/integration/apply/postTx/postTx.test.js +7 -33
- package/tests/integration/apply/removeIndexer.test.js +11 -7
- package/tests/integration/apply/removeWriter.test.js +20 -19
- package/tests/integration/apply/transfer.test.js +18 -16
- package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +2 -2
- package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +2 -1
- package/tests/unit/messageOperations/assembleAdminMessage.test.js +9 -10
- package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +3 -2
- package/tests/unit/messageOperations/assemblePostTransaction.test.js +25 -43
- package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +2 -2
- package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +2 -2
- package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +5 -4
- package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +4 -3
- package/tests/unit/network/ConnectionManager.test.js +41 -70
- package/tests/unit/network/NetworkWalletFactory.test.js +14 -14
- package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +6 -6
- package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +8 -8
- package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +6 -5
- package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +24 -23
- package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +10 -16
- package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +2 -1
- package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +45 -41
- package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +3 -7
- package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +17 -16
- package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +3 -4
- package/tests/unit/state/apply/balanceInitialization/nodeEntryBalanceUpdateFailureScenario.js +2 -1
- package/tests/unit/state/apply/banValidator/banValidatorBanAndReWhitelistScenario.js +2 -1
- package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +23 -25
- package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +2 -1
- package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +19 -18
- package/tests/unit/state/apply/common/access-control/adminConsistencyMismatchScenario.js +5 -4
- package/tests/unit/state/apply/common/access-control/adminPublicKeyDecodeFailureScenario.js +4 -3
- package/tests/unit/state/apply/common/balances/base/requesterBalanceScenarioBase.js +2 -1
- package/tests/unit/state/apply/common/commonScenarioHelper.js +3 -4
- package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +2 -2
- package/tests/unit/state/apply/common/payload-structure/invalidHashValidationScenario.js +2 -2
- package/tests/unit/state/apply/common/requester/requesterNodeEntryBufferMissingScenario.js +2 -1
- package/tests/unit/state/apply/common/requester/requesterNodeEntryDecodeFailureScenario.js +2 -1
- package/tests/unit/state/apply/common/validatorConsistency/base/validatorConsistencyScenarioBase.js +2 -1
- package/tests/unit/state/apply/common/validatorEntryValidation/base/validatorEntryValidationScenarioBase.js +2 -1
- package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +11 -10
- package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +6 -5
- package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +6 -7
- package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +35 -34
- package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +44 -43
- package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +26 -25
- package/tests/unit/state/apply/txOperation/txOperationTransferFeeGuardScenarioFactory.js +2 -1
- package/tests/unit/state/stateModule.test.js +0 -1
- package/tests/unit/state/stateTestUtils.js +7 -3
- package/tests/unit/state/utils/address.test.js +3 -3
- package/tests/unit/state/utils/adminEntry.test.js +10 -9
- package/tests/unit/utils/check/adminControlOperation.test.js +3 -3
- package/tests/unit/utils/check/balanceInitializationOperation.test.js +2 -2
- package/tests/unit/utils/check/bootstrapDeploymentOperation.test.js +2 -3
- package/tests/unit/utils/check/common.test.js +7 -6
- package/tests/unit/utils/check/coreAdminOperation.test.js +3 -3
- package/tests/unit/utils/check/roleAccessOperation.test.js +3 -2
- package/tests/unit/utils/check/transactionOperation.test.js +3 -3
- package/tests/unit/utils/check/transferOperation.test.js +3 -3
- package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +2 -1
- package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +2 -1
- package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +7 -0
- package/tests/unit/utils/utils.test.js +0 -1
- package/src/core/state/utils/indexerEntry.js +0 -105
- package/src/utils/crypto.js +0 -11
- package/tests/unit/state/utils/indexerEntry.test.js +0 -83
- package/tests/unit/state/utils/transaction.test.js +0 -97
- package/tests/unit/utils/crypto/createHash.test.js +0 -15
- /package/rpc/{constants.mjs → constants.js} +0 -0
- /package/rpc/{cors.mjs → cors.js} +0 -0
- /package/rpc/utils/{confirmedParameter.mjs → confirmedParameter.js} +0 -0
- /package/rpc/utils/{helpers.mjs → helpers.js} +0 -0
- /package/rpc/utils/{url.mjs → url.js} +0 -0
|
@@ -1,27 +1,50 @@
|
|
|
1
1
|
import PeerWallet from "trac-wallet";
|
|
2
2
|
import b4a from "b4a";
|
|
3
|
-
import { MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION
|
|
3
|
+
import { MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION } from '../../../utils/constants.js';
|
|
4
4
|
import { bufferToAddress } from '../../state/utils/address.js';
|
|
5
5
|
import { sleep } from '../../../utils/helpers.js';
|
|
6
6
|
import Scheduler from "../../../utils/Scheduler.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const DELAY_INTERVAL =
|
|
7
|
+
import Network from "../Network.js";
|
|
8
|
+
|
|
9
|
+
const DELAY_INTERVAL = 50
|
|
10
|
+
const VALIDATOR_CANDIDATES_PER_CYCLE = 10
|
|
11
|
+
const POLL_INTERVAL = (VALIDATOR_CANDIDATES_PER_CYCLE + 1) * DELAY_INTERVAL // This is to avoid more than one instance of the worker running at the same time
|
|
12
|
+
|
|
13
|
+
// -- Debug Mode --
|
|
14
|
+
// TODO: Implement a better debug system in the future. This is just temporary.
|
|
15
|
+
const DEBUG = false;
|
|
16
|
+
const debugLog = (...args) => {
|
|
17
|
+
if (DEBUG) {
|
|
18
|
+
console.log('DEBUG [ValidatorObserverService] ==> ', ...args);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
10
21
|
|
|
11
22
|
class ValidatorObserverService {
|
|
12
|
-
#
|
|
23
|
+
#config;
|
|
13
24
|
#state;
|
|
14
25
|
#network;
|
|
15
26
|
#scheduler;
|
|
16
27
|
#address;
|
|
17
28
|
#isInterrupted
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @param {Network} network
|
|
32
|
+
* @param {State} state
|
|
33
|
+
* @param {string} address
|
|
34
|
+
* @param {object} config
|
|
35
|
+
**/
|
|
36
|
+
constructor(network, state, address, config) {
|
|
37
|
+
this.#config = config
|
|
21
38
|
this.#network = network;
|
|
22
39
|
this.#state = state;
|
|
23
40
|
this.#address = address;
|
|
24
41
|
this.#isInterrupted = false;
|
|
42
|
+
if (DEBUG) {
|
|
43
|
+
this.initTimestamp = Date.now();
|
|
44
|
+
this.reachedMax = false;
|
|
45
|
+
this.end = 0;
|
|
46
|
+
this.begin = 0;
|
|
47
|
+
}
|
|
25
48
|
}
|
|
26
49
|
|
|
27
50
|
get state() {
|
|
@@ -55,36 +78,80 @@ class ValidatorObserverService {
|
|
|
55
78
|
}
|
|
56
79
|
|
|
57
80
|
async #worker(next) {
|
|
58
|
-
if (!this.#network.validatorConnectionManager.
|
|
81
|
+
if (!this.#network.validatorConnectionManager.maxConnectionsReached()) {
|
|
82
|
+
if (DEBUG) this.begin = Date.now();
|
|
59
83
|
const length = await this.#lengthEntry()
|
|
60
84
|
|
|
61
85
|
const promises = [];
|
|
62
|
-
for (let i = 0; i <
|
|
63
|
-
promises.push(this.#findValidator(this.#address, length));
|
|
86
|
+
for (let i = 0; i < VALIDATOR_CANDIDATES_PER_CYCLE; i++) {
|
|
87
|
+
promises.push(this.#findValidator(this.#address, length + 1));
|
|
64
88
|
await sleep(DELAY_INTERVAL); // Low key dangerous as the network progresses
|
|
65
89
|
}
|
|
66
90
|
await Promise.all(promises);
|
|
91
|
+
|
|
92
|
+
if (DEBUG) this.end = Date.now();
|
|
93
|
+
debugLog('Worker cycle completed in (ms):', this.end - this.begin, '| Validator Connections:', this.#network.validatorConnectionManager.connectionCount(), " | Pending: ", this.#network.pendingConnectionsCount());
|
|
67
94
|
}
|
|
68
|
-
|
|
95
|
+
else if (DEBUG) {
|
|
96
|
+
if (!this.reachedMax) {
|
|
97
|
+
this.reachedMax = true;
|
|
98
|
+
debugLog('Max validator connections reached. Skipping this cycle.');
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
const elapsed = now - this.initTimestamp;
|
|
101
|
+
debugLog('>>> Time elapsed since start (ms):', elapsed);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
next(POLL_INTERVAL);
|
|
69
105
|
}
|
|
70
106
|
|
|
71
|
-
async #findValidator(address,
|
|
72
|
-
if (
|
|
107
|
+
async #findValidator(address, validatorListLength) {
|
|
108
|
+
if (!this.#shouldRun()) return;
|
|
109
|
+
const maxAttempts = 50; // TODO: make configurable
|
|
110
|
+
let attempts = 0;
|
|
111
|
+
let isValidatorValid = false;
|
|
112
|
+
let validatorAddressBuffer = b4a.alloc(0);
|
|
113
|
+
|
|
114
|
+
while (attempts < maxAttempts && !isValidatorValid) {
|
|
115
|
+
const rndIndex = Math.floor(Math.random() * validatorListLength);
|
|
116
|
+
validatorAddressBuffer = await this.state.getWriterIndex(rndIndex);
|
|
117
|
+
isValidatorValid = await this.#isValidatorValid(address, validatorAddressBuffer, validatorListLength);
|
|
118
|
+
attempts++;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (attempts >= maxAttempts) {
|
|
122
|
+
debugLog('Max attempts reached without finding a valid validator.');
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
debugLog(`Found valid validator to connect after ${attempts} attempts.`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (!isValidatorValid) return;
|
|
73
129
|
|
|
74
|
-
const
|
|
75
|
-
const
|
|
130
|
+
const validatorAddress = bufferToAddress(validatorAddressBuffer, this.#config.addressPrefix);
|
|
131
|
+
const validatorPubKeyBuffer = PeerWallet.decodeBech32m(validatorAddress);
|
|
132
|
+
const validatorPubKeyHex = validatorPubKeyBuffer.toString('hex');
|
|
133
|
+
const adminEntry = await this.state.getAdminEntry();
|
|
134
|
+
|
|
135
|
+
if (validatorAddress !== adminEntry?.address || validatorListLength < MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION) {
|
|
136
|
+
this.#network.tryConnect(validatorPubKeyHex, 'validator');
|
|
137
|
+
}
|
|
138
|
+
};
|
|
76
139
|
|
|
77
|
-
|
|
140
|
+
async #isValidatorValid(forbiddenAddress, validatorAddressBuffer, validatorListLength) {
|
|
141
|
+
if (validatorAddressBuffer === null || b4a.byteLength(validatorAddressBuffer) !== this.#config.addressLength) return false;
|
|
78
142
|
|
|
79
|
-
const validatorAddress = bufferToAddress(validatorAddressBuffer);
|
|
80
|
-
if (validatorAddress ===
|
|
143
|
+
const validatorAddress = bufferToAddress(validatorAddressBuffer, this.#config.addressPrefix);
|
|
144
|
+
if (validatorAddress === forbiddenAddress) return false;
|
|
81
145
|
|
|
82
|
-
const
|
|
146
|
+
const validatorPubKeyBuffer = PeerWallet.decodeBech32m(validatorAddress);
|
|
83
147
|
const validatorEntry = await this.state.getNodeEntry(validatorAddress);
|
|
84
148
|
const adminEntry = await this.state.getAdminEntry();
|
|
85
149
|
|
|
86
|
-
if (
|
|
87
|
-
|
|
150
|
+
if (this.#network.isConnectionPending(validatorPubKeyBuffer.toString('hex'))) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (validatorAddress === adminEntry?.address && validatorListLength >= MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION) {
|
|
88
155
|
if (this.#network.validatorConnectionManager.exists(validatorPubKeyBuffer)) {
|
|
89
156
|
this.#network.validatorConnectionManager.remove(validatorPubKeyBuffer)
|
|
90
157
|
}
|
|
@@ -95,28 +162,22 @@ class ValidatorObserverService {
|
|
|
95
162
|
// - Validator must exist and be a writer
|
|
96
163
|
// - Cannot connect to indexers, except for admin-indexer
|
|
97
164
|
// - Admin-indexer connection is allowed only when writers length has less than 10 writers
|
|
98
|
-
if (
|
|
99
|
-
this.#network.validatorConnectionManager.
|
|
165
|
+
if (this.#network.validatorConnectionManager.connected(validatorPubKeyBuffer) ||
|
|
166
|
+
this.#network.validatorConnectionManager.maxConnectionsReached() ||
|
|
100
167
|
validatorEntry === null ||
|
|
101
168
|
!validatorEntry.isWriter ||
|
|
102
|
-
(validatorEntry.isIndexer && (validatorAddress !== adminEntry?.address ||
|
|
169
|
+
(validatorEntry.isIndexer && (validatorAddress !== adminEntry?.address || validatorListLength >= MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION))
|
|
103
170
|
) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (validatorAddress !== adminEntry?.address || length < MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION) {
|
|
108
|
-
await this.#network.tryConnect(validatorPubKey, 'validator');
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
#shouldRun() {
|
|
113
|
-
if (!this.#enable_validator_observer || this.#isInterrupted) {
|
|
114
171
|
return false;
|
|
115
172
|
}
|
|
116
173
|
|
|
117
174
|
return true;
|
|
118
175
|
}
|
|
119
176
|
|
|
177
|
+
#shouldRun() {
|
|
178
|
+
return this.#config.enableValidatorObserver && !this.#isInterrupted
|
|
179
|
+
}
|
|
180
|
+
|
|
120
181
|
async #lengthEntry() {
|
|
121
182
|
const lengthEntry = await this.state.getWriterLength();
|
|
122
183
|
return Number.isInteger(lengthEntry) && lengthEntry > 0 ? lengthEntry : 0;
|