@aztec/p2p 0.69.0-devnet → 0.69.1-devnet
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/dest/client/p2p_client.d.ts +6 -0
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +13 -3
- package/dest/mem_pools/attestation_pool/mocks.js +2 -2
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +65 -49
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +6 -2
- package/dest/mem_pools/tx_pool/priority.d.ts +8 -0
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/priority.js +12 -0
- package/dest/mem_pools/tx_pool/tx_pool.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 +19 -3
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -3
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +16 -17
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +11 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/block_header_validator.js +21 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -3
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +5 -17
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +4 -6
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/double_spend_validator.js +16 -45
- package/dest/msg_validators/tx_validator/index.d.ts +1 -0
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +2 -1
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +2 -3
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/metadata_validator.js +9 -18
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -3
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +8 -17
- package/dest/services/libp2p/libp2p_service.d.ts +1 -2
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +12 -11
- package/package.json +7 -7
- package/src/client/p2p_client.ts +20 -3
- package/src/mem_pools/attestation_pool/mocks.ts +2 -2
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +68 -46
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +5 -1
- package/src/mem_pools/tx_pool/priority.ts +13 -0
- package/src/mem_pools/tx_pool/tx_pool.ts +1 -1
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +27 -5
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +16 -20
- package/src/msg_validators/tx_validator/block_header_validator.ts +25 -0
- package/src/msg_validators/tx_validator/data_validator.ts +7 -22
- package/src/msg_validators/tx_validator/double_spend_validator.ts +9 -45
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +9 -22
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +12 -18
- package/src/services/libp2p/libp2p_service.ts +14 -11
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ProcessedTx, type Tx, type TxValidator } from '@aztec/circuit-types';
|
|
1
|
+
import { type ProcessedTx, type Tx, type TxValidationResult, type TxValidator } from '@aztec/circuit-types';
|
|
2
2
|
|
|
3
3
|
export class AggregateTxValidator<T extends Tx | ProcessedTx> implements TxValidator<T> {
|
|
4
4
|
#validators: TxValidator<T>[];
|
|
@@ -10,27 +10,23 @@ export class AggregateTxValidator<T extends Tx | ProcessedTx> implements TxValid
|
|
|
10
10
|
this.#validators = validators;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
async
|
|
14
|
-
const
|
|
15
|
-
const skippedTxs: T[] = [];
|
|
16
|
-
let txPool = txs;
|
|
13
|
+
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
14
|
+
const aggregate: { result: string; reason?: string[] } = { result: 'valid', reason: [] };
|
|
17
15
|
for (const validator of this.#validators) {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
async validateTx(tx: T): Promise<boolean> {
|
|
28
|
-
for (const validator of this.#validators) {
|
|
29
|
-
const valid = await validator.validateTx(tx);
|
|
30
|
-
if (!valid) {
|
|
31
|
-
return false;
|
|
16
|
+
const result = await validator.validateTx(tx);
|
|
17
|
+
if (result.result === 'invalid') {
|
|
18
|
+
aggregate.result = 'invalid';
|
|
19
|
+
aggregate.reason!.push(...result.reason);
|
|
20
|
+
} else if (result.result === 'skipped') {
|
|
21
|
+
if (aggregate.result === 'valid') {
|
|
22
|
+
aggregate.result = 'skipped';
|
|
23
|
+
}
|
|
24
|
+
aggregate.reason!.push(...result.reason);
|
|
32
25
|
}
|
|
33
26
|
}
|
|
34
|
-
|
|
27
|
+
if (aggregate.result === 'valid') {
|
|
28
|
+
delete aggregate.reason;
|
|
29
|
+
}
|
|
30
|
+
return aggregate as TxValidationResult;
|
|
35
31
|
}
|
|
36
32
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type AnyTx, Tx, type TxValidationResult, type TxValidator } from '@aztec/circuit-types';
|
|
2
|
+
import { type Fr } from '@aztec/circuits.js';
|
|
3
|
+
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
|
|
5
|
+
export interface ArchiveSource {
|
|
6
|
+
getArchiveIndices: (archives: Fr[]) => Promise<(bigint | undefined)[]>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class BlockHeaderTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
10
|
+
#log = createLogger('p2p:tx_validator:tx_block_header');
|
|
11
|
+
#archiveSource: ArchiveSource;
|
|
12
|
+
|
|
13
|
+
constructor(archiveSource: ArchiveSource) {
|
|
14
|
+
this.#archiveSource = archiveSource;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
18
|
+
const [index] = await this.#archiveSource.getArchiveIndices([tx.data.constants.historicalHeader.hash()]);
|
|
19
|
+
if (index === undefined) {
|
|
20
|
+
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for referencing an unknown block header`);
|
|
21
|
+
return { result: 'invalid', reason: ['Block header not found'] };
|
|
22
|
+
}
|
|
23
|
+
return { result: 'valid' };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -1,29 +1,14 @@
|
|
|
1
|
-
import { Tx, type TxValidator } from '@aztec/circuit-types';
|
|
1
|
+
import { Tx, type TxValidationResult, type TxValidator } from '@aztec/circuit-types';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
export class DataTxValidator implements TxValidator<Tx> {
|
|
5
5
|
#log = createLogger('p2p:tx_validator:tx_data');
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
const validTxs: Tx[] = [];
|
|
9
|
-
const invalidTxs: Tx[] = [];
|
|
10
|
-
for (const tx of txs) {
|
|
11
|
-
if (!this.#hasCorrectExecutionRequests(tx)) {
|
|
12
|
-
invalidTxs.push(tx);
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
validTxs.push(tx);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return Promise.resolve([validTxs, invalidTxs]);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
validateTx(tx: Tx): Promise<boolean> {
|
|
7
|
+
validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
23
8
|
return Promise.resolve(this.#hasCorrectExecutionRequests(tx));
|
|
24
9
|
}
|
|
25
10
|
|
|
26
|
-
#hasCorrectExecutionRequests(tx: Tx):
|
|
11
|
+
#hasCorrectExecutionRequests(tx: Tx): TxValidationResult {
|
|
27
12
|
const callRequests = [
|
|
28
13
|
...tx.data.getRevertiblePublicCallRequests(),
|
|
29
14
|
...tx.data.getNonRevertiblePublicCallRequests(),
|
|
@@ -34,7 +19,7 @@ export class DataTxValidator implements TxValidator<Tx> {
|
|
|
34
19
|
callRequests.length
|
|
35
20
|
}. Got ${tx.enqueuedPublicFunctionCalls.length}.`,
|
|
36
21
|
);
|
|
37
|
-
return
|
|
22
|
+
return { result: 'invalid', reason: ['Wrong number of execution requests for public calls'] };
|
|
38
23
|
}
|
|
39
24
|
|
|
40
25
|
const invalidExecutionRequestIndex = tx.enqueuedPublicFunctionCalls.findIndex(
|
|
@@ -46,7 +31,7 @@ export class DataTxValidator implements TxValidator<Tx> {
|
|
|
46
31
|
tx,
|
|
47
32
|
)} because of incorrect execution requests for public call at index ${invalidExecutionRequestIndex}.`,
|
|
48
33
|
);
|
|
49
|
-
return
|
|
34
|
+
return { result: 'invalid', reason: ['Incorrect execution request for public call'] };
|
|
50
35
|
}
|
|
51
36
|
|
|
52
37
|
const teardownCallRequest = tx.data.getTeardownPublicCallRequest();
|
|
@@ -55,10 +40,10 @@ export class DataTxValidator implements TxValidator<Tx> {
|
|
|
55
40
|
(teardownCallRequest && !tx.publicTeardownFunctionCall.isForCallRequest(teardownCallRequest));
|
|
56
41
|
if (isInvalidTeardownExecutionRequest) {
|
|
57
42
|
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} because of incorrect teardown execution requests.`);
|
|
58
|
-
return
|
|
43
|
+
return { result: 'invalid', reason: ['Incorrect teardown execution request'] };
|
|
59
44
|
}
|
|
60
45
|
|
|
61
|
-
return
|
|
46
|
+
return { result: 'valid' };
|
|
62
47
|
}
|
|
63
48
|
|
|
64
49
|
// TODO: Check logs.
|
|
@@ -1,69 +1,33 @@
|
|
|
1
|
-
import { type AnyTx, Tx, type TxValidator } from '@aztec/circuit-types';
|
|
1
|
+
import { type AnyTx, Tx, type TxValidationResult, type TxValidator } from '@aztec/circuit-types';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
|
|
4
4
|
export interface NullifierSource {
|
|
5
|
-
|
|
5
|
+
nullifiersExist: (nullifiers: Buffer[]) => Promise<boolean[]>;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export class DoubleSpendTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
9
9
|
#log = createLogger('p2p:tx_validator:tx_double_spend');
|
|
10
10
|
#nullifierSource: NullifierSource;
|
|
11
11
|
|
|
12
|
-
constructor(nullifierSource: NullifierSource
|
|
12
|
+
constructor(nullifierSource: NullifierSource) {
|
|
13
13
|
this.#nullifierSource = nullifierSource;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
async
|
|
17
|
-
const validTxs: T[] = [];
|
|
18
|
-
const invalidTxs: T[] = [];
|
|
19
|
-
const thisBlockNullifiers = new Set<bigint>();
|
|
20
|
-
|
|
21
|
-
for (const tx of txs) {
|
|
22
|
-
if (!(await this.#uniqueNullifiers(tx, thisBlockNullifiers))) {
|
|
23
|
-
invalidTxs.push(tx);
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
validTxs.push(tx);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return [validTxs, invalidTxs];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
validateTx(tx: T): Promise<boolean> {
|
|
34
|
-
return this.#uniqueNullifiers(tx, new Set<bigint>());
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async #uniqueNullifiers(tx: AnyTx, thisBlockNullifiers: Set<bigint>): Promise<boolean> {
|
|
16
|
+
async validateTx(tx: T): Promise<TxValidationResult> {
|
|
38
17
|
const nullifiers = tx instanceof Tx ? tx.data.getNonEmptyNullifiers() : tx.txEffect.nullifiers;
|
|
39
18
|
|
|
40
19
|
// Ditch this tx if it has repeated nullifiers
|
|
41
20
|
const uniqueNullifiers = new Set(nullifiers);
|
|
42
21
|
if (uniqueNullifiers.size !== nullifiers.length) {
|
|
43
22
|
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for emitting duplicate nullifiers`);
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (this.isValidatingBlock) {
|
|
48
|
-
for (const nullifier of nullifiers) {
|
|
49
|
-
const nullifierBigInt = nullifier.toBigInt();
|
|
50
|
-
if (thisBlockNullifiers.has(nullifierBigInt)) {
|
|
51
|
-
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating a nullifier in the same block`);
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
thisBlockNullifiers.add(nullifierBigInt);
|
|
56
|
-
}
|
|
23
|
+
return { result: 'invalid', reason: ['Duplicate nullifier in tx'] };
|
|
57
24
|
}
|
|
58
25
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (hasDuplicates) {
|
|
63
|
-
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating nullifiers present in state trees`);
|
|
64
|
-
return false;
|
|
26
|
+
if ((await this.#nullifierSource.nullifiersExist(nullifiers.map(n => n.toBuffer()))).some(Boolean)) {
|
|
27
|
+
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for repeating a nullifier`);
|
|
28
|
+
return { result: 'invalid', reason: ['Existing nullifier'] };
|
|
65
29
|
}
|
|
66
30
|
|
|
67
|
-
return
|
|
31
|
+
return { result: 'valid' };
|
|
68
32
|
}
|
|
69
33
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AnyTx, Tx, type TxValidator } from '@aztec/circuit-types';
|
|
1
|
+
import { type AnyTx, Tx, type TxValidationResult, type TxValidator } from '@aztec/circuit-types';
|
|
2
2
|
import { type Fr } from '@aztec/circuits.js';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
|
|
@@ -7,28 +7,15 @@ export class MetadataTxValidator<T extends AnyTx> implements TxValidator<T> {
|
|
|
7
7
|
|
|
8
8
|
constructor(private chainId: Fr, private blockNumber: Fr) {}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (!this.#hasCorrectChainId(tx)) {
|
|
15
|
-
invalidTxs.push(tx);
|
|
16
|
-
continue;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (!this.#isValidForBlockNumber(tx)) {
|
|
20
|
-
invalidTxs.push(tx);
|
|
21
|
-
continue;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
validTxs.push(tx);
|
|
10
|
+
validateTx(tx: T): Promise<TxValidationResult> {
|
|
11
|
+
const errors = [];
|
|
12
|
+
if (!this.#hasCorrectChainId(tx)) {
|
|
13
|
+
errors.push('Incorrect chain id');
|
|
25
14
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
validateTx(tx: T): Promise<boolean> {
|
|
31
|
-
return Promise.resolve(this.#hasCorrectChainId(tx) && this.#isValidForBlockNumber(tx));
|
|
15
|
+
if (!this.#isValidForBlockNumber(tx)) {
|
|
16
|
+
errors.push('Invalid block number');
|
|
17
|
+
}
|
|
18
|
+
return Promise.resolve(errors.length > 0 ? { result: 'invalid', reason: errors } : { result: 'valid' });
|
|
32
19
|
}
|
|
33
20
|
|
|
34
21
|
#hasCorrectChainId(tx: T): boolean {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type ClientProtocolCircuitVerifier,
|
|
3
|
+
Tx,
|
|
4
|
+
type TxValidationResult,
|
|
5
|
+
type TxValidator,
|
|
6
|
+
} from '@aztec/circuit-types';
|
|
2
7
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
8
|
|
|
4
9
|
export class TxProofValidator implements TxValidator<Tx> {
|
|
@@ -6,23 +11,12 @@ export class TxProofValidator implements TxValidator<Tx> {
|
|
|
6
11
|
|
|
7
12
|
constructor(private verifier: ClientProtocolCircuitVerifier) {}
|
|
8
13
|
|
|
9
|
-
async
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
for (const tx of txs) {
|
|
14
|
-
if (await this.verifier.verifyProof(tx)) {
|
|
15
|
-
validTxs.push(tx);
|
|
16
|
-
} else {
|
|
17
|
-
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for invalid proof`);
|
|
18
|
-
invalidTxs.push(tx);
|
|
19
|
-
}
|
|
14
|
+
async validateTx(tx: Tx): Promise<TxValidationResult> {
|
|
15
|
+
if (!(await this.verifier.verifyProof(tx))) {
|
|
16
|
+
this.#log.warn(`Rejecting tx ${Tx.getHash(tx)} for invalid proof`);
|
|
17
|
+
return { result: 'invalid', reason: ['Invalid proof'] };
|
|
20
18
|
}
|
|
21
|
-
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
validateTx(tx: Tx): Promise<boolean> {
|
|
26
|
-
return this.verifier.verifyProof(tx);
|
|
19
|
+
this.#log.trace(`Accepted ${Tx.getHash(tx)} with valid proof`);
|
|
20
|
+
return { result: 'valid' };
|
|
27
21
|
}
|
|
28
22
|
}
|
|
@@ -6,17 +6,18 @@ import {
|
|
|
6
6
|
type Gossipable,
|
|
7
7
|
type L2BlockSource,
|
|
8
8
|
MerkleTreeId,
|
|
9
|
+
P2PClientType,
|
|
9
10
|
PeerErrorSeverity,
|
|
10
11
|
type PeerInfo,
|
|
11
12
|
type RawGossipMessage,
|
|
12
13
|
TopicTypeMap,
|
|
13
14
|
Tx,
|
|
14
15
|
TxHash,
|
|
16
|
+
type TxValidationResult,
|
|
15
17
|
type WorldStateSynchronizer,
|
|
16
18
|
getTopicTypeForClientType,
|
|
17
19
|
metricsTopicStrToLabels,
|
|
18
20
|
} from '@aztec/circuit-types';
|
|
19
|
-
import { P2PClientType } from '@aztec/circuit-types';
|
|
20
21
|
import { Fr } from '@aztec/circuits.js';
|
|
21
22
|
import { type EpochCache } from '@aztec/epoch-cache';
|
|
22
23
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -73,14 +74,14 @@ import { GossipSubEvent } from '../types.js';
|
|
|
73
74
|
|
|
74
75
|
interface MessageValidator {
|
|
75
76
|
validator: {
|
|
76
|
-
validateTx(tx: Tx): Promise<
|
|
77
|
+
validateTx(tx: Tx): Promise<TxValidationResult>;
|
|
77
78
|
};
|
|
78
79
|
severity: PeerErrorSeverity;
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
interface ValidationResult {
|
|
82
83
|
name: string;
|
|
83
|
-
isValid:
|
|
84
|
+
isValid: TxValidationResult;
|
|
84
85
|
severity: PeerErrorSeverity;
|
|
85
86
|
}
|
|
86
87
|
|
|
@@ -568,7 +569,7 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
568
569
|
return false;
|
|
569
570
|
}
|
|
570
571
|
|
|
571
|
-
if (
|
|
572
|
+
if (validProof.result === 'invalid') {
|
|
572
573
|
// If the proof is invalid, but the txHash is correct, then this is an active attack and we severly punish
|
|
573
574
|
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
574
575
|
return false;
|
|
@@ -704,9 +705,10 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
704
705
|
},
|
|
705
706
|
doubleSpendValidator: {
|
|
706
707
|
validator: new DoubleSpendTxValidator({
|
|
707
|
-
|
|
708
|
+
nullifiersExist: async (nullifiers: Buffer[]) => {
|
|
708
709
|
const merkleTree = this.worldStateSynchronizer.getCommitted();
|
|
709
|
-
|
|
710
|
+
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
711
|
+
return indices.map(index => index !== undefined);
|
|
710
712
|
},
|
|
711
713
|
}),
|
|
712
714
|
severity: PeerErrorSeverity.HighToleranceError,
|
|
@@ -725,8 +727,8 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
725
727
|
messageValidators: Record<string, MessageValidator>,
|
|
726
728
|
): Promise<ValidationOutcome> {
|
|
727
729
|
const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
|
|
728
|
-
const
|
|
729
|
-
return { name, isValid, severity };
|
|
730
|
+
const { result } = await validator.validateTx(tx);
|
|
731
|
+
return { name, isValid: result === 'valid', severity };
|
|
730
732
|
});
|
|
731
733
|
|
|
732
734
|
// A promise that resolves when all validations have been run
|
|
@@ -767,16 +769,17 @@ export class LibP2PService<T extends P2PClientType> extends WithTracer implement
|
|
|
767
769
|
}
|
|
768
770
|
|
|
769
771
|
const snapshotValidator = new DoubleSpendTxValidator({
|
|
770
|
-
|
|
772
|
+
nullifiersExist: async (nullifiers: Buffer[]) => {
|
|
771
773
|
const merkleTree = this.worldStateSynchronizer.getSnapshot(
|
|
772
774
|
blockNumber - this.config.severePeerPenaltyBlockLength,
|
|
773
775
|
);
|
|
774
|
-
|
|
776
|
+
const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
|
|
777
|
+
return indices.map(index => index !== undefined);
|
|
775
778
|
},
|
|
776
779
|
});
|
|
777
780
|
|
|
778
781
|
const validSnapshot = await snapshotValidator.validateTx(tx);
|
|
779
|
-
if (
|
|
782
|
+
if (validSnapshot.result !== 'valid') {
|
|
780
783
|
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
781
784
|
return false;
|
|
782
785
|
}
|