trac-msb 0.2.7 → 0.2.9
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/msb.mjs +13 -25
- package/package.json +8 -4
- package/proto/network.proto +74 -0
- package/rpc/{create_server.mjs → create_server.js} +4 -4
- package/rpc/{handlers.mjs → handlers.js} +7 -7
- package/rpc/routes/{index.mjs → index.js} +1 -1
- package/rpc/routes/{v1.mjs → v1.js} +1 -1
- package/rpc/rpc_server.js +10 -0
- package/rpc/rpc_services.js +48 -7
- package/rpc/utils/{helpers.mjs → helpers.js} +1 -1
- package/src/config/config.js +137 -0
- package/src/config/env.js +63 -0
- package/src/core/network/Network.js +133 -119
- package/src/core/network/identity/NetworkWalletFactory.js +5 -6
- 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/ValidatorResponse.js +2 -2
- package/src/core/network/{messaging → protocols/legacy}/validators/base/BaseResponse.js +13 -6
- 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/protocols/shared/handlers/TransferOperationHandler.js +57 -0
- package/src/core/network/{messaging → protocols/shared}/handlers/base/BaseOperationHandler.js +21 -26
- package/src/core/network/{messaging → protocols/shared}/validators/PartialBootstrapDeployment.js +3 -3
- package/src/core/network/{messaging → protocols/shared}/validators/PartialRoleAccess.js +15 -12
- package/src/core/network/{messaging → protocols/shared}/validators/PartialTransaction.js +10 -11
- package/src/core/network/{messaging → protocols/shared}/validators/PartialTransfer.js +10 -7
- package/src/core/network/{messaging → protocols/shared}/validators/base/PartialOperation.js +40 -22
- package/src/core/network/protocols/v1/NetworkMessageRouter.js +15 -0
- package/src/core/network/services/ConnectionManager.js +13 -19
- package/src/core/network/services/MessageOrchestrator.js +10 -22
- package/src/core/network/services/TransactionPoolService.js +10 -10
- package/src/core/network/services/TransactionRateLimiterService.js +5 -3
- package/src/core/network/services/ValidatorObserverService.js +46 -21
- package/src/core/state/State.js +137 -141
- 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 +250 -325
- 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 +21 -17
- package/src/utils/cli.js +0 -8
- package/src/utils/cliCommands.js +11 -11
- package/src/utils/constants.js +36 -24
- 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 +94 -11
- package/src/utils/protobuf/network.cjs +840 -0
- package/src/utils/protobuf/operationHelpers.js +10 -0
- 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 +10 -10
- 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/networkV1.fixtures.js +84 -0
- package/tests/fixtures/protobuf.fixtures.js +110 -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 +113 -99
- package/tests/helpers/transactionPayloads.mjs +26 -12
- 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 +203 -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 +10 -7
- package/tests/unit/network/NetworkWalletFactory.test.js +14 -14
- 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 +11 -8
- package/tests/unit/state/apply/addAdmin/state.apply.addAdmin.test.js +11 -7
- package/tests/unit/state/apply/addIndexer/addIndexerScenarioHelpers.js +18 -20
- package/tests/unit/state/apply/addWriter/addWriterScenarioHelpers.js +57 -48
- package/tests/unit/state/apply/addWriter/addWriterValidatorRewardScenario.js +2 -1
- package/tests/unit/state/apply/adminRecovery/adminRecoveryScenarioHelpers.js +72 -57
- package/tests/unit/state/apply/adminRecovery/state.apply.adminRecovery.test.js +3 -7
- package/tests/unit/state/apply/appendWhitelist/appendWhitelistScenarioHelpers.js +12 -14
- package/tests/unit/state/apply/balanceInitialization/balanceInitializationScenarioHelpers.js +18 -13
- 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 +27 -30
- package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentDuplicateRegistrationScenario.js +2 -1
- package/tests/unit/state/apply/bootstrapDeployment/bootstrapDeploymentScenarioHelpers.js +24 -21
- 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 +16 -16
- package/tests/unit/state/apply/common/payload-structure/initializationDisabledScenario.js +10 -5
- 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 +16 -9
- package/tests/unit/state/apply/removeIndexer/removeIndexerScenarioHelpers.js +6 -5
- package/tests/unit/state/apply/removeWriter/removeWriterScenarioHelpers.js +23 -19
- package/tests/unit/state/apply/transfer/transferDoubleSpendAcrossValidatorsScenario.js +45 -36
- package/tests/unit/state/apply/transfer/transferScenarioHelpers.js +48 -45
- package/tests/unit/state/apply/txOperation/txOperationScenarioHelpers.js +32 -29
- 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/unit.test.js +1 -1
- package/tests/unit/utils/buffer/buffer.test.js +62 -1
- 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/normalizers/normalizers.test.js +469 -0
- package/tests/unit/utils/protobuf/operationHelpers.test.js +120 -2
- package/tests/unit/utils/utils.test.js +0 -1
- package/rpc/rpc_server.mjs +0 -10
- package/src/core/network/messaging/NetworkMessages.js +0 -63
- package/src/core/network/messaging/handlers/GetRequestHandler.js +0 -112
- package/src/core/network/messaging/handlers/ResponseHandler.js +0 -108
- package/src/core/network/messaging/handlers/RoleOperationHandler.js +0 -116
- package/src/core/network/messaging/handlers/SubnetworkOperationHandler.js +0 -143
- package/src/core/network/messaging/handlers/TransferOperationHandler.js +0 -52
- package/src/core/network/messaging/routes/NetworkMessageRouter.js +0 -94
- package/src/core/network/messaging/validators/AdminResponse.js +0 -58
- package/src/core/network/messaging/validators/CustomNodeResponse.js +0 -46
- package/src/core/state/utils/indexerEntry.js +0 -105
- package/src/messages/base/StateBuilder.js +0 -25
- package/src/messages/completeStateMessages/CompleteStateMessageBuilder.js +0 -421
- package/src/messages/completeStateMessages/CompleteStateMessageDirector.js +0 -252
- package/src/messages/completeStateMessages/CompleteStateMessageOperations.js +0 -299
- package/src/messages/partialStateMessages/PartialStateMessageBuilder.js +0 -272
- package/src/messages/partialStateMessages/PartialStateMessageDirector.js +0 -137
- package/src/messages/partialStateMessages/PartialStateMessageOperations.js +0 -131
- package/src/utils/crypto.js +0 -11
- package/tests/integration/apply/addAdmin/addAdminBasic.test.js +0 -68
- package/tests/integration/apply/addAdmin/addAdminRecovery.test.js +0 -125
- package/tests/integration/apply/addIndexer.test.js +0 -237
- package/tests/integration/apply/addWhitelist.test.js +0 -53
- package/tests/integration/apply/addWriter.test.js +0 -244
- package/tests/integration/apply/apply.test.js +0 -19
- package/tests/integration/apply/banValidator.test.js +0 -109
- package/tests/integration/apply/postTx/invalidSubValues.test.js +0 -103
- package/tests/integration/apply/postTx/postTx.test.js +0 -222
- package/tests/integration/apply/removeIndexer.test.js +0 -128
- package/tests/integration/apply/removeWriter.test.js +0 -167
- package/tests/integration/apply/transfer.test.js +0 -81
- 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 -16
- package/tests/unit/messageOperations/assembleAdminMessage.test.js +0 -69
- package/tests/unit/messageOperations/assembleBanWriterMessage.test.js +0 -16
- package/tests/unit/messageOperations/assemblePostTransaction.test.js +0 -442
- 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 -58
- package/tests/unit/messageOperations/commonsStateMessageOperationsTest.js +0 -277
- package/tests/unit/messageOperations/stateMessageOperations.test.js +0 -19
- 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/{url.mjs → url.js} +0 -0
- /package/src/utils/{operations.js → applyOperations.js} +0 -0
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { test } from 'brittle';
|
|
2
|
+
import b4a from 'b4a';
|
|
3
|
+
import PeerWallet from 'trac-wallet';
|
|
4
|
+
import { TRAC_NETWORK_MSB_MAINNET_PREFIX } from 'trac-wallet/constants.js';
|
|
5
|
+
import { v7 as uuidv7 } from 'uuid';
|
|
6
|
+
import NetworkWalletFactory from '../../../../src/core/network/identity/NetworkWalletFactory.js';
|
|
7
|
+
import NetworkMessageBuilder from '../../../../src/messages/network/v1/NetworkMessageBuilder.js';
|
|
8
|
+
import {
|
|
9
|
+
NetworkOperationType,
|
|
10
|
+
ResultCode as NetworkResultCode
|
|
11
|
+
} from '../../../../src/utils/constants.js';
|
|
12
|
+
import { decodeV1networkOperation, encodeV1networkOperation } from '../../../../src/utils/protobuf/operationHelpers.js';
|
|
13
|
+
import { errorMessageIncludes } from '../../../helpers/regexHelper.js';
|
|
14
|
+
import {
|
|
15
|
+
createMessage,
|
|
16
|
+
encodeCapabilities,
|
|
17
|
+
safeWriteUInt32BE,
|
|
18
|
+
idToBuffer,
|
|
19
|
+
timestampToBuffer
|
|
20
|
+
} from '../../../../src/utils/buffer.js';
|
|
21
|
+
import { addressToBuffer } from '../../../../src/core/state/utils/address.js';
|
|
22
|
+
import { config } from '../../../helpers/config.js';
|
|
23
|
+
import { testKeyPair1 } from '../../../fixtures/apply.fixtures.js';
|
|
24
|
+
|
|
25
|
+
function createWallet() {
|
|
26
|
+
const keyPair = {
|
|
27
|
+
publicKey: b4a.from(testKeyPair1.publicKey, 'hex'),
|
|
28
|
+
secretKey: b4a.from(testKeyPair1.secretKey, 'hex')
|
|
29
|
+
};
|
|
30
|
+
return NetworkWalletFactory.provide({
|
|
31
|
+
enableWallet: false,
|
|
32
|
+
keyPair,
|
|
33
|
+
networkPrefix: TRAC_NETWORK_MSB_MAINNET_PREFIX
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function uniqueResultCodes() {
|
|
38
|
+
return [...new Set(Object.values(NetworkResultCode))].sort((a, b) => a - b);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
test('NetworkMessageBuilder builds validator connection request and verifies signature', async t => {
|
|
42
|
+
const wallet = createWallet();
|
|
43
|
+
const builder = new NetworkMessageBuilder(wallet, config);
|
|
44
|
+
|
|
45
|
+
const id = uuidv7();
|
|
46
|
+
const caps = ['cap:b', 'cap:a'];
|
|
47
|
+
|
|
48
|
+
await builder
|
|
49
|
+
.setType(NetworkOperationType.VALIDATOR_CONNECTION_REQUEST)
|
|
50
|
+
.setId(id)
|
|
51
|
+
.setTimestamp()
|
|
52
|
+
.setIssuerAddress(wallet.address)
|
|
53
|
+
.setCapabilities(caps)
|
|
54
|
+
.buildPayload();
|
|
55
|
+
|
|
56
|
+
const payload = builder.getResult();
|
|
57
|
+
t.is(payload.type, NetworkOperationType.VALIDATOR_CONNECTION_REQUEST);
|
|
58
|
+
t.is(payload.id, id);
|
|
59
|
+
t.alike(payload.capabilities, caps);
|
|
60
|
+
t.ok(b4a.isBuffer(payload.validator_connection_request.nonce));
|
|
61
|
+
t.ok(b4a.isBuffer(payload.validator_connection_request.signature));
|
|
62
|
+
|
|
63
|
+
const message = createMessage(
|
|
64
|
+
payload.type,
|
|
65
|
+
idToBuffer(id),
|
|
66
|
+
timestampToBuffer(payload.timestamp),
|
|
67
|
+
addressToBuffer(wallet.address, config.addressPrefix),
|
|
68
|
+
payload.validator_connection_request.nonce,
|
|
69
|
+
encodeCapabilities(caps)
|
|
70
|
+
);
|
|
71
|
+
const hash = await PeerWallet.blake3(message);
|
|
72
|
+
t.ok(wallet.verify(payload.validator_connection_request.signature, hash, wallet.publicKey));
|
|
73
|
+
|
|
74
|
+
const roundTrip = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
75
|
+
t.is(roundTrip.type, NetworkOperationType.VALIDATOR_CONNECTION_REQUEST);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test('NetworkMessageBuilder iterates validator connection response ResultCode values', async t => {
|
|
79
|
+
const wallet = createWallet();
|
|
80
|
+
const builder = new NetworkMessageBuilder(wallet, config);
|
|
81
|
+
const id = uuidv7();
|
|
82
|
+
const otherAddress = 'trac1xm76l9qaujh7vqktk8302mw9sfrxau3l45w62hqfl4kasswt6yts0autkh';
|
|
83
|
+
const caps = ['cap:b', 'cap:a'];
|
|
84
|
+
|
|
85
|
+
for (const code of uniqueResultCodes()) {
|
|
86
|
+
await builder
|
|
87
|
+
.setType(NetworkOperationType.VALIDATOR_CONNECTION_RESPONSE)
|
|
88
|
+
.setId(id)
|
|
89
|
+
.setTimestamp()
|
|
90
|
+
.setIssuerAddress(otherAddress)
|
|
91
|
+
.setCapabilities(caps)
|
|
92
|
+
.setResultCode(code)
|
|
93
|
+
.buildPayload();
|
|
94
|
+
|
|
95
|
+
const payload = builder.getResult();
|
|
96
|
+
t.is(payload.type, NetworkOperationType.VALIDATOR_CONNECTION_RESPONSE);
|
|
97
|
+
t.is(payload.validator_connection_response.result, code);
|
|
98
|
+
|
|
99
|
+
const msg = createMessage(
|
|
100
|
+
payload.type,
|
|
101
|
+
idToBuffer(payload.id),
|
|
102
|
+
timestampToBuffer(payload.timestamp),
|
|
103
|
+
addressToBuffer(otherAddress, config.addressPrefix),
|
|
104
|
+
payload.validator_connection_response.nonce,
|
|
105
|
+
safeWriteUInt32BE(code, 0),
|
|
106
|
+
encodeCapabilities(caps)
|
|
107
|
+
);
|
|
108
|
+
const hash = await PeerWallet.blake3(msg);
|
|
109
|
+
t.ok(wallet.verify(payload.validator_connection_response.signature, hash, wallet.publicKey));
|
|
110
|
+
|
|
111
|
+
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
112
|
+
t.is(decoded.validator_connection_response.result, code);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('NetworkMessageBuilder iterates liveness response ResultCode values', async t => {
|
|
117
|
+
const wallet = createWallet();
|
|
118
|
+
const builder = new NetworkMessageBuilder(wallet, config);
|
|
119
|
+
const id = uuidv7();
|
|
120
|
+
const caps = ['cap:b', 'cap:a'];
|
|
121
|
+
const data = b4a.from('ping', 'utf8');
|
|
122
|
+
|
|
123
|
+
for (const code of uniqueResultCodes()) {
|
|
124
|
+
await builder
|
|
125
|
+
.setType(NetworkOperationType.LIVENESS_RESPONSE)
|
|
126
|
+
.setId(id)
|
|
127
|
+
.setTimestamp()
|
|
128
|
+
.setData(data)
|
|
129
|
+
.setCapabilities(caps)
|
|
130
|
+
.setResultCode(code)
|
|
131
|
+
.buildPayload();
|
|
132
|
+
|
|
133
|
+
const payload = builder.getResult();
|
|
134
|
+
t.is(payload.type, NetworkOperationType.LIVENESS_RESPONSE);
|
|
135
|
+
t.is(payload.liveness_response.result, code);
|
|
136
|
+
|
|
137
|
+
const msg = createMessage(
|
|
138
|
+
payload.type,
|
|
139
|
+
idToBuffer(payload.id),
|
|
140
|
+
timestampToBuffer(payload.timestamp),
|
|
141
|
+
payload.liveness_response.nonce,
|
|
142
|
+
safeWriteUInt32BE(code, 0),
|
|
143
|
+
encodeCapabilities(caps)
|
|
144
|
+
);
|
|
145
|
+
const hash = await PeerWallet.blake3(msg);
|
|
146
|
+
t.ok(wallet.verify(payload.liveness_response.signature, hash, wallet.publicKey));
|
|
147
|
+
|
|
148
|
+
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
149
|
+
t.is(decoded.liveness_response.result, code);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
test('NetworkMessageBuilder builds liveness request and verifies signature (data not signed)', async t => {
|
|
154
|
+
const wallet = createWallet();
|
|
155
|
+
const builder = new NetworkMessageBuilder(wallet, config);
|
|
156
|
+
|
|
157
|
+
const id = uuidv7();
|
|
158
|
+
const caps = ['cap:b', 'cap:a'];
|
|
159
|
+
const data = b4a.from('ping', 'utf8');
|
|
160
|
+
|
|
161
|
+
await builder
|
|
162
|
+
.setType(NetworkOperationType.LIVENESS_REQUEST)
|
|
163
|
+
.setId(id)
|
|
164
|
+
.setTimestamp()
|
|
165
|
+
.setData(data)
|
|
166
|
+
.setCapabilities(caps)
|
|
167
|
+
.buildPayload();
|
|
168
|
+
|
|
169
|
+
const payload = builder.getResult();
|
|
170
|
+
t.is(payload.type, NetworkOperationType.LIVENESS_REQUEST);
|
|
171
|
+
t.ok(b4a.isBuffer(payload.liveness_request.nonce));
|
|
172
|
+
t.ok(b4a.isBuffer(payload.liveness_request.signature));
|
|
173
|
+
|
|
174
|
+
const msg = createMessage(
|
|
175
|
+
payload.type,
|
|
176
|
+
idToBuffer(payload.id),
|
|
177
|
+
timestampToBuffer(payload.timestamp),
|
|
178
|
+
payload.liveness_request.nonce,
|
|
179
|
+
encodeCapabilities(caps)
|
|
180
|
+
);
|
|
181
|
+
const hash = await PeerWallet.blake3(msg);
|
|
182
|
+
t.ok(wallet.verify(payload.liveness_request.signature, hash, wallet.publicKey));
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('NetworkMessageBuilder iterates broadcast transaction response ResultCode values', async t => {
|
|
186
|
+
const wallet = createWallet();
|
|
187
|
+
const builder = new NetworkMessageBuilder(wallet, config);
|
|
188
|
+
const id = uuidv7();
|
|
189
|
+
const caps = ['cap:b', 'cap:a'];
|
|
190
|
+
|
|
191
|
+
for (const code of uniqueResultCodes()) {
|
|
192
|
+
await builder
|
|
193
|
+
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
194
|
+
.setId(id)
|
|
195
|
+
.setTimestamp()
|
|
196
|
+
.setCapabilities(caps)
|
|
197
|
+
.setResultCode(code)
|
|
198
|
+
.buildPayload();
|
|
199
|
+
|
|
200
|
+
const payload = builder.getResult();
|
|
201
|
+
t.is(payload.type, NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE);
|
|
202
|
+
t.is(payload.broadcast_transaction_response.result, code);
|
|
203
|
+
|
|
204
|
+
const msg = createMessage(
|
|
205
|
+
payload.type,
|
|
206
|
+
idToBuffer(payload.id),
|
|
207
|
+
timestampToBuffer(payload.timestamp),
|
|
208
|
+
payload.broadcast_transaction_response.nonce,
|
|
209
|
+
safeWriteUInt32BE(code, 0),
|
|
210
|
+
encodeCapabilities(caps)
|
|
211
|
+
);
|
|
212
|
+
const hash = await PeerWallet.blake3(msg);
|
|
213
|
+
t.ok(wallet.verify(payload.broadcast_transaction_response.signature, hash, wallet.publicKey));
|
|
214
|
+
|
|
215
|
+
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
216
|
+
t.is(decoded.broadcast_transaction_response.result, code);
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
test('NetworkMessageBuilder builds broadcast transaction request and verifies signature', async t => {
|
|
221
|
+
const wallet = createWallet();
|
|
222
|
+
const builder = new NetworkMessageBuilder(wallet, config);
|
|
223
|
+
|
|
224
|
+
const id = uuidv7();
|
|
225
|
+
const caps = ['cap:b', 'cap:a'];
|
|
226
|
+
const data = b4a.from('deadbeef', 'hex');
|
|
227
|
+
|
|
228
|
+
await builder
|
|
229
|
+
.setType(NetworkOperationType.BROADCAST_TRANSACTION_REQUEST)
|
|
230
|
+
.setId(id)
|
|
231
|
+
.setTimestamp()
|
|
232
|
+
.setData(data)
|
|
233
|
+
.setCapabilities(caps)
|
|
234
|
+
.buildPayload();
|
|
235
|
+
|
|
236
|
+
const payload = builder.getResult();
|
|
237
|
+
t.is(payload.type, NetworkOperationType.BROADCAST_TRANSACTION_REQUEST);
|
|
238
|
+
t.alike(payload.broadcast_transaction_request.data, data);
|
|
239
|
+
|
|
240
|
+
const msg = createMessage(
|
|
241
|
+
payload.type,
|
|
242
|
+
idToBuffer(payload.id),
|
|
243
|
+
timestampToBuffer(payload.timestamp),
|
|
244
|
+
data,
|
|
245
|
+
payload.broadcast_transaction_request.nonce,
|
|
246
|
+
encodeCapabilities(caps)
|
|
247
|
+
);
|
|
248
|
+
const hash = await PeerWallet.blake3(msg);
|
|
249
|
+
t.ok(wallet.verify(payload.broadcast_transaction_request.signature, hash, wallet.publicKey));
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test('NetworkMessageBuilder validates required inputs', async t => {
|
|
253
|
+
const wallet = createWallet();
|
|
254
|
+
const builder = new NetworkMessageBuilder(wallet, config);
|
|
255
|
+
const id = uuidv7();
|
|
256
|
+
await t.exception(
|
|
257
|
+
() => builder.setType(undefined),
|
|
258
|
+
errorMessageIncludes('Invalid operation type')
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
await t.exception(
|
|
262
|
+
() => builder.setCapabilities('not-an-array'),
|
|
263
|
+
errorMessageIncludes('Capabilities must be a string array.')
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
await t.exception(
|
|
267
|
+
() =>
|
|
268
|
+
builder
|
|
269
|
+
.setType(NetworkOperationType.BROADCAST_TRANSACTION_REQUEST)
|
|
270
|
+
.setId(id)
|
|
271
|
+
.setTimestamp()
|
|
272
|
+
.setCapabilities([])
|
|
273
|
+
.buildPayload(),
|
|
274
|
+
errorMessageIncludes('Data must be set before building broadcast transaction request')
|
|
275
|
+
);
|
|
276
|
+
});
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { test } from 'brittle';
|
|
2
|
+
import b4a from 'b4a';
|
|
3
|
+
import PeerWallet from 'trac-wallet';
|
|
4
|
+
import { TRAC_NETWORK_MSB_MAINNET_PREFIX } from 'trac-wallet/constants.js';
|
|
5
|
+
|
|
6
|
+
import NetworkWalletFactory from '../../../../src/core/network/identity/NetworkWalletFactory.js';
|
|
7
|
+
import NetworkMessageDirector from '../../../../src/messages/network/v1/NetworkMessageDirector.js';
|
|
8
|
+
import NetworkMessageBuilder from '../../../../src/messages/network/v1/NetworkMessageBuilder.js';
|
|
9
|
+
import { NetworkOperationType, ResultCode as NetworkResultCode } from '../../../../src/utils/constants.js';
|
|
10
|
+
import { decodeV1networkOperation, encodeV1networkOperation } from '../../../../src/utils/protobuf/operationHelpers.js';
|
|
11
|
+
import {
|
|
12
|
+
createMessage,
|
|
13
|
+
encodeCapabilities,
|
|
14
|
+
safeWriteUInt32BE,
|
|
15
|
+
idToBuffer,
|
|
16
|
+
timestampToBuffer
|
|
17
|
+
} from '../../../../src/utils/buffer.js';
|
|
18
|
+
import { addressToBuffer } from '../../../../src/core/state/utils/address.js';
|
|
19
|
+
import { config } from '../../../helpers/config.js';
|
|
20
|
+
import { testKeyPair1 } from '../../../fixtures/apply.fixtures.js';
|
|
21
|
+
|
|
22
|
+
function createWallet() {
|
|
23
|
+
const keyPair = {
|
|
24
|
+
publicKey: b4a.from(testKeyPair1.publicKey, 'hex'),
|
|
25
|
+
secretKey: b4a.from(testKeyPair1.secretKey, 'hex')
|
|
26
|
+
};
|
|
27
|
+
return NetworkWalletFactory.provide({
|
|
28
|
+
enableWallet: false,
|
|
29
|
+
keyPair,
|
|
30
|
+
networkPrefix: TRAC_NETWORK_MSB_MAINNET_PREFIX
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function uniqueResultCodes() {
|
|
35
|
+
return [...new Set(Object.values(NetworkResultCode))].sort((a, b) => a - b);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
test('NetworkMessageDirector builds validator connection request and verifies signature', async t => {
|
|
39
|
+
const wallet = createWallet();
|
|
40
|
+
const director = new NetworkMessageDirector(new NetworkMessageBuilder(wallet, config));
|
|
41
|
+
|
|
42
|
+
const id = '1';
|
|
43
|
+
const caps = ['cap:b', 'cap:a'];
|
|
44
|
+
|
|
45
|
+
const payload = await director.buildValidatorConnectionRequest(id, wallet.address, caps);
|
|
46
|
+
t.is(payload.type, NetworkOperationType.VALIDATOR_CONNECTION_REQUEST);
|
|
47
|
+
t.is(payload.id, id);
|
|
48
|
+
t.alike(payload.capabilities, caps);
|
|
49
|
+
|
|
50
|
+
const msg = createMessage(
|
|
51
|
+
payload.type,
|
|
52
|
+
idToBuffer(payload.id),
|
|
53
|
+
timestampToBuffer(payload.timestamp),
|
|
54
|
+
addressToBuffer(wallet.address, config.addressPrefix),
|
|
55
|
+
payload.validator_connection_request.nonce,
|
|
56
|
+
encodeCapabilities(caps)
|
|
57
|
+
);
|
|
58
|
+
const hash = await PeerWallet.blake3(msg);
|
|
59
|
+
t.ok(wallet.verify(payload.validator_connection_request.signature, hash, wallet.publicKey));
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('NetworkMessageDirector builds liveness request and verifies signature', async t => {
|
|
63
|
+
const wallet = createWallet();
|
|
64
|
+
const director = new NetworkMessageDirector(new NetworkMessageBuilder(wallet, config));
|
|
65
|
+
|
|
66
|
+
const id = '1';
|
|
67
|
+
const caps = ['cap:b', 'cap:a'];
|
|
68
|
+
const data = b4a.from('ping', 'utf8');
|
|
69
|
+
|
|
70
|
+
const payload = await director.buildLivenessRequest(id, data, caps);
|
|
71
|
+
t.is(payload.type, NetworkOperationType.LIVENESS_REQUEST);
|
|
72
|
+
t.is(payload.id, id);
|
|
73
|
+
t.alike(payload.capabilities, caps);
|
|
74
|
+
|
|
75
|
+
const msg = createMessage(
|
|
76
|
+
payload.type,
|
|
77
|
+
idToBuffer(payload.id),
|
|
78
|
+
timestampToBuffer(payload.timestamp),
|
|
79
|
+
payload.liveness_request.nonce,
|
|
80
|
+
encodeCapabilities(caps)
|
|
81
|
+
);
|
|
82
|
+
const hash = await PeerWallet.blake3(msg);
|
|
83
|
+
t.ok(wallet.verify(payload.liveness_request.signature, hash, wallet.publicKey));
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('NetworkMessageDirector iterates liveness response ResultCode values', async t => {
|
|
87
|
+
const wallet = createWallet();
|
|
88
|
+
const director = new NetworkMessageDirector(new NetworkMessageBuilder(wallet, config));
|
|
89
|
+
|
|
90
|
+
const id = '1';
|
|
91
|
+
const caps = ['cap:b', 'cap:a'];
|
|
92
|
+
const data = b4a.from('ping', 'utf8');
|
|
93
|
+
|
|
94
|
+
for (const code of uniqueResultCodes()) {
|
|
95
|
+
const payload = await director.buildLivenessResponse(id, data, caps, code);
|
|
96
|
+
t.is(payload.type, NetworkOperationType.LIVENESS_RESPONSE);
|
|
97
|
+
t.is(payload.liveness_response.result, code);
|
|
98
|
+
|
|
99
|
+
const msg = createMessage(
|
|
100
|
+
payload.type,
|
|
101
|
+
idToBuffer(payload.id),
|
|
102
|
+
timestampToBuffer(payload.timestamp),
|
|
103
|
+
payload.liveness_response.nonce,
|
|
104
|
+
safeWriteUInt32BE(code, 0),
|
|
105
|
+
encodeCapabilities(caps)
|
|
106
|
+
);
|
|
107
|
+
const hash = await PeerWallet.blake3(msg);
|
|
108
|
+
t.ok(wallet.verify(payload.liveness_response.signature, hash, wallet.publicKey));
|
|
109
|
+
|
|
110
|
+
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
111
|
+
t.is(decoded.liveness_response.result, code);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
test('NetworkMessageDirector builds broadcast transaction request and verifies signature', async t => {
|
|
116
|
+
const wallet = createWallet();
|
|
117
|
+
const director = new NetworkMessageDirector(new NetworkMessageBuilder(wallet, config));
|
|
118
|
+
|
|
119
|
+
const id = '1';
|
|
120
|
+
const data = b4a.from('deadbeef', 'hex');
|
|
121
|
+
const caps = ['cap:b', 'cap:a'];
|
|
122
|
+
|
|
123
|
+
const payload = await director.buildBroadcastTransactionRequest(id, data, caps);
|
|
124
|
+
t.is(payload.type, NetworkOperationType.BROADCAST_TRANSACTION_REQUEST);
|
|
125
|
+
t.is(payload.id, id);
|
|
126
|
+
t.alike(payload.capabilities, caps);
|
|
127
|
+
t.alike(payload.broadcast_transaction_request.data, data);
|
|
128
|
+
|
|
129
|
+
const message = createMessage(
|
|
130
|
+
payload.type,
|
|
131
|
+
idToBuffer(id),
|
|
132
|
+
timestampToBuffer(payload.timestamp),
|
|
133
|
+
data,
|
|
134
|
+
payload.broadcast_transaction_request.nonce,
|
|
135
|
+
encodeCapabilities(caps)
|
|
136
|
+
);
|
|
137
|
+
const hash = await PeerWallet.blake3(message);
|
|
138
|
+
t.ok(wallet.verify(payload.broadcast_transaction_request.signature, hash, wallet.publicKey));
|
|
139
|
+
|
|
140
|
+
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
141
|
+
t.is(decoded.type, NetworkOperationType.BROADCAST_TRANSACTION_REQUEST);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test('NetworkMessageDirector iterates broadcast transaction response ResultCode values', async t => {
|
|
145
|
+
const wallet = createWallet();
|
|
146
|
+
const director = new NetworkMessageDirector(new NetworkMessageBuilder(wallet, config));
|
|
147
|
+
|
|
148
|
+
const id = '1';
|
|
149
|
+
const caps = ['cap:b', 'cap:a'];
|
|
150
|
+
|
|
151
|
+
for (const code of uniqueResultCodes()) {
|
|
152
|
+
const payload = await director.buildBroadcastTransactionResponse(id, caps, code);
|
|
153
|
+
t.is(payload.type, NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE);
|
|
154
|
+
t.is(payload.broadcast_transaction_response.result, code);
|
|
155
|
+
|
|
156
|
+
const msg = createMessage(
|
|
157
|
+
payload.type,
|
|
158
|
+
idToBuffer(payload.id),
|
|
159
|
+
timestampToBuffer(payload.timestamp),
|
|
160
|
+
payload.broadcast_transaction_response.nonce,
|
|
161
|
+
safeWriteUInt32BE(code, 0),
|
|
162
|
+
encodeCapabilities(caps)
|
|
163
|
+
);
|
|
164
|
+
const hash = await PeerWallet.blake3(msg);
|
|
165
|
+
t.ok(wallet.verify(payload.broadcast_transaction_response.signature, hash, wallet.publicKey));
|
|
166
|
+
|
|
167
|
+
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
168
|
+
t.is(decoded.broadcast_transaction_response.result, code);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
test('NetworkMessageDirector iterates validator connection response ResultCode values', async t => {
|
|
173
|
+
const wallet = createWallet();
|
|
174
|
+
const director = new NetworkMessageDirector(new NetworkMessageBuilder(wallet, config));
|
|
175
|
+
|
|
176
|
+
const id = '1';
|
|
177
|
+
const caps = ['cap:b', 'cap:a'];
|
|
178
|
+
const otherAddress =
|
|
179
|
+
'trac1xm76l9qaujh7vqktk8302mw9sfrxau3l45w62hqfl4kasswt6yts0autkh';
|
|
180
|
+
|
|
181
|
+
for (const code of uniqueResultCodes()) {
|
|
182
|
+
const payload = await director.buildValidatorConnectionResponse(
|
|
183
|
+
id,
|
|
184
|
+
otherAddress,
|
|
185
|
+
caps,
|
|
186
|
+
code
|
|
187
|
+
);
|
|
188
|
+
t.is(payload.type, NetworkOperationType.VALIDATOR_CONNECTION_RESPONSE);
|
|
189
|
+
t.is(payload.validator_connection_response.result, code);
|
|
190
|
+
|
|
191
|
+
const msg = createMessage(
|
|
192
|
+
payload.type,
|
|
193
|
+
idToBuffer(payload.id),
|
|
194
|
+
timestampToBuffer(payload.timestamp),
|
|
195
|
+
addressToBuffer(otherAddress, config.addressPrefix),
|
|
196
|
+
payload.validator_connection_response.nonce,
|
|
197
|
+
safeWriteUInt32BE(code, 0),
|
|
198
|
+
encodeCapabilities(caps)
|
|
199
|
+
);
|
|
200
|
+
const hash = await PeerWallet.blake3(msg);
|
|
201
|
+
t.ok(wallet.verify(payload.validator_connection_response.signature, hash, wallet.publicKey));
|
|
202
|
+
}
|
|
203
|
+
});
|