trac-msb 0.2.13 → 0.2.15
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 +38 -0
- package/.github/workflows/lint-pr-title.yml +26 -0
- package/.github/workflows/publish.yml +33 -0
- package/.github/workflows/unit-tests.yml +34 -0
- package/package.json +7 -12
- package/proto/network.proto +74 -0
- package/rpc/rpc_services.js +4 -22
- package/scripts/generate-protobufs.js +12 -37
- package/src/config/config.js +9 -26
- package/src/config/env.js +17 -27
- package/src/core/network/Network.js +36 -73
- package/src/core/network/protocols/LegacyProtocol.js +11 -21
- package/src/core/network/protocols/NetworkMessages.js +17 -38
- package/src/core/network/protocols/ProtocolInterface.js +2 -14
- package/src/core/network/protocols/ProtocolSession.js +17 -144
- package/src/core/network/protocols/V1Protocol.js +18 -37
- package/src/core/network/protocols/legacy/NetworkMessageRouter.js +19 -25
- package/src/core/network/protocols/legacy/handlers/{LegacyGetRequestHandler.js → GetRequestHandler.js} +6 -6
- package/src/core/network/protocols/legacy/handlers/ResponseHandler.js +37 -0
- package/src/core/network/protocols/{legacy/handlers/LegacyRoleOperationHandler.js → shared/handlers/RoleOperationHandler.js} +11 -18
- package/src/core/network/protocols/{legacy/handlers/LegacySubnetworkOperationHandler.js → shared/handlers/SubnetworkOperationHandler.js} +17 -28
- package/src/core/network/protocols/{legacy/handlers/LegacyTransferOperationHandler.js → shared/handlers/TransferOperationHandler.js} +11 -17
- package/src/core/network/protocols/{legacy/handlers/BaseStateOperationHandler.js → shared/handlers/base/BaseOperationHandler.js} +12 -23
- package/src/core/network/protocols/shared/validators/{PartialBootstrapDeploymentValidator.js → PartialBootstrapDeployment.js} +4 -9
- package/src/core/network/protocols/shared/validators/{PartialRoleAccessValidator.js → PartialRoleAccess.js} +17 -51
- package/src/core/network/protocols/shared/validators/{PartialTransactionValidator.js → PartialTransaction.js} +7 -21
- package/src/core/network/protocols/shared/validators/{PartialTransferValidator.js → PartialTransfer.js} +9 -26
- package/src/core/network/protocols/shared/validators/{PartialOperationValidator.js → base/PartialOperation.js} +25 -47
- package/src/core/network/protocols/v1/NetworkMessageRouter.js +7 -91
- package/src/core/network/services/ConnectionManager.js +94 -146
- package/src/core/network/services/MessageOrchestrator.js +27 -151
- package/src/core/network/services/TransactionPoolService.js +18 -129
- package/src/core/network/services/TransactionRateLimiterService.js +34 -52
- package/src/core/network/services/ValidatorObserverService.js +26 -18
- package/src/core/state/State.js +19 -70
- package/src/index.js +8 -6
- package/src/messages/network/v1/NetworkMessageBuilder.js +79 -59
- package/src/messages/network/v1/NetworkMessageDirector.js +50 -16
- package/src/utils/Scheduler.js +8 -0
- package/src/utils/constants.js +5 -71
- package/src/utils/helpers.js +1 -10
- package/src/utils/normalizers.js +0 -38
- package/src/utils/protobuf/network.cjs +840 -0
- package/src/utils/protobuf/operationHelpers.js +3 -24
- package/tests/acceptance/v1/account/account.test.mjs +2 -8
- package/tests/acceptance/v1/tx/tx.test.mjs +1 -23
- package/tests/acceptance/v1/tx-details/tx-details.test.mjs +6 -34
- package/tests/fixtures/assembleMessage.fixtures.js +8 -7
- package/tests/fixtures/networkV1.fixtures.js +28 -2
- package/tests/helpers/autobaseTestHelpers.js +5 -2
- package/tests/helpers/createTestSignature.js +3 -2
- package/tests/helpers/transactionPayloads.mjs +2 -2
- package/tests/unit/messages/network/NetworkMessageBuilder.test.js +79 -239
- package/tests/unit/messages/network/NetworkMessageDirector.test.js +77 -223
- package/tests/unit/messages/state/applyStateMessageBuilder.complete.test.js +5 -1
- package/tests/unit/messages/state/applyStateMessageBuilder.partial.test.js +5 -1
- package/tests/unit/network/ConnectionManager.test.js +191 -0
- package/tests/unit/network/networkModule.test.js +1 -4
- package/tests/unit/unit.test.js +2 -2
- package/tests/unit/utils/fileUtils/readAddressesFromWhitelistFile.test.js +2 -2
- package/tests/unit/utils/fileUtils/readBalanceMigrationFile.test.js +2 -2
- package/tests/unit/utils/protobuf/operationHelpers.test.js +4 -2
- package/tests/unit/utils/utils.test.js +0 -1
- package/proto/network/v1/enums/message_type.proto +0 -16
- package/proto/network/v1/enums/result_code.proto +0 -84
- package/proto/network/v1/messages/broadcast_transaction_request.proto +0 -9
- package/proto/network/v1/messages/broadcast_transaction_response.proto +0 -13
- package/proto/network/v1/messages/liveness_request.proto +0 -8
- package/proto/network/v1/messages/liveness_response.proto +0 -11
- package/proto/network/v1/network_message.proto +0 -22
- package/src/core/network/protocols/connectionPolicies.js +0 -88
- package/src/core/network/protocols/legacy/handlers/LegacyResponseHandler.js +0 -23
- package/src/core/network/protocols/shared/errors/SharedValidatorRejectionError.js +0 -27
- package/src/core/network/protocols/v1/V1ProtocolError.js +0 -91
- package/src/core/network/protocols/v1/handlers/V1BaseOperationHandler.js +0 -65
- package/src/core/network/protocols/v1/handlers/V1BroadcastTransactionOperationHandler.js +0 -389
- package/src/core/network/protocols/v1/handlers/V1LivenessOperationHandler.js +0 -87
- package/src/core/network/protocols/v1/validators/V1BaseOperation.js +0 -211
- package/src/core/network/protocols/v1/validators/V1BroadcastTransactionRequest.js +0 -26
- package/src/core/network/protocols/v1/validators/V1BroadcastTransactionResponse.js +0 -276
- package/src/core/network/protocols/v1/validators/V1LivenessRequest.js +0 -15
- package/src/core/network/protocols/v1/validators/V1LivenessResponse.js +0 -17
- package/src/core/network/protocols/v1/validators/V1ValidationSchema.js +0 -210
- package/src/core/network/services/PendingRequestService.js +0 -172
- package/src/core/network/services/TransactionCommitService.js +0 -149
- package/src/core/network/services/ValidatorHealthCheckService.js +0 -127
- package/src/utils/deepEqualApplyPayload.js +0 -40
- package/src/utils/logger.js +0 -25
- package/src/utils/protobuf/networkV1.generated.cjs +0 -2460
- package/tests/unit/network/LegacyNetworkMessageRouter.test.js +0 -54
- package/tests/unit/network/ProtocolSession.test.js +0 -127
- package/tests/unit/network/services/ConnectionManager.test.js +0 -450
- package/tests/unit/network/services/MessageOrchestrator.test.js +0 -445
- package/tests/unit/network/services/PendingRequestService.test.js +0 -431
- package/tests/unit/network/services/TransactionCommitService.test.js +0 -246
- package/tests/unit/network/services/TransactionPoolService.test.js +0 -489
- package/tests/unit/network/services/TransactionRateLimiterService.test.js +0 -139
- package/tests/unit/network/services/ValidatorHealthCheckService.test.js +0 -115
- package/tests/unit/network/services/services.test.js +0 -17
- package/tests/unit/network/utils/v1TestUtils.js +0 -153
- package/tests/unit/network/v1/NetworkMessageRouterV1.test.js +0 -151
- package/tests/unit/network/v1/V1BaseOperation.test.js +0 -356
- package/tests/unit/network/v1/V1BroadcastTransactionOperationHandler.test.js +0 -129
- package/tests/unit/network/v1/V1BroadcastTransactionRequest.test.js +0 -53
- package/tests/unit/network/v1/V1BroadcastTransactionResponse.test.js +0 -512
- package/tests/unit/network/v1/V1LivenessRequest.test.js +0 -32
- package/tests/unit/network/v1/V1LivenessResponse.test.js +0 -45
- package/tests/unit/network/v1/V1ResultCode.test.js +0 -84
- package/tests/unit/network/v1/V1ValidationSchema.test.js +0 -13
- package/tests/unit/network/v1/connectionPolicies.test.js +0 -49
- package/tests/unit/network/v1/handlers/V1BaseOperationHandler.test.js +0 -284
- package/tests/unit/network/v1/handlers/V1BroadcastTransactionOperationHandler.test.js +0 -794
- package/tests/unit/network/v1/handlers/V1LivenessOperationHandler.test.js +0 -193
- package/tests/unit/network/v1/v1.handlers.test.js +0 -15
- package/tests/unit/network/v1/v1.test.js +0 -19
- package/tests/unit/network/v1/v1ValidationSchema/broadcastTransactionRequest.test.js +0 -119
- package/tests/unit/network/v1/v1ValidationSchema/broadcastTransactionResponse.test.js +0 -136
- package/tests/unit/network/v1/v1ValidationSchema/common.test.js +0 -308
- package/tests/unit/network/v1/v1ValidationSchema/livenessRequest.test.js +0 -90
- package/tests/unit/network/v1/v1ValidationSchema/livenessResponse.test.js +0 -133
- package/tests/unit/utils/deepEqualApplyPayload/deepEqualApplyPayload.test.js +0 -102
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
idToBuffer,
|
|
18
18
|
timestampToBuffer
|
|
19
19
|
} from '../../../../src/utils/buffer.js';
|
|
20
|
+
import { addressToBuffer } from '../../../../src/core/state/utils/address.js';
|
|
20
21
|
import { config } from '../../../helpers/config.js';
|
|
21
22
|
import { asAddress } from '../../../helpers/address.js';
|
|
22
23
|
import { testKeyPair1 } from '../../../fixtures/apply.fixtures.js';
|
|
@@ -37,6 +38,81 @@ function uniqueResultCodes() {
|
|
|
37
38
|
return [...new Set(Object.values(NetworkResultCode))].sort((a, b) => a - b);
|
|
38
39
|
}
|
|
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 = asAddress('36fdaf941de4afe602cbb1e2f56dc582466ef23fad1da55c09fd6dd841cbd117');
|
|
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
|
+
|
|
40
116
|
test('NetworkMessageBuilder iterates liveness response ResultCode values', async t => {
|
|
41
117
|
const wallet = createWallet();
|
|
42
118
|
const builder = new NetworkMessageBuilder(wallet, config);
|
|
@@ -49,6 +125,7 @@ test('NetworkMessageBuilder iterates liveness response ResultCode values', async
|
|
|
49
125
|
.setType(NetworkOperationType.LIVENESS_RESPONSE)
|
|
50
126
|
.setId(id)
|
|
51
127
|
.setTimestamp()
|
|
128
|
+
.setData(data)
|
|
52
129
|
.setCapabilities(caps)
|
|
53
130
|
.setResultCode(code)
|
|
54
131
|
.buildPayload();
|
|
@@ -79,11 +156,13 @@ test('NetworkMessageBuilder builds liveness request and verifies signature (data
|
|
|
79
156
|
|
|
80
157
|
const id = uuidv7();
|
|
81
158
|
const caps = ['cap:b', 'cap:a'];
|
|
159
|
+
const data = b4a.from('ping', 'utf8');
|
|
82
160
|
|
|
83
161
|
await builder
|
|
84
162
|
.setType(NetworkOperationType.LIVENESS_REQUEST)
|
|
85
163
|
.setId(id)
|
|
86
164
|
.setTimestamp()
|
|
165
|
+
.setData(data)
|
|
87
166
|
.setCapabilities(caps)
|
|
88
167
|
.buildPayload();
|
|
89
168
|
|
|
@@ -108,275 +187,36 @@ test('NetworkMessageBuilder iterates broadcast transaction response ResultCode v
|
|
|
108
187
|
const builder = new NetworkMessageBuilder(wallet, config);
|
|
109
188
|
const id = uuidv7();
|
|
110
189
|
const caps = ['cap:b', 'cap:a'];
|
|
111
|
-
const proof = b4a.from('deadbeef', 'hex');
|
|
112
|
-
const timestamp = Date.now();
|
|
113
|
-
const emptyProof = b4a.alloc(0);
|
|
114
190
|
|
|
115
191
|
for (const code of uniqueResultCodes()) {
|
|
116
|
-
const includeProof = code === NetworkResultCode.OK;
|
|
117
|
-
const proofUnavailable = code === NetworkResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE;
|
|
118
|
-
const responseProof = includeProof ? proof : emptyProof;
|
|
119
|
-
const responseTimestampLedger = includeProof || proofUnavailable ? timestamp : 0;
|
|
120
192
|
await builder
|
|
121
193
|
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
122
194
|
.setId(id)
|
|
123
195
|
.setTimestamp()
|
|
124
196
|
.setCapabilities(caps)
|
|
125
|
-
.setProof(responseProof)
|
|
126
|
-
.setTimestampLedger(responseTimestampLedger)
|
|
127
197
|
.setResultCode(code)
|
|
128
198
|
.buildPayload();
|
|
129
199
|
|
|
130
200
|
const payload = builder.getResult();
|
|
131
201
|
t.is(payload.type, NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE);
|
|
132
202
|
t.is(payload.broadcast_transaction_response.result, code);
|
|
133
|
-
t.alike(payload.broadcast_transaction_response.proof, responseProof);
|
|
134
|
-
t.is(payload.broadcast_transaction_response.timestamp, responseTimestampLedger);
|
|
135
203
|
|
|
136
204
|
const msg = createMessage(
|
|
137
205
|
payload.type,
|
|
138
206
|
idToBuffer(payload.id),
|
|
139
207
|
timestampToBuffer(payload.timestamp),
|
|
140
208
|
payload.broadcast_transaction_response.nonce,
|
|
141
|
-
responseProof,
|
|
142
|
-
timestampToBuffer(responseTimestampLedger),
|
|
143
209
|
safeWriteUInt32BE(code, 0),
|
|
144
210
|
encodeCapabilities(caps)
|
|
145
211
|
);
|
|
146
|
-
|
|
147
212
|
const hash = await PeerWallet.blake3(msg);
|
|
148
213
|
t.ok(wallet.verify(payload.broadcast_transaction_response.signature, hash, wallet.publicKey));
|
|
149
214
|
|
|
150
215
|
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
151
216
|
t.is(decoded.broadcast_transaction_response.result, code);
|
|
152
|
-
t.alike(decoded.broadcast_transaction_response.proof, responseProof);
|
|
153
|
-
t.is(decoded.broadcast_transaction_response.timestamp, responseTimestampLedger);
|
|
154
217
|
}
|
|
155
218
|
});
|
|
156
219
|
|
|
157
|
-
test('NetworkMessageBuilder builds broadcast transaction response with proof and timestamp', async t => {
|
|
158
|
-
const wallet = createWallet();
|
|
159
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
160
|
-
const id = uuidv7();
|
|
161
|
-
const caps = ['cap:b', 'cap:a'];
|
|
162
|
-
const proof = b4a.from('deadbeef', 'hex');
|
|
163
|
-
const timestamp = Date.now();
|
|
164
|
-
|
|
165
|
-
await builder
|
|
166
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
167
|
-
.setId(id)
|
|
168
|
-
.setTimestamp()
|
|
169
|
-
.setCapabilities(caps)
|
|
170
|
-
.setProof(proof)
|
|
171
|
-
.setTimestampLedger(timestamp)
|
|
172
|
-
.setResultCode(NetworkResultCode.OK)
|
|
173
|
-
.buildPayload();
|
|
174
|
-
|
|
175
|
-
const payload = builder.getResult();
|
|
176
|
-
t.alike(payload.broadcast_transaction_response.proof, proof);
|
|
177
|
-
t.is(payload.broadcast_transaction_response.timestamp, timestamp);
|
|
178
|
-
|
|
179
|
-
const msg = createMessage(
|
|
180
|
-
payload.type,
|
|
181
|
-
idToBuffer(payload.id),
|
|
182
|
-
timestampToBuffer(payload.timestamp),
|
|
183
|
-
payload.broadcast_transaction_response.nonce,
|
|
184
|
-
proof,
|
|
185
|
-
timestampToBuffer(timestamp),
|
|
186
|
-
safeWriteUInt32BE(NetworkResultCode.OK, 0),
|
|
187
|
-
encodeCapabilities(caps)
|
|
188
|
-
);
|
|
189
|
-
const hash = await PeerWallet.blake3(msg);
|
|
190
|
-
t.ok(wallet.verify(payload.broadcast_transaction_response.signature, hash, wallet.publicKey));
|
|
191
|
-
|
|
192
|
-
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
193
|
-
t.alike(decoded.broadcast_transaction_response.proof, proof);
|
|
194
|
-
t.is(decoded.broadcast_transaction_response.timestamp, timestamp);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
test('NetworkMessageBuilder rejects OK response when proof is provided without timestamp', async t => {
|
|
198
|
-
const wallet = createWallet();
|
|
199
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
200
|
-
const id = uuidv7();
|
|
201
|
-
const caps = ['cap:b', 'cap:a'];
|
|
202
|
-
const proof = b4a.from('deadbeef', 'hex');
|
|
203
|
-
|
|
204
|
-
await t.exception(
|
|
205
|
-
() =>
|
|
206
|
-
builder
|
|
207
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
208
|
-
.setId(id)
|
|
209
|
-
.setTimestamp()
|
|
210
|
-
.setCapabilities(caps)
|
|
211
|
-
.setProof(proof)
|
|
212
|
-
.setResultCode(NetworkResultCode.OK)
|
|
213
|
-
.buildPayload(),
|
|
214
|
-
errorMessageIncludes('Result code OK requires non-empty proof and timestamp > 0.')
|
|
215
|
-
);
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
test('NetworkMessageBuilder rejects OK response when timestamp is provided without proof', async t => {
|
|
219
|
-
const wallet = createWallet();
|
|
220
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
221
|
-
const id = uuidv7();
|
|
222
|
-
const caps = ['cap:b', 'cap:a'];
|
|
223
|
-
const timestamp = Date.now();
|
|
224
|
-
|
|
225
|
-
await t.exception(
|
|
226
|
-
() =>
|
|
227
|
-
builder
|
|
228
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
229
|
-
.setId(id)
|
|
230
|
-
.setTimestamp()
|
|
231
|
-
.setCapabilities(caps)
|
|
232
|
-
.setTimestampLedger(timestamp)
|
|
233
|
-
.setResultCode(NetworkResultCode.OK)
|
|
234
|
-
.buildPayload(),
|
|
235
|
-
errorMessageIncludes('Result code OK requires non-empty proof and timestamp > 0.')
|
|
236
|
-
);
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
test('NetworkMessageBuilder allows TX_ACCEPTED_PROOF_UNAVAILABLE response with timestamp and empty proof', async t => {
|
|
240
|
-
const wallet = createWallet();
|
|
241
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
242
|
-
const id = uuidv7();
|
|
243
|
-
const caps = ['cap:b', 'cap:a'];
|
|
244
|
-
const timestamp = Date.now();
|
|
245
|
-
const emptyProof = b4a.alloc(0);
|
|
246
|
-
|
|
247
|
-
await builder
|
|
248
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
249
|
-
.setId(id)
|
|
250
|
-
.setTimestamp()
|
|
251
|
-
.setCapabilities(caps)
|
|
252
|
-
.setProof(emptyProof)
|
|
253
|
-
.setTimestampLedger(timestamp)
|
|
254
|
-
.setResultCode(NetworkResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE)
|
|
255
|
-
.buildPayload();
|
|
256
|
-
|
|
257
|
-
const payload = builder.getResult();
|
|
258
|
-
t.alike(payload.broadcast_transaction_response.proof, emptyProof);
|
|
259
|
-
t.is(payload.broadcast_transaction_response.timestamp, timestamp);
|
|
260
|
-
t.is(payload.broadcast_transaction_response.result, NetworkResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE);
|
|
261
|
-
|
|
262
|
-
const msg = createMessage(
|
|
263
|
-
payload.type,
|
|
264
|
-
idToBuffer(payload.id),
|
|
265
|
-
timestampToBuffer(payload.timestamp),
|
|
266
|
-
payload.broadcast_transaction_response.nonce,
|
|
267
|
-
emptyProof,
|
|
268
|
-
timestampToBuffer(timestamp),
|
|
269
|
-
safeWriteUInt32BE(NetworkResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE, 0),
|
|
270
|
-
encodeCapabilities(caps)
|
|
271
|
-
);
|
|
272
|
-
const hash = await PeerWallet.blake3(msg);
|
|
273
|
-
t.ok(wallet.verify(payload.broadcast_transaction_response.signature, hash, wallet.publicKey));
|
|
274
|
-
|
|
275
|
-
const decoded = decodeV1networkOperation(encodeV1networkOperation(payload));
|
|
276
|
-
t.is(decoded.broadcast_transaction_response.timestamp, timestamp);
|
|
277
|
-
t.is(decoded.broadcast_transaction_response.result, NetworkResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE);
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
test('NetworkMessageBuilder rejects OK response when proof and timestamp are both missing', async t => {
|
|
281
|
-
const wallet = createWallet();
|
|
282
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
283
|
-
const id = uuidv7();
|
|
284
|
-
const caps = ['cap:b', 'cap:a'];
|
|
285
|
-
|
|
286
|
-
await t.exception(
|
|
287
|
-
() =>
|
|
288
|
-
builder
|
|
289
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
290
|
-
.setId(id)
|
|
291
|
-
.setTimestamp()
|
|
292
|
-
.setCapabilities(caps)
|
|
293
|
-
.setResultCode(NetworkResultCode.OK)
|
|
294
|
-
.buildPayload(),
|
|
295
|
-
errorMessageIncludes('Result code OK requires non-empty proof and timestamp > 0.')
|
|
296
|
-
);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
test('NetworkMessageBuilder rejects TX_ACCEPTED_PROOF_UNAVAILABLE response when timestamp is missing', async t => {
|
|
300
|
-
const wallet = createWallet();
|
|
301
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
302
|
-
const id = uuidv7();
|
|
303
|
-
const caps = ['cap:b', 'cap:a'];
|
|
304
|
-
|
|
305
|
-
await t.exception(
|
|
306
|
-
() =>
|
|
307
|
-
builder
|
|
308
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
309
|
-
.setId(id)
|
|
310
|
-
.setTimestamp()
|
|
311
|
-
.setCapabilities(caps)
|
|
312
|
-
.setResultCode(NetworkResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE)
|
|
313
|
-
.buildPayload(),
|
|
314
|
-
errorMessageIncludes('Result code TX_ACCEPTED_PROOF_UNAVAILABLE requires timestamp > 0.')
|
|
315
|
-
);
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
test('NetworkMessageBuilder rejects TX_ACCEPTED_PROOF_UNAVAILABLE response when proof is non-empty', async t => {
|
|
319
|
-
const wallet = createWallet();
|
|
320
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
321
|
-
const id = uuidv7();
|
|
322
|
-
const caps = ['cap:b', 'cap:a'];
|
|
323
|
-
|
|
324
|
-
await t.exception(
|
|
325
|
-
() =>
|
|
326
|
-
builder
|
|
327
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
328
|
-
.setId(id)
|
|
329
|
-
.setTimestamp()
|
|
330
|
-
.setCapabilities(caps)
|
|
331
|
-
.setProof(b4a.from('deadbeef', 'hex'))
|
|
332
|
-
.setTimestampLedger(Date.now())
|
|
333
|
-
.setResultCode(NetworkResultCode.TX_ACCEPTED_PROOF_UNAVAILABLE)
|
|
334
|
-
.buildPayload(),
|
|
335
|
-
errorMessageIncludes('Result code TX_ACCEPTED_PROOF_UNAVAILABLE requires empty proof.')
|
|
336
|
-
);
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
test('NetworkMessageBuilder rejects non-OK response when proof is non-empty', async t => {
|
|
340
|
-
const wallet = createWallet();
|
|
341
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
342
|
-
const id = uuidv7();
|
|
343
|
-
const caps = ['cap:b', 'cap:a'];
|
|
344
|
-
|
|
345
|
-
await t.exception(
|
|
346
|
-
() =>
|
|
347
|
-
builder
|
|
348
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
349
|
-
.setId(id)
|
|
350
|
-
.setTimestamp()
|
|
351
|
-
.setCapabilities(caps)
|
|
352
|
-
.setProof(b4a.from('deadbeef', 'hex'))
|
|
353
|
-
.setTimestampLedger(0)
|
|
354
|
-
.setResultCode(NetworkResultCode.INVALID_PAYLOAD)
|
|
355
|
-
.buildPayload(),
|
|
356
|
-
errorMessageIncludes('Non-OK result code requires empty proof.')
|
|
357
|
-
);
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
test('NetworkMessageBuilder rejects non-OK response with timestamp > 0 unless proof is unavailable', async t => {
|
|
361
|
-
const wallet = createWallet();
|
|
362
|
-
const builder = new NetworkMessageBuilder(wallet, config);
|
|
363
|
-
const id = uuidv7();
|
|
364
|
-
const caps = ['cap:b', 'cap:a'];
|
|
365
|
-
|
|
366
|
-
await t.exception(
|
|
367
|
-
() =>
|
|
368
|
-
builder
|
|
369
|
-
.setType(NetworkOperationType.BROADCAST_TRANSACTION_RESPONSE)
|
|
370
|
-
.setId(id)
|
|
371
|
-
.setTimestamp()
|
|
372
|
-
.setCapabilities(caps)
|
|
373
|
-
.setTimestampLedger(Date.now())
|
|
374
|
-
.setResultCode(NetworkResultCode.INVALID_PAYLOAD)
|
|
375
|
-
.buildPayload(),
|
|
376
|
-
errorMessageIncludes('Non-OK result code requires timestamp to be 0, except TX_ACCEPTED_PROOF_UNAVAILABLE.')
|
|
377
|
-
);
|
|
378
|
-
});
|
|
379
|
-
|
|
380
220
|
test('NetworkMessageBuilder builds broadcast transaction request and verifies signature', async t => {
|
|
381
221
|
const wallet = createWallet();
|
|
382
222
|
const builder = new NetworkMessageBuilder(wallet, config);
|