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,107 +0,0 @@
|
|
|
1
|
-
import { NETWORK_MESSAGE_TYPES } from '../../../../utils/constants.js';
|
|
2
|
-
import ValidatorResponse from '../validators/ValidatorResponse.js';
|
|
3
|
-
import AdminResponse from '../validators/AdminResponse.js';
|
|
4
|
-
import CustomNodeResponse from '../validators/CustomNodeResponse.js';
|
|
5
|
-
import PeerWallet from 'trac-wallet';
|
|
6
|
-
|
|
7
|
-
class ResponseHandler {
|
|
8
|
-
#network;
|
|
9
|
-
#state;
|
|
10
|
-
#responseValidator;
|
|
11
|
-
#adminValidator;
|
|
12
|
-
#customNodeValidator;
|
|
13
|
-
|
|
14
|
-
constructor(network, state, wallet, config) {
|
|
15
|
-
this.#network = network;
|
|
16
|
-
this.#state = state;
|
|
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);
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get network() {
|
|
24
|
-
return this.#network;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get state() {
|
|
28
|
-
return this.#state;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
get responseValidator() {
|
|
32
|
-
return this.#responseValidator;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get adminValidator() {
|
|
36
|
-
return this.#adminValidator;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
get customNodeValidator() {
|
|
40
|
-
return this.#customNodeValidator;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async handle(message, connection, channelString) {
|
|
44
|
-
switch (message.op) {
|
|
45
|
-
case NETWORK_MESSAGE_TYPES.RESPONSE.VALIDATOR:
|
|
46
|
-
await this.#handleValidatorResponse(message, connection, channelString);
|
|
47
|
-
break;
|
|
48
|
-
case NETWORK_MESSAGE_TYPES.RESPONSE.ADMIN:
|
|
49
|
-
await this.#handleAdminResponse(message, connection, channelString);
|
|
50
|
-
break;
|
|
51
|
-
case NETWORK_MESSAGE_TYPES.RESPONSE.NODE:
|
|
52
|
-
await this.#handleCustomNodeResponse(message, connection, channelString);
|
|
53
|
-
break;
|
|
54
|
-
default:
|
|
55
|
-
throw new Error(`Unhandled RESPONSE type: ${message}`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
async #handleValidatorResponse(message, connection, channelString) {
|
|
60
|
-
const isValid = await this.responseValidator.validate(message, channelString);
|
|
61
|
-
if (isValid) {
|
|
62
|
-
const validatorAddressString = message.address;
|
|
63
|
-
const validatorPublicKey = PeerWallet.decodeBech32m(validatorAddressString);
|
|
64
|
-
|
|
65
|
-
if (this.network.validatorConnectionManager.connected(validatorPublicKey)) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
console.log('Validator stream established', validatorAddressString);
|
|
70
|
-
this.network.validatorConnectionManager.addValidator(validatorPublicKey, connection)
|
|
71
|
-
} else {
|
|
72
|
-
throw new Error("Validator response verification failed");
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async #handleAdminResponse(message, connection, channelString) {
|
|
77
|
-
const isValid = await this.adminValidator.validate(message, channelString);
|
|
78
|
-
if (isValid) {
|
|
79
|
-
const adminEntry = await this.state.getAdminEntry();
|
|
80
|
-
const adminPublicKey = PeerWallet.decodeBech32m(adminEntry.address);
|
|
81
|
-
|
|
82
|
-
console.log('Admin stream established:', adminEntry.address);
|
|
83
|
-
this.network.admin_stream = connection;
|
|
84
|
-
this.network.admin = adminPublicKey;
|
|
85
|
-
} else {
|
|
86
|
-
throw new Error("Admin response verification failed");
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async #handleCustomNodeResponse(message, connection, channelString) {
|
|
91
|
-
const isValid = await this.customNodeValidator.validate(message, channelString);
|
|
92
|
-
if (isValid) {
|
|
93
|
-
const customNodeAddressString = message.address;
|
|
94
|
-
const customNodePublicKey = PeerWallet.decodeBech32m(customNodeAddressString);
|
|
95
|
-
|
|
96
|
-
console.log('Custom node stream established:', customNodeAddressString);
|
|
97
|
-
this.network.custom_stream = connection;
|
|
98
|
-
this.network.custom_node = customNodePublicKey;
|
|
99
|
-
} else {
|
|
100
|
-
throw new Error("Custom node response verification failed");
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export default ResponseHandler;
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import {OperationType} from '../../../../utils/constants.js';
|
|
2
|
-
import PartialRoleAccess from "../validators/PartialRoleAccess.js";
|
|
3
|
-
import {addressToBuffer} from "../../../state/utils/address.js";
|
|
4
|
-
import CompleteStateMessageOperations
|
|
5
|
-
from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
|
|
6
|
-
import {normalizeHex} from "../../../../utils/helpers.js";
|
|
7
|
-
import BaseOperationHandler from './base/BaseOperationHandler.js';
|
|
8
|
-
|
|
9
|
-
class RoleOperationHandler extends BaseOperationHandler {
|
|
10
|
-
#partialRoleAccessValidator;
|
|
11
|
-
#wallet;
|
|
12
|
-
#network;
|
|
13
|
-
#config;
|
|
14
|
-
|
|
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);
|
|
24
|
-
this.#wallet = wallet;
|
|
25
|
-
this.#config = config;
|
|
26
|
-
this.#network = network;
|
|
27
|
-
this.#partialRoleAccessValidator = new PartialRoleAccess(state, wallet ,this.#config)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
get partialRoleAccessValidator() {
|
|
31
|
-
return this.#partialRoleAccessValidator;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async handleOperation(message, connection) {
|
|
35
|
-
const normalizedPartialRoleAccessPayload = this.#normalizePartialRoleAccess(message)
|
|
36
|
-
const isValid = await this.partialRoleAccessValidator.validate(normalizedPartialRoleAccessPayload)
|
|
37
|
-
let completePayload = null
|
|
38
|
-
if (!isValid) {
|
|
39
|
-
throw new Error("OperationHandler: partial role access payload validation failed.");
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
switch (normalizedPartialRoleAccessPayload.type) {
|
|
43
|
-
case OperationType.ADD_WRITER:
|
|
44
|
-
completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleAddWriterMessage(
|
|
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 new CompleteStateMessageOperations(this.#wallet, this.#config).assembleRemoveWriterMessage(
|
|
55
|
-
normalizedPartialRoleAccessPayload.address,
|
|
56
|
-
normalizedPartialRoleAccessPayload.rao.tx,
|
|
57
|
-
normalizedPartialRoleAccessPayload.rao.txv,
|
|
58
|
-
normalizedPartialRoleAccessPayload.rao.iw,
|
|
59
|
-
normalizedPartialRoleAccessPayload.rao.in,
|
|
60
|
-
normalizedPartialRoleAccessPayload.rao.is,
|
|
61
|
-
);
|
|
62
|
-
break;
|
|
63
|
-
case OperationType.ADMIN_RECOVERY:
|
|
64
|
-
completePayload = await new CompleteStateMessageOperations(this.#wallet, this.#config).assembleAdminRecoveryMessage(
|
|
65
|
-
normalizedPartialRoleAccessPayload.address,
|
|
66
|
-
normalizedPartialRoleAccessPayload.rao.tx,
|
|
67
|
-
normalizedPartialRoleAccessPayload.rao.txv,
|
|
68
|
-
normalizedPartialRoleAccessPayload.rao.iw,
|
|
69
|
-
normalizedPartialRoleAccessPayload.rao.in,
|
|
70
|
-
normalizedPartialRoleAccessPayload.rao.is,
|
|
71
|
-
);
|
|
72
|
-
console.log("Assembled complete role access operation:", completePayload);
|
|
73
|
-
break;
|
|
74
|
-
default:
|
|
75
|
-
throw new Error("OperationHandler: Assembling complete role access operation failed due to unsupported operation type.");
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (!completePayload) {
|
|
79
|
-
throw new Error("OperationHandler: Assembling complete role access operation failed.");
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
this.#network.transactionPoolService.addTransaction(completePayload)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
#normalizePartialRoleAccess(payload) {
|
|
86
|
-
if (!payload || typeof payload !== 'object' || !payload.rao) {
|
|
87
|
-
throw new Error('Invalid payload for bootstrap deployment normalization.');
|
|
88
|
-
}
|
|
89
|
-
const {type, address, rao} = payload;
|
|
90
|
-
if (
|
|
91
|
-
!type ||
|
|
92
|
-
!address ||
|
|
93
|
-
!rao.tx || !rao.txv || !rao.iw || !rao.in || !rao.is
|
|
94
|
-
) {
|
|
95
|
-
throw new Error('Missing required fields in bootstrap deployment payload.');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const normalizedRao = {
|
|
99
|
-
tx: normalizeHex(rao.tx),
|
|
100
|
-
txv: normalizeHex(rao.txv),
|
|
101
|
-
iw: normalizeHex(rao.iw),
|
|
102
|
-
in: normalizeHex(rao.in),
|
|
103
|
-
is: normalizeHex(rao.is)
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
type,
|
|
108
|
-
address: addressToBuffer(address, this.#config.addressPrefix),
|
|
109
|
-
rao: normalizedRao
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export default RoleOperationHandler;
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import BaseOperationHandler from './base/BaseOperationHandler.js';
|
|
2
|
-
import CompleteStateMessageOperations
|
|
3
|
-
from "../../../../messages/completeStateMessages/CompleteStateMessageOperations.js";
|
|
4
|
-
import {
|
|
5
|
-
OperationType
|
|
6
|
-
} from '../../../../utils/constants.js';
|
|
7
|
-
import PartialBootstrapDeployment from "../validators/PartialBootstrapDeployment.js";
|
|
8
|
-
import {addressToBuffer} from "../../../state/utils/address.js";
|
|
9
|
-
import PartialTransaction from "../validators/PartialTransaction.js";
|
|
10
|
-
import {normalizeHex} from "../../../../utils/helpers.js";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class SubnetworkOperationHandler extends BaseOperationHandler {
|
|
14
|
-
#partialBootstrapDeploymentValidator;
|
|
15
|
-
#partialTransactionValidator;
|
|
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);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async handleOperation(payload) {
|
|
35
|
-
if (payload.type === OperationType.TX) {
|
|
36
|
-
await this.#partialTransactionSubHandler(payload);
|
|
37
|
-
} else if (payload.type === OperationType.BOOTSTRAP_DEPLOYMENT) {
|
|
38
|
-
await this.#partialBootstrapDeploymentSubHandler(payload);
|
|
39
|
-
} else {
|
|
40
|
-
throw new Error('Unsupported operation type for SubnetworkOperationHandler');
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async #partialTransactionSubHandler(payload) {
|
|
45
|
-
const normalizedPayload = this.#normalizeTransactionOperation(payload, this.#config);
|
|
46
|
-
const isValid = await this.#partialTransactionValidator.validate(normalizedPayload);
|
|
47
|
-
if (!isValid) {
|
|
48
|
-
throw new Error("SubnetworkHandler: Transaction validation failed.");
|
|
49
|
-
}
|
|
50
|
-
|
|
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
|
-
);
|
|
63
|
-
this.network.transactionPoolService.addTransaction(completeTransactionOperation);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async #partialBootstrapDeploymentSubHandler(payload) {
|
|
67
|
-
const normalizedPayload = this.#normalizeBootstrapDeployment(payload);
|
|
68
|
-
const isValid = await this.#partialBootstrapDeploymentValidator.validate(normalizedPayload);
|
|
69
|
-
if (!isValid) {
|
|
70
|
-
throw new Error("SubnetworkHandler: Bootstrap deployment validation failed.");
|
|
71
|
-
}
|
|
72
|
-
|
|
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
|
-
)
|
|
83
|
-
this.network.transactionPoolService.addTransaction(completeBootstrapDeploymentOperation);
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
#normalizeBootstrapDeployment(payload) {
|
|
88
|
-
if (!payload || typeof payload !== 'object' || !payload.bdo) {
|
|
89
|
-
throw new Error('Invalid payload for bootstrap deployment normalization.');
|
|
90
|
-
}
|
|
91
|
-
const {type, address, bdo} = payload;
|
|
92
|
-
if (
|
|
93
|
-
type !== OperationType.BOOTSTRAP_DEPLOYMENT ||
|
|
94
|
-
!address ||
|
|
95
|
-
!bdo.tx || !bdo.bs || !bdo.in || !bdo.is || !bdo.txv
|
|
96
|
-
) {
|
|
97
|
-
throw new Error('Missing required fields in bootstrap deployment payload.');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const normalizedBdo = {
|
|
101
|
-
tx: normalizeHex(bdo.tx), // Transaction hash
|
|
102
|
-
txv: normalizeHex(bdo.txv), // Transaction validity
|
|
103
|
-
bs: normalizeHex(bdo.bs), // External bootstrap
|
|
104
|
-
ic: normalizeHex(bdo.ic), // Channel
|
|
105
|
-
in: normalizeHex(bdo.in), // Nonce
|
|
106
|
-
is: normalizeHex(bdo.is) // Signature
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
return {
|
|
110
|
-
type,
|
|
111
|
-
address: addressToBuffer(address, this.#config.addressPrefix),
|
|
112
|
-
bdo: normalizedBdo
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
#normalizeTransactionOperation(payload) {
|
|
117
|
-
if (!payload || typeof payload !== 'object' || !payload.txo) {
|
|
118
|
-
throw new Error('Invalid payload for transaction operation normalization.');
|
|
119
|
-
}
|
|
120
|
-
const {type, address, txo} = payload;
|
|
121
|
-
if (
|
|
122
|
-
type !== OperationType.TX ||
|
|
123
|
-
!address ||
|
|
124
|
-
!txo.tx || !txo.txv || !txo.iw || !txo.in ||
|
|
125
|
-
!txo.ch || !txo.is || !txo.bs || !txo.mbs
|
|
126
|
-
) {
|
|
127
|
-
throw new Error('Missing required fields in transaction operation payload.');
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const normalizedTxo = {
|
|
131
|
-
tx: normalizeHex(txo.tx), // Transaction hash
|
|
132
|
-
txv: normalizeHex(txo.txv), // Transaction validity
|
|
133
|
-
iw: normalizeHex(txo.iw), // Writing key
|
|
134
|
-
in: normalizeHex(txo.in), // Nonce
|
|
135
|
-
ch: normalizeHex(txo.ch), // Content hash
|
|
136
|
-
is: normalizeHex(txo.is), // Signature
|
|
137
|
-
bs: normalizeHex(txo.bs), // External bootstrap
|
|
138
|
-
mbs: normalizeHex(txo.mbs) // MSB bootstrap key
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
return {
|
|
142
|
-
type,
|
|
143
|
-
address: addressToBuffer(address, this.#config.addressPrefix),
|
|
144
|
-
txo: normalizedTxo
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export default SubnetworkOperationHandler;
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import b4a from "b4a";
|
|
2
|
-
import GetRequestHandler from "../handlers/GetRequestHandler.js";
|
|
3
|
-
import ResponseHandler from "../handlers/ResponseHandler.js";
|
|
4
|
-
import RoleOperationHandler from "../handlers/RoleOperationHandler.js";
|
|
5
|
-
import SubnetworkOperationHandler from "../handlers/SubnetworkOperationHandler.js";
|
|
6
|
-
import TransferOperationHandler from "../handlers/TransferOperationHandler.js";
|
|
7
|
-
import {NETWORK_MESSAGE_TYPES} from '../../../../utils/constants.js';
|
|
8
|
-
import * as operation from '../../../../utils/operations.js';
|
|
9
|
-
import TransactionRateLimiterService from "../../services/TransactionRateLimiterService.js";
|
|
10
|
-
import State from "../../../state/State.js";
|
|
11
|
-
import PeerWallet from "trac-wallet";
|
|
12
|
-
|
|
13
|
-
class NetworkMessageRouter {
|
|
14
|
-
#network;
|
|
15
|
-
#handlers;
|
|
16
|
-
#config;
|
|
17
|
-
#rateLimiter;
|
|
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) {
|
|
26
|
-
this.#network = network;
|
|
27
|
-
this.#config = config;
|
|
28
|
-
this.#rateLimiter = new TransactionRateLimiterService();
|
|
29
|
-
this.#handlers = {
|
|
30
|
-
get: new GetRequestHandler(wallet, state),
|
|
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),
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async route(incomingMessage, connection, messageProtomux) {
|
|
39
|
-
try {
|
|
40
|
-
// TODO: Add a check here — only a writer should be able to process the handlers isRoleAccessOperation,isSubnetworkOperation
|
|
41
|
-
// and admin nodes until the writers' index is less than 25. OperationType.APPEND_WHITELIST can be processed by only READERS
|
|
42
|
-
|
|
43
|
-
const channelString = b4a.toString(this.#config.channel, 'utf8');
|
|
44
|
-
if (this.#isGetRequest(incomingMessage)) {
|
|
45
|
-
await this.#handlers.get.handle(incomingMessage, messageProtomux, connection, channelString);
|
|
46
|
-
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
47
|
-
}
|
|
48
|
-
else if (this.#isResponse(incomingMessage)) {
|
|
49
|
-
await this.#handlers.response.handle(incomingMessage, connection, channelString);
|
|
50
|
-
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
51
|
-
}
|
|
52
|
-
else if (this.#isRoleAccessOperation(incomingMessage)) {
|
|
53
|
-
await this.#handlers.roleTransaction.handle(incomingMessage, connection);
|
|
54
|
-
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
else if (this.#isSubnetworkOperation(incomingMessage)) {
|
|
58
|
-
await this.#handlers.subNetworkTransaction.handle(incomingMessage, connection);
|
|
59
|
-
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
60
|
-
}
|
|
61
|
-
else if(this.#isTransferOperation(incomingMessage)) {
|
|
62
|
-
await this.#handlers.tracNetworkTransaction.handle(incomingMessage, connection);
|
|
63
|
-
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
this.#network.swarm.leavePeer(connection.remotePublicKey);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
} catch (error) {
|
|
70
|
-
throw new Error(`Failed to route message: ${error.message}. Pubkey of requester is ${connection.remotePublicKey ? b4a.toString(connection.remotePublicKey, 'hex') : 'unknown'}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
#isGetRequest(message) {
|
|
75
|
-
return Object.values(NETWORK_MESSAGE_TYPES.GET).includes(message);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
#isResponse(message) {
|
|
80
|
-
return Object.values(NETWORK_MESSAGE_TYPES.RESPONSE).includes(message.op);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
#isRoleAccessOperation(message) {
|
|
84
|
-
return operation.isRoleAccess(message.type)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
#isSubnetworkOperation(message) {
|
|
88
|
-
return operation.isTransaction(message.type) ||
|
|
89
|
-
operation.isBootstrapDeployment(message.type)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
#isTransferOperation(message) {
|
|
93
|
-
return operation.isTransfer(message.type)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
export default NetworkMessageRouter;
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import b4a from 'b4a';
|
|
2
|
-
import PeerWallet from 'trac-wallet';
|
|
3
|
-
import BaseResponse from './base/BaseResponse.js';
|
|
4
|
-
|
|
5
|
-
class AdminResponse extends BaseResponse {
|
|
6
|
-
|
|
7
|
-
constructor(state, wallet, config) {
|
|
8
|
-
super(state, wallet, config);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async validate(message, channelString) {
|
|
12
|
-
if (
|
|
13
|
-
!this.validatePayload(message) ||
|
|
14
|
-
!this.validateIssuerPublicKey(message) ||
|
|
15
|
-
!this.validateTimestamp(message) ||
|
|
16
|
-
!await this.validateAdminData(message) ||
|
|
17
|
-
!await this.validateSignature(message) ||
|
|
18
|
-
!this.validateChannel(message, channelString)
|
|
19
|
-
) {
|
|
20
|
-
throw new Error("Admin response validation failed");
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
validatePayload(message) {
|
|
27
|
-
if (!message ||
|
|
28
|
-
!message.op ||
|
|
29
|
-
!message.wk ||
|
|
30
|
-
!message.address ||
|
|
31
|
-
!message.nonce ||
|
|
32
|
-
!message.channel ||
|
|
33
|
-
!message.issuer ||
|
|
34
|
-
!message.timestamp) {
|
|
35
|
-
throw new Error("Admin response is missing required fields.");
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async validateAdminData(message) {
|
|
41
|
-
const adminEntry = await this.state.getAdminEntry();
|
|
42
|
-
if (!adminEntry) {
|
|
43
|
-
throw new Error("Admin entry is null");
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const adminPublicKey = PeerWallet.decodeBech32m(adminEntry.address);
|
|
47
|
-
const receivedAdminPublicKey = PeerWallet.decodeBech32m(message.address);
|
|
48
|
-
const adminWritingKey = b4a.from(message.wk, 'hex');
|
|
49
|
-
|
|
50
|
-
if (!b4a.equals(adminPublicKey, receivedAdminPublicKey) || !b4a.equals(adminEntry.wk, adminWritingKey)) {
|
|
51
|
-
throw new Error("Admin public key or writing key mismatch in response.");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export default AdminResponse;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import BaseResponse from './base/BaseResponse.js';
|
|
2
|
-
|
|
3
|
-
class CustomNodeResponse extends BaseResponse {
|
|
4
|
-
|
|
5
|
-
constructor(state, wallet, config) {
|
|
6
|
-
super(state, wallet, config);
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
async validate(message, channelString) {
|
|
10
|
-
if (
|
|
11
|
-
!this.validatePayload(message) ||
|
|
12
|
-
!this.validateIssuerPublicKey(message) ||
|
|
13
|
-
!this.validateTimestamp(message) ||
|
|
14
|
-
!await this.validateCustomNodeEntry(message) ||
|
|
15
|
-
!await this.validateSignature(message) ||
|
|
16
|
-
!this.validateChannel(message, channelString)
|
|
17
|
-
) {
|
|
18
|
-
throw new Error("Custom node response validation failed");
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return true;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
validatePayload(message) {
|
|
25
|
-
if (!message ||
|
|
26
|
-
!message.op ||
|
|
27
|
-
!message.address ||
|
|
28
|
-
!message.nonce ||
|
|
29
|
-
!message.channel ||
|
|
30
|
-
!message.issuer ||
|
|
31
|
-
!message.timestamp) {
|
|
32
|
-
throw new Error("Custom node response is missing required fields.");
|
|
33
|
-
}
|
|
34
|
-
return true;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async validateCustomNodeEntry(message) {
|
|
38
|
-
const customNodeAddressString = message.address;
|
|
39
|
-
const customNodeEntry = await this.state.getNodeEntry(customNodeAddressString);
|
|
40
|
-
if (customNodeEntry === null) {
|
|
41
|
-
throw new Error("Custom node entry is null - entry is not initialized.");
|
|
42
|
-
}
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
export default CustomNodeResponse;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
class StateBuilder {
|
|
2
|
-
|
|
3
|
-
constructor() {
|
|
4
|
-
if (this.constructor === StateBuilder) {
|
|
5
|
-
throw new Error("Builder is an abstract class and cannot be instantiated directly.");
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
reset() { throw new Error("Method 'reset()' must be implemented.");}
|
|
9
|
-
forOperationType(operationType) {throw new Error("Method 'forOperationType()' must be implemented.");}
|
|
10
|
-
withAddress(address) { throw new Error("Method 'withAddress()' must be implemented.");}
|
|
11
|
-
withWriterKey(writerKey) { throw new Error("Method 'withWriterKey()' must be implemented.");}
|
|
12
|
-
async buildValueAndSign() { throw new Error("Method 'buildValueAndSign()' must be implemented.");}
|
|
13
|
-
withIncomingAddress(address) { throw new Error("Method 'withIncomingAddress()' must be implemented.");}
|
|
14
|
-
withIncomingWriterKey(writerKey) { throw new Error("Method 'withIncomingWriterKey()' must be implemented.");}
|
|
15
|
-
withIncomingNonce(nonce) { throw new Error("Method 'withIncomingNonce()' must be implemented.");}
|
|
16
|
-
withContentHash(contentHash) { throw new Error("Method 'withContentHash()' must be implemented.");}
|
|
17
|
-
withIncomingSignature(signature) { throw new Error("Method 'withIncomingSignature()' must be implemented.");}
|
|
18
|
-
withExternalBootstrap(bootstrapKey) { throw new Error("Method 'withExternalBootstrap()' must be implemented.");}
|
|
19
|
-
withMsbBootstrap(msbBootstrap) { throw new Error("Method 'withMsbBootstrap()' must be implemented.");}
|
|
20
|
-
withTxHash(txHash) { throw new Error("Method 'withTxHash()' must be implemented.");}
|
|
21
|
-
withTxValidity(txValidity) { throw new Error("Method 'withTxValidity()' must be implemented.");}
|
|
22
|
-
withAmount(amount) { throw new Error("Method 'withAmount()' must be implemented.");}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export default StateBuilder;
|