trac-msb 0.2.8 → 0.2.10
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/acceptance-tests.yml +7 -11
- package/.github/workflows/lint-pr-title.yml +26 -0
- package/.github/workflows/unit-tests.yml +2 -8
- package/CODE_OF_CONDUCT.md +128 -0
- package/README.md +33 -18
- package/docker-compose.yml +1 -0
- package/docs/trac_network_http_api.openapi.yaml +889 -0
- package/msb.mjs +5 -22
- package/package.json +14 -10
- package/proto/network.proto +74 -0
- package/rpc/create_server.js +2 -2
- package/rpc/handlers.js +165 -92
- package/rpc/routes/v1.js +3 -1
- package/rpc/rpc_server.js +4 -4
- package/rpc/rpc_services.js +62 -25
- package/rpc/utils/helpers.js +83 -52
- package/src/config/args.js +46 -0
- package/src/config/config.js +78 -5
- package/src/config/env.js +70 -3
- package/src/core/network/Network.js +34 -70
- package/src/core/network/identity/NetworkWalletFactory.js +2 -2
- package/src/core/network/protocols/LegacyProtocol.js +67 -0
- package/src/core/network/protocols/NetworkMessages.js +48 -0
- package/src/core/network/protocols/ProtocolInterface.js +31 -0
- package/src/core/network/protocols/ProtocolSession.js +59 -0
- package/src/core/network/protocols/V1Protocol.js +64 -0
- package/src/core/network/protocols/legacy/NetworkMessageRouter.js +84 -0
- package/src/core/network/protocols/legacy/handlers/GetRequestHandler.js +53 -0
- package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +37 -0
- package/src/core/network/{messaging → protocols/legacy}/validators/base/BaseResponse.js +2 -3
- package/src/core/network/protocols/shared/handlers/RoleOperationHandler.js +88 -0
- package/src/core/network/protocols/shared/handlers/SubnetworkOperationHandler.js +93 -0
- package/src/core/network/{messaging → protocols/shared}/handlers/TransferOperationHandler.js +17 -16
- package/src/core/network/{messaging → protocols/shared}/handlers/base/BaseOperationHandler.js +10 -15
- package/src/core/network/{messaging → protocols/shared}/validators/PartialBootstrapDeployment.js +2 -2
- package/src/core/network/{messaging → protocols/shared}/validators/PartialRoleAccess.js +5 -5
- package/src/core/network/{messaging → protocols/shared}/validators/PartialTransaction.js +4 -4
- package/src/core/network/{messaging → protocols/shared}/validators/PartialTransfer.js +4 -4
- package/src/core/network/{messaging → protocols/shared}/validators/base/PartialOperation.js +14 -12
- package/src/core/network/protocols/v1/NetworkMessageRouter.js +15 -0
- package/src/core/network/services/ConnectionManager.js +5 -5
- package/src/core/network/services/MessageOrchestrator.js +2 -2
- package/src/core/network/services/TransactionPoolService.js +5 -6
- package/src/core/network/services/TransactionRateLimiterService.js +12 -13
- package/src/core/network/services/ValidatorObserverService.js +5 -6
- package/src/core/state/State.js +3 -5
- package/src/index.js +156 -181
- package/src/messages/network/v1/NetworkMessageBuilder.js +325 -0
- package/src/messages/network/v1/NetworkMessageDirector.js +137 -0
- package/src/messages/network/v1/networkMessageFactory.js +12 -0
- package/src/messages/state/ApplyStateMessageBuilder.js +661 -0
- package/src/messages/state/ApplyStateMessageDirector.js +516 -0
- package/src/messages/state/applyStateMessageFactory.js +12 -0
- package/src/utils/buffer.js +53 -1
- package/src/utils/check.js +1 -1
- package/src/utils/cli.js +0 -8
- package/src/utils/constants.js +33 -30
- package/src/utils/fileUtils.js +13 -0
- package/src/utils/normalizers.js +84 -2
- package/src/utils/protobuf/network.cjs +840 -0
- package/src/utils/protobuf/operationHelpers.js +10 -0
- package/src/utils/type.js +26 -0
- package/tests/acceptance/v1/balance/balance.test.mjs +1 -2
- package/tests/acceptance/v1/broadcast-transaction/broadcast-transaction.test.mjs +26 -30
- package/tests/acceptance/v1/health/health.test.mjs +33 -0
- package/tests/acceptance/v1/rpc.test.mjs +4 -3
- package/tests/acceptance/v1/tx/tx.test.mjs +27 -16
- package/tests/acceptance/v1/tx-details/tx-details.test.mjs +26 -12
- package/tests/fixtures/check.fixtures.js +33 -32
- package/tests/fixtures/networkV1.fixtures.js +85 -0
- package/tests/fixtures/protobuf.fixtures.js +109 -25
- package/tests/helpers/StateNetworkFactory.js +2 -2
- package/tests/helpers/address.js +6 -0
- package/tests/helpers/autobaseTestHelpers.js +2 -1
- package/tests/helpers/config.js +2 -1
- package/tests/helpers/setupApplyTests.js +59 -56
- package/tests/unit/messages/messages.test.js +12 -0
- package/tests/unit/messages/network/NetworkMessageBuilder.test.js +276 -0
- package/tests/unit/messages/network/NetworkMessageDirector.test.js +201 -0
- package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +521 -0
- package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +233 -0
- package/tests/unit/network/ConnectionManager.test.js +6 -5
- package/tests/unit/network/networkModule.test.js +3 -2
- package/tests/unit/state/apply/addAdmin/addAdminHappyPathScenario.js +10 -6
- package/tests/unit/state/apply/addAdmin/addAdminScenarioHelpers.js +9 -6
- package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +10 -7
- package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +18 -21
- package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +53 -38
- package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +46 -35
- package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +13 -16
- package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +17 -11
- package/tests/unit/state/apply/banValidator/banValidatorScenarioHelpers.js +11 -12
- package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +9 -7
- package/tests/unit/state/apply/common/commonScenarioHelper.js +15 -14
- package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +9 -4
- package/tests/unit/state/apply/disableInitialization/disableInitializationScenarioHelpers.js +17 -11
- package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +19 -14
- package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +37 -29
- package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +9 -7
- package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +11 -9
- package/tests/unit/unit.test.js +1 -1
- package/tests/unit/utils/buffer/buffer.test.js +62 -1
- package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +4 -3
- package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +3 -2
- package/tests/unit/utils/migrationUtils/validateAddressFromIncomingFile.test.js +3 -2
- package/tests/unit/utils/normalizers/normalizers.test.js +469 -0
- package/tests/unit/utils/protobuf/operationHelpers.test.js +120 -2
- package/tests/unit/utils/type/type.test.js +25 -0
- package/tests/unit/utils/utils.test.js +1 -0
- package/docs/networking-dualstack-plan.md +0 -75
- package/docs/networking-layer-redesign.md +0 -155
- package/src/core/network/messaging/NetworkMessages.js +0 -64
- package/src/core/network/messaging/handlers/GetRequestHandler.js +0 -113
- package/src/core/network/messaging/handlers/ResponseHandler.js +0 -107
- package/src/core/network/messaging/handlers/RoleOperationHandler.js +0 -114
- package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +0 -149
- package/src/core/network/messaging/routes/NetworkMessageRouter.js +0 -98
- package/src/core/network/messaging/validators/AdminResponse.js +0 -58
- package/src/core/network/messaging/validators/CustomNodeResponse.js +0 -46
- package/src/messages/base/StateBuilder.js +0 -25
- package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +0 -425
- package/src/messages/completeStateMessages/CompleteStateMessageDirector.js +0 -252
- package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +0 -296
- package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +0 -272
- package/src/messages/partialStateMessages/PartialStateMessageDirector.js +0 -137
- package/src/messages/partialStateMessages/PartialStateMessageOperations.js +0 -138
- package/tests/integration/apply/addAdmin/addAdminBasic.test.js +0 -69
- package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +0 -126
- package/tests/integration/apply/addIndexer.test.js +0 -239
- package/tests/integration/apply/addWhitelist.test.js +0 -53
- package/tests/integration/apply/addWriter.test.js +0 -245
- package/tests/integration/apply/apply.test.js +0 -19
- package/tests/integration/apply/banValidator.test.js +0 -116
- package/tests/integration/apply/postTx/invalidSubValues.test.js +0 -103
- package/tests/integration/apply/postTx/postTx.test.js +0 -196
- package/tests/integration/apply/removeIndexer.test.js +0 -132
- package/tests/integration/apply/removeWriter.test.js +0 -168
- package/tests/integration/apply/transfer.test.js +0 -83
- package/tests/integration/integration.test.js +0 -9
- package/tests/unit/messageOperations/assembleAddIndexerMessage.test.js +0 -21
- package/tests/unit/messageOperations/assembleAddWriterMessage.test.js +0 -17
- package/tests/unit/messageOperations/assembleAdminMessage.test.js +0 -68
- package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +0 -17
- package/tests/unit/messageOperations/assemblePostTransaction.test.js +0 -424
- package/tests/unit/messageOperations/assembleRemoveIndexerMessage.test.js +0 -19
- package/tests/unit/messageOperations/assembleRemoveWriterMessage.test.js +0 -17
- package/tests/unit/messageOperations/assembleWhitelistMessages.test.js +0 -59
- package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +0 -278
- package/tests/unit/messageOperations/stateMessageOperations.test.js +0 -19
- /package/src/core/network/{messaging → protocols/legacy}/validators/ValidatorResponse.js +0 -0
- /package/src/utils/{operations.js → applyOperations.js} +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
2
|
import PeerWallet from 'trac-wallet';
|
|
3
|
-
import
|
|
4
|
-
import State from '../../../../state/State.js';
|
|
3
|
+
import State from '../../../../../state/State.js';
|
|
5
4
|
|
|
6
5
|
/*
|
|
7
6
|
BaseResponse class for handling common validation logic for network responses.
|
|
@@ -16,7 +15,7 @@ class BaseResponse {
|
|
|
16
15
|
*
|
|
17
16
|
* @param {State} state
|
|
18
17
|
* @param {PeerWallet} wallet
|
|
19
|
-
* @param {
|
|
18
|
+
* @param {Config} config
|
|
20
19
|
*/
|
|
21
20
|
constructor(state, wallet, config) {
|
|
22
21
|
this.#state = state;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import {OperationType} from '../../../../../utils/constants.js';
|
|
2
|
+
import PartialRoleAccess from "../validators/PartialRoleAccess.js";
|
|
3
|
+
import BaseOperationHandler from './base/BaseOperationHandler.js';
|
|
4
|
+
import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
|
|
5
|
+
import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
|
|
6
|
+
import {normalizeRoleAccessOperation} from "../../../../../utils/normalizers.js";
|
|
7
|
+
|
|
8
|
+
class RoleOperationHandler extends BaseOperationHandler {
|
|
9
|
+
#partialRoleAccessValidator;
|
|
10
|
+
#wallet;
|
|
11
|
+
#config;
|
|
12
|
+
#txPoolService;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {State} state
|
|
16
|
+
* @param {PeerWallet} wallet
|
|
17
|
+
* @param {TransactionRateLimiterService} rateLimiter
|
|
18
|
+
* @param {TransactionPoolService} txPoolService
|
|
19
|
+
* @param {Config} config
|
|
20
|
+
**/
|
|
21
|
+
constructor(state, wallet, rateLimiter, txPoolService, config) {
|
|
22
|
+
super(state, wallet, rateLimiter, txPoolService, config);
|
|
23
|
+
this.#wallet = wallet;
|
|
24
|
+
this.#config = config;
|
|
25
|
+
this.#partialRoleAccessValidator = new PartialRoleAccess(state, this.#wallet.address ,this.#config)
|
|
26
|
+
this.#txPoolService = txPoolService;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get partialRoleAccessValidator() {
|
|
30
|
+
return this.#partialRoleAccessValidator;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async handleOperation(message, connection) {
|
|
34
|
+
const normalizedPartialRoleAccessPayload = normalizeRoleAccessOperation(message, this.#config)
|
|
35
|
+
const isValid = await this.partialRoleAccessValidator.validate(normalizedPartialRoleAccessPayload)
|
|
36
|
+
let completePayload = null
|
|
37
|
+
if (!isValid) {
|
|
38
|
+
throw new Error("OperationHandler: partial role access payload validation failed.");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
switch (normalizedPartialRoleAccessPayload.type) {
|
|
42
|
+
case OperationType.ADD_WRITER:
|
|
43
|
+
completePayload = await applyStateMessageFactory(this.#wallet, this.#config)
|
|
44
|
+
.buildCompleteAddWriterMessage(
|
|
45
|
+
normalizedPartialRoleAccessPayload.address,
|
|
46
|
+
normalizedPartialRoleAccessPayload.rao.tx,
|
|
47
|
+
normalizedPartialRoleAccessPayload.rao.txv,
|
|
48
|
+
normalizedPartialRoleAccessPayload.rao.iw,
|
|
49
|
+
normalizedPartialRoleAccessPayload.rao.in,
|
|
50
|
+
normalizedPartialRoleAccessPayload.rao.is,
|
|
51
|
+
)
|
|
52
|
+
break;
|
|
53
|
+
case OperationType.REMOVE_WRITER:
|
|
54
|
+
completePayload = await applyStateMessageFactory(this.#wallet, this.#config)
|
|
55
|
+
.buildCompleteRemoveWriterMessage(
|
|
56
|
+
normalizedPartialRoleAccessPayload.address,
|
|
57
|
+
normalizedPartialRoleAccessPayload.rao.tx,
|
|
58
|
+
normalizedPartialRoleAccessPayload.rao.txv,
|
|
59
|
+
normalizedPartialRoleAccessPayload.rao.iw,
|
|
60
|
+
normalizedPartialRoleAccessPayload.rao.in,
|
|
61
|
+
normalizedPartialRoleAccessPayload.rao.is,
|
|
62
|
+
)
|
|
63
|
+
break;
|
|
64
|
+
case OperationType.ADMIN_RECOVERY:
|
|
65
|
+
|
|
66
|
+
completePayload = await applyStateMessageFactory(this.#wallet, this.#config)
|
|
67
|
+
.buildCompleteAdminRecoveryMessage(
|
|
68
|
+
normalizedPartialRoleAccessPayload.address,
|
|
69
|
+
normalizedPartialRoleAccessPayload.rao.tx,
|
|
70
|
+
normalizedPartialRoleAccessPayload.rao.txv,
|
|
71
|
+
normalizedPartialRoleAccessPayload.rao.iw,
|
|
72
|
+
normalizedPartialRoleAccessPayload.rao.in,
|
|
73
|
+
normalizedPartialRoleAccessPayload.rao.is,
|
|
74
|
+
)
|
|
75
|
+
break;
|
|
76
|
+
default:
|
|
77
|
+
throw new Error("OperationHandler: Assembling complete role access operation failed due to unsupported operation type.");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!completePayload) {
|
|
81
|
+
throw new Error("OperationHandler: Assembling complete role access operation failed.");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
this.#txPoolService.addTransaction(safeEncodeApplyOperation(completePayload))
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default RoleOperationHandler;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import BaseOperationHandler from './base/BaseOperationHandler.js';
|
|
2
|
+
import {
|
|
3
|
+
OperationType
|
|
4
|
+
} from '../../../../../utils/constants.js';
|
|
5
|
+
import PartialBootstrapDeployment from "../validators/PartialBootstrapDeployment.js";
|
|
6
|
+
import PartialTransaction from "../validators/PartialTransaction.js";
|
|
7
|
+
import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
|
|
8
|
+
import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
|
|
9
|
+
import {
|
|
10
|
+
normalizeBootstrapDeploymentOperation,
|
|
11
|
+
normalizeTransactionOperation
|
|
12
|
+
} from "../../../../../utils/normalizers.js";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SubnetworkOperationHandler extends BaseOperationHandler {
|
|
16
|
+
#partialBootstrapDeploymentValidator;
|
|
17
|
+
#partialTransactionValidator;
|
|
18
|
+
#config;
|
|
19
|
+
#wallet;
|
|
20
|
+
#txPoolService;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* @param {State} state
|
|
24
|
+
* @param {PeerWallet} wallet
|
|
25
|
+
* @param {TransactionRateLimiterService} rateLimiter
|
|
26
|
+
* @param {TransactionPoolService} txPoolService
|
|
27
|
+
* @param {Config} config
|
|
28
|
+
**/
|
|
29
|
+
constructor( state, wallet, rateLimiter, txPoolService, config) {
|
|
30
|
+
super(state, wallet, rateLimiter, txPoolService, config);
|
|
31
|
+
this.#config = config;
|
|
32
|
+
this.#wallet = wallet
|
|
33
|
+
this.#partialBootstrapDeploymentValidator = new PartialBootstrapDeployment(state, this.#wallet.address, config);
|
|
34
|
+
this.#partialTransactionValidator = new PartialTransaction(state, this.#wallet.address, config);
|
|
35
|
+
this.#txPoolService = txPoolService;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async handleOperation(payload, connection) {
|
|
39
|
+
if (payload.type === OperationType.TX) {
|
|
40
|
+
await this.#partialTransactionSubHandler(payload, connection);
|
|
41
|
+
} else if (payload.type === OperationType.BOOTSTRAP_DEPLOYMENT) {
|
|
42
|
+
await this.#partialBootstrapDeploymentSubHandler(payload, connection);
|
|
43
|
+
} else {
|
|
44
|
+
throw new Error('Unsupported operation type for SubnetworkOperationHandler');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async #partialTransactionSubHandler(payload, connection) {
|
|
49
|
+
const normalizedPayload = normalizeTransactionOperation(payload, this.#config);
|
|
50
|
+
const isValid = await this.#partialTransactionValidator.validate(normalizedPayload);
|
|
51
|
+
if (!isValid) {
|
|
52
|
+
throw new Error("SubnetworkHandler: Transaction validation failed.");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const completeTransactionOperation = await applyStateMessageFactory(this.#wallet,this.#config)
|
|
56
|
+
.buildCompleteTransactionOperationMessage(
|
|
57
|
+
normalizedPayload.address,
|
|
58
|
+
normalizedPayload.txo.tx,
|
|
59
|
+
normalizedPayload.txo.txv,
|
|
60
|
+
normalizedPayload.txo.iw,
|
|
61
|
+
normalizedPayload.txo.in,
|
|
62
|
+
normalizedPayload.txo.ch,
|
|
63
|
+
normalizedPayload.txo.is,
|
|
64
|
+
normalizedPayload.txo.bs,
|
|
65
|
+
normalizedPayload.txo.mbs
|
|
66
|
+
)
|
|
67
|
+
this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeTransactionOperation));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async #partialBootstrapDeploymentSubHandler(payload, connection) {
|
|
71
|
+
const normalizedPayload = normalizeBootstrapDeploymentOperation(payload, this.#config);
|
|
72
|
+
const isValid = await this.#partialBootstrapDeploymentValidator.validate(normalizedPayload);
|
|
73
|
+
if (!isValid) {
|
|
74
|
+
throw new Error("SubnetworkHandler: Bootstrap deployment validation failed.");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
const completeBootstrapDeploymentOperation = await applyStateMessageFactory(this.#wallet, this.#config)
|
|
79
|
+
.buildCompleteBootstrapDeploymentMessage(
|
|
80
|
+
normalizedPayload.address,
|
|
81
|
+
normalizedPayload.bdo.tx,
|
|
82
|
+
normalizedPayload.bdo.txv,
|
|
83
|
+
normalizedPayload.bdo.bs,
|
|
84
|
+
normalizedPayload.bdo.ic,
|
|
85
|
+
normalizedPayload.bdo.in,
|
|
86
|
+
normalizedPayload.bdo.is
|
|
87
|
+
)
|
|
88
|
+
this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeBootstrapDeploymentOperation));
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export default SubnetworkOperationHandler;
|
package/src/core/network/{messaging → protocols/shared}/handlers/TransferOperationHandler.js
RENAMED
|
@@ -1,45 +1,46 @@
|
|
|
1
1
|
import BaseOperationHandler from './base/BaseOperationHandler.js';
|
|
2
|
-
import
|
|
3
|
-
from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
|
|
4
|
-
import {OperationType} from '../../../../utils/constants.js';
|
|
2
|
+
import {OperationType} from '../../../../../utils/constants.js';
|
|
5
3
|
import PartialTransfer from "../validators/PartialTransfer.js";
|
|
6
|
-
import {normalizeTransferOperation} from "
|
|
4
|
+
import {normalizeTransferOperation} from "../../../../../utils/normalizers.js"
|
|
5
|
+
import {applyStateMessageFactory} from "../../../../../messages/state/applyStateMessageFactory.js";
|
|
6
|
+
import {safeEncodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
|
|
7
7
|
|
|
8
8
|
class TransferOperationHandler extends BaseOperationHandler {
|
|
9
9
|
#partialTransferValidator;
|
|
10
10
|
#config;
|
|
11
11
|
#wallet;
|
|
12
|
+
#txPoolService;
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
|
-
* @param {Network} network
|
|
15
15
|
* @param {State} state
|
|
16
16
|
* @param {PeerWallet} wallet
|
|
17
17
|
* @param {TransactionRateLimiterService} rateLimiter
|
|
18
|
-
* @param {
|
|
18
|
+
* @param {Config} config
|
|
19
19
|
**/
|
|
20
|
-
constructor(
|
|
21
|
-
super(
|
|
20
|
+
constructor(state, wallet, rateLimiter, txPoolService, config) {
|
|
21
|
+
super(state, wallet, rateLimiter, txPoolService, config);
|
|
22
22
|
this.#config = config;
|
|
23
23
|
this.#wallet = wallet;
|
|
24
|
-
this.#partialTransferValidator = new PartialTransfer(state, wallet, this.#config);
|
|
24
|
+
this.#partialTransferValidator = new PartialTransfer(state, this.#wallet.address, this.#config);
|
|
25
|
+
this.#txPoolService = txPoolService;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
async handleOperation(payload) {
|
|
28
|
+
async handleOperation(payload, connection) {
|
|
28
29
|
if (payload.type !== OperationType.TRANSFER) {
|
|
29
30
|
throw new Error('Unsupported operation type for TransferOperationHandler');
|
|
30
31
|
}
|
|
31
|
-
await this.#handleTransfer(payload);
|
|
32
|
+
await this.#handleTransfer(payload, connection);
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
async #handleTransfer(payload) {
|
|
35
|
+
async #handleTransfer(payload, connection) {
|
|
35
36
|
const normalizedPayload = normalizeTransferOperation(payload, this.#config);
|
|
36
37
|
const isValid = await this.#partialTransferValidator.validate(normalizedPayload);
|
|
37
38
|
if (!isValid) {
|
|
38
39
|
throw new Error("TransferHandler: Transfer validation failed.");
|
|
39
40
|
}
|
|
40
41
|
|
|
41
|
-
const completeTransferOperation = await
|
|
42
|
-
.
|
|
42
|
+
const completeTransferOperation = await applyStateMessageFactory(this.#wallet, this.#config)
|
|
43
|
+
.buildCompleteTransferOperationMessage(
|
|
43
44
|
normalizedPayload.address,
|
|
44
45
|
normalizedPayload.tro.tx,
|
|
45
46
|
normalizedPayload.tro.txv,
|
|
@@ -47,9 +48,9 @@ class TransferOperationHandler extends BaseOperationHandler {
|
|
|
47
48
|
normalizedPayload.tro.to,
|
|
48
49
|
normalizedPayload.tro.am,
|
|
49
50
|
normalizedPayload.tro.is
|
|
50
|
-
)
|
|
51
|
+
)
|
|
51
52
|
|
|
52
|
-
this.
|
|
53
|
+
this.#txPoolService.addTransaction(safeEncodeApplyOperation(completeTransferOperation));
|
|
53
54
|
}
|
|
54
55
|
}
|
|
55
56
|
|
package/src/core/network/{messaging → protocols/shared}/handlers/base/BaseOperationHandler.js
RENAMED
|
@@ -1,40 +1,35 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
|
-
import {MAX_PARTIAL_TX_PAYLOAD_BYTE_SIZE, TRANSACTION_POOL_SIZE} from '../../../../../utils/constants.js';
|
|
3
2
|
|
|
4
3
|
class BaseOperationHandler {
|
|
5
|
-
#network;
|
|
6
4
|
#state;
|
|
7
5
|
#wallet;
|
|
8
6
|
#rateLimiter;
|
|
7
|
+
#txPoolService;
|
|
9
8
|
#config;
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
|
-
* @param {Network} network
|
|
13
11
|
* @param {State} state
|
|
14
12
|
* @param {PeerWallet} wallet
|
|
15
13
|
* @param {TransactionRateLimiterService} rateLimiter
|
|
16
|
-
* @param {
|
|
14
|
+
* @param {TransactionPoolService} txPoolService
|
|
15
|
+
* @param {Config} config
|
|
17
16
|
**/
|
|
18
|
-
constructor(
|
|
17
|
+
constructor(state, wallet, rateLimiter, txPoolService, config) {
|
|
19
18
|
if (new.target === BaseOperationHandler) {
|
|
20
19
|
throw new Error('BaseOperationHandler is abstract and cannot be instantiated directly');
|
|
21
20
|
}
|
|
22
|
-
this.#network = network;
|
|
23
21
|
this.#state = state;
|
|
24
22
|
this.#wallet = wallet;
|
|
25
23
|
this.#rateLimiter = rateLimiter;
|
|
24
|
+
this.#txPoolService = txPoolService;
|
|
26
25
|
this.#config = config;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
get network() {
|
|
30
|
-
return this.#network;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
28
|
async validateBasicRequirements(payload, connection) {
|
|
34
29
|
// Validate if operation can be processed:
|
|
35
30
|
// - Non-writable nodes cannot process operations
|
|
36
31
|
// - Regular indexers cannot process operations
|
|
37
|
-
// - Admin-indexer can process operations only when network has less than
|
|
32
|
+
// - Admin-indexer can process operations only when network has less than maxWritersForAdminIndexerConnection writers
|
|
38
33
|
const isAllowedToValidate = await this.#state.allowedToValidate(this.#wallet.address);
|
|
39
34
|
const isAdminAllowedToValidate = await this.#state.isAdminAllowedToValidate();
|
|
40
35
|
const canValidate = isAllowedToValidate || isAdminAllowedToValidate;
|
|
@@ -42,16 +37,16 @@ class BaseOperationHandler {
|
|
|
42
37
|
throw new Error('OperationHandler: State is not writable or is an indexer without admin privileges.');
|
|
43
38
|
}
|
|
44
39
|
|
|
45
|
-
if (this.#
|
|
40
|
+
if (this.#txPoolService.tx_pool.length >= this.#config.transactionPoolSize) {
|
|
46
41
|
throw new Error("OperationHandler: Transaction pool is full, ignoring incoming transaction.");
|
|
47
42
|
}
|
|
48
43
|
|
|
49
|
-
if (b4a.byteLength(JSON.stringify(payload)) >
|
|
50
|
-
throw new Error(`OperationHandler: Payload size exceeds maximum limit of ${
|
|
44
|
+
if (b4a.byteLength(JSON.stringify(payload)) > this.#config.maxPartialTxPayloadByteSize) {
|
|
45
|
+
throw new Error(`OperationHandler: Payload size exceeds maximum limit of ${this.#config.maxPartialTxPayloadByteSize} bytes by ${b4a.byteLength(JSON.stringify(payload)) - this.#config.maxPartialTxPayloadByteSize} bytes.`);
|
|
51
46
|
}
|
|
52
47
|
|
|
53
48
|
if (!this.#config.disableRateLimit) {
|
|
54
|
-
const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection
|
|
49
|
+
const shouldDisconnect = this.#rateLimiter.handleRateLimit(connection);
|
|
55
50
|
if (shouldDisconnect) {
|
|
56
51
|
throw new Error(`OperationHandler: Rate limit exceeded for peer ${b4a.toString(connection.remotePublicKey, 'hex')}. Disconnecting...`);
|
|
57
52
|
}
|
package/src/core/network/{messaging → protocols/shared}/validators/PartialBootstrapDeployment.js
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import PartialOperation from './base/PartialOperation.js';
|
|
2
2
|
|
|
3
3
|
class PartialBootstrapDeployment extends PartialOperation {
|
|
4
|
-
constructor(state,
|
|
5
|
-
super(state,
|
|
4
|
+
constructor(state, selfAddress , config) {
|
|
5
|
+
super(state, selfAddress , config);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
async validate(payload) {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
|
-
import {OperationType} from "
|
|
3
|
-
import {bufferToAddress} from "
|
|
2
|
+
import {OperationType} from "../../../../../utils/constants.js";
|
|
3
|
+
import {bufferToAddress} from "../../../../state/utils/address.js";
|
|
4
4
|
import PartialOperation from './base/PartialOperation.js';
|
|
5
|
-
import {bufferToBigInt} from "
|
|
5
|
+
import {bufferToBigInt} from "../../../../../utils/amountSerialization.js";
|
|
6
6
|
|
|
7
7
|
class PartialRoleAccess extends PartialOperation {
|
|
8
8
|
#config;
|
|
9
9
|
|
|
10
|
-
constructor(state,
|
|
11
|
-
super(state,
|
|
10
|
+
constructor(state, selfAddress, config) {
|
|
11
|
+
super(state, selfAddress, config);
|
|
12
12
|
this.#config = config
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
|
-
import {safeDecodeApplyOperation} from "
|
|
3
|
-
import deploymentEntryUtils from "
|
|
2
|
+
import {safeDecodeApplyOperation} from "../../../../../utils/protobuf/operationHelpers.js";
|
|
3
|
+
import deploymentEntryUtils from "../../../../state/utils/deploymentEntry.js";
|
|
4
4
|
import PartialOperation from './base/PartialOperation.js';
|
|
5
5
|
|
|
6
6
|
class PartialTransaction extends PartialOperation {
|
|
7
7
|
#config
|
|
8
8
|
|
|
9
|
-
constructor(state,
|
|
10
|
-
super(state,
|
|
9
|
+
constructor(state, selfAddress, config) {
|
|
10
|
+
super(state, selfAddress, config);
|
|
11
11
|
this.#config = config
|
|
12
12
|
}
|
|
13
13
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import PeerWallet from 'trac-wallet';
|
|
2
2
|
|
|
3
|
-
import {bufferToAddress} from "
|
|
4
|
-
import {bufferToBigInt} from "
|
|
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
8
|
#config
|
|
9
9
|
|
|
10
|
-
constructor(state,
|
|
11
|
-
super(state,
|
|
10
|
+
constructor(state, selfAddress, config) {
|
|
11
|
+
super(state, selfAddress, config);
|
|
12
12
|
this.#config = config
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import b4a from 'b4a';
|
|
2
2
|
import PeerWallet from 'trac-wallet';
|
|
3
|
-
import Check from '
|
|
4
|
-
import {bufferToAddress} from "
|
|
5
|
-
import {createMessage} from "
|
|
6
|
-
import {OperationType} from "
|
|
7
|
-
import {bufferToBigInt} from "
|
|
8
|
-
import {FEE} from "
|
|
9
|
-
import * as operationsUtils from '
|
|
3
|
+
import Check from '../../../../../../utils/check.js';
|
|
4
|
+
import {bufferToAddress} from "../../../../../state/utils/address.js";
|
|
5
|
+
import {createMessage} from "../../../../../../utils/buffer.js";
|
|
6
|
+
import {OperationType} from "../../../../../../utils/constants.js";
|
|
7
|
+
import {bufferToBigInt} from "../../../../../../utils/amountSerialization.js";
|
|
8
|
+
import {FEE} from "../../../../../state/utils/transaction.js";
|
|
9
|
+
import * as operationsUtils from '../../../../../../utils/applyOperations.js';
|
|
10
10
|
|
|
11
11
|
const MAX_AMOUNT = BigInt('0xffffffffffffffffffffffffffffffff');
|
|
12
12
|
const FEE_BIGINT = bufferToBigInt(FEE);
|
|
@@ -16,15 +16,15 @@ class PartialOperation {
|
|
|
16
16
|
#state;
|
|
17
17
|
#check;
|
|
18
18
|
#config
|
|
19
|
-
#
|
|
19
|
+
#selfAddress
|
|
20
20
|
|
|
21
|
-
constructor(state,
|
|
21
|
+
constructor(state, selfAddress, config) {
|
|
22
22
|
this.#state = state;
|
|
23
23
|
this.#config = config;
|
|
24
24
|
this.#check = new Check(this.#config);
|
|
25
25
|
this.max_amount = MAX_AMOUNT;
|
|
26
26
|
this.fee = FEE_BIGINT;
|
|
27
|
-
this.#
|
|
27
|
+
this.#selfAddress = selfAddress;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
get state() {
|
|
@@ -176,7 +176,7 @@ class PartialOperation {
|
|
|
176
176
|
isOperationNotCompleted(payload) {
|
|
177
177
|
const operationKey = operationsUtils.operationToPayload(payload.type);
|
|
178
178
|
const operation = payload[operationKey];
|
|
179
|
-
const {va, vn, vs} = operation;
|
|
179
|
+
const { va, vn, vs } = operation;
|
|
180
180
|
|
|
181
181
|
const condition = va === undefined && vn === undefined && vs === undefined
|
|
182
182
|
if (!condition) {
|
|
@@ -219,8 +219,10 @@ class PartialOperation {
|
|
|
219
219
|
* Flow: Validator -> submits tx with tap-wallet -> RPC-> Validator -validates tx-> REJECT (self-validation)
|
|
220
220
|
*/
|
|
221
221
|
validateNoSelfValidation(payload) {
|
|
222
|
+
if (!this.#selfAddress) return;
|
|
223
|
+
|
|
222
224
|
const requesterAddress = bufferToAddress(payload.address, this.#config.addressPrefix);
|
|
223
|
-
if (this.#
|
|
225
|
+
if (this.#selfAddress === requesterAddress) {
|
|
224
226
|
throw new Error('Requester address cannot be the same as the validator wallet address.');
|
|
225
227
|
}
|
|
226
228
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { MessageHeader } from '../../../../utils/protobuf/network.cjs';
|
|
2
|
+
|
|
3
|
+
class NetworkMessageRouterV1 {
|
|
4
|
+
#config;
|
|
5
|
+
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.#config = config;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async route(incomingMessage) {
|
|
11
|
+
MessageHeader.decode(incomingMessage);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default NetworkMessageRouterV1;
|
|
@@ -20,7 +20,7 @@ class ConnectionManager {
|
|
|
20
20
|
// As Buffers are objects, we will rely on internal conversions done by JS to compare them.
|
|
21
21
|
// It would be better to handle these conversions manually by using hex strings as keys to avoid issues
|
|
22
22
|
/**
|
|
23
|
-
* @param {
|
|
23
|
+
* @param {Config} config
|
|
24
24
|
**/
|
|
25
25
|
constructor(config) {
|
|
26
26
|
this.#validators = new Map();
|
|
@@ -44,10 +44,10 @@ class ConnectionManager {
|
|
|
44
44
|
|
|
45
45
|
const target = this.pickRandomValidator(connectedValidators);
|
|
46
46
|
const entry = this.#validators.get(target);
|
|
47
|
-
if (!entry || !entry.connection || !entry.connection.
|
|
47
|
+
if (!entry || !entry.connection || !entry.connection.protocolSession?.has('legacy')) return null;
|
|
48
48
|
|
|
49
49
|
try {
|
|
50
|
-
entry.connection.
|
|
50
|
+
entry.connection.protocolSession.send(message);
|
|
51
51
|
entry.sent = (entry.sent || 0) + 1;
|
|
52
52
|
} catch (e) {
|
|
53
53
|
// Swallow individual send errors.
|
|
@@ -67,9 +67,9 @@ class ConnectionManager {
|
|
|
67
67
|
if (!this.exists(publicKeyHex) || !this.connected(publicKeyHex)) return false; // Fail silently
|
|
68
68
|
|
|
69
69
|
const validator = this.#validators.get(publicKeyHex);
|
|
70
|
-
if (!validator || !validator.connection || !validator.connection.
|
|
70
|
+
if (!validator || !validator.connection || !validator.connection.protocolSession) return false;
|
|
71
71
|
try {
|
|
72
|
-
validator.connection.
|
|
72
|
+
validator.connection.protocolSession.send(message);
|
|
73
73
|
} catch (e) {
|
|
74
74
|
// Swallow individual send errors.
|
|
75
75
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sleep } from '../../../utils/helpers.js';
|
|
2
|
-
import { operationToPayload } from '../../../utils/
|
|
2
|
+
import { operationToPayload } from '../../../utils/applyOperations.js';
|
|
3
3
|
/**
|
|
4
4
|
* MessageOrchestrator coordinates message submission, retry, and validator management.
|
|
5
5
|
* It works with ConnectionManager and ledger state to ensure reliable message delivery.
|
|
@@ -10,7 +10,7 @@ class MessageOrchestrator {
|
|
|
10
10
|
* Attempts to send a message to validators with retries and state checks.
|
|
11
11
|
* @param {ConnectionManager} connectionManager - The connection manager instance
|
|
12
12
|
* @param {object} state - The state to look for the message outcome
|
|
13
|
-
* @param {
|
|
13
|
+
* @param {Config} config - Configuration options:
|
|
14
14
|
*/
|
|
15
15
|
constructor(connectionManager, state, config) {
|
|
16
16
|
this.connectionManager = connectionManager;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// PoolService.js
|
|
2
|
-
import { BATCH_SIZE
|
|
2
|
+
import { BATCH_SIZE } from '../../../utils/constants.js';
|
|
3
3
|
import Scheduler from '../../../utils/Scheduler.js';
|
|
4
4
|
|
|
5
5
|
class TransactionPoolService {
|
|
@@ -12,7 +12,7 @@ class TransactionPoolService {
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {State} state
|
|
14
14
|
* @param {string} address
|
|
15
|
-
* @param {
|
|
15
|
+
* @param {Config} config
|
|
16
16
|
**/
|
|
17
17
|
constructor(state, address, config) {
|
|
18
18
|
this.#state = state;
|
|
@@ -37,7 +37,7 @@ class TransactionPoolService {
|
|
|
37
37
|
console.info('TransactionPoolService can not start. Wallet is not enabled');
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
40
|
-
if (this
|
|
40
|
+
if (this.#scheduler && this.#scheduler.isRunning) {
|
|
41
41
|
console.info('TransactionPoolService is already started');
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
@@ -52,7 +52,7 @@ class TransactionPoolService {
|
|
|
52
52
|
if (this.#tx_pool.length > 0) {
|
|
53
53
|
next(0);
|
|
54
54
|
} else {
|
|
55
|
-
next(
|
|
55
|
+
next(this.#config.processIntervalMs);
|
|
56
56
|
}
|
|
57
57
|
} catch (error) {
|
|
58
58
|
throw new Error(`TransactionPoolService worker error: ${error.message}`);
|
|
@@ -60,12 +60,11 @@ class TransactionPoolService {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
#createScheduler() {
|
|
63
|
-
return new Scheduler((next) => this.#worker(next),
|
|
63
|
+
return new Scheduler((next) => this.#worker(next), this.#config.processIntervalMs);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
async #processTransactions() {
|
|
67
67
|
const canValidate = await this.#checkValidationPermissions();
|
|
68
|
-
|
|
69
68
|
if (canValidate && this.#tx_pool.length > 0) {
|
|
70
69
|
const batch = this.#prepareBatch();
|
|
71
70
|
await this.#state.append(batch);
|