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
|
@@ -2,7 +2,6 @@ import ReadyResource from 'ready-resource';
|
|
|
2
2
|
import Hyperswarm from 'hyperswarm';
|
|
3
3
|
import w from 'protomux-wakeup';
|
|
4
4
|
import b4a from 'b4a';
|
|
5
|
-
|
|
6
5
|
import TransactionPoolService from './services/TransactionPoolService.js';
|
|
7
6
|
import ValidatorObserverService from './services/ValidatorObserverService.js';
|
|
8
7
|
import NetworkMessages from './messaging/NetworkMessages.js';
|
|
@@ -13,34 +12,54 @@ import {
|
|
|
13
12
|
MAX_PARALLEL,
|
|
14
13
|
MAX_SERVER_CONNECTIONS,
|
|
15
14
|
MAX_CLIENT_CONNECTIONS,
|
|
16
|
-
NETWORK_MESSAGE_TYPES
|
|
17
|
-
DHT_BOOTSTRAPS
|
|
15
|
+
NETWORK_MESSAGE_TYPES
|
|
18
16
|
} from '../../utils/constants.js';
|
|
19
17
|
import ConnectionManager from './services/ConnectionManager.js';
|
|
18
|
+
import MessageOrchestrator from './services/MessageOrchestrator.js';
|
|
20
19
|
import NetworkWalletFactory from './identity/NetworkWalletFactory.js';
|
|
20
|
+
import { EventType } from '../../utils/constants.js';
|
|
21
|
+
|
|
22
|
+
// -- Debug Mode --
|
|
23
|
+
// TODO: Implement a better debug system in the future. This is just temporary.
|
|
24
|
+
const DEBUG = false;
|
|
25
|
+
const debugLog = (...args) => {
|
|
26
|
+
if (DEBUG) {
|
|
27
|
+
console.log('DEBUG [Network] ==> ', ...args);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
21
31
|
const wakeup = new w();
|
|
22
32
|
|
|
23
33
|
class Network extends ReadyResource {
|
|
24
|
-
#dht_bootstrap = DHT_BOOTSTRAPS;
|
|
25
34
|
#swarm = null;
|
|
26
|
-
#enable_wallet;
|
|
27
|
-
#channel;
|
|
28
35
|
#networkMessages;
|
|
29
36
|
#transactionPoolService;
|
|
30
37
|
#validatorObserverService;
|
|
31
38
|
#validatorConnectionManager;
|
|
32
|
-
#
|
|
39
|
+
#validatorMessageOrchestrator;
|
|
40
|
+
#config;
|
|
33
41
|
#identityProvider = null;
|
|
34
|
-
|
|
35
|
-
|
|
42
|
+
#pendingConnections;
|
|
43
|
+
#connectTimeoutMs;
|
|
44
|
+
#maxPendingConnections;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {State} state
|
|
48
|
+
* @param {object} config
|
|
49
|
+
* @param {string} address
|
|
50
|
+
**/
|
|
51
|
+
constructor(state, config, address = null) {
|
|
36
52
|
super();
|
|
37
|
-
this.#
|
|
38
|
-
this.#
|
|
39
|
-
this.#
|
|
40
|
-
|
|
41
|
-
this.#
|
|
42
|
-
this.#
|
|
43
|
-
this.#
|
|
53
|
+
this.#config = config
|
|
54
|
+
this.#connectTimeoutMs = config.connectTimeoutMs || 5000;
|
|
55
|
+
this.#maxPendingConnections = config.maxPendingConnections || 50;
|
|
56
|
+
|
|
57
|
+
this.#pendingConnections = new Map();
|
|
58
|
+
this.#transactionPoolService = new TransactionPoolService(state, address, this.#config);
|
|
59
|
+
this.#validatorObserverService = new ValidatorObserverService(this, state, address, this.#config);
|
|
60
|
+
this.#networkMessages = new NetworkMessages(this, this.#config);
|
|
61
|
+
this.#validatorConnectionManager = new ConnectionManager(this.#config);
|
|
62
|
+
this.#validatorMessageOrchestrator = new MessageOrchestrator(this.#validatorConnectionManager, state, this.#config);
|
|
44
63
|
this.admin_stream = null;
|
|
45
64
|
this.admin = null;
|
|
46
65
|
this.validator = null;
|
|
@@ -52,10 +71,6 @@ class Network extends ReadyResource {
|
|
|
52
71
|
return this.#swarm;
|
|
53
72
|
}
|
|
54
73
|
|
|
55
|
-
get channel() {
|
|
56
|
-
return this.#channel;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
74
|
get transactionPoolService() {
|
|
60
75
|
return this.#transactionPoolService;
|
|
61
76
|
}
|
|
@@ -68,8 +83,15 @@ class Network extends ReadyResource {
|
|
|
68
83
|
return this.#validatorConnectionManager;
|
|
69
84
|
}
|
|
70
85
|
|
|
86
|
+
get validatorMessageOrchestrator() {
|
|
87
|
+
return this.#validatorMessageOrchestrator;
|
|
88
|
+
}
|
|
89
|
+
|
|
71
90
|
async _open() {
|
|
72
91
|
console.log('Network initialization...');
|
|
92
|
+
|
|
93
|
+
this.setupNetworkListeners();
|
|
94
|
+
|
|
73
95
|
this.transactionPoolService.start();
|
|
74
96
|
this.validatorObserverService.start();
|
|
75
97
|
}
|
|
@@ -81,11 +103,53 @@ class Network extends ReadyResource {
|
|
|
81
103
|
this.#validatorObserverService.stopValidatorObserver();
|
|
82
104
|
await sleep(5_000);
|
|
83
105
|
|
|
106
|
+
this.cleanupNetworkListeners();
|
|
107
|
+
this.cleanupPendingConnections();
|
|
108
|
+
|
|
84
109
|
if (this.#swarm !== null) {
|
|
85
110
|
this.#swarm.destroy();
|
|
86
111
|
}
|
|
87
112
|
}
|
|
88
113
|
|
|
114
|
+
setupNetworkListeners() {
|
|
115
|
+
// VALIDATOR_CONNECTION_TIMEOUT
|
|
116
|
+
this.on(EventType.VALIDATOR_CONNECTION_TIMEOUT, ({ publicKey, type, timeoutMs }) => {
|
|
117
|
+
debugLog(`Network Event: VALIDATOR_CONNECTION_TIMEOUT | PublicKey: ${publicKey} | Type: ${type} | TimeoutMs: ${timeoutMs}`);
|
|
118
|
+
this.#pendingConnections.delete(publicKey);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
// VALIDATOR_CONNECTION_READY
|
|
122
|
+
this.on(EventType.VALIDATOR_CONNECTION_READY, ({ publicKey, type, connection }) => {
|
|
123
|
+
debugLog(`Network Event: VALIDATOR_CONNECTION_READY | PublicKey: ${publicKey} | Type: ${type}`);
|
|
124
|
+
const { timeoutId } = this.#pendingConnections.get(publicKey);
|
|
125
|
+
if (!timeoutId) return;
|
|
126
|
+
|
|
127
|
+
clearTimeout(timeoutId);
|
|
128
|
+
this.#pendingConnections.delete(publicKey);
|
|
129
|
+
|
|
130
|
+
if (type === 'validator') {
|
|
131
|
+
const target = b4a.from(publicKey, 'hex');
|
|
132
|
+
this.#validatorConnectionManager.addValidator(target, connection);
|
|
133
|
+
this.#sendRequestByType(connection, type);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
cleanupNetworkListeners() {
|
|
139
|
+
// connect:timeout
|
|
140
|
+
this.removeAllListeners('connect:timeout');
|
|
141
|
+
|
|
142
|
+
// connect:ready
|
|
143
|
+
this.removeAllListeners('connect:ready');
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
cleanupPendingConnections() {
|
|
147
|
+
for (const { timeoutId } of this.#pendingConnections.values()) {
|
|
148
|
+
clearTimeout(timeoutId);
|
|
149
|
+
}
|
|
150
|
+
this.#pendingConnections.clear();
|
|
151
|
+
}
|
|
152
|
+
|
|
89
153
|
async replicate(
|
|
90
154
|
state,
|
|
91
155
|
store,
|
|
@@ -96,14 +160,14 @@ class Network extends ReadyResource {
|
|
|
96
160
|
const wrappedWallet = this.#getNetworkWalletWrapper(wallet, keyPair);
|
|
97
161
|
this.#swarm = new Hyperswarm({
|
|
98
162
|
keyPair,
|
|
99
|
-
bootstrap: this.#
|
|
163
|
+
bootstrap: this.#config.dhtBootstrap,
|
|
100
164
|
maxPeers: MAX_PEERS,
|
|
101
165
|
maxParallel: MAX_PARALLEL,
|
|
102
166
|
maxServerConnections: MAX_SERVER_CONNECTIONS,
|
|
103
167
|
maxClientConnections: MAX_CLIENT_CONNECTIONS
|
|
104
168
|
});
|
|
105
169
|
|
|
106
|
-
console.log(`Channel: ${b4a.toString(this.#channel)}`);
|
|
170
|
+
console.log(`Channel: ${b4a.toString(this.#config.channel)}`);
|
|
107
171
|
this.#networkMessages.initializeMessageRouter(state, wrappedWallet);
|
|
108
172
|
|
|
109
173
|
this.#swarm.on('connection', async (connection) => {
|
|
@@ -114,6 +178,12 @@ class Network extends ReadyResource {
|
|
|
114
178
|
const stream = store.replicate(connection);
|
|
115
179
|
wakeup.addStream(stream);
|
|
116
180
|
|
|
181
|
+
const publicKey = b4a.toString(connection.remotePublicKey, 'hex');
|
|
182
|
+
if (this.#pendingConnections.has(publicKey)) {
|
|
183
|
+
const { type } = this.#pendingConnections.get(publicKey);
|
|
184
|
+
await this.#finalizeConnection(publicKey, type, connection);
|
|
185
|
+
}
|
|
186
|
+
|
|
117
187
|
connection.on('close', () => {
|
|
118
188
|
if (this.admin_stream === connection) {
|
|
119
189
|
this.admin_stream = null;
|
|
@@ -144,13 +214,21 @@ class Network extends ReadyResource {
|
|
|
144
214
|
|
|
145
215
|
});
|
|
146
216
|
|
|
147
|
-
this.#swarm.join(this.#channel, { server: true, client: true });
|
|
217
|
+
this.#swarm.join(this.#config.channel, { server: true, client: true });
|
|
148
218
|
this.#swarm.flush();
|
|
149
219
|
}
|
|
150
220
|
}
|
|
151
221
|
|
|
222
|
+
isConnectionPending(publicKey) {
|
|
223
|
+
return this.#pendingConnections.has(publicKey);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
pendingConnectionsCount() {
|
|
227
|
+
return this.#pendingConnections.size;
|
|
228
|
+
}
|
|
229
|
+
|
|
152
230
|
async initializeNetworkingKeyPair(store, wallet) {
|
|
153
|
-
if (!this.#
|
|
231
|
+
if (!this.#config.enableWallet) {
|
|
154
232
|
return await store.createKeyPair(TRAC_NAMESPACE);
|
|
155
233
|
} else {
|
|
156
234
|
return {
|
|
@@ -161,27 +239,28 @@ class Network extends ReadyResource {
|
|
|
161
239
|
}
|
|
162
240
|
|
|
163
241
|
async tryConnect(publicKey, type = null) {
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
let cnt = 0;
|
|
169
|
-
while (false === this.#swarm.peers.has(publicKey)) {
|
|
170
|
-
if (cnt >= 1500) break;
|
|
171
|
-
await sleep(10);
|
|
172
|
-
cnt += 1;
|
|
173
|
-
}
|
|
242
|
+
if (this.#swarm === null) throw new Error('Network swarm is not initialized');
|
|
243
|
+
if (this.#pendingConnections.has(publicKey) || this.#pendingConnections.size >= this.#maxPendingConnections) {
|
|
244
|
+
debugLog(`Network.tryConnect: Connection to peer: ${publicKey} as type: ${type} is already pending or max pending connections reached.`);
|
|
245
|
+
return;
|
|
174
246
|
}
|
|
175
247
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
248
|
+
const timeoutId = setTimeout(() => {
|
|
249
|
+
if (!this.#pendingConnections.has(publicKey)) return;
|
|
250
|
+
this.emit(EventType.VALIDATOR_CONNECTION_TIMEOUT, { publicKey, type, timeoutMs: this.#connectTimeoutMs });
|
|
251
|
+
}, this.#connectTimeoutMs);
|
|
252
|
+
this.#pendingConnections.set(publicKey, { type, timeoutId });
|
|
253
|
+
|
|
254
|
+
const target = b4a.from(publicKey, 'hex');
|
|
255
|
+
if (!this.#swarm.peers.has(publicKey)) {
|
|
256
|
+
this.#swarm.joinPeer(target);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const peerInfo = this.#swarm.peers.get(publicKey);
|
|
260
|
+
if (peerInfo) {
|
|
261
|
+
const connection = this.#swarm._allConnections.get(peerInfo.publicKey);
|
|
262
|
+
if (connection && connection.messenger) {
|
|
263
|
+
await this.#finalizeConnection(publicKey, type, connection);
|
|
185
264
|
}
|
|
186
265
|
}
|
|
187
266
|
}
|
|
@@ -191,6 +270,12 @@ class Network extends ReadyResource {
|
|
|
191
270
|
this.#swarm.peers.get(publicKey).connectedTime != -1
|
|
192
271
|
}
|
|
193
272
|
|
|
273
|
+
async #finalizeConnection(publicKey, type, connection) {
|
|
274
|
+
if (!this.#pendingConnections.has(publicKey)) return;
|
|
275
|
+
this.emit(EventType.VALIDATOR_CONNECTION_READY, { publicKey, type, connection });
|
|
276
|
+
debugLog(`Network.finalizeConnection: Connected to peer: ${publicKey} as type: ${type}`);
|
|
277
|
+
}
|
|
278
|
+
|
|
194
279
|
async #sendRequestByType(stream, type) {
|
|
195
280
|
const waitFor = {
|
|
196
281
|
validator: () => this.validatorConnectionManager.connectionCount(),
|
|
@@ -207,7 +292,7 @@ class Network extends ReadyResource {
|
|
|
207
292
|
} else {
|
|
208
293
|
return;
|
|
209
294
|
}
|
|
210
|
-
await this.spinLock(() => !waitFor)
|
|
295
|
+
await this.spinLock(() => !waitFor())
|
|
211
296
|
};
|
|
212
297
|
|
|
213
298
|
async spinLock(conditionFn, maxIterations = 1500, intervalMs = 10) {
|
|
@@ -218,39 +303,13 @@ class Network extends ReadyResource {
|
|
|
218
303
|
}
|
|
219
304
|
}
|
|
220
305
|
|
|
221
|
-
async sendMessageToNode(nodePublicKey, message) {
|
|
222
|
-
try {
|
|
223
|
-
if (!nodePublicKey || !message) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
await this.tryConnect(nodePublicKey, 'node');
|
|
227
|
-
|
|
228
|
-
await this.spinLock(() =>
|
|
229
|
-
this.custom_stream === null ||
|
|
230
|
-
!b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
|
|
231
|
-
);
|
|
232
|
-
if (
|
|
233
|
-
this.custom_stream !== null &&
|
|
234
|
-
this.custom_node !== null &&
|
|
235
|
-
b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
|
|
236
|
-
) {
|
|
237
|
-
await this.custom_stream.messenger.send(message);
|
|
238
|
-
} else {
|
|
239
|
-
throw new Error(`Failed to send message to node: ${nodePublicKey}`);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
} catch (e) {
|
|
243
|
-
console.log(e)
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
|
|
247
306
|
#getNetworkWalletWrapper(wallet, keyPair) {
|
|
248
307
|
if (!this.#identityProvider) {
|
|
249
308
|
this.#identityProvider = NetworkWalletFactory.provide({
|
|
250
|
-
enableWallet: this.#
|
|
309
|
+
enableWallet: this.#config.enableWallet,
|
|
251
310
|
wallet,
|
|
252
311
|
keyPair,
|
|
253
|
-
networkPrefix: this.#
|
|
312
|
+
networkPrefix: this.#config.addressPrefix
|
|
254
313
|
});
|
|
255
314
|
}
|
|
256
315
|
return this.#identityProvider;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import PeerWallet from 'trac-wallet';
|
|
2
|
-
import { TRAC_NETWORK_MSB_MAINNET_PREFIX } from 'trac-wallet/constants.js';
|
|
3
2
|
import b4a from 'b4a';
|
|
4
3
|
|
|
5
4
|
export class NetworkWalletFactory {
|
|
6
5
|
static provide(options = {}) {
|
|
7
6
|
const {
|
|
8
|
-
enableWallet
|
|
7
|
+
enableWallet,
|
|
9
8
|
wallet,
|
|
10
9
|
keyPair,
|
|
11
|
-
networkPrefix
|
|
10
|
+
networkPrefix
|
|
12
11
|
} = options;
|
|
13
12
|
|
|
14
13
|
if (enableWallet) {
|
|
@@ -34,7 +33,7 @@ class EphemeralWallet {
|
|
|
34
33
|
#secretKey;
|
|
35
34
|
#address;
|
|
36
35
|
|
|
37
|
-
constructor(keyPair, networkPrefix
|
|
36
|
+
constructor(keyPair, networkPrefix) {
|
|
38
37
|
|
|
39
38
|
if (!keyPair?.publicKey || !keyPair?.secretKey) {
|
|
40
39
|
throw new Error('NetworkIdentityProvider: keyPair with publicKey and secretKey is required');
|
|
@@ -3,27 +3,28 @@ import Protomux from 'protomux';
|
|
|
3
3
|
import b4a from 'b4a';
|
|
4
4
|
import c from 'compact-encoding';
|
|
5
5
|
import NetworkMessageRouter from './routes/NetworkMessageRouter.js';
|
|
6
|
+
import Network from '../Network.js';
|
|
6
7
|
|
|
7
8
|
class NetworkMessages {
|
|
8
9
|
#messageRouter;
|
|
9
10
|
#network;
|
|
10
|
-
#
|
|
11
|
+
#config;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @param {Network} network
|
|
15
|
+
* @param {object} config
|
|
16
|
+
**/
|
|
17
|
+
constructor(network, config) {
|
|
13
18
|
this.#network = network;
|
|
14
|
-
this.#
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
get network() {
|
|
18
|
-
return this.#network;
|
|
19
|
+
this.#config = config;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
initializeMessageRouter(state, wallet) {
|
|
22
23
|
this.#messageRouter = new NetworkMessageRouter(
|
|
23
|
-
this
|
|
24
|
+
this.#network,
|
|
24
25
|
state,
|
|
25
26
|
wallet,
|
|
26
|
-
this.#
|
|
27
|
+
this.#config
|
|
27
28
|
);
|
|
28
29
|
}
|
|
29
30
|
|
|
@@ -31,7 +32,7 @@ class NetworkMessages {
|
|
|
31
32
|
const mux = Protomux.from(connection);
|
|
32
33
|
connection.userData = mux;
|
|
33
34
|
const message_channel = mux.createChannel({
|
|
34
|
-
protocol: b4a.toString(this.
|
|
35
|
+
protocol: b4a.toString(this.#config.channel, 'utf8'),
|
|
35
36
|
onopen() { },
|
|
36
37
|
onclose() { }
|
|
37
38
|
});
|
|
@@ -50,7 +51,7 @@ class NetworkMessages {
|
|
|
50
51
|
} catch (error) {
|
|
51
52
|
console.error(`NetworkMessages: Failed to handle incoming message: ${error.message}`);
|
|
52
53
|
} finally {
|
|
53
|
-
this
|
|
54
|
+
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
57
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { NETWORK_MESSAGE_TYPES } from '../../../../utils/constants.js';
|
|
2
2
|
import PeerWallet from 'trac-wallet';
|
|
3
3
|
import b4a from 'b4a';
|
|
4
|
-
import { blake3Hash } from '../../../../utils/crypto.js';
|
|
5
4
|
|
|
6
5
|
class GetRequestHandler {
|
|
7
6
|
#wallet;
|
|
@@ -44,7 +43,9 @@ class GetRequestHandler {
|
|
|
44
43
|
timestamp: Date.now(),
|
|
45
44
|
};
|
|
46
45
|
|
|
47
|
-
|
|
46
|
+
|
|
47
|
+
const hashInput = b4a.from(JSON.stringify(payload), 'utf8');
|
|
48
|
+
const hash = await PeerWallet.blake3(hashInput);
|
|
48
49
|
const sig = this.#wallet.sign(hash);
|
|
49
50
|
|
|
50
51
|
const responseMessage = {
|
|
@@ -76,7 +77,7 @@ class GetRequestHandler {
|
|
|
76
77
|
issuer: connection.remotePublicKey.toString('hex'),
|
|
77
78
|
timestamp: Date.now(),
|
|
78
79
|
};
|
|
79
|
-
const hash = await
|
|
80
|
+
const hash = await PeerWallet.blake3(JSON.stringify(payload));
|
|
80
81
|
const sig = this.#wallet.sign(hash);
|
|
81
82
|
|
|
82
83
|
const responseMessage = {
|
|
@@ -97,7 +98,7 @@ class GetRequestHandler {
|
|
|
97
98
|
timestamp: Date.now(),
|
|
98
99
|
};
|
|
99
100
|
|
|
100
|
-
const hash = await
|
|
101
|
+
const hash = await PeerWallet.blake3(JSON.stringify(payload));
|
|
101
102
|
const sig = this.#wallet.sign(hash);
|
|
102
103
|
|
|
103
104
|
const responseMessage = {
|
|
@@ -3,7 +3,6 @@ import ValidatorResponse from '../validators/ValidatorResponse.js';
|
|
|
3
3
|
import AdminResponse from '../validators/AdminResponse.js';
|
|
4
4
|
import CustomNodeResponse from '../validators/CustomNodeResponse.js';
|
|
5
5
|
import PeerWallet from 'trac-wallet';
|
|
6
|
-
import b4a from "b4a";
|
|
7
6
|
|
|
8
7
|
class ResponseHandler {
|
|
9
8
|
#network;
|
|
@@ -12,12 +11,12 @@ class ResponseHandler {
|
|
|
12
11
|
#adminValidator;
|
|
13
12
|
#customNodeValidator;
|
|
14
13
|
|
|
15
|
-
constructor(network, state, wallet) {
|
|
14
|
+
constructor(network, state, wallet, config) {
|
|
16
15
|
this.#network = network;
|
|
17
16
|
this.#state = state;
|
|
18
|
-
this.#responseValidator = new ValidatorResponse(this.state, wallet);
|
|
19
|
-
this.#adminValidator = new AdminResponse(this.state, wallet);
|
|
20
|
-
this.#customNodeValidator = new CustomNodeResponse(this.state, wallet);
|
|
17
|
+
this.#responseValidator = new ValidatorResponse(this.state, wallet, config);
|
|
18
|
+
this.#adminValidator = new AdminResponse(this.state, wallet, config);
|
|
19
|
+
this.#customNodeValidator = new CustomNodeResponse(this.state, wallet, config);
|
|
21
20
|
|
|
22
21
|
}
|
|
23
22
|
|
|
@@ -10,20 +10,21 @@ class RoleOperationHandler extends BaseOperationHandler {
|
|
|
10
10
|
#partialRoleAccessValidator;
|
|
11
11
|
#wallet;
|
|
12
12
|
#network;
|
|
13
|
+
#config;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* @param {Network} network
|
|
17
|
+
* @param {State} state
|
|
18
|
+
* @param {PeerWallet} wallet
|
|
19
|
+
* @param {TransactionRateLimiterService} rateLimiter
|
|
20
|
+
* @param {object} config
|
|
21
|
+
**/
|
|
22
|
+
constructor(network, state, wallet, rateLimiter, config) {
|
|
23
|
+
super(network, state, wallet, rateLimiter, config);
|
|
16
24
|
this.#wallet = wallet;
|
|
25
|
+
this.#config = config;
|
|
17
26
|
this.#network = network;
|
|
18
|
-
this.#partialRoleAccessValidator = new PartialRoleAccess(state)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
get wallet() {
|
|
22
|
-
return this.#wallet;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get network() {
|
|
26
|
-
return this.#network;
|
|
27
|
+
this.#partialRoleAccessValidator = new PartialRoleAccess(state, wallet ,this.#config)
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
get partialRoleAccessValidator() {
|
|
@@ -40,8 +41,7 @@ class RoleOperationHandler extends BaseOperationHandler {
|
|
|
40
41
|
|
|
41
42
|
switch (normalizedPartialRoleAccessPayload.type) {
|
|
42
43
|
case OperationType.ADD_WRITER:
|
|
43
|
-
completePayload = await CompleteStateMessageOperations.assembleAddWriterMessage(
|
|
44
|
-
this.wallet,
|
|
44
|
+
completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleAddWriterMessage(
|
|
45
45
|
normalizedPartialRoleAccessPayload.address,
|
|
46
46
|
normalizedPartialRoleAccessPayload.rao.tx,
|
|
47
47
|
normalizedPartialRoleAccessPayload.rao.txv,
|
|
@@ -51,8 +51,7 @@ class RoleOperationHandler extends BaseOperationHandler {
|
|
|
51
51
|
);
|
|
52
52
|
break;
|
|
53
53
|
case OperationType.REMOVE_WRITER:
|
|
54
|
-
completePayload = await CompleteStateMessageOperations.assembleRemoveWriterMessage(
|
|
55
|
-
this.wallet,
|
|
54
|
+
completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleRemoveWriterMessage(
|
|
56
55
|
normalizedPartialRoleAccessPayload.address,
|
|
57
56
|
normalizedPartialRoleAccessPayload.rao.tx,
|
|
58
57
|
normalizedPartialRoleAccessPayload.rao.txv,
|
|
@@ -62,8 +61,7 @@ class RoleOperationHandler extends BaseOperationHandler {
|
|
|
62
61
|
);
|
|
63
62
|
break;
|
|
64
63
|
case OperationType.ADMIN_RECOVERY:
|
|
65
|
-
completePayload = await CompleteStateMessageOperations.assembleAdminRecoveryMessage(
|
|
66
|
-
this.wallet,
|
|
64
|
+
completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleAdminRecoveryMessage(
|
|
67
65
|
normalizedPartialRoleAccessPayload.address,
|
|
68
66
|
normalizedPartialRoleAccessPayload.rao.tx,
|
|
69
67
|
normalizedPartialRoleAccessPayload.rao.txv,
|
|
@@ -81,7 +79,7 @@ class RoleOperationHandler extends BaseOperationHandler {
|
|
|
81
79
|
throw new Error("OperationHandler: Assembling complete role access operation failed.");
|
|
82
80
|
}
|
|
83
81
|
|
|
84
|
-
this
|
|
82
|
+
this.#network.transactionPoolService.addTransaction(completePayload)
|
|
85
83
|
}
|
|
86
84
|
|
|
87
85
|
#normalizePartialRoleAccess(payload) {
|
|
@@ -107,7 +105,7 @@ class RoleOperationHandler extends BaseOperationHandler {
|
|
|
107
105
|
|
|
108
106
|
return {
|
|
109
107
|
type,
|
|
110
|
-
address: addressToBuffer(address),
|
|
108
|
+
address: addressToBuffer(address, this.#config.addressPrefix),
|
|
111
109
|
rao: normalizedRao
|
|
112
110
|
};
|
|
113
111
|
}
|
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
import BaseOperationHandler from './base/BaseOperationHandler.js';
|
|
2
|
-
import CompleteStateMessageOperations
|
|
2
|
+
import CompleteStateMessageOperations
|
|
3
|
+
from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
|
|
3
4
|
import {
|
|
4
5
|
OperationType
|
|
5
6
|
} from '../../../../utils/constants.js';
|
|
6
7
|
import PartialBootstrapDeployment from "../validators/PartialBootstrapDeployment.js";
|
|
7
|
-
import {addressToBuffer
|
|
8
|
+
import {addressToBuffer} from "../../../state/utils/address.js";
|
|
8
9
|
import PartialTransaction from "../validators/PartialTransaction.js";
|
|
9
10
|
import {normalizeHex} from "../../../../utils/helpers.js";
|
|
10
11
|
|
|
11
|
-
/**
|
|
12
|
-
* THIS CLASS IS ULTRA IMPORTANT BECAUSE IF SOMEONE WILL SEND A TRASH TO VALIDATOR AND IT WON'T BE HANDLED PROPERTLY -
|
|
13
|
-
* FOR EXAMPLE VALIDATOR WILL BROADCAST IT TO THE INDEXER LAYER THEN IT WILL BE BANNED. SO EVERYTHING WHAT IS TRASH
|
|
14
|
-
* MUST BE REFUSED.
|
|
15
|
-
* TODO: WE SHOULD AUDIT VALIDATORS AND MAKE SURE THEY ARE NOT BROADCASTING TRASH TO THE INDEXER LAYER.
|
|
16
|
-
*/
|
|
17
12
|
|
|
18
13
|
class SubnetworkOperationHandler extends BaseOperationHandler {
|
|
19
14
|
#partialBootstrapDeploymentValidator;
|
|
20
15
|
#partialTransactionValidator;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
#config;
|
|
17
|
+
#wallet;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Network} network
|
|
21
|
+
* @param {State} state
|
|
22
|
+
* @param {PeerWallet} wallet
|
|
23
|
+
* @param {TransactionRateLimiterService} rateLimiter
|
|
24
|
+
* @param {object} config
|
|
25
|
+
**/
|
|
26
|
+
constructor(network, state, wallet, rateLimiter, config) {
|
|
27
|
+
super(network, state, wallet, rateLimiter, config);
|
|
28
|
+
this.#config = config
|
|
29
|
+
this.#wallet = wallet
|
|
30
|
+
this.#partialBootstrapDeploymentValidator = new PartialBootstrapDeployment(state, wallet, config);
|
|
31
|
+
this.#partialTransactionValidator = new PartialTransaction(state, wallet, config);
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
async handleOperation(payload) {
|
|
@@ -36,24 +42,24 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
|
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
async #partialTransactionSubHandler(payload) {
|
|
39
|
-
const normalizedPayload = this.#normalizeTransactionOperation(payload);
|
|
45
|
+
const normalizedPayload = this.#normalizeTransactionOperation(payload, this.#config);
|
|
40
46
|
const isValid = await this.#partialTransactionValidator.validate(normalizedPayload);
|
|
41
47
|
if (!isValid) {
|
|
42
48
|
throw new Error("SubnetworkHandler: Transaction validation failed.");
|
|
43
49
|
}
|
|
44
50
|
|
|
45
|
-
const completeTransactionOperation = await CompleteStateMessageOperations
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
const completeTransactionOperation = await new CompleteStateMessageOperations(this.#wallet, this.#config)
|
|
52
|
+
.assembleCompleteTransactionOperationMessage(
|
|
53
|
+
normalizedPayload.address,
|
|
54
|
+
normalizedPayload.txo.tx,
|
|
55
|
+
normalizedPayload.txo.txv,
|
|
56
|
+
normalizedPayload.txo.iw,
|
|
57
|
+
normalizedPayload.txo.in,
|
|
58
|
+
normalizedPayload.txo.ch,
|
|
59
|
+
normalizedPayload.txo.is,
|
|
60
|
+
normalizedPayload.txo.bs,
|
|
61
|
+
normalizedPayload.txo.mbs
|
|
62
|
+
);
|
|
57
63
|
this.network.transactionPoolService.addTransaction(completeTransactionOperation);
|
|
58
64
|
}
|
|
59
65
|
|
|
@@ -64,16 +70,16 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
|
|
|
64
70
|
throw new Error("SubnetworkHandler: Bootstrap deployment validation failed.");
|
|
65
71
|
}
|
|
66
72
|
|
|
67
|
-
const completeBootstrapDeploymentOperation = await CompleteStateMessageOperations
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
const completeBootstrapDeploymentOperation = await new CompleteStateMessageOperations(this.#wallet, this.#config)
|
|
74
|
+
.assembleCompleteBootstrapDeployment(
|
|
75
|
+
normalizedPayload.address,
|
|
76
|
+
normalizedPayload.bdo.tx,
|
|
77
|
+
normalizedPayload.bdo.txv,
|
|
78
|
+
normalizedPayload.bdo.bs,
|
|
79
|
+
normalizedPayload.bdo.ic,
|
|
80
|
+
normalizedPayload.bdo.in,
|
|
81
|
+
normalizedPayload.bdo.is,
|
|
82
|
+
)
|
|
77
83
|
this.network.transactionPoolService.addTransaction(completeBootstrapDeploymentOperation);
|
|
78
84
|
|
|
79
85
|
}
|
|
@@ -102,7 +108,7 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
|
|
|
102
108
|
|
|
103
109
|
return {
|
|
104
110
|
type,
|
|
105
|
-
address: addressToBuffer(address),
|
|
111
|
+
address: addressToBuffer(address, this.#config.addressPrefix),
|
|
106
112
|
bdo: normalizedBdo
|
|
107
113
|
};
|
|
108
114
|
}
|
|
@@ -134,7 +140,7 @@ class SubnetworkOperationHandler extends BaseOperationHandler {
|
|
|
134
140
|
|
|
135
141
|
return {
|
|
136
142
|
type,
|
|
137
|
-
address: addressToBuffer(address),
|
|
143
|
+
address: addressToBuffer(address, this.#config.addressPrefix),
|
|
138
144
|
txo: normalizedTxo
|
|
139
145
|
};
|
|
140
146
|
}
|