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
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import BaseOperationHandler from './base/BaseOperationHandler.js';
|
|
2
|
-
import CompleteStateMessageOperations
|
|
3
|
-
|
|
2
|
+
import CompleteStateMessageOperations
|
|
3
|
+
from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
|
|
4
|
+
import {OperationType} from '../../../../utils/constants.js';
|
|
4
5
|
import PartialTransfer from "../validators/PartialTransfer.js";
|
|
5
6
|
import {normalizeTransferOperation} from "../../../../utils/normalizers.js"
|
|
6
7
|
|
|
7
|
-
/**
|
|
8
|
-
* THIS CLASS IS ULTRA IMPORTANT BECAUSE IF SOMEONE WILL SEND A TRASH TO VALIDATOR AND IT WON'T BE HANDLED PROPERTLY -
|
|
9
|
-
* FOR EXAMPLE VALIDATOR WILL BROADCAST IT TO THE INDEXER LAYER THEN IT WILL BE BANNED. SO EVERYTHING WHAT IS TRASH
|
|
10
|
-
* MUST BE REFUSED.
|
|
11
|
-
* TODO: WE SHOULD AUDIT VALIDATORS AND MAKE SURE THEY ARE NOT BROADCASTING TRASH TO THE INDEXER LAYER.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
8
|
class TransferOperationHandler extends BaseOperationHandler {
|
|
16
9
|
#partialTransferValidator;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
#config;
|
|
11
|
+
#wallet;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {Network} network
|
|
15
|
+
* @param {State} state
|
|
16
|
+
* @param {PeerWallet} wallet
|
|
17
|
+
* @param {TransactionRateLimiterService} rateLimiter
|
|
18
|
+
* @param {object} config
|
|
19
|
+
**/
|
|
20
|
+
constructor(network, state, wallet, rateLimiter, config) {
|
|
21
|
+
super(network, state, wallet, rateLimiter, config);
|
|
22
|
+
this.#config = config;
|
|
23
|
+
this.#wallet = wallet;
|
|
24
|
+
this.#partialTransferValidator = new PartialTransfer(state, wallet, this.#config);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
async handleOperation(payload) {
|
|
@@ -28,22 +32,22 @@ class TransferOperationHandler extends BaseOperationHandler {
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
async #handleTransfer(payload) {
|
|
31
|
-
const normalizedPayload = normalizeTransferOperation(payload);
|
|
35
|
+
const normalizedPayload = normalizeTransferOperation(payload, this.#config);
|
|
32
36
|
const isValid = await this.#partialTransferValidator.validate(normalizedPayload);
|
|
33
37
|
if (!isValid) {
|
|
34
38
|
throw new Error("TransferHandler: Transfer validation failed.");
|
|
35
39
|
}
|
|
36
40
|
|
|
37
|
-
const completeTransferOperation = await CompleteStateMessageOperations
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
const completeTransferOperation = await new CompleteStateMessageOperations(this.#wallet, this.#config)
|
|
42
|
+
.assembleCompleteTransferOperationMessage(
|
|
43
|
+
normalizedPayload.address,
|
|
44
|
+
normalizedPayload.tro.tx,
|
|
45
|
+
normalizedPayload.tro.txv,
|
|
46
|
+
normalizedPayload.tro.in,
|
|
47
|
+
normalizedPayload.tro.to,
|
|
48
|
+
normalizedPayload.tro.am,
|
|
49
|
+
normalizedPayload.tro.is
|
|
50
|
+
);
|
|
47
51
|
|
|
48
52
|
this.network.transactionPoolService.addTransaction(completeTransferOperation);
|
|
49
53
|
}
|
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
|
-
import {MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE, TRANSACTION_POOL_SIZE
|
|
2
|
+
import {MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE, TRANSACTION_POOL_SIZE} from '../../../../../utils/constants.js';
|
|
3
|
+
|
|
3
4
|
class BaseOperationHandler {
|
|
4
5
|
#network;
|
|
5
6
|
#state;
|
|
6
7
|
#wallet;
|
|
7
8
|
#rateLimiter;
|
|
8
|
-
#
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
#config;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {Network} network
|
|
13
|
+
* @param {State} state
|
|
14
|
+
* @param {PeerWallet} wallet
|
|
15
|
+
* @param {TransactionRateLimiterService} rateLimiter
|
|
16
|
+
* @param {object} config
|
|
17
|
+
**/
|
|
18
|
+
constructor(network, state, wallet, rateLimiter, config) {
|
|
11
19
|
if (new.target === BaseOperationHandler) {
|
|
12
20
|
throw new Error('BaseOperationHandler is abstract and cannot be instantiated directly');
|
|
13
21
|
}
|
|
@@ -15,35 +23,26 @@ class BaseOperationHandler {
|
|
|
15
23
|
this.#state = state;
|
|
16
24
|
this.#wallet = wallet;
|
|
17
25
|
this.#rateLimiter = rateLimiter;
|
|
18
|
-
this.#
|
|
19
|
-
this.#options = options;
|
|
26
|
+
this.#config = config;
|
|
20
27
|
}
|
|
28
|
+
|
|
21
29
|
get network() {
|
|
22
30
|
return this.#network;
|
|
23
31
|
}
|
|
24
|
-
|
|
25
|
-
return this.#state;
|
|
26
|
-
}
|
|
27
|
-
get wallet() {
|
|
28
|
-
return this.#wallet;
|
|
29
|
-
}
|
|
30
|
-
get options() {
|
|
31
|
-
return this.#options;
|
|
32
|
-
}
|
|
33
|
-
|
|
32
|
+
|
|
34
33
|
async validateBasicRequirements(payload, connection) {
|
|
35
34
|
// Validate if operation can be processed:
|
|
36
35
|
// - Non-writable nodes cannot process operations
|
|
37
36
|
// - Regular indexers cannot process operations
|
|
38
37
|
// - Admin-indexer can process operations only when network has less than MAX_WRITERS_FOR_ADMIN_INDEXER_CONNECTION writers
|
|
39
|
-
const isAllowedToValidate = await this
|
|
40
|
-
const isAdminAllowedToValidate = await this
|
|
38
|
+
const isAllowedToValidate = await this.#state.allowedToValidate(this.#wallet.address);
|
|
39
|
+
const isAdminAllowedToValidate = await this.#state.isAdminAllowedToValidate();
|
|
41
40
|
const canValidate = isAllowedToValidate || isAdminAllowedToValidate;
|
|
42
41
|
if (!canValidate) {
|
|
43
42
|
throw new Error('OperationHandler: State is not writable or is an indexer without admin privileges.');
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
if (this
|
|
45
|
+
if (this.#network.transactionPoolService.tx_pool.length >= TRANSACTION_POOL_SIZE) {
|
|
47
46
|
throw new Error("OperationHandler: Transaction pool is full, ignoring incoming transaction.");
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -51,8 +50,8 @@ class BaseOperationHandler {
|
|
|
51
50
|
throw new Error(`OperationHandler: Payload size exceeds maximum limit of ${MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE} bytes by ${b4a.byteLength(JSON.stringify(payload)) - MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE} bytes.`);
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
if (this.#
|
|
55
|
-
const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection, this
|
|
53
|
+
if (!this.#config.disableRateLimit) {
|
|
54
|
+
const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection, this.#network);
|
|
56
55
|
if (shouldDisconnect) {
|
|
57
56
|
throw new Error(`OperationHandler: Rate limit exceeded for peer ${b4a.toString(connection.remotePublicKey, 'hex')}. Disconnecting...`);
|
|
58
57
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import b4a from "b4a";
|
|
2
|
-
|
|
3
2
|
import GetRequestHandler from "../handlers/GetRequestHandler.js";
|
|
4
3
|
import ResponseHandler from "../handlers/ResponseHandler.js";
|
|
5
4
|
import RoleOperationHandler from "../handlers/RoleOperationHandler.js";
|
|
@@ -8,27 +7,32 @@ import TransferOperationHandler from "../handlers/TransferOperationHandler.js";
|
|
|
8
7
|
import {NETWORK_MESSAGE_TYPES} from '../../../../utils/constants.js';
|
|
9
8
|
import * as operation from '../../../../utils/operations.js';
|
|
10
9
|
import TransactionRateLimiterService from "../../services/TransactionRateLimiterService.js";
|
|
10
|
+
import State from "../../../state/State.js";
|
|
11
|
+
import PeerWallet from "trac-wallet";
|
|
11
12
|
|
|
12
13
|
class NetworkMessageRouter {
|
|
13
14
|
#network;
|
|
14
15
|
#handlers;
|
|
15
|
-
#
|
|
16
|
+
#config;
|
|
16
17
|
#rateLimiter;
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {Network} network
|
|
21
|
+
* @param {State} state
|
|
22
|
+
* @param {PeerWallet} wallet
|
|
23
|
+
* @param {object} config
|
|
24
|
+
**/
|
|
25
|
+
constructor(network, state, wallet, config) {
|
|
18
26
|
this.#network = network;
|
|
27
|
+
this.#config = config;
|
|
19
28
|
this.#rateLimiter = new TransactionRateLimiterService();
|
|
20
29
|
this.#handlers = {
|
|
21
30
|
get: new GetRequestHandler(wallet, state),
|
|
22
|
-
response: new ResponseHandler(network, state, wallet),
|
|
23
|
-
|
|
24
|
-
subNetworkTransaction: new SubnetworkOperationHandler(network, state, wallet, this.#rateLimiter,
|
|
25
|
-
tracNetworkTransaction: new TransferOperationHandler(network, state, wallet, this.#rateLimiter,
|
|
31
|
+
response: new ResponseHandler(network, state, wallet, this.#config),
|
|
32
|
+
roleTransaction: new RoleOperationHandler(network, state, wallet, this.#rateLimiter, this.#config),
|
|
33
|
+
subNetworkTransaction: new SubnetworkOperationHandler(network, state, wallet, this.#rateLimiter, this.#config),
|
|
34
|
+
tracNetworkTransaction: new TransferOperationHandler(network, state, wallet, this.#rateLimiter, this.#config),
|
|
26
35
|
}
|
|
27
|
-
this.#options = options;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
get network() {
|
|
31
|
-
return this.#network;
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
async route(incomingMessage, connection, messageProtomux) {
|
|
@@ -36,30 +40,30 @@ class NetworkMessageRouter {
|
|
|
36
40
|
// TODO: Add a check here — only a writer should be able to process the handlers isRoleAccessOperation,isSubnetworkOperation
|
|
37
41
|
// and admin nodes until the writers' index is less than 25. OperationType.APPEND_WHITELIST can be processed by only READERS
|
|
38
42
|
|
|
39
|
-
const channelString = b4a.toString(this.
|
|
43
|
+
const channelString = b4a.toString(this.#config.channel, 'utf8');
|
|
40
44
|
if (this.#isGetRequest(incomingMessage)) {
|
|
41
45
|
await this.#handlers.get.handle(incomingMessage, messageProtomux, connection, channelString);
|
|
42
|
-
this
|
|
46
|
+
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
43
47
|
}
|
|
44
48
|
else if (this.#isResponse(incomingMessage)) {
|
|
45
49
|
await this.#handlers.response.handle(incomingMessage, connection, channelString);
|
|
46
|
-
this
|
|
50
|
+
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
47
51
|
}
|
|
48
52
|
else if (this.#isRoleAccessOperation(incomingMessage)) {
|
|
49
|
-
await this.#handlers.
|
|
50
|
-
this
|
|
53
|
+
await this.#handlers.roleTransaction.handle(incomingMessage, connection);
|
|
54
|
+
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
51
55
|
|
|
52
56
|
}
|
|
53
57
|
else if (this.#isSubnetworkOperation(incomingMessage)) {
|
|
54
58
|
await this.#handlers.subNetworkTransaction.handle(incomingMessage, connection);
|
|
55
|
-
this
|
|
59
|
+
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
56
60
|
}
|
|
57
61
|
else if(this.#isTransferOperation(incomingMessage)) {
|
|
58
62
|
await this.#handlers.tracNetworkTransaction.handle(incomingMessage, connection);
|
|
59
|
-
this
|
|
63
|
+
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
60
64
|
}
|
|
61
65
|
else {
|
|
62
|
-
this
|
|
66
|
+
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
} catch (error) {
|
|
@@ -4,8 +4,8 @@ import BaseResponse from './base/BaseResponse.js';
|
|
|
4
4
|
|
|
5
5
|
class AdminResponse extends BaseResponse {
|
|
6
6
|
|
|
7
|
-
constructor(state, wallet) {
|
|
8
|
-
super(state, wallet);
|
|
7
|
+
constructor(state, wallet, config) {
|
|
8
|
+
super(state, wallet, config);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
async validate(message, channelString) {
|
|
@@ -2,8 +2,8 @@ import BaseResponse from './base/BaseResponse.js';
|
|
|
2
2
|
|
|
3
3
|
class CustomNodeResponse extends BaseResponse {
|
|
4
4
|
|
|
5
|
-
constructor(state, wallet) {
|
|
6
|
-
super(state, wallet);
|
|
5
|
+
constructor(state, wallet, config) {
|
|
6
|
+
super(state, wallet, config);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
async validate(message, channelString) {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import PartialOperation from './base/PartialOperation.js';
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
class PartialBootstrapDeployment extends PartialOperation {
|
|
5
|
-
constructor(state) {
|
|
6
|
-
super(state);
|
|
4
|
+
constructor(state, wallet , config) {
|
|
5
|
+
super(state, wallet , config);
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
async validate(payload) {
|
|
10
9
|
this.isPayloadSchemaValid(payload);
|
|
10
|
+
this.validateNoSelfValidation(payload);
|
|
11
11
|
this.validateRequesterAddress(payload);
|
|
12
12
|
await this.validateTransactionUniqueness(payload);
|
|
13
13
|
await this.validateSignature(payload);
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import { bufferToAddress } from "../../../state/utils/address.js";
|
|
2
|
+
import {OperationType} from "../../../../utils/constants.js";
|
|
3
|
+
import {bufferToAddress} from "../../../state/utils/address.js";
|
|
5
4
|
import PartialOperation from './base/PartialOperation.js';
|
|
6
|
-
import {
|
|
5
|
+
import {bufferToBigInt} from "../../../../utils/amountSerialization.js";
|
|
7
6
|
|
|
8
7
|
class PartialRoleAccess extends PartialOperation {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
#config;
|
|
9
|
+
|
|
10
|
+
constructor(state, wallet, config) {
|
|
11
|
+
super(state, wallet, config);
|
|
12
|
+
this.#config = config
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
async validate(payload) {
|
|
14
16
|
this.isPayloadSchemaValid(payload);
|
|
17
|
+
this.validateNoSelfValidation(payload);
|
|
15
18
|
this.validateRequesterAddress(payload);
|
|
16
19
|
await this.validateTransactionUniqueness(payload);
|
|
17
20
|
await this.validateSignature(payload);
|
|
@@ -33,10 +36,10 @@ class PartialRoleAccess extends PartialOperation {
|
|
|
33
36
|
}
|
|
34
37
|
|
|
35
38
|
async isRequesterAllowedToChangeRole(payload) {
|
|
36
|
-
const {
|
|
39
|
+
const {type} = payload;
|
|
37
40
|
|
|
38
41
|
if (type === OperationType.ADD_WRITER) {
|
|
39
|
-
const nodeAddress = bufferToAddress(payload.address);
|
|
42
|
+
const nodeAddress = bufferToAddress(payload.address, this.#config.addressPrefix);
|
|
40
43
|
const nodeEntry = await this.state.getNodeEntry(nodeAddress);
|
|
41
44
|
if (!nodeEntry) {
|
|
42
45
|
throw new Error(`Node with address ${nodeAddress} entry does not exist.`);
|
|
@@ -54,7 +57,7 @@ class PartialRoleAccess extends PartialOperation {
|
|
|
54
57
|
return;
|
|
55
58
|
|
|
56
59
|
} else if (type === OperationType.REMOVE_WRITER) {
|
|
57
|
-
const nodeAddress = bufferToAddress(payload.address);
|
|
60
|
+
const nodeAddress = bufferToAddress(payload.address, this.#config.addressPrefix);
|
|
58
61
|
const nodeEntry = await this.state.getNodeEntry(nodeAddress);
|
|
59
62
|
if (!nodeEntry) {
|
|
60
63
|
throw new Error(`Node with address ${nodeAddress} entry does not exist.`);
|
|
@@ -78,7 +81,7 @@ class PartialRoleAccess extends PartialOperation {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
const adminAddressBuffer = payload.address;
|
|
81
|
-
const adminAddress = bufferToAddress(adminAddressBuffer);
|
|
84
|
+
const adminAddress = bufferToAddress(adminAddressBuffer, this.#config.addressPrefix);
|
|
82
85
|
const isRecoveryCase = !!(
|
|
83
86
|
adminEntry.address === adminAddress &&
|
|
84
87
|
!b4a.equals(payload.rao.iw, adminEntry.wk)
|
|
@@ -94,7 +97,7 @@ class PartialRoleAccess extends PartialOperation {
|
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
async validateWriterKey(payload) {
|
|
97
|
-
const requesterAddress = bufferToAddress(payload.address);
|
|
100
|
+
const requesterAddress = bufferToAddress(payload.address, this.#config.addressPrefix);
|
|
98
101
|
const nodeEntry = await this.state.getNodeEntry(requesterAddress);
|
|
99
102
|
if (!nodeEntry) {
|
|
100
103
|
throw new Error(`Node entry not found for address ${requesterAddress}`);
|
|
@@ -114,7 +117,7 @@ class PartialRoleAccess extends PartialOperation {
|
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
async validateRequesterBalanceForAddWriterOperation(payload, signed = false) {
|
|
117
|
-
const requesterAddress = bufferToAddress(payload.address);
|
|
120
|
+
const requesterAddress = bufferToAddress(payload.address, this.#config.addressPrefix);
|
|
118
121
|
let requesterEntry;
|
|
119
122
|
if (signed) {
|
|
120
123
|
requesterEntry = await this.state.getNodeEntry(requesterAddress);
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
|
-
|
|
3
|
-
import { safeDecodeApplyOperation } from "../../../../utils/protobuf/operationHelpers.js";
|
|
2
|
+
import {safeDecodeApplyOperation} from "../../../../utils/protobuf/operationHelpers.js";
|
|
4
3
|
import deploymentEntryUtils from "../../../state/utils/deploymentEntry.js";
|
|
5
4
|
import PartialOperation from './base/PartialOperation.js';
|
|
6
5
|
|
|
7
6
|
class PartialTransaction extends PartialOperation {
|
|
7
|
+
#config
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
constructor(state, wallet, config) {
|
|
10
|
+
super(state, wallet, config);
|
|
11
|
+
this.#config = config
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
async validate(payload) {
|
|
15
15
|
this.isPayloadSchemaValid(payload);
|
|
16
|
+
this.validateNoSelfValidation(payload);
|
|
16
17
|
this.validateRequesterAddress(payload);
|
|
17
18
|
await this.validateTransactionUniqueness(payload);
|
|
18
19
|
await this.validateSignature(payload);
|
|
@@ -21,8 +22,6 @@ class PartialTransaction extends PartialOperation {
|
|
|
21
22
|
await this.validateRequesterBalance(payload);
|
|
22
23
|
await this.validateRequesterBalance(payload, true);
|
|
23
24
|
this.validateSubnetworkBootstrapEquality(payload);
|
|
24
|
-
|
|
25
|
-
|
|
26
25
|
|
|
27
26
|
// non common validations below
|
|
28
27
|
this.validateMsbBootstrap(payload);
|
|
@@ -32,7 +31,7 @@ class PartialTransaction extends PartialOperation {
|
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
validateMsbBootstrap(payload) {
|
|
35
|
-
if (!b4a.equals(this.
|
|
34
|
+
if (!b4a.equals(this.#config.bootstrap, payload.txo.mbs)) {
|
|
36
35
|
throw new Error(`Declared MSB bootstrap is different than network bootstrap in transaction operation: ${payload.txo.mbs.toString('hex')}`);
|
|
37
36
|
}
|
|
38
37
|
}
|
|
@@ -43,10 +42,10 @@ class PartialTransaction extends PartialOperation {
|
|
|
43
42
|
throw new Error(`External bootstrap with hash ${payload.txo.bs.toString('hex')} is not registered as deployment entry.`);
|
|
44
43
|
}
|
|
45
44
|
|
|
46
|
-
const decodedPayload = deploymentEntryUtils.decode(externalBootstrapResult);
|
|
45
|
+
const decodedPayload = deploymentEntryUtils.decode(externalBootstrapResult, this.#config.addressLength);
|
|
47
46
|
const txHash = decodedPayload.txHash
|
|
48
47
|
const getBootstrapTransactionTxPayload = await this.state.get(txHash.toString('hex'));
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
if (getBootstrapTransactionTxPayload === null) {
|
|
51
50
|
throw new Error(`External bootstrap is not registered as usual tx ${externalBootstrapResult.toString('hex')}: ${payload}`);
|
|
52
51
|
}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import PeerWallet from 'trac-wallet';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import {bufferToAddress} from "../../../state/utils/address.js";
|
|
4
|
+
import {bufferToBigInt} from "../../../../utils/amountSerialization.js";
|
|
5
5
|
import PartialOperation from './base/PartialOperation.js';
|
|
6
6
|
|
|
7
7
|
class PartialTransfer extends PartialOperation {
|
|
8
|
+
#config
|
|
8
9
|
|
|
9
|
-
constructor(state) {
|
|
10
|
-
super(state);
|
|
10
|
+
constructor(state, wallet, config) {
|
|
11
|
+
super(state, wallet, config);
|
|
12
|
+
this.#config = config
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
async validate(payload) {
|
|
14
16
|
this.isPayloadSchemaValid(payload);
|
|
17
|
+
this.validateNoSelfValidation(payload);
|
|
15
18
|
this.validateRequesterAddress(payload);
|
|
16
19
|
await this.validateTransactionUniqueness(payload);
|
|
17
20
|
await this.validateSignature(payload);
|
|
@@ -26,7 +29,7 @@ class PartialTransfer extends PartialOperation {
|
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
#validateRecipientAddress(payload) {
|
|
29
|
-
const incomingAddress = bufferToAddress(payload.tro.to);
|
|
32
|
+
const incomingAddress = bufferToAddress(payload.tro.to, this.#config.addressPrefix);
|
|
30
33
|
if (!incomingAddress) {
|
|
31
34
|
throw new Error('Invalid recipient address in transfer payload.');
|
|
32
35
|
}
|
|
@@ -39,8 +42,8 @@ class PartialTransfer extends PartialOperation {
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
async #validateStateBalances(payload) {
|
|
42
|
-
const senderAddress = bufferToAddress(payload.address);
|
|
43
|
-
const recipientAddress = bufferToAddress(payload.tro.to);
|
|
45
|
+
const senderAddress = bufferToAddress(payload.address, this.#config.addressPrefix);
|
|
46
|
+
const recipientAddress = bufferToAddress(payload.tro.to, this.#config.addressPrefix);
|
|
44
47
|
|
|
45
48
|
const transferAmount = bufferToBigInt(payload.tro.am);
|
|
46
49
|
if (transferAmount > this.max_amount) {
|
|
@@ -2,8 +2,8 @@ import b4a from 'b4a';
|
|
|
2
2
|
import BaseResponse from './base/BaseResponse.js';
|
|
3
3
|
class ValidatorResponse extends BaseResponse {
|
|
4
4
|
|
|
5
|
-
constructor(state, wallet) {
|
|
6
|
-
super(state, wallet);
|
|
5
|
+
constructor(state, wallet, config) {
|
|
6
|
+
super(state, wallet, config);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
async validate(message, channelString) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
2
|
import PeerWallet from 'trac-wallet';
|
|
3
3
|
import { bufferToAddress } from '../../../../state/utils/address.js';
|
|
4
|
-
import
|
|
4
|
+
import State from '../../../../state/State.js';
|
|
5
5
|
|
|
6
6
|
/*
|
|
7
7
|
BaseResponse class for handling common validation logic for network responses.
|
|
@@ -10,10 +10,18 @@ import { blake3Hash } from '../../../../../utils/crypto.js';
|
|
|
10
10
|
class BaseResponse {
|
|
11
11
|
#wallet;
|
|
12
12
|
#state;
|
|
13
|
+
#config
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param {State} state
|
|
18
|
+
* @param {PeerWallet} wallet
|
|
19
|
+
* @param {object} config
|
|
20
|
+
*/
|
|
21
|
+
constructor(state, wallet, config) {
|
|
15
22
|
this.#state = state;
|
|
16
23
|
this.#wallet = wallet;
|
|
24
|
+
this.#config = config;
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
get state() {
|
|
@@ -63,8 +71,7 @@ class BaseResponse {
|
|
|
63
71
|
|
|
64
72
|
break;
|
|
65
73
|
default:
|
|
66
|
-
|
|
67
|
-
publicKey = PeerWallet.decodeBech32m(addressString);
|
|
74
|
+
publicKey = PeerWallet.decodeBech32m(message.address);
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
if (!publicKey) {
|
|
@@ -73,7 +80,8 @@ class BaseResponse {
|
|
|
73
80
|
|
|
74
81
|
const messageWithoutSig = { ...message };
|
|
75
82
|
delete messageWithoutSig.sig;
|
|
76
|
-
const
|
|
83
|
+
const hashInput = b4a.from(JSON.stringify(messageWithoutSig), 'utf8');
|
|
84
|
+
const hash = await PeerWallet.blake3(hashInput);
|
|
77
85
|
const signature = b4a.from(message.sig, 'hex');
|
|
78
86
|
const verified = this.#wallet.verify(signature, hash, publicKey);
|
|
79
87
|
|