@aztec/p2p 0.0.1-commit.cb6bed7c2 → 0.0.1-commit.cbf2c2d5d
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/README.md +129 -3
- package/dest/client/factory.d.ts +1 -1
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +19 -7
- package/dest/client/p2p_client.d.ts +1 -1
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +22 -10
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +3 -3
- package/dest/config.d.ts +13 -1
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +20 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +3 -3
- package/dest/mem_pools/attestation_pool/attestation_pool.js +3 -3
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
- package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/priority.js +4 -4
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +2 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +7 -5
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +9 -2
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +7 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +4 -2
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +3 -0
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +19 -5
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +5 -4
- package/dest/msg_validators/clock_tolerance.d.ts +1 -1
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
- package/dest/msg_validators/clock_tolerance.js +4 -3
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +5 -5
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +35 -2
- package/dest/msg_validators/tx_validator/factory.d.ts +23 -4
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +36 -10
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +13 -4
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +39 -9
- package/dest/msg_validators/tx_validator/phases_validator.d.ts +21 -1
- package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/phases_validator.js +28 -1
- package/dest/services/encoding.d.ts +5 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +7 -1
- package/dest/services/libp2p/libp2p_service.d.ts +4 -9
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +115 -59
- package/dest/services/peer-manager/peer_manager.d.ts +1 -1
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +4 -2
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -8
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +69 -65
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts +3 -2
- package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
- package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
- package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
- package/dest/services/reqresp/reqresp.d.ts +1 -1
- package/dest/services/reqresp/reqresp.d.ts.map +1 -1
- package/dest/services/reqresp/reqresp.js +17 -9
- package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -4
- package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/fast_tx_collection.js +57 -73
- package/dest/services/tx_collection/proposal_tx_collector.d.ts +6 -7
- package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
- package/dest/services/tx_collection/request_tracker.d.ts +53 -0
- package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
- package/dest/services/tx_collection/request_tracker.js +84 -0
- package/dest/services/tx_collection/slow_tx_collection.js +1 -1
- package/dest/services/tx_collection/tx_collection.d.ts +3 -6
- package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.d.ts +1 -1
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/test-helpers/testbench-utils.js +22 -3
- package/dest/testbench/p2p_client_testbench_worker.js +3 -3
- package/package.json +14 -14
- package/src/client/factory.ts +34 -11
- package/src/client/p2p_client.ts +22 -12
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +3 -5
- package/src/config.ts +33 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +3 -3
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
- package/src/mem_pools/tx_pool/priority.ts +4 -4
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +2 -1
- package/src/mem_pools/tx_pool_v2/interfaces.ts +6 -4
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +11 -1
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +13 -1
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +20 -5
- package/src/msg_validators/attestation_validator/README.md +49 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +5 -4
- package/src/msg_validators/clock_tolerance.ts +4 -3
- package/src/msg_validators/proposal_validator/README.md +123 -0
- package/src/msg_validators/proposal_validator/proposal_validator.ts +6 -5
- package/src/msg_validators/tx_validator/README.md +5 -1
- package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
- package/src/msg_validators/tx_validator/data_validator.ts +42 -1
- package/src/msg_validators/tx_validator/factory.ts +43 -3
- package/src/msg_validators/tx_validator/gas_validator.ts +41 -8
- package/src/msg_validators/tx_validator/phases_validator.ts +31 -1
- package/src/services/encoding.ts +9 -1
- package/src/services/libp2p/libp2p_service.ts +108 -70
- package/src/services/peer-manager/peer_manager.ts +5 -2
- package/src/services/reqresp/README.md +229 -0
- package/src/services/reqresp/batch-tx-requester/README.md +46 -7
- package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +64 -69
- package/src/services/reqresp/batch-tx-requester/interface.ts +2 -1
- package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
- package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
- package/src/services/reqresp/reqresp.ts +19 -11
- package/src/services/tx_collection/fast_tx_collection.ts +57 -83
- package/src/services/tx_collection/proposal_tx_collector.ts +8 -13
- package/src/services/tx_collection/request_tracker.ts +127 -0
- package/src/services/tx_collection/slow_tx_collection.ts +1 -1
- package/src/services/tx_collection/tx_collection.ts +3 -5
- package/src/test-helpers/testbench-utils.ts +29 -3
- package/src/testbench/p2p_client_testbench_worker.ts +3 -5
- package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
- package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
- package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
- package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT,
|
|
2
3
|
MAX_PROCESSABLE_L2_GAS,
|
|
3
4
|
PRIVATE_TX_L2_GAS_OVERHEAD,
|
|
4
5
|
PUBLIC_TX_L2_GAS_OVERHEAD,
|
|
@@ -49,16 +50,31 @@ export interface HasGasLimitData {
|
|
|
49
50
|
*/
|
|
50
51
|
export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidator<T> {
|
|
51
52
|
#log: Logger;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
#effectiveMaxL2Gas: number;
|
|
54
|
+
#effectiveMaxDAGas: number;
|
|
55
|
+
#rollupManaLimit: number;
|
|
56
|
+
#maxBlockL2Gas: number;
|
|
57
|
+
#maxBlockDAGas: number;
|
|
58
|
+
|
|
59
|
+
constructor(opts?: {
|
|
60
|
+
rollupManaLimit?: number;
|
|
61
|
+
maxBlockL2Gas?: number;
|
|
62
|
+
maxBlockDAGas?: number;
|
|
63
|
+
bindings?: LoggerBindings;
|
|
64
|
+
}) {
|
|
65
|
+
this.#log = createLogger('sequencer:tx_validator:tx_gas', opts?.bindings);
|
|
66
|
+
this.#rollupManaLimit = opts?.rollupManaLimit ?? Infinity;
|
|
67
|
+
this.#maxBlockL2Gas = opts?.maxBlockL2Gas ?? Infinity;
|
|
68
|
+
this.#maxBlockDAGas = opts?.maxBlockDAGas ?? Infinity;
|
|
69
|
+
this.#effectiveMaxL2Gas = Math.min(MAX_PROCESSABLE_L2_GAS, this.#rollupManaLimit, this.#maxBlockL2Gas);
|
|
70
|
+
this.#effectiveMaxDAGas = Math.min(MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT, this.#maxBlockDAGas);
|
|
55
71
|
}
|
|
56
72
|
|
|
57
73
|
validateTx(tx: T): Promise<TxValidationResult> {
|
|
58
74
|
return Promise.resolve(this.validateGasLimit(tx));
|
|
59
75
|
}
|
|
60
76
|
|
|
61
|
-
/** Checks gas limits are >= fixed minimums and <=
|
|
77
|
+
/** Checks gas limits are >= fixed minimums and <= effective max gas (L2 and DA). */
|
|
62
78
|
validateGasLimit(tx: T): TxValidationResult {
|
|
63
79
|
const gasLimits = tx.data.constants.txContext.gasSettings.gasLimits;
|
|
64
80
|
const minGasLimits = new Gas(
|
|
@@ -74,10 +90,21 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
|
|
|
74
90
|
return { result: 'invalid', reason: [TX_ERROR_INSUFFICIENT_GAS_LIMIT] };
|
|
75
91
|
}
|
|
76
92
|
|
|
77
|
-
if (gasLimits.l2Gas >
|
|
78
|
-
this.#log.verbose(`Rejecting transaction due to the gas limit
|
|
93
|
+
if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
|
|
94
|
+
this.#log.verbose(`Rejecting transaction due to the L2 gas limit being higher than the effective maximum`, {
|
|
79
95
|
gasLimits,
|
|
80
|
-
|
|
96
|
+
effectiveMaxL2Gas: this.#effectiveMaxL2Gas,
|
|
97
|
+
rollupManaLimit: this.#rollupManaLimit,
|
|
98
|
+
maxBlockL2Gas: this.#maxBlockL2Gas,
|
|
99
|
+
});
|
|
100
|
+
return { result: 'invalid', reason: [TX_ERROR_GAS_LIMIT_TOO_HIGH] };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (gasLimits.daGas > this.#effectiveMaxDAGas) {
|
|
104
|
+
this.#log.verbose(`Rejecting transaction due to the DA gas limit being higher than the effective maximum`, {
|
|
105
|
+
gasLimits,
|
|
106
|
+
effectiveMaxDAGas: this.#effectiveMaxDAGas,
|
|
107
|
+
maxBlockDAGas: this.#maxBlockDAGas,
|
|
81
108
|
});
|
|
82
109
|
return { result: 'invalid', reason: [TX_ERROR_GAS_LIMIT_TOO_HIGH] };
|
|
83
110
|
}
|
|
@@ -106,21 +133,27 @@ export class GasTxValidator implements TxValidator<Tx> {
|
|
|
106
133
|
#publicDataSource: PublicStateSource;
|
|
107
134
|
#feeJuiceAddress: AztecAddress;
|
|
108
135
|
#gasFees: GasFees;
|
|
136
|
+
#gasLimitOpts?: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number };
|
|
109
137
|
|
|
110
138
|
constructor(
|
|
111
139
|
publicDataSource: PublicStateSource,
|
|
112
140
|
feeJuiceAddress: AztecAddress,
|
|
113
141
|
gasFees: GasFees,
|
|
114
142
|
private bindings?: LoggerBindings,
|
|
143
|
+
opts?: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
|
|
115
144
|
) {
|
|
116
145
|
this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
|
|
117
146
|
this.#publicDataSource = publicDataSource;
|
|
118
147
|
this.#feeJuiceAddress = feeJuiceAddress;
|
|
119
148
|
this.#gasFees = gasFees;
|
|
149
|
+
this.#gasLimitOpts = opts;
|
|
120
150
|
}
|
|
121
151
|
|
|
122
152
|
async validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
123
|
-
const gasLimitValidation = new GasLimitsValidator(
|
|
153
|
+
const gasLimitValidation = new GasLimitsValidator({
|
|
154
|
+
...this.#gasLimitOpts,
|
|
155
|
+
bindings: this.bindings,
|
|
156
|
+
}).validateGasLimit(tx);
|
|
124
157
|
if (gasLimitValidation.result === 'invalid') {
|
|
125
158
|
return Promise.resolve(gasLimitValidation);
|
|
126
159
|
}
|
|
@@ -40,7 +40,7 @@ export class PhasesTxValidator implements TxValidator<Tx> {
|
|
|
40
40
|
// which are needed for public FPC flows, but fail if the account contract hasnt been deployed yet,
|
|
41
41
|
// which is what we're trying to do as part of the current txs.
|
|
42
42
|
// We only need to create/revert checkpoint here because of this addNewContracts call.
|
|
43
|
-
|
|
43
|
+
this.contractsDB.addNewContracts(tx);
|
|
44
44
|
|
|
45
45
|
if (!tx.data.forPublic) {
|
|
46
46
|
this.#log.debug(
|
|
@@ -141,3 +141,33 @@ export class PhasesTxValidator implements TxValidator<Tx> {
|
|
|
141
141
|
return TX_ERROR_SETUP_FUNCTION_NOT_ALLOWED;
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
+
|
|
145
|
+
/** Structural interface for the allowed-setup-calls flag check. */
|
|
146
|
+
export interface HasAllowedSetupCallsData {
|
|
147
|
+
txHash: { toString(): string };
|
|
148
|
+
allowedSetupCalls: boolean;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Validates that a transaction's setup-phase calls were allowed at receipt time.
|
|
153
|
+
*
|
|
154
|
+
* Checks the precomputed `allowedSetupCalls` flag on TxMetaData. The flag is
|
|
155
|
+
* computed by running the PhasesTxValidator on the full Tx when it first enters
|
|
156
|
+
* the pool. This lightweight validator is used during pending pool migration to
|
|
157
|
+
* reject txs whose setup calls are not on the allow list.
|
|
158
|
+
*/
|
|
159
|
+
export class AllowedSetupCallsMetaValidator<T extends HasAllowedSetupCallsData> implements TxValidator<T> {
|
|
160
|
+
#log: Logger;
|
|
161
|
+
|
|
162
|
+
constructor(bindings?: LoggerBindings) {
|
|
163
|
+
this.#log = createLogger('sequencer:tx_validator:tx_phases_meta', bindings);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
validateTx(tx: T): Promise<TxValidationResult> {
|
|
167
|
+
if (!tx.allowedSetupCalls) {
|
|
168
|
+
this.#log.verbose(`Rejecting tx ${tx.txHash} because its setup calls are not on the allow list`);
|
|
169
|
+
return Promise.resolve({ result: 'invalid', reason: [TX_ERROR_SETUP_FUNCTION_NOT_ALLOWED] });
|
|
170
|
+
}
|
|
171
|
+
return Promise.resolve({ result: 'valid' });
|
|
172
|
+
}
|
|
173
|
+
}
|
package/src/services/encoding.ts
CHANGED
|
@@ -9,6 +9,14 @@ import { webcrypto } from 'node:crypto';
|
|
|
9
9
|
import { compressSync, uncompressSync } from 'snappy';
|
|
10
10
|
import xxhashFactory from 'xxhash-wasm';
|
|
11
11
|
|
|
12
|
+
/** Thrown when a Snappy-compressed response exceeds the allowed decompressed size. */
|
|
13
|
+
export class OversizedSnappyResponseError extends Error {
|
|
14
|
+
constructor(decompressedSize: number, maxSizeKb: number) {
|
|
15
|
+
super(`Decompressed size ${decompressedSize} exceeds maximum allowed size of ${maxSizeKb}kb`);
|
|
16
|
+
this.name = 'OversizedSnappyResponseError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
12
20
|
// Load WASM
|
|
13
21
|
const xxhash = await xxhashFactory();
|
|
14
22
|
|
|
@@ -86,7 +94,7 @@ export class SnappyTransform implements DataTransform {
|
|
|
86
94
|
const { decompressedSize } = readSnappyPreamble(data);
|
|
87
95
|
if (decompressedSize > maxSizeKb * 1024) {
|
|
88
96
|
this.logger.warn(`Decompressed size ${decompressedSize} exceeds maximum allowed size of ${maxSizeKb}kb`);
|
|
89
|
-
throw new
|
|
97
|
+
throw new OversizedSnappyResponseError(decompressedSize, maxSizeKb);
|
|
90
98
|
}
|
|
91
99
|
|
|
92
100
|
return Buffer.from(uncompressSync(data, { asBuffer: true }));
|
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
type CheckpointProposalCore,
|
|
19
19
|
type Gossipable,
|
|
20
20
|
P2PMessage,
|
|
21
|
-
type ValidationResult as P2PValidationResult,
|
|
22
21
|
PeerErrorSeverity,
|
|
23
22
|
PeerErrorSeverityByHarshness,
|
|
24
23
|
TopicType,
|
|
@@ -131,7 +130,7 @@ type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: Vali
|
|
|
131
130
|
// REFACTOR: Unify with the type above
|
|
132
131
|
type ReceivedMessageValidationResult<T, M = undefined> =
|
|
133
132
|
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
|
|
134
|
-
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
|
|
133
|
+
| { obj?: T; result: TopicValidatorResult.Reject; metadata?: M; severity: PeerErrorSeverity };
|
|
135
134
|
|
|
136
135
|
/**
|
|
137
136
|
* Lib P2P implementation of the P2PService interface.
|
|
@@ -226,7 +225,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
226
225
|
|
|
227
226
|
const proposalValidatorOpts = {
|
|
228
227
|
txsPermitted: !config.disableTransactions,
|
|
229
|
-
maxTxsPerBlock: config.validateMaxTxsPerBlock,
|
|
228
|
+
maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
|
|
230
229
|
};
|
|
231
230
|
this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
|
|
232
231
|
this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
|
|
@@ -237,11 +236,11 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
237
236
|
this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
|
|
238
237
|
|
|
239
238
|
this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
|
|
240
|
-
this.logger.
|
|
241
|
-
`Handler not yet registered
|
|
239
|
+
this.logger.warn(
|
|
240
|
+
`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
|
|
242
241
|
{ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
|
|
243
242
|
);
|
|
244
|
-
return
|
|
243
|
+
return true;
|
|
245
244
|
};
|
|
246
245
|
|
|
247
246
|
this.checkpointReceivedCallback = (
|
|
@@ -754,6 +753,9 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
754
753
|
if (!validator || !validator.addMessage(msgId)) {
|
|
755
754
|
this.instrumentation.incMessagePrevalidationStatus(false, topicType);
|
|
756
755
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
|
|
756
|
+
if (topicType === TopicType.tx) {
|
|
757
|
+
this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
|
|
758
|
+
}
|
|
757
759
|
return { result: false, topicType };
|
|
758
760
|
}
|
|
759
761
|
|
|
@@ -880,30 +882,56 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
880
882
|
source: PeerId,
|
|
881
883
|
topicType: TopicType,
|
|
882
884
|
): Promise<ReceivedMessageValidationResult<T, M>> {
|
|
883
|
-
|
|
885
|
+
// Default to reject result with a penalty if validation function throws an error
|
|
886
|
+
let resultAndObj: ReceivedMessageValidationResult<T, M> = {
|
|
887
|
+
result: TopicValidatorResult.Reject,
|
|
888
|
+
severity: PeerErrorSeverity.MidToleranceError,
|
|
889
|
+
};
|
|
884
890
|
const timer = new Timer();
|
|
885
891
|
try {
|
|
886
892
|
resultAndObj = await validationFunc();
|
|
887
893
|
} catch (err) {
|
|
888
|
-
this.
|
|
889
|
-
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
890
|
-
msgId,
|
|
891
|
-
source: source.toString(),
|
|
892
|
-
topicType,
|
|
893
|
-
});
|
|
894
|
+
this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
|
|
894
895
|
}
|
|
895
896
|
|
|
896
897
|
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
898
|
+
this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
|
|
897
899
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
900
|
+
} else if (resultAndObj.result === TopicValidatorResult.Reject) {
|
|
901
|
+
this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
|
|
902
|
+
msgId,
|
|
903
|
+
source: source.toString(),
|
|
904
|
+
topicType,
|
|
905
|
+
severity: resultAndObj.severity,
|
|
906
|
+
});
|
|
907
|
+
this.peerManager.penalizePeer(source, resultAndObj.severity);
|
|
908
|
+
} else {
|
|
909
|
+
this.logger.trace(`Message ${topicType} ignored by validator`, { msgId, source: source.toString(), topicType });
|
|
898
910
|
}
|
|
899
911
|
|
|
900
912
|
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
|
|
901
913
|
return resultAndObj;
|
|
902
914
|
}
|
|
903
915
|
|
|
916
|
+
private tryDeserialize<T>(deserializeFunc: () => T, msgId: string, source: PeerId): T | undefined {
|
|
917
|
+
try {
|
|
918
|
+
return deserializeFunc();
|
|
919
|
+
} catch (err) {
|
|
920
|
+
this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
|
|
921
|
+
err,
|
|
922
|
+
msgId,
|
|
923
|
+
source: source.toString(),
|
|
924
|
+
});
|
|
925
|
+
return undefined;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
904
929
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
905
930
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
906
|
-
const tx = Tx.fromBuffer(payloadData);
|
|
931
|
+
const tx = this.tryDeserialize(() => Tx.fromBuffer(payloadData), msgId, source);
|
|
932
|
+
if (!tx) {
|
|
933
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.LowToleranceError };
|
|
934
|
+
}
|
|
907
935
|
|
|
908
936
|
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
909
937
|
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
@@ -923,13 +951,20 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
923
951
|
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
924
952
|
}
|
|
925
953
|
|
|
926
|
-
this.
|
|
927
|
-
|
|
954
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
|
|
955
|
+
validator: name,
|
|
956
|
+
severity,
|
|
957
|
+
source: source.toString(),
|
|
958
|
+
});
|
|
959
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
928
960
|
}
|
|
929
961
|
|
|
930
962
|
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
931
963
|
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
932
964
|
if (canAdd === 'ignored') {
|
|
965
|
+
this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
|
|
966
|
+
source: source.toString(),
|
|
967
|
+
});
|
|
933
968
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
934
969
|
}
|
|
935
970
|
|
|
@@ -937,9 +972,13 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
937
972
|
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
938
973
|
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
939
974
|
if (!secondStageOutcome.allPassed) {
|
|
940
|
-
const { severity } = secondStageOutcome.failure;
|
|
941
|
-
this.
|
|
942
|
-
|
|
975
|
+
const { severity, name } = secondStageOutcome.failure;
|
|
976
|
+
this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
|
|
977
|
+
validator: name,
|
|
978
|
+
severity,
|
|
979
|
+
source: source.toString(),
|
|
980
|
+
});
|
|
981
|
+
return { result: TopicValidatorResult.Reject, severity };
|
|
943
982
|
}
|
|
944
983
|
|
|
945
984
|
// Pool add: persist the tx
|
|
@@ -949,7 +988,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
949
988
|
const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
|
|
950
989
|
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
951
990
|
|
|
952
|
-
this.logger.
|
|
991
|
+
this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
|
|
953
992
|
wasAccepted,
|
|
954
993
|
wasIgnored,
|
|
955
994
|
[Attributes.P2P_ID]: source.toString(),
|
|
@@ -960,7 +999,11 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
960
999
|
} else if (wasIgnored) {
|
|
961
1000
|
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
962
1001
|
} else {
|
|
963
|
-
|
|
1002
|
+
this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
|
|
1003
|
+
source: source.toString(),
|
|
1004
|
+
txHash: txHash.toString(),
|
|
1005
|
+
});
|
|
1006
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
964
1007
|
}
|
|
965
1008
|
};
|
|
966
1009
|
|
|
@@ -990,7 +1033,16 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
990
1033
|
source: PeerId,
|
|
991
1034
|
): Promise<void> {
|
|
992
1035
|
const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
|
|
993
|
-
() =>
|
|
1036
|
+
() => {
|
|
1037
|
+
const attestation = this.tryDeserialize(() => CheckpointAttestation.fromBuffer(payloadData), msgId, source);
|
|
1038
|
+
if (!attestation) {
|
|
1039
|
+
return Promise.resolve({
|
|
1040
|
+
result: TopicValidatorResult.Reject,
|
|
1041
|
+
severity: PeerErrorSeverity.LowToleranceError,
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
return this.validateAndStoreCheckpointAttestation(source, attestation);
|
|
1045
|
+
},
|
|
994
1046
|
msgId,
|
|
995
1047
|
source,
|
|
996
1048
|
TopicType.checkpoint_attestation,
|
|
@@ -1023,8 +1075,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1023
1075
|
|
|
1024
1076
|
if (validationResult.result === 'reject') {
|
|
1025
1077
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1026
|
-
|
|
1027
|
-
return { result: TopicValidatorResult.Reject };
|
|
1078
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1028
1079
|
}
|
|
1029
1080
|
|
|
1030
1081
|
if (validationResult.result === 'ignore') {
|
|
@@ -1050,16 +1101,16 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1050
1101
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
1051
1102
|
}
|
|
1052
1103
|
|
|
1053
|
-
// Could not add (cap reached for signer),
|
|
1104
|
+
// Could not add (cap reached for signer), penalize and do not re-broadcast
|
|
1054
1105
|
if (!added) {
|
|
1055
|
-
this.logger.warn(`
|
|
1106
|
+
this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
|
|
1056
1107
|
slot: slot.toString(),
|
|
1057
1108
|
archive: attestation.archive.toString(),
|
|
1058
1109
|
source: peerId.toString(),
|
|
1059
1110
|
attester: attestation.getSender()?.toString(),
|
|
1060
1111
|
count,
|
|
1061
1112
|
});
|
|
1062
|
-
return { result: TopicValidatorResult.
|
|
1113
|
+
return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
|
|
1063
1114
|
}
|
|
1064
1115
|
|
|
1065
1116
|
// Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
|
|
@@ -1114,8 +1165,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1114
1165
|
|
|
1115
1166
|
if (validationResult.result === 'reject') {
|
|
1116
1167
|
this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1117
|
-
|
|
1118
|
-
return { result: TopicValidatorResult.Reject };
|
|
1168
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1119
1169
|
}
|
|
1120
1170
|
|
|
1121
1171
|
if (validationResult.result === 'ignore') {
|
|
@@ -1139,7 +1189,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1139
1189
|
|
|
1140
1190
|
// Too many blocks received for this slot and index, penalize peer and do not re-broadcast
|
|
1141
1191
|
if (!added) {
|
|
1142
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1143
1192
|
this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
|
|
1144
1193
|
...block.toBlockInfo(),
|
|
1145
1194
|
indexWithinCheckpoint: block.indexWithinCheckpoint,
|
|
@@ -1147,7 +1196,11 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1147
1196
|
proposer: block.getSender()?.toString(),
|
|
1148
1197
|
source: peerId.toString(),
|
|
1149
1198
|
});
|
|
1150
|
-
return {
|
|
1199
|
+
return {
|
|
1200
|
+
result: TopicValidatorResult.Reject,
|
|
1201
|
+
metadata: { isEquivocated },
|
|
1202
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1203
|
+
};
|
|
1151
1204
|
}
|
|
1152
1205
|
|
|
1153
1206
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1192,7 +1245,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1192
1245
|
// Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
|
|
1193
1246
|
const isValid = await this.blockReceivedCallback(block, sender);
|
|
1194
1247
|
if (!isValid) {
|
|
1195
|
-
this.logger.
|
|
1248
|
+
this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
|
|
1196
1249
|
}
|
|
1197
1250
|
}
|
|
1198
1251
|
|
|
@@ -1240,8 +1293,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1240
1293
|
|
|
1241
1294
|
if (validationResult.result === 'reject') {
|
|
1242
1295
|
this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1243
|
-
|
|
1244
|
-
return { result: TopicValidatorResult.Reject };
|
|
1296
|
+
return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
|
|
1245
1297
|
}
|
|
1246
1298
|
|
|
1247
1299
|
if (validationResult.result === 'ignore') {
|
|
@@ -1256,20 +1308,21 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1256
1308
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1257
1309
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1258
1310
|
});
|
|
1259
|
-
const
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
metadata: { isEquivocated } = {},
|
|
1263
|
-
} = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1264
|
-
if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1311
|
+
const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
|
|
1312
|
+
const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
|
|
1313
|
+
if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
|
|
1265
1314
|
this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
|
|
1266
1315
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1267
1316
|
[Attributes.P2P_ID]: peerId.toString(),
|
|
1268
1317
|
isEquivocated,
|
|
1269
|
-
result,
|
|
1318
|
+
result: blockProposalResult.result,
|
|
1270
1319
|
});
|
|
1271
|
-
return {
|
|
1272
|
-
|
|
1320
|
+
return {
|
|
1321
|
+
result: TopicValidatorResult.Reject,
|
|
1322
|
+
severity:
|
|
1323
|
+
'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError,
|
|
1324
|
+
};
|
|
1325
|
+
} else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
|
|
1273
1326
|
processBlock = true;
|
|
1274
1327
|
}
|
|
1275
1328
|
}
|
|
@@ -1296,13 +1349,17 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1296
1349
|
// Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
|
|
1297
1350
|
// Note: We still return the checkpoint obj so the lastBlock can be processed if valid
|
|
1298
1351
|
if (!added) {
|
|
1299
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
1300
1352
|
this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
|
|
1301
1353
|
...checkpoint.toCheckpointInfo(),
|
|
1302
1354
|
count,
|
|
1303
1355
|
source: peerId.toString(),
|
|
1304
1356
|
});
|
|
1305
|
-
return {
|
|
1357
|
+
return {
|
|
1358
|
+
result: TopicValidatorResult.Reject,
|
|
1359
|
+
obj: checkpoint,
|
|
1360
|
+
metadata: { isEquivocated, processBlock },
|
|
1361
|
+
severity: PeerErrorSeverity.HighToleranceError,
|
|
1362
|
+
};
|
|
1306
1363
|
}
|
|
1307
1364
|
|
|
1308
1365
|
// If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
|
|
@@ -1626,6 +1683,7 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1626
1683
|
...(this.config.txPublicSetupAllowListExtend ?? []),
|
|
1627
1684
|
];
|
|
1628
1685
|
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1686
|
+
const l1Constants = await this.archiver.getL1Constants();
|
|
1629
1687
|
|
|
1630
1688
|
return createFirstStageTxValidationsForGossipedTransactions(
|
|
1631
1689
|
nextSlotTimestamp,
|
|
@@ -1639,6 +1697,11 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1639
1697
|
!this.config.disableTransactions,
|
|
1640
1698
|
allowedInSetup,
|
|
1641
1699
|
this.logger.getBindings(),
|
|
1700
|
+
{
|
|
1701
|
+
rollupManaLimit: l1Constants.rollupManaLimit,
|
|
1702
|
+
maxBlockL2Gas: this.config.validateMaxL2BlockGas,
|
|
1703
|
+
maxBlockDAGas: this.config.validateMaxDABlockGas,
|
|
1704
|
+
},
|
|
1642
1705
|
);
|
|
1643
1706
|
}
|
|
1644
1707
|
|
|
@@ -1720,31 +1783,6 @@ export class LibP2PService extends WithTracer implements P2PService {
|
|
|
1720
1783
|
return PeerErrorSeverity.HighToleranceError;
|
|
1721
1784
|
}
|
|
1722
1785
|
|
|
1723
|
-
/**
|
|
1724
|
-
* Validate a checkpoint attestation.
|
|
1725
|
-
*
|
|
1726
|
-
* @param attestation - The checkpoint attestation to validate.
|
|
1727
|
-
* @returns True if the checkpoint attestation is valid, false otherwise.
|
|
1728
|
-
*/
|
|
1729
|
-
@trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
|
|
1730
|
-
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
|
|
1731
|
-
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1732
|
-
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1733
|
-
}))
|
|
1734
|
-
public async validateCheckpointAttestation(
|
|
1735
|
-
peerId: PeerId,
|
|
1736
|
-
attestation: CheckpointAttestation,
|
|
1737
|
-
): Promise<P2PValidationResult> {
|
|
1738
|
-
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1739
|
-
|
|
1740
|
-
if (result.result === 'reject') {
|
|
1741
|
-
this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1742
|
-
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1743
|
-
}
|
|
1744
|
-
|
|
1745
|
-
return result;
|
|
1746
|
-
}
|
|
1747
|
-
|
|
1748
1786
|
public getPeerScore(peerId: PeerId): number {
|
|
1749
1787
|
return this.node.services.pubsub.score.score(peerId.toString());
|
|
1750
1788
|
}
|
|
@@ -32,7 +32,7 @@ import { PeerScoreState, type PeerScoring } from './peer_scoring.js';
|
|
|
32
32
|
const MAX_DIAL_ATTEMPTS = 3;
|
|
33
33
|
const MAX_CACHED_PEERS = 100;
|
|
34
34
|
const MAX_CACHED_PEER_AGE_MS = 5 * 60 * 1000; // 5 minutes
|
|
35
|
-
const
|
|
35
|
+
const DEFAULT_FAILED_PEER_BAN_TIME_MS = 5 * 60 * 1000; // 5 minutes timeout after failing MAX_DIAL_ATTEMPTS
|
|
36
36
|
const GOODBYE_DIAL_TIMEOUT_MS = 1000;
|
|
37
37
|
const FAILED_AUTH_HANDSHAKE_EXPIRY_MS = 60 * 60 * 1000; // 1 hour
|
|
38
38
|
|
|
@@ -776,7 +776,8 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
776
776
|
// Add to timed out peers
|
|
777
777
|
this.timedOutPeers.set(id, {
|
|
778
778
|
peerId: id,
|
|
779
|
-
timeoutUntilMs:
|
|
779
|
+
timeoutUntilMs:
|
|
780
|
+
this.dateProvider.now() + (this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS),
|
|
780
781
|
});
|
|
781
782
|
}
|
|
782
783
|
}
|
|
@@ -938,6 +939,8 @@ export class PeerManager implements PeerManagerInterface {
|
|
|
938
939
|
`Received auth for validator ${sender.toString()} from peer ${peerIdString}, but this validator is already authenticated to peer ${peerForAddress.toString()}`,
|
|
939
940
|
{ ...logData, address: sender.toString() },
|
|
940
941
|
);
|
|
942
|
+
this.markAuthHandshakeFailed(peerId);
|
|
943
|
+
this.markPeerForDisconnect(peerId);
|
|
941
944
|
return;
|
|
942
945
|
}
|
|
943
946
|
|