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
|
@@ -5,37 +5,29 @@ on:
|
|
|
5
5
|
types: [published]
|
|
6
6
|
|
|
7
7
|
permissions:
|
|
8
|
+
id-token: write # Required for OIDC
|
|
8
9
|
contents: read
|
|
9
10
|
|
|
10
11
|
jobs:
|
|
11
|
-
publish
|
|
12
|
+
publish:
|
|
12
13
|
runs-on: ubuntu-latest
|
|
13
|
-
|
|
14
14
|
steps:
|
|
15
|
-
- name: Checkout
|
|
15
|
+
- name: Checkout release tag
|
|
16
16
|
uses: actions/checkout@v4
|
|
17
|
+
with:
|
|
18
|
+
ref: ${{ github.event.release.tag_name }}
|
|
17
19
|
|
|
18
20
|
- name: Use Node.js
|
|
19
21
|
uses: actions/setup-node@v4
|
|
20
22
|
with:
|
|
21
23
|
node-version: '24'
|
|
22
24
|
registry-url: 'https://registry.npmjs.org'
|
|
25
|
+
- name: Install dependencies
|
|
26
|
+
run: npm ci
|
|
23
27
|
|
|
24
|
-
- name: Set package.json version from tag
|
|
25
|
-
run: |
|
|
26
|
-
TAG="${GITHUB_REF#refs/tags/}"
|
|
27
|
-
VERSION="${TAG#v}"
|
|
28
|
-
echo "Version from tag: $VERSION"
|
|
29
|
-
npm version "$VERSION" --no-git-tag-version
|
|
30
|
-
|
|
31
28
|
# unit tests are temporarily disabled because they lost stability on GH runners.
|
|
32
|
-
#- name: Install dependencies
|
|
33
|
-
# run: npm ci
|
|
34
|
-
|
|
35
29
|
#- name: Run unit tests
|
|
36
30
|
# run: npm run test:unit:all
|
|
37
31
|
|
|
38
32
|
- name: Publish to npm
|
|
39
|
-
|
|
40
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_MSB_PUBLISH_TOKEN }}
|
|
41
|
-
run: npm publish
|
|
33
|
+
run: npm publish --access public
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Dual-stack plan with design patterns (legacy JSON + network/v1)
|
|
2
|
+
|
|
3
|
+
This is a design plan only (no implementation yet).
|
|
4
|
+
|
|
5
|
+
## Project map (current)
|
|
6
|
+
- `src/core/network/Network.js`: facade for swarm, services, and message setup.
|
|
7
|
+
- `src/core/network/protocols/NetworkMessages.js`: Protomux wiring for legacy JSON.
|
|
8
|
+
- `src/core/network/protocols/legacy/`: legacy router + handlers + validators.
|
|
9
|
+
- `src/core/network/protocols/shared/`: shared operation handlers + validators.
|
|
10
|
+
- `src/core/network/services/ConnectionManager.js`: validator pool and messaging.
|
|
11
|
+
- `src/core/network/services/MessageOrchestrator.js`: legacy broadcast heuristic.
|
|
12
|
+
- `src/messages/network/v1/`: builder/director/factory for v1 messages.
|
|
13
|
+
- `proto/network.proto` + `src/utils/protobuf/network.cjs`: v1 schema/codec.
|
|
14
|
+
|
|
15
|
+
## Design patterns to use (and where)
|
|
16
|
+
- Strategy + Adapter: protocol-specific adapters per version (`legacy`, `v1`, future `v2`).
|
|
17
|
+
- Registry + Factory: centralized list of protocol descriptors, created once.
|
|
18
|
+
- Chain of Responsibility: routing table of predicates -> handlers (replace long if/else).
|
|
19
|
+
- Template Method: already in `BaseOperationHandler`, keep as shared entry point.
|
|
20
|
+
- Command: operation handlers as commands dispatched by a protocol router.
|
|
21
|
+
- State Machine: handshake + capability negotiation for `network/v1`.
|
|
22
|
+
- Mediator: `MessageOrchestrator` coordinates `ConnectionManager` and state.
|
|
23
|
+
- Observer: emit connection/protocol events to interested services.
|
|
24
|
+
- Decorator: wrap handlers with rate limit, logging, metrics.
|
|
25
|
+
- Null Object: no-op messenger to avoid null checks in send paths.
|
|
26
|
+
|
|
27
|
+
## Target architecture (pattern-oriented)
|
|
28
|
+
1. ProtocolAdapter interface (Strategy + Adapter)
|
|
29
|
+
- Shape: `id`, `protocolName`, `encoding`, `router`, `handshake`, `encode`, `decode`.
|
|
30
|
+
- `LegacyProtocolAdapter` wraps `legacy/NetworkMessageRouter` with `c.json`.
|
|
31
|
+
- `V1ProtocolAdapter` wraps protobuf decode/encode and a v1 router.
|
|
32
|
+
|
|
33
|
+
2. ProtocolRegistry (Registry + Factory)
|
|
34
|
+
- Single source of enabled protocols: `[legacyAdapter, v1Adapter]`.
|
|
35
|
+
- Owns protocol names (`legacy` channel from config, `network/v1`).
|
|
36
|
+
- Exposed to `NetworkMessages` for channel creation.
|
|
37
|
+
|
|
38
|
+
3. ProtocolSession per connection (Facade + Null Object)
|
|
39
|
+
- `session.messengers.{legacy,v1}` with a `NullMessenger` fallback.
|
|
40
|
+
- `session.protocols` is a `Set` of negotiated protocols.
|
|
41
|
+
- Stored in `ConnectionManager` alongside peer metadata.
|
|
42
|
+
|
|
43
|
+
4. Router refactor (Chain of Responsibility + Command)
|
|
44
|
+
- `legacy` router: table of `canHandle(message)` + `handler.execute()`.
|
|
45
|
+
- `v1` router: map `MessageType -> handler`.
|
|
46
|
+
- Shared operation handlers remain in `shared/handlers/`.
|
|
47
|
+
|
|
48
|
+
5. Handshake state machine (State)
|
|
49
|
+
- Per-connection state: `init -> awaiting_ack -> open -> failed`.
|
|
50
|
+
- On success, mark `session.protocols.add('v1')`.
|
|
51
|
+
- On timeout, keep `legacy` only (no disconnect).
|
|
52
|
+
|
|
53
|
+
6. Orchestrator protocol selection (Strategy)
|
|
54
|
+
- `ProtocolSelector`: choose v1 if peer supports it, else legacy.
|
|
55
|
+
- v1 ACK uses response codes; legacy uses state-based heuristic.
|
|
56
|
+
- Optional strict verify for v1: wait for append before success.
|
|
57
|
+
|
|
58
|
+
7. Validators layout (Template Method + Adapter)
|
|
59
|
+
- Keep shared validators in `shared/validators/`.
|
|
60
|
+
- Protocol-specific validators live under `legacy/validators/` and `v1/validators/`.
|
|
61
|
+
- Protocol adapter decides which validator set to use.
|
|
62
|
+
|
|
63
|
+
## Step-by-step plan
|
|
64
|
+
1. Add `ProtocolRegistry` and `ProtocolAdapter` definitions (design only).
|
|
65
|
+
2. Update `NetworkMessages` to iterate registry and open one channel per protocol.
|
|
66
|
+
3. Introduce `ProtocolSession` and store it in `ConnectionManager`.
|
|
67
|
+
4. Implement v1 router map based on `proto/network.proto` types.
|
|
68
|
+
5. Add v1 handshake state machine and capability negotiation.
|
|
69
|
+
6. Add `ProtocolSelector` in `MessageOrchestrator` with legacy fallback.
|
|
70
|
+
7. Align validators: shared core + protocol-specific wrappers.
|
|
71
|
+
8. Tests (future): legacy-only peers, v1 negotiation, mixed cluster.
|
|
72
|
+
|
|
73
|
+
## Notes for v2
|
|
74
|
+
- Add `network/v2` adapter + protobuf schema.
|
|
75
|
+
- Registry chooses the highest common protocol per peer.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Networking layer redesign (draft)
|
|
2
|
+
|
|
3
|
+
Cel: uporządkować warstwę sieciową w `src/core/network`, wprowadzić binarne wiadomości (Protobuf + Protomux), system ACK/heartbeat, zunifikowane kody błędów oraz nowy endpoint RPC, bez ingerencji w istniejącą implementację (ten dokument jest tylko projektem).
|
|
4
|
+
|
|
5
|
+
## Założenia
|
|
6
|
+
- Komunikacja p2p przez Hyperswarm zostaje, ale wiadomości idą binarnie (Protobuf) na kanałach Protomux.
|
|
7
|
+
- Każdy typ wiadomości zwraca `Result` z kodem sukcesu/błędu (własne kody, nie HTTP).
|
|
8
|
+
- Heartbeat/liveness co ~10s z losowym jitterem; łatwa konfiguracja z `config`/`constants`.
|
|
9
|
+
- Handshake z zachowaniem PKI, ale mniej round-tripów i z ochroną DoS.
|
|
10
|
+
- Modularna architektura (klasy/serwisy), separacja transportu, protokołu, zdrowia, bezpieczeństwa i RPC.
|
|
11
|
+
|
|
12
|
+
## Architektura warstw
|
|
13
|
+
- **Transport (HyperswarmTransport)**: zarządza swarmem, tworzy kanały Protomux (binary encoding), egzekwuje limity połączeń.
|
|
14
|
+
- **Protocol (EnvelopeCodec, Protobuf schemas)**: wspólny `Envelope` + `Result`; mapowanie typów wiadomości; validacja długości/pól przed dekodowaniem.
|
|
15
|
+
- **Handshake (ValidatorHandshake)**: szybki trójfazowy handshake z wyzwaniem nonce + podpis, negocjacja wersji/capabilities, limity prób.
|
|
16
|
+
- **Health (HeartbeatScheduler + LivenessStore)**: wysyła heartbeat do wszystkich znanych peerów (z konekcji lub z listy validatorów), aktualizuje liveness, generuje zdarzenia dla RPC.
|
|
17
|
+
- **Security (DosGuard)**: rate limit per peer/endpoint, maks. rozmiary payloadów, kolejki handshake, banlista czasowa.
|
|
18
|
+
- **RPC adapter (ValidatorStatusController)**: odczytuje `LivenessStore` i zwraca status walidatora.
|
|
19
|
+
|
|
20
|
+
## Proponowane moduły / pliki (kierunek, bez implementacji)
|
|
21
|
+
- `src/core/network/transport/HyperswarmTransport.js`: opakowanie na Hyperswarm + Protomux, jednolity interfejs kanałów binarnych.
|
|
22
|
+
- `src/core/network/protocol/EnvelopeCodec.js`: enkodowanie/dekodowanie Protobuf, walidacja schematu, mapowanie `MessageType` -> handler.
|
|
23
|
+
- `src/core/network/protocol/error-codes.js`: stałe kodów (`ErrorCode` enum) współdzielone między node'ami.
|
|
24
|
+
- `src/core/network/handshake/ValidatorHandshake.js`: stan maszyny handshake, ochrona DoS, fallbacki wersji.
|
|
25
|
+
- `src/core/network/health/HeartbeatScheduler.js`: harmonogram heartbeatów + jitter, retry/backoff.
|
|
26
|
+
- `src/core/network/health/LivenessStore.js`: przechowuje `lastSeen`, `missed`, `state=active/inactive/banned`.
|
|
27
|
+
- `src/core/network/security/DosGuard.js`: token bucket + ograniczenia równoległych handshake, limit rozmiaru wiadomości.
|
|
28
|
+
- `src/core/network/rpc/ValidatorStatusController.js`: integracja z istniejącym RPC routerem (`/validators/:address/status`).
|
|
29
|
+
|
|
30
|
+
## Szkic Protobuf (draft, do dodania jako nowy `.proto`)
|
|
31
|
+
```proto
|
|
32
|
+
syntax = "proto3";
|
|
33
|
+
package network.v1;
|
|
34
|
+
|
|
35
|
+
enum MessageType {
|
|
36
|
+
UNKNOWN = 0;
|
|
37
|
+
HANDSHAKE_INIT = 1;
|
|
38
|
+
HANDSHAKE_ACK = 2;
|
|
39
|
+
HEARTBEAT_PING = 3;
|
|
40
|
+
HEARTBEAT_ACK = 4;
|
|
41
|
+
VALIDATOR_STATUS_REQUEST = 5;
|
|
42
|
+
VALIDATOR_STATUS_RESPONSE = 6;
|
|
43
|
+
// ...pozostałe typy operacyjne (transfer/role) mogą być zmapowane później
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
enum ResultCode {
|
|
47
|
+
RESULT_OK = 0;
|
|
48
|
+
RESULT_RETRY = 1; // używane do łagodnego backoffu
|
|
49
|
+
RESULT_INVALID_PAYLOAD = 2;
|
|
50
|
+
RESULT_UNAUTHORIZED = 3;
|
|
51
|
+
RESULT_UNAUTHENTICATED = 4;
|
|
52
|
+
RESULT_UNSUPPORTED_VERSION = 5;
|
|
53
|
+
RESULT_RATE_LIMITED = 6;
|
|
54
|
+
RESULT_TOO_MANY_CONNECTIONS = 7;
|
|
55
|
+
RESULT_BUSY = 8;
|
|
56
|
+
RESULT_TIMEOUT = 9;
|
|
57
|
+
RESULT_PEER_BANNED = 10;
|
|
58
|
+
RESULT_SIGNATURE_INVALID = 11;
|
|
59
|
+
RESULT_NOT_VALIDATOR = 12;
|
|
60
|
+
RESULT_INTERNAL = 13;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
message Result {
|
|
64
|
+
ResultCode code = 1;
|
|
65
|
+
string reason = 2;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
message Envelope {
|
|
69
|
+
uint64 session_id = 1;
|
|
70
|
+
MessageType type = 3;
|
|
71
|
+
bytes payload = 4; // zakodowany message specyficzny dla type
|
|
72
|
+
Result result = 5; // dla odpowiedzi/ACK
|
|
73
|
+
uint64 timestamp = 6;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
message HandshakeInit {
|
|
77
|
+
bytes node_pk = 1;
|
|
78
|
+
uint32 version = 2;
|
|
79
|
+
bytes nonce = 3;
|
|
80
|
+
bytes signature = 4; // sig(nonce || channel || version)
|
|
81
|
+
repeated string capabilities = 5; // np. ["binary", "hb:v1"]
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
message HandshakeAck {
|
|
85
|
+
bytes nonce = 1; // nonce od inicjatora
|
|
86
|
+
bytes signature = 2; // sig(nonce || channel || version)
|
|
87
|
+
uint32 version = 3; // negocjowany
|
|
88
|
+
Result result = 4; // ERROR_UNSUPPORTED_VERSION itd.
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
message HeartbeatPing {
|
|
92
|
+
bytes node_pk = 1;
|
|
93
|
+
uint64 sequence = 2;
|
|
94
|
+
uint64 timestamp_ms = 3;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
message HeartbeatAck {
|
|
98
|
+
uint64 sequence = 1;
|
|
99
|
+
Result result = 2; // ERROR_OK lub powód degradacji
|
|
100
|
+
uint64 timestamp_ms = 3;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
message ValidatorStatusRequest {
|
|
104
|
+
bytes validator_pk = 1;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
message ValidatorStatusResponse {
|
|
108
|
+
Result result = 1;
|
|
109
|
+
bool active = 2;
|
|
110
|
+
uint64 last_seen_ms = 3;
|
|
111
|
+
uint32 missed_heartbeats = 4;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Handshake (przykładowy przebieg)
|
|
116
|
+
1. **Init**: inicjator wysyła `HandshakeInit` na dedykowany kanał Protomux `protocol:handshake/v1` (binary). Dodajemy `DosGuard` limitujący równoległe init-y i weryfikujący rozmiar.
|
|
117
|
+
2. **Ack**: odbiorca weryfikuje podpis i wersję, odpowiada `HandshakeAck` (sukces lub błąd). Przy sukcesie odkłada połączenie do `ConnectionManager` razem z metadanymi (rola, capabilities).
|
|
118
|
+
3. **Promotion**: dopiero po sukcesie handshake kanały operacyjne/heartbeat są otwierane; w przeciwnym razie połączenie jest zamykane i peer może trafić na banlistę czasową.
|
|
119
|
+
|
|
120
|
+
Minimalizuje to round-trip (1.5 RTT), utrzymuje PKI (nonce + podpis) i pozwala na rollback do niższej wersji jeśli różne węzły.
|
|
121
|
+
|
|
122
|
+
## Heartbeat / liveness
|
|
123
|
+
- **Interwał**: domyślnie 10s ± losowy jitter (np. 0–2s) by uniknąć szpilek. Parametryzacja w constants/config.
|
|
124
|
+
- **Zakres**: każda znana para (aktywny validator + inne role) dostaje `HeartbeatPing`. Po 3 nieudanych ACK (lub braków w oknie czasowym) peer przechodzi w `inactive`, po większej liczbie w `unhealthy`.
|
|
125
|
+
- **Integracja**: `HeartbeatScheduler` korzysta z `ConnectionManager` do nadawania; `LivenessStore` aktualizuje się na podstawie `HeartbeatAck` i czasu.
|
|
126
|
+
- **Odpowiedź**: `HeartbeatAck.result.code` pozwala zakomunikować throttle (`ERROR_RATE_LIMITED`) lub przepełnienie (`ERROR_BUSY`), co zmniejsza logowanie błędów.
|
|
127
|
+
|
|
128
|
+
## Nowy endpoint RPC
|
|
129
|
+
- Ścieżka: `GET /validators/:address/status` w warstwie RPC.
|
|
130
|
+
- Źródło prawdy: `LivenessStore` (ostatni heartbeat, liczba nieodebranych, stan). `active=true` gdy ostatni heartbeat < 3*interval i brak poważnych błędów.
|
|
131
|
+
- Payload (200): `{ address, active, lastSeenMs, missed, reason }`. Brak zależności od kodów HTTP dla logiki aplikacyjnej; HTTP 404 tylko gdy adres niepoprawny (opcjonalnie 200 z `active:false` i `result.code=ERROR_NOT_VALIDATOR`).
|
|
132
|
+
- Przygotować kontrakt dla klientów (CLI/SDK) by interpretowali `Result`.
|
|
133
|
+
|
|
134
|
+
## Ochrona przed DoS
|
|
135
|
+
- **Rate limiting**: token bucket per peer na handshake i heartbeat, limity równoległych handshake w `DosGuard`.
|
|
136
|
+
- **Rozmiary**: twarde limity na rozmiar pakietu Protobuf przed deserializacją; odrzucenie z `ERROR_INVALID_PAYLOAD`.
|
|
137
|
+
- **Kolejki**: ograniczona kolejka zadań handshake/heartbeat; przy przepełnieniu `ERROR_BUSY` w ACK i zamknięcie połączenia.
|
|
138
|
+
- **Bany czasowe**: peer wysyłający zbyt wiele złych podpisów lub oversize payloadów trafia na banlistę na X minut.
|
|
139
|
+
- **Separacja kanałów**: osobne kanały Protomux (handshake, control/heartbeat, operations) by odciąć hałas od głównych operacji.
|
|
140
|
+
|
|
141
|
+
## Kody błędów (wspólny enum)
|
|
142
|
+
- Sukces: `ERROR_OK`.
|
|
143
|
+
- Autoryzacja: `ERROR_UNAUTHENTICATED`, `ERROR_UNAUTHORIZED`, `ERROR_SIGNATURE_INVALID`, `ERROR_NOT_VALIDATOR`.
|
|
144
|
+
- Dostępność: `ERROR_RATE_LIMITED`, `ERROR_BUSY`, `ERROR_TOO_MANY_CONNECTIONS`, `ERROR_PEER_BANNED`.
|
|
145
|
+
- Protokół: `ERROR_INVALID_PAYLOAD`, `ERROR_UNSUPPORTED_VERSION`, `ERROR_TIMEOUT`.
|
|
146
|
+
- Ogólne: `ERROR_RETRY` (miękkie), `ERROR_INTERNAL`.
|
|
147
|
+
|
|
148
|
+
## Plan wdrożenia (wysoki poziom)
|
|
149
|
+
1. Dodać schemat `.proto` z Envelope/Result/Handshake/Heartbeat/Status.
|
|
150
|
+
2. Wydzielić `transport/` + `protocol/` + `handshake/` + `health/` + `security/` katalogi i przenieść istniejące odpowiedniki (`NetworkMessages`, router, itp.) stopniowo.
|
|
151
|
+
3. Zaimplementować `EnvelopeCodec` w Protomux (binary), przełączyć routing na typy wiadomości zamiast JSON.
|
|
152
|
+
4. Zaimplementować handshake (1.5 RTT) i dołożyć `DosGuard` oraz limity na poziomie Protomux channel.
|
|
153
|
+
5. Dodać HeartbeatScheduler + LivenessStore, zasilić je danymi do RPC.
|
|
154
|
+
6. Dodać endpoint RPC `/validators/:address/status`, mapujący dane z LivenessStore.
|
|
155
|
+
7. Testy: symulacja DoS (próby handshake > limit, oversize payload), degradacja heartbeat, negocjacja wersji i kompatybilności.
|
package/msb.mjs
CHANGED
|
@@ -1,33 +1,22 @@
|
|
|
1
1
|
import { MainSettlementBus } from './src/index.js';
|
|
2
|
+
import { startRpcServer } from './rpc/rpc_server.js';
|
|
3
|
+
import { createConfig, ENV } from './src/config/env.js';
|
|
2
4
|
|
|
3
5
|
const pearApp = typeof Pear !== 'undefined' ? (Pear.app ?? Pear.config) : undefined;
|
|
4
6
|
const runtimeArgs = typeof process !== 'undefined' ? process.argv.slice(2) : [];
|
|
5
7
|
const args = pearApp?.args ?? runtimeArgs;
|
|
6
8
|
const runRpc = args.includes('--rpc');
|
|
9
|
+
const storeName = pearApp?.args?.[0] ?? runtimeArgs[0]
|
|
7
10
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
enable_role_requester: false,
|
|
14
|
-
enable_wallet: true,
|
|
15
|
-
enable_validator_observer: true,
|
|
16
|
-
enable_interactive_mode: true,
|
|
17
|
-
disable_rate_limit: false,
|
|
18
|
-
enable_tx_apply_logs: false,
|
|
19
|
-
enable_error_apply_logs: false,
|
|
20
|
-
};
|
|
11
|
+
const rpc = {
|
|
12
|
+
storeName: pearApp?.args?.[0] ?? runtimeArgs[0],
|
|
13
|
+
enableWallet: false,
|
|
14
|
+
enableInteractiveMode: false
|
|
15
|
+
}
|
|
21
16
|
|
|
22
|
-
const
|
|
23
|
-
...opts,
|
|
24
|
-
enable_tx_apply_logs: false,
|
|
25
|
-
enable_error_apply_logs: false,
|
|
26
|
-
enable_wallet: false,
|
|
27
|
-
enable_interactive_mode: false,
|
|
28
|
-
};
|
|
17
|
+
const options = args.includes('--rpc') ? rpc : { storeName }
|
|
29
18
|
|
|
30
|
-
const msb = new MainSettlementBus(
|
|
19
|
+
const msb = new MainSettlementBus(createConfig(ENV.MAINNET, options));
|
|
31
20
|
|
|
32
21
|
msb.ready().then(async () => {
|
|
33
22
|
if (runRpc) {
|
|
@@ -36,10 +25,9 @@ msb.ready().then(async () => {
|
|
|
36
25
|
const port = (portIndex !== -1 && args[portIndex + 1]) ? parseInt(args[portIndex + 1], 10) : 5000;
|
|
37
26
|
const hostIndex = args.indexOf('--host');
|
|
38
27
|
const host = (hostIndex !== -1 && args[hostIndex + 1]) ? args[hostIndex + 1] : 'localhost';
|
|
39
|
-
|
|
40
|
-
const {startRpcServer} = await import('./rpc/rpc_server.mjs');
|
|
41
28
|
startRpcServer(msb, host, port);
|
|
42
29
|
} else {
|
|
30
|
+
console.log('RPC server will not be started.');
|
|
43
31
|
msb.interactiveMode();
|
|
44
32
|
}
|
|
45
33
|
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trac-msb",
|
|
3
3
|
"main": "msb.mjs",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.8",
|
|
5
5
|
"pear": {
|
|
6
6
|
"name": "trac-msb",
|
|
7
7
|
"type": "terminal"
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
"test:unit:bare:cov": "brittle-bare -c -t 60000 tests/unit/unit.test.js"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@tracsystems/blake3": "0.0.13",
|
|
29
28
|
"autobase": "7.20.1",
|
|
30
29
|
"b4a": "1.6.7",
|
|
31
30
|
"bare-crypto": "1.12.0",
|
|
@@ -50,7 +49,7 @@
|
|
|
50
49
|
"protomux-wakeup": "2.4.0",
|
|
51
50
|
"readline": "npm:bare-node-readline",
|
|
52
51
|
"ready-resource": "1.1.2",
|
|
53
|
-
"trac-wallet": "0.0.43-msb-r2.
|
|
52
|
+
"trac-wallet": "0.0.43-msb-r2.9",
|
|
54
53
|
"tty": "npm:bare-node-tty"
|
|
55
54
|
},
|
|
56
55
|
"devDependencies": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// rpc_server.mjs
|
|
2
2
|
import http from 'http'
|
|
3
|
-
import { applyCors } from './cors.
|
|
4
|
-
import { routes } from './routes/index.
|
|
3
|
+
import { applyCors } from './cors.js';
|
|
4
|
+
import { routes } from './routes/index.js';
|
|
5
5
|
|
|
6
6
|
export const createServer = (msbInstance) => {
|
|
7
7
|
const server = http.createServer({}, async (req, res) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { decodeBase64Payload, isBase64, sanitizeBulkPayloadsRequestBody, sanitizeTransferPayload, validatePayloadStructure } from "./utils/helpers.
|
|
2
|
-
import { MAX_SIGNED_LENGTH, ZERO_WK } from "./constants.
|
|
3
|
-
import { buildRequestUrl } from "./utils/url.
|
|
1
|
+
import { decodeBase64Payload, isBase64, sanitizeBulkPayloadsRequestBody, sanitizeTransferPayload, validatePayloadStructure } from "./utils/helpers.js"
|
|
2
|
+
import { MAX_SIGNED_LENGTH, ZERO_WK } from "./constants.js";
|
|
3
|
+
import { buildRequestUrl } from "./utils/url.js";
|
|
4
4
|
import { isHexString } from "../src/utils/helpers.js";
|
|
5
5
|
import {
|
|
6
6
|
getBalance,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "./rpc_services.js";
|
|
17
17
|
import { bufferToBigInt, licenseBufferToBigInt } from "../src/utils/amountSerialization.js";
|
|
18
18
|
import { isAddressValid } from "../src/core/state/utils/address.js";
|
|
19
|
-
import { getConfirmedParameter } from "./utils/confirmedParameter.
|
|
19
|
+
import { getConfirmedParameter } from "./utils/confirmedParameter.js";
|
|
20
20
|
|
|
21
21
|
export async function handleBalance({ req, respond, msbInstance }) {
|
|
22
22
|
const url = buildRequestUrl(req);
|
|
@@ -258,7 +258,7 @@ export async function handleAccountDetails({ msbInstance, respond, req }) {
|
|
|
258
258
|
return respond(400, { error: 'Parameter "confirmed" must be exactly "true" or "false"' });
|
|
259
259
|
}
|
|
260
260
|
|
|
261
|
-
if (!isAddressValid(address)) {
|
|
261
|
+
if (!isAddressValid(address, msbInstance.config.addressPrefix)) {
|
|
262
262
|
return respond(400, { error: "Invalid account address format" });
|
|
263
263
|
}
|
|
264
264
|
|
package/rpc/rpc_services.js
CHANGED
|
@@ -51,7 +51,7 @@ export async function getTxDetails(msbInstance, hash) {
|
|
|
51
51
|
return null;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
return normalizeDecodedPayloadForJson(rawPayload.decoded);
|
|
54
|
+
return normalizeDecodedPayloadForJson(rawPayload.decoded, msbInstance.config);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
export async function fetchBulkTxPayloads(msbInstance, hashes) {
|
|
@@ -73,7 +73,7 @@ export async function fetchBulkTxPayloads(msbInstance, hashes) {
|
|
|
73
73
|
if (result === null || result === undefined) {
|
|
74
74
|
res.missing.push(hash);
|
|
75
75
|
} else {
|
|
76
|
-
const decodedResult = normalizeDecodedPayloadForJson(result.decoded);
|
|
76
|
+
const decodedResult = normalizeDecodedPayloadForJson(result.decoded, msbInstance.config);
|
|
77
77
|
res.results.push({ hash, payload: decodedResult });
|
|
78
78
|
}
|
|
79
79
|
});
|
|
@@ -93,7 +93,7 @@ export async function getExtendedTxDetails(msbInstance, hash, confirmed) {
|
|
|
93
93
|
if (confirmedLength === null) {
|
|
94
94
|
throw new Error(`No confirmed length found for tx hash: ${hash} in confirmed mode`);
|
|
95
95
|
}
|
|
96
|
-
const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded,
|
|
96
|
+
const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, msbInstance.config);
|
|
97
97
|
const feeBuffer = state.getFee();
|
|
98
98
|
return {
|
|
99
99
|
txDetails: normalizedPayload,
|
|
@@ -107,7 +107,7 @@ export async function getExtendedTxDetails(msbInstance, hash, confirmed) {
|
|
|
107
107
|
throw new Error(`No payload found for tx hash: ${hash}`);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded,
|
|
110
|
+
const normalizedPayload = normalizeDecodedPayloadForJson(rawPayload.decoded, msbInstance.config);
|
|
111
111
|
const length = await state.getTransactionConfirmedLength(hash);
|
|
112
112
|
if (length === null) {
|
|
113
113
|
return {
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import b4a from 'b4a'
|
|
2
|
+
|
|
3
|
+
export class Config {
|
|
4
|
+
#options
|
|
5
|
+
#config
|
|
6
|
+
#bootstrap
|
|
7
|
+
#channel
|
|
8
|
+
|
|
9
|
+
constructor(options = {}, config = {}) {
|
|
10
|
+
this.#validate(options, config)
|
|
11
|
+
this.#options = options
|
|
12
|
+
this.#config = config
|
|
13
|
+
this.#bootstrap = b4a.from(this.#options.bootstrap || this.#config.bootstrap, 'hex')
|
|
14
|
+
// Ensure a 32-byte channel buffer (repeat-fill from string/Buffer if provided)
|
|
15
|
+
this.#channel = b4a.alloc(32).fill(this.#options.channel || this.#config.channel)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get addressLength() {
|
|
19
|
+
return this.#config.addressLength
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get addressPrefix() {
|
|
23
|
+
return this.#config.addressPrefix
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get addressPrefixLength() {
|
|
27
|
+
return this.addressPrefix.length
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get bech32mHrpLength() {
|
|
31
|
+
return this.#config.bech32mHrpLength
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
get bootstrap() {
|
|
35
|
+
return this.#bootstrap
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get channel() {
|
|
39
|
+
return this.#channel
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get dhtBootstrap() {
|
|
43
|
+
if (this.#isOverriden('dhtBootstrap')) return this.#options.dhtBootstrap
|
|
44
|
+
return this.#config.dhtBootstrap
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
get disableRateLimit() {
|
|
48
|
+
if (this.#isOverriden('disableRateLimit')) return !!this.#options.disableRateLimit
|
|
49
|
+
return !!this.#config.disableRateLimit
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get enableErrorApplyLogs() {
|
|
53
|
+
if (this.#isOverriden('enableErrorApplyLogs')) return !!this.#options.enableErrorApplyLogs
|
|
54
|
+
return !!this.#config.enableErrorApplyLogs
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get enableInteractiveMode() {
|
|
58
|
+
if (this.#isOverriden('enableInteractiveMode')) return this.#options.enableInteractiveMode !== false
|
|
59
|
+
return !!this.#config.enableInteractiveMode
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
get enableRoleRequester() {
|
|
63
|
+
if (this.#isOverriden('enableRoleRequester')) return !!this.#options.enableRoleRequester
|
|
64
|
+
return !!this.#config.enableRoleRequester
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get enableValidatorObserver() {
|
|
68
|
+
if (this.#isOverriden('enableValidatorObserver')) return !!this.#options.enableValidatorObserver
|
|
69
|
+
return !!this.#config.enableValidatorObserver
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
get enableTxApplyLogs() {
|
|
73
|
+
if (this.#isOverriden('enableTxApplyLogs')) return !!this.#options.enableTxApplyLogs
|
|
74
|
+
return !!this.#config.enableTxApplyLogs
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get enableWallet() {
|
|
78
|
+
if (this.#isOverriden('enableWallet')) return this.#options.enableWallet !== false
|
|
79
|
+
return !!this.#config.enableWallet
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
get isAdminMode() {
|
|
83
|
+
return this.#options.storeName === 'admin'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
get keyPairPath() {
|
|
87
|
+
return `${this.storesFullPath}/db/keypair.json`
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get maxRetries() {
|
|
91
|
+
if (this.#isOverriden('maxRetries')) return this.#options.maxRetries
|
|
92
|
+
return this.#config.maxRetries
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
get maxValidators() {
|
|
96
|
+
if (this.#isOverriden('maxValidators')) return this.#options.maxValidators
|
|
97
|
+
return this.#config.maxValidators
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
get networkId() {
|
|
101
|
+
return this.#config.networkId
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
get storesDirectory() {
|
|
105
|
+
if (this.#isOverriden('storesDirectory')) return this.#options.storesDirectory
|
|
106
|
+
return this.#config.storesDirectory
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
get storesFullPath() {
|
|
110
|
+
return `${this.storesDirectory}${this.#options.storeName}`
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
get messageThreshold() {
|
|
114
|
+
return this.#config.messageThreshold
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
get messageValidatorRetryDelay() {
|
|
118
|
+
return this.#config.messageValidatorRetryDelay
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
get messageValidatorResponseTimeout() {
|
|
122
|
+
return this.#config.messageValidatorResponseTimeout
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Most of these properties are boolean
|
|
126
|
+
#isOverriden(prop) {
|
|
127
|
+
return this.#options.hasOwnProperty(prop)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
#validate(options, config) {
|
|
131
|
+
if (!options.channel && !config.channel) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"MainSettlementBus: Channel is required. Application cannot start without channel."
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { TRAC_NETWORK_MSB_MAINNET_PREFIX } from 'trac-wallet/constants.js';
|
|
2
|
+
import { Config } from './config.js';
|
|
3
|
+
|
|
4
|
+
export const ENV = {
|
|
5
|
+
MAINNET: 'mainnet',
|
|
6
|
+
DEVELOPMENT: 'development',
|
|
7
|
+
TESTNET1: 'testnet1'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const configData = {
|
|
11
|
+
[ENV.MAINNET]: {
|
|
12
|
+
addressLength: 63,
|
|
13
|
+
addressPrefix: TRAC_NETWORK_MSB_MAINNET_PREFIX,
|
|
14
|
+
addressPrefixLength: TRAC_NETWORK_MSB_MAINNET_PREFIX.length,
|
|
15
|
+
bech32mHrpLength: TRAC_NETWORK_MSB_MAINNET_PREFIX.length + 1, // len(addressPrefix + separator)
|
|
16
|
+
bootstrap: 'acbc3a4344d3a804101d40e53db1dda82b767646425af73599d4cd6577d69685',
|
|
17
|
+
channel: '0000trac0network0msb0mainnet0000',
|
|
18
|
+
dhtBootstrap: ['116.202.214.149:10001', '157.180.12.214:10001', 'node1.hyperdht.org:49737', 'node2.hyperdht.org:49737', 'node3.hyperdht.org:49737'],
|
|
19
|
+
disableRateLimit: false,
|
|
20
|
+
enableErrorApplyLogs: false,
|
|
21
|
+
enableInteractiveMode: true,
|
|
22
|
+
enableRoleRequester: false,
|
|
23
|
+
enableTxApplyLogs: false,
|
|
24
|
+
enableValidatorObserver: true,
|
|
25
|
+
enableWallet: true,
|
|
26
|
+
maxValidators: 50,
|
|
27
|
+
maxRetries: 3,
|
|
28
|
+
messageThreshold: 3,
|
|
29
|
+
messageValidatorRetryDelay: 1000, //How long to wait before retrying (ms) MESSAGE_VALIDATOR_RETRY_DELAY_MS
|
|
30
|
+
messageValidatorResponseTimeout: 3 * 3 * 1000, //Overall timeout for sending a message (ms). This is 3 * maxRetries * messageValidatorRetryDelay;
|
|
31
|
+
networkId: 918,
|
|
32
|
+
storesDirectory: 'stores/',
|
|
33
|
+
},
|
|
34
|
+
[ENV.DEVELOPMENT]: {
|
|
35
|
+
addressLength: 63,
|
|
36
|
+
addressPrefix: TRAC_NETWORK_MSB_MAINNET_PREFIX,
|
|
37
|
+
addressPrefixLength: TRAC_NETWORK_MSB_MAINNET_PREFIX.length,
|
|
38
|
+
bech32mHrpLength: TRAC_NETWORK_MSB_MAINNET_PREFIX.length + 1, // len(addressPrefix + separator)
|
|
39
|
+
bootstrap: 'e90cca53847a12a82f3bf0f67401e45e2ccc1698ee163e61414c2894eb3c6b12',
|
|
40
|
+
channel: '12312313123123',
|
|
41
|
+
dhtBootstrap: ['116.202.214.149:10001', '157.180.12.214:10001', 'node1.hyperdht.org:49737', 'node2.hyperdht.org:49737', 'node3.hyperdht.org:49737'],
|
|
42
|
+
disableRateLimit: false,
|
|
43
|
+
enableErrorApplyLogs: true,
|
|
44
|
+
enableInteractiveMode: true,
|
|
45
|
+
enableRoleRequester: false,
|
|
46
|
+
enableTxApplyLogs: true,
|
|
47
|
+
enableValidatorObserver: true,
|
|
48
|
+
enableWallet: true,
|
|
49
|
+
maxValidators: 6,
|
|
50
|
+
maxRetries: 0,
|
|
51
|
+
messageThreshold: 1000,
|
|
52
|
+
messageValidatorRetryDelay: 1000, //How long to wait before retrying (ms) MESSAGE_VALIDATOR_RETRY_DELAY_MS
|
|
53
|
+
messageValidatorResponseTimeout: 3 * 3 * 1000, //Overall timeout for sending a message (ms). This is 3 * maxRetries * messageValidatorRetryDelay;
|
|
54
|
+
networkId: 918,
|
|
55
|
+
storesDirectory : 'stores/',
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const createConfig = (environment, options) => {
|
|
60
|
+
return new Config(options, configData[environment])
|
|
61
|
+
}
|