trac-msb 0.2.7 → 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 +8 -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 +119 -73
- 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 +9 -15
- package/src/core/network/services/MessageOrchestrator.js +10 -22
- package/src/core/network/services/TransactionPoolService.js +9 -8
- package/src/core/network/services/ValidatorObserverService.js +46 -21
- 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 -10
- 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 +1 -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 +4 -2
- 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,37 +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';
|
|
20
18
|
import MessageOrchestrator from './services/MessageOrchestrator.js';
|
|
21
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
|
+
|
|
22
31
|
const wakeup = new w();
|
|
23
32
|
|
|
24
33
|
class Network extends ReadyResource {
|
|
25
|
-
#dht_bootstrap = DHT_BOOTSTRAPS;
|
|
26
34
|
#swarm = null;
|
|
27
|
-
#enable_wallet;
|
|
28
|
-
#channel;
|
|
29
35
|
#networkMessages;
|
|
30
36
|
#transactionPoolService;
|
|
31
37
|
#validatorObserverService;
|
|
32
38
|
#validatorConnectionManager;
|
|
33
39
|
#validatorMessageOrchestrator;
|
|
34
|
-
#
|
|
40
|
+
#config;
|
|
35
41
|
#identityProvider = null;
|
|
36
|
-
|
|
37
|
-
|
|
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) {
|
|
38
52
|
super();
|
|
39
|
-
this.#
|
|
40
|
-
this.#
|
|
41
|
-
this.#
|
|
42
|
-
|
|
43
|
-
this.#
|
|
44
|
-
this.#
|
|
45
|
-
this.#
|
|
46
|
-
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);
|
|
47
63
|
this.admin_stream = null;
|
|
48
64
|
this.admin = null;
|
|
49
65
|
this.validator = null;
|
|
@@ -55,10 +71,6 @@ class Network extends ReadyResource {
|
|
|
55
71
|
return this.#swarm;
|
|
56
72
|
}
|
|
57
73
|
|
|
58
|
-
get channel() {
|
|
59
|
-
return this.#channel;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
74
|
get transactionPoolService() {
|
|
63
75
|
return this.#transactionPoolService;
|
|
64
76
|
}
|
|
@@ -77,6 +89,9 @@ class Network extends ReadyResource {
|
|
|
77
89
|
|
|
78
90
|
async _open() {
|
|
79
91
|
console.log('Network initialization...');
|
|
92
|
+
|
|
93
|
+
this.setupNetworkListeners();
|
|
94
|
+
|
|
80
95
|
this.transactionPoolService.start();
|
|
81
96
|
this.validatorObserverService.start();
|
|
82
97
|
}
|
|
@@ -88,11 +103,53 @@ class Network extends ReadyResource {
|
|
|
88
103
|
this.#validatorObserverService.stopValidatorObserver();
|
|
89
104
|
await sleep(5_000);
|
|
90
105
|
|
|
106
|
+
this.cleanupNetworkListeners();
|
|
107
|
+
this.cleanupPendingConnections();
|
|
108
|
+
|
|
91
109
|
if (this.#swarm !== null) {
|
|
92
110
|
this.#swarm.destroy();
|
|
93
111
|
}
|
|
94
112
|
}
|
|
95
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
|
+
|
|
96
153
|
async replicate(
|
|
97
154
|
state,
|
|
98
155
|
store,
|
|
@@ -103,14 +160,14 @@ class Network extends ReadyResource {
|
|
|
103
160
|
const wrappedWallet = this.#getNetworkWalletWrapper(wallet, keyPair);
|
|
104
161
|
this.#swarm = new Hyperswarm({
|
|
105
162
|
keyPair,
|
|
106
|
-
bootstrap: this.#
|
|
163
|
+
bootstrap: this.#config.dhtBootstrap,
|
|
107
164
|
maxPeers: MAX_PEERS,
|
|
108
165
|
maxParallel: MAX_PARALLEL,
|
|
109
166
|
maxServerConnections: MAX_SERVER_CONNECTIONS,
|
|
110
167
|
maxClientConnections: MAX_CLIENT_CONNECTIONS
|
|
111
168
|
});
|
|
112
169
|
|
|
113
|
-
console.log(`Channel: ${b4a.toString(this.#channel)}`);
|
|
170
|
+
console.log(`Channel: ${b4a.toString(this.#config.channel)}`);
|
|
114
171
|
this.#networkMessages.initializeMessageRouter(state, wrappedWallet);
|
|
115
172
|
|
|
116
173
|
this.#swarm.on('connection', async (connection) => {
|
|
@@ -121,6 +178,12 @@ class Network extends ReadyResource {
|
|
|
121
178
|
const stream = store.replicate(connection);
|
|
122
179
|
wakeup.addStream(stream);
|
|
123
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
|
+
|
|
124
187
|
connection.on('close', () => {
|
|
125
188
|
if (this.admin_stream === connection) {
|
|
126
189
|
this.admin_stream = null;
|
|
@@ -151,13 +214,21 @@ class Network extends ReadyResource {
|
|
|
151
214
|
|
|
152
215
|
});
|
|
153
216
|
|
|
154
|
-
this.#swarm.join(this.#channel, { server: true, client: true });
|
|
217
|
+
this.#swarm.join(this.#config.channel, { server: true, client: true });
|
|
155
218
|
this.#swarm.flush();
|
|
156
219
|
}
|
|
157
220
|
}
|
|
158
221
|
|
|
222
|
+
isConnectionPending(publicKey) {
|
|
223
|
+
return this.#pendingConnections.has(publicKey);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
pendingConnectionsCount() {
|
|
227
|
+
return this.#pendingConnections.size;
|
|
228
|
+
}
|
|
229
|
+
|
|
159
230
|
async initializeNetworkingKeyPair(store, wallet) {
|
|
160
|
-
if (!this.#
|
|
231
|
+
if (!this.#config.enableWallet) {
|
|
161
232
|
return await store.createKeyPair(TRAC_NAMESPACE);
|
|
162
233
|
} else {
|
|
163
234
|
return {
|
|
@@ -169,34 +240,29 @@ class Network extends ReadyResource {
|
|
|
169
240
|
|
|
170
241
|
async tryConnect(publicKey, type = null) {
|
|
171
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;
|
|
246
|
+
}
|
|
247
|
+
|
|
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 });
|
|
172
253
|
|
|
173
254
|
const target = b4a.from(publicKey, 'hex');
|
|
174
255
|
if (!this.#swarm.peers.has(publicKey)) {
|
|
175
256
|
this.#swarm.joinPeer(target);
|
|
176
|
-
let cnt = 0;
|
|
177
|
-
while (!this.#swarm.peers.has(publicKey) && cnt < 1500) { // TODO: Get rid of the magic number and add a config option for this
|
|
178
|
-
await sleep(10);
|
|
179
|
-
cnt += 1;
|
|
180
|
-
}
|
|
181
257
|
}
|
|
182
258
|
|
|
183
259
|
const peerInfo = this.#swarm.peers.get(publicKey);
|
|
184
|
-
if (
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
while ((!stream || !stream.messenger) && attempts < 1500) { // TODO: Get rid of the magic number and add a config option
|
|
190
|
-
await sleep(10);
|
|
191
|
-
attempts += 1;
|
|
192
|
-
stream = this.#swarm._allConnections.get(peerInfo.publicKey);
|
|
193
|
-
}
|
|
194
|
-
if (!stream || !stream.messenger) return;
|
|
195
|
-
|
|
196
|
-
if (type === 'validator') {
|
|
197
|
-
this.#validatorConnectionManager.addValidator(target, stream);
|
|
260
|
+
if (peerInfo) {
|
|
261
|
+
const connection = this.#swarm._allConnections.get(peerInfo.publicKey);
|
|
262
|
+
if (connection && connection.messenger) {
|
|
263
|
+
await this.#finalizeConnection(publicKey, type, connection);
|
|
264
|
+
}
|
|
198
265
|
}
|
|
199
|
-
await this.#sendRequestByType(stream, type);
|
|
200
266
|
}
|
|
201
267
|
|
|
202
268
|
async isConnected(publicKey) {
|
|
@@ -204,6 +270,12 @@ class Network extends ReadyResource {
|
|
|
204
270
|
this.#swarm.peers.get(publicKey).connectedTime != -1
|
|
205
271
|
}
|
|
206
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
|
+
|
|
207
279
|
async #sendRequestByType(stream, type) {
|
|
208
280
|
const waitFor = {
|
|
209
281
|
validator: () => this.validatorConnectionManager.connectionCount(),
|
|
@@ -231,39 +303,13 @@ class Network extends ReadyResource {
|
|
|
231
303
|
}
|
|
232
304
|
}
|
|
233
305
|
|
|
234
|
-
async sendMessageToNode(nodePublicKey, message) {
|
|
235
|
-
try {
|
|
236
|
-
if (!nodePublicKey || !message) {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
await this.tryConnect(nodePublicKey, 'node');
|
|
240
|
-
|
|
241
|
-
await this.spinLock(() =>
|
|
242
|
-
this.custom_stream === null ||
|
|
243
|
-
!b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
|
|
244
|
-
);
|
|
245
|
-
if (
|
|
246
|
-
this.custom_stream !== null &&
|
|
247
|
-
this.custom_node !== null &&
|
|
248
|
-
b4a.equals(this.custom_node, b4a.from(nodePublicKey, 'hex'))
|
|
249
|
-
) {
|
|
250
|
-
await this.custom_stream.messenger.send(message);
|
|
251
|
-
} else {
|
|
252
|
-
throw new Error(`Failed to send message to node: ${nodePublicKey}`);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
} catch (e) {
|
|
256
|
-
console.log(e)
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
306
|
#getNetworkWalletWrapper(wallet, keyPair) {
|
|
261
307
|
if (!this.#identityProvider) {
|
|
262
308
|
this.#identityProvider = NetworkWalletFactory.provide({
|
|
263
|
-
enableWallet: this.#
|
|
309
|
+
enableWallet: this.#config.enableWallet,
|
|
264
310
|
wallet,
|
|
265
311
|
keyPair,
|
|
266
|
-
networkPrefix: this.#
|
|
312
|
+
networkPrefix: this.#config.addressPrefix
|
|
267
313
|
});
|
|
268
314
|
}
|
|
269
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
|
}
|