@aztec/p2p 4.0.0-rc.5 → 4.0.0-rc.7
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/factory.d.ts +1 -1
- package/dest/client/factory.d.ts.map +1 -1
- package/dest/client/factory.js +8 -20
- package/dest/client/interface.d.ts +6 -11
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +4 -11
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +5 -57
- package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +1 -2
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +2 -0
- package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
- package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/index.js +1 -1
- package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +5 -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 +26 -4
- package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_metadata.js +48 -7
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +9 -10
- package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +2 -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_impl.d.ts +2 -2
- 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 +37 -28
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
- package/dest/msg_validators/tx_validator/factory.d.ts +114 -6
- package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/factory.js +219 -58
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +58 -3
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +72 -35
- package/dest/msg_validators/tx_validator/index.d.ts +2 -1
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/index.js +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
- package/dest/services/dummy_service.d.ts +4 -4
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/dummy_service.js +4 -4
- package/dest/services/encoding.d.ts +2 -2
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +7 -7
- package/dest/services/libp2p/libp2p_service.d.ts +11 -7
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +60 -70
- package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
- package/dest/services/service.d.ts +5 -3
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_provider.d.ts +3 -3
- package/dest/services/tx_provider.d.ts.map +1 -1
- package/dest/services/tx_provider.js +4 -4
- package/dest/test-helpers/mock-pubsub.d.ts +3 -2
- package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
- package/dest/test-helpers/mock-pubsub.js +6 -0
- package/dest/test-helpers/testbench-utils.d.ts +2 -2
- package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
- package/dest/util.d.ts +2 -2
- package/dest/util.d.ts.map +1 -1
- package/package.json +14 -14
- package/src/client/factory.ts +13 -33
- package/src/client/interface.ts +12 -11
- package/src/client/p2p_client.ts +7 -76
- package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +1 -1
- package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +3 -0
- package/src/mem_pools/tx_pool_v2/index.ts +1 -1
- package/src/mem_pools/tx_pool_v2/interfaces.ts +4 -4
- package/src/mem_pools/tx_pool_v2/tx_metadata.ts +65 -10
- package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +11 -11
- package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +1 -1
- package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +42 -28
- package/src/msg_validators/tx_validator/README.md +115 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
- package/src/msg_validators/tx_validator/factory.ts +353 -77
- package/src/msg_validators/tx_validator/gas_validator.ts +84 -29
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
- package/src/services/dummy_service.ts +6 -6
- package/src/services/encoding.ts +5 -6
- package/src/services/libp2p/libp2p_service.ts +74 -79
- package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
- package/src/services/service.ts +11 -2
- package/src/services/tx_provider.ts +2 -2
- package/src/test-helpers/mock-pubsub.ts +10 -0
- package/src/test-helpers/testbench-utils.ts +1 -1
- package/src/util.ts +7 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
3
|
-
import type { Gossipable, PeerErrorSeverity } from '@aztec/stdlib/p2p';
|
|
3
|
+
import type { Gossipable, PeerErrorSeverity, TopicType } from '@aztec/stdlib/p2p';
|
|
4
4
|
import { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
5
5
|
|
|
6
6
|
import type { PeerId } from '@libp2p/interface';
|
|
@@ -44,6 +44,10 @@ export class DummyP2PService implements P2PService {
|
|
|
44
44
|
return [];
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
getGossipMeshPeerCount(_topicType: TopicType): number {
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
|
|
47
51
|
/**
|
|
48
52
|
* Starts the dummy implementation.
|
|
49
53
|
* @returns A resolved promise.
|
|
@@ -137,14 +141,10 @@ export class DummyP2PService implements P2PService {
|
|
|
137
141
|
return undefined;
|
|
138
142
|
}
|
|
139
143
|
|
|
140
|
-
|
|
144
|
+
validateTxsReceivedInBlockProposal(_txs: Tx[]): Promise<void> {
|
|
141
145
|
return Promise.resolve();
|
|
142
146
|
}
|
|
143
147
|
|
|
144
|
-
validatePropagatedTx(_tx: Tx, _peerId: PeerId): Promise<boolean> {
|
|
145
|
-
return Promise.resolve(true);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
148
|
addReqRespSubProtocol(
|
|
149
149
|
_subProtocol: ReqRespSubProtocol,
|
|
150
150
|
_handler: ReqRespSubProtocolHandler,
|
package/src/services/encoding.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Taken from lodestar: https://github.com/ChainSafe/lodestar
|
|
2
|
-
import { sha256 } from '@aztec/foundation/crypto/sha256';
|
|
3
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
3
|
import { MAX_TX_SIZE_KB, TopicType, getTopicFromString } from '@aztec/stdlib/p2p';
|
|
5
4
|
|
|
6
5
|
import type { RPC } from '@chainsafe/libp2p-gossipsub/message';
|
|
7
6
|
import type { DataTransform } from '@chainsafe/libp2p-gossipsub/types';
|
|
8
7
|
import type { Message } from '@libp2p/interface';
|
|
8
|
+
import { webcrypto } from 'node:crypto';
|
|
9
9
|
import { compressSync, uncompressSync } from 'snappy';
|
|
10
10
|
import xxhashFactory from 'xxhash-wasm';
|
|
11
11
|
|
|
@@ -44,11 +44,10 @@ export function msgIdToStrFn(msgId: Uint8Array): string {
|
|
|
44
44
|
* @param message - The libp2p message
|
|
45
45
|
* @returns The message identifier
|
|
46
46
|
*/
|
|
47
|
-
export function getMsgIdFn(
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return sha256(Buffer.concat(vec)).subarray(0, 20);
|
|
47
|
+
export async function getMsgIdFn({ topic, data }: Message): Promise<Uint8Array> {
|
|
48
|
+
const buffer = Buffer.concat([Buffer.from(topic), data]);
|
|
49
|
+
const hash = await webcrypto.subtle.digest('SHA-256', buffer);
|
|
50
|
+
return Buffer.from(hash.slice(0, 20));
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
const DefaultMaxSizesKb: Record<TopicType, number> = {
|
|
@@ -69,9 +69,11 @@ import {
|
|
|
69
69
|
} from '../../msg_validators/index.js';
|
|
70
70
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
71
71
|
import {
|
|
72
|
-
type
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
type TransactionValidator,
|
|
73
|
+
createFirstStageTxValidationsForGossipedTransactions,
|
|
74
|
+
createSecondStageTxValidationsForGossipedTransactions,
|
|
75
|
+
createTxValidatorForBlockProposalReceivedTxs,
|
|
76
|
+
createTxValidatorForReqResponseReceivedTxs,
|
|
75
77
|
} from '../../msg_validators/tx_validator/factory.js';
|
|
76
78
|
import { GossipSubEvent } from '../../types/index.js';
|
|
77
79
|
import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
|
|
@@ -87,6 +89,9 @@ import { PeerScoring } from '../peer-manager/peer_scoring.js';
|
|
|
87
89
|
import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
|
|
88
90
|
import type { P2PReqRespConfig } from '../reqresp/config.js';
|
|
89
91
|
import {
|
|
92
|
+
AuthRequest,
|
|
93
|
+
BlockTxsRequest,
|
|
94
|
+
BlockTxsResponse,
|
|
90
95
|
DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
91
96
|
type ReqRespInterface,
|
|
92
97
|
type ReqRespResponse,
|
|
@@ -94,14 +99,9 @@ import {
|
|
|
94
99
|
type ReqRespSubProtocolHandler,
|
|
95
100
|
type ReqRespSubProtocolHandlers,
|
|
96
101
|
type ReqRespSubProtocolValidators,
|
|
102
|
+
StatusMessage,
|
|
97
103
|
type SubProtocolMap,
|
|
98
104
|
ValidationError,
|
|
99
|
-
} from '../reqresp/index.js';
|
|
100
|
-
import {
|
|
101
|
-
AuthRequest,
|
|
102
|
-
BlockTxsRequest,
|
|
103
|
-
BlockTxsResponse,
|
|
104
|
-
StatusMessage,
|
|
105
105
|
pingHandler,
|
|
106
106
|
reqGoodbyeHandler,
|
|
107
107
|
reqRespBlockHandler,
|
|
@@ -615,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
615
615
|
return this.peerManager.getPeers(includePending);
|
|
616
616
|
}
|
|
617
617
|
|
|
618
|
+
public getGossipMeshPeerCount(topicType: TopicType): number {
|
|
619
|
+
return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
|
|
620
|
+
}
|
|
621
|
+
|
|
618
622
|
private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
|
|
619
623
|
this.logger.trace(`Received PUBSUB message.`);
|
|
620
624
|
|
|
@@ -902,15 +906,45 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
902
906
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
903
907
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
904
908
|
const tx = Tx.fromBuffer(payloadData);
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
909
|
+
|
|
910
|
+
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
911
|
+
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
912
|
+
|
|
913
|
+
// Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
|
|
914
|
+
const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
915
|
+
const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
|
|
916
|
+
if (!firstStageOutcome.allPassed) {
|
|
917
|
+
const { name } = firstStageOutcome.failure;
|
|
918
|
+
let { severity } = firstStageOutcome.failure;
|
|
919
|
+
|
|
920
|
+
// Double spend validator has a special case handler. We perform more detailed examination
|
|
921
|
+
// as to how recently the nullifier was entered into the tree and if the transaction should
|
|
922
|
+
// have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
|
|
923
|
+
if (name === 'doubleSpendValidator') {
|
|
924
|
+
const txBlockNumber = BlockNumber(currentBlockNumber + 1);
|
|
925
|
+
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
this.peerManager.penalizePeer(source, severity);
|
|
929
|
+
return { result: TopicValidatorResult.Reject };
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
// Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
|
|
933
|
+
const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
|
|
934
|
+
if (canAdd === 'ignored') {
|
|
935
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
// Stage 2: expensive proof verification
|
|
939
|
+
const secondStageValidators = this.createSecondStageMessageValidators();
|
|
940
|
+
const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
|
|
941
|
+
if (!secondStageOutcome.allPassed) {
|
|
942
|
+
const { severity } = secondStageOutcome.failure;
|
|
943
|
+
this.peerManager.penalizePeer(source, severity);
|
|
910
944
|
return { result: TopicValidatorResult.Reject };
|
|
911
945
|
}
|
|
912
946
|
|
|
913
|
-
//
|
|
947
|
+
// Pool add: persist the tx
|
|
914
948
|
const txHash = tx.getTxHash();
|
|
915
949
|
const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
|
|
916
950
|
|
|
@@ -918,7 +952,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
918
952
|
const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
|
|
919
953
|
|
|
920
954
|
this.logger.trace(`Validate propagated tx`, {
|
|
921
|
-
isValid,
|
|
922
955
|
wasAccepted,
|
|
923
956
|
wasIgnored,
|
|
924
957
|
[Attributes.P2P_ID]: source.toString(),
|
|
@@ -1533,43 +1566,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1533
1566
|
}
|
|
1534
1567
|
|
|
1535
1568
|
protected createRequestedTxValidator(): TxValidator {
|
|
1536
|
-
return
|
|
1569
|
+
return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
|
|
1537
1570
|
l1ChainId: this.config.l1ChainId,
|
|
1538
1571
|
rollupVersion: this.config.rollupVersion,
|
|
1539
1572
|
});
|
|
1540
1573
|
}
|
|
1541
1574
|
|
|
1542
|
-
@trackSpan('Libp2pService.validatePropagatedTx', tx => ({
|
|
1543
|
-
[Attributes.TX_HASH]: tx.getTxHash().toString(),
|
|
1544
|
-
}))
|
|
1545
|
-
protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
|
|
1546
|
-
const currentBlockNumber = await this.archiver.getBlockNumber();
|
|
1547
|
-
|
|
1548
|
-
// We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
|
|
1549
|
-
const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
|
|
1550
|
-
const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
|
|
1551
|
-
|
|
1552
|
-
for (const validator of messageValidators) {
|
|
1553
|
-
const outcome = await this.runValidations(tx, validator);
|
|
1554
|
-
|
|
1555
|
-
if (outcome.allPassed) {
|
|
1556
|
-
continue;
|
|
1557
|
-
}
|
|
1558
|
-
const { name } = outcome.failure;
|
|
1559
|
-
let { severity } = outcome.failure;
|
|
1560
|
-
|
|
1561
|
-
// Double spend validator has a special case handler
|
|
1562
|
-
if (name === 'doubleSpendValidator') {
|
|
1563
|
-
const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
|
|
1564
|
-
severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
|
|
1565
|
-
}
|
|
1566
|
-
|
|
1567
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1568
|
-
return false;
|
|
1569
|
-
}
|
|
1570
|
-
return true;
|
|
1571
|
-
}
|
|
1572
|
-
|
|
1573
1575
|
private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
|
|
1574
1576
|
if (blockNumber === this.feesCache?.blockNumber) {
|
|
1575
1577
|
return this.feesCache.gasFees;
|
|
@@ -1597,60 +1599,53 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1597
1599
|
};
|
|
1598
1600
|
}
|
|
1599
1601
|
|
|
1600
|
-
public async
|
|
1601
|
-
const
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1602
|
+
public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
|
|
1603
|
+
const validator = createTxValidatorForBlockProposalReceivedTxs(
|
|
1604
|
+
this.proofVerifier,
|
|
1605
|
+
{ l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
|
|
1606
|
+
this.logger.getBindings(),
|
|
1607
|
+
);
|
|
1606
1608
|
|
|
1607
|
-
await Promise.all(
|
|
1609
|
+
const results = await Promise.all(
|
|
1608
1610
|
txs.map(async tx => {
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
if (!outcome.allPassed) {
|
|
1612
|
-
throw new Error('Invalid tx detected', { cause: { outcome } });
|
|
1613
|
-
}
|
|
1614
|
-
}
|
|
1611
|
+
const result = await validator.validateTx(tx);
|
|
1612
|
+
return result.result !== 'invalid';
|
|
1615
1613
|
}),
|
|
1616
1614
|
);
|
|
1615
|
+
if (results.some(value => value === false)) {
|
|
1616
|
+
throw new Error('Invalid tx detected');
|
|
1617
|
+
}
|
|
1617
1618
|
}
|
|
1618
1619
|
|
|
1619
|
-
/**
|
|
1620
|
-
|
|
1621
|
-
*
|
|
1622
|
-
* Each validator is a pair of a validator and a severity.
|
|
1623
|
-
* If a validator fails, the peer is penalized with the severity of the validator.
|
|
1624
|
-
*
|
|
1625
|
-
* @param currentBlockNumber - The current synced block number.
|
|
1626
|
-
* @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
|
|
1627
|
-
* @returns The message validators.
|
|
1628
|
-
*/
|
|
1629
|
-
private async createMessageValidators(
|
|
1620
|
+
/** Creates the first stage (fast) validators for gossiped transactions. */
|
|
1621
|
+
protected async createFirstStageMessageValidators(
|
|
1630
1622
|
currentBlockNumber: BlockNumber,
|
|
1631
1623
|
nextSlotTimestamp: UInt64,
|
|
1632
|
-
): Promise<Record<string,
|
|
1624
|
+
): Promise<Record<string, TransactionValidator>> {
|
|
1633
1625
|
const gasFees = await this.getGasFees(currentBlockNumber);
|
|
1634
1626
|
const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
|
|
1627
|
+
const blockNumber = BlockNumber(currentBlockNumber + 1);
|
|
1635
1628
|
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
return createTxMessageValidators(
|
|
1629
|
+
return createFirstStageTxValidationsForGossipedTransactions(
|
|
1639
1630
|
nextSlotTimestamp,
|
|
1640
|
-
|
|
1631
|
+
blockNumber,
|
|
1641
1632
|
this.worldStateSynchronizer,
|
|
1642
1633
|
gasFees,
|
|
1643
1634
|
this.config.l1ChainId,
|
|
1644
1635
|
this.config.rollupVersion,
|
|
1645
1636
|
protocolContractsHash,
|
|
1646
1637
|
this.archiver,
|
|
1647
|
-
this.proofVerifier,
|
|
1648
1638
|
!this.config.disableTransactions,
|
|
1649
1639
|
allowedInSetup,
|
|
1650
1640
|
this.logger.getBindings(),
|
|
1651
1641
|
);
|
|
1652
1642
|
}
|
|
1653
1643
|
|
|
1644
|
+
/** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
|
|
1645
|
+
protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
|
|
1646
|
+
return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1654
1649
|
/**
|
|
1655
1650
|
* Run validations on a tx.
|
|
1656
1651
|
* @param tx - The tx to validate.
|
|
@@ -1659,7 +1654,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1659
1654
|
*/
|
|
1660
1655
|
private async runValidations(
|
|
1661
1656
|
tx: Tx,
|
|
1662
|
-
messageValidators: Record<string,
|
|
1657
|
+
messageValidators: Record<string, TransactionValidator>,
|
|
1663
1658
|
): Promise<ValidationOutcome> {
|
|
1664
1659
|
const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
|
|
1665
1660
|
const { result } = await validator.validateTx(tx);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
|
|
2
2
|
import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { createTxValidatorForReqResponseReceivedTxs } from '../../../msg_validators/index.js';
|
|
5
5
|
|
|
6
6
|
export interface BatchRequestTxValidatorConfig {
|
|
7
7
|
l1ChainId: number;
|
|
@@ -29,7 +29,7 @@ export class BatchRequestTxValidator implements IBatchRequestTxValidator {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
static createRequestedTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
|
|
32
|
-
return
|
|
32
|
+
return createTxValidatorForReqResponseReceivedTxs(config.proofVerifier, {
|
|
33
33
|
l1ChainId: config.l1ChainId,
|
|
34
34
|
rollupVersion: config.rollupVersion,
|
|
35
35
|
});
|
package/src/services/service.ts
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import type { SlotNumber } from '@aztec/foundation/branded-types';
|
|
2
2
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import type { PeerInfo } from '@aztec/stdlib/interfaces/server';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
BlockProposal,
|
|
6
|
+
CheckpointAttestation,
|
|
7
|
+
CheckpointProposalCore,
|
|
8
|
+
Gossipable,
|
|
9
|
+
TopicType,
|
|
10
|
+
} from '@aztec/stdlib/p2p';
|
|
5
11
|
import type { Tx } from '@aztec/stdlib/tx';
|
|
6
12
|
|
|
7
13
|
import type { PeerId } from '@libp2p/interface';
|
|
@@ -130,7 +136,10 @@ export interface P2PService {
|
|
|
130
136
|
|
|
131
137
|
getPeers(includePending?: boolean): PeerInfo[];
|
|
132
138
|
|
|
133
|
-
|
|
139
|
+
/** Returns the number of peers in the GossipSub mesh for a given topic type. */
|
|
140
|
+
getGossipMeshPeerCount(topicType: TopicType): number;
|
|
141
|
+
|
|
142
|
+
validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void>;
|
|
134
143
|
|
|
135
144
|
addReqRespSubProtocol(
|
|
136
145
|
subProtocol: ReqRespSubProtocol,
|
|
@@ -25,7 +25,7 @@ export class TxProvider implements ITxProvider {
|
|
|
25
25
|
constructor(
|
|
26
26
|
private txCollection: TxCollection,
|
|
27
27
|
private txPool: TxPoolV2,
|
|
28
|
-
private
|
|
28
|
+
private blockProposalTransactionValidator: Pick<P2PClient, 'validateTxsReceivedInBlockProposal'>,
|
|
29
29
|
private log: Logger = createLogger('p2p:tx-collector'),
|
|
30
30
|
client: TelemetryClient = getTelemetryClient(),
|
|
31
31
|
) {
|
|
@@ -227,7 +227,7 @@ export class TxProvider implements ITxProvider {
|
|
|
227
227
|
if (txs.length === 0) {
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
|
-
await this.
|
|
230
|
+
await this.blockProposalTransactionValidator.validateTxsReceivedInBlockProposal(txs);
|
|
231
231
|
await this.txPool.addProtectedTxs(txs, blockHeader);
|
|
232
232
|
}
|
|
233
233
|
}
|
|
@@ -270,6 +270,16 @@ class MockGossipSubService extends TypedEventEmitter<GossipsubEvents> implements
|
|
|
270
270
|
{ msgId, propagationSource, acceptance },
|
|
271
271
|
);
|
|
272
272
|
}
|
|
273
|
+
|
|
274
|
+
getMeshPeers(topic?: TopicStr): PeerIdStr[] {
|
|
275
|
+
if (topic && !this.subscribedTopics.has(topic)) {
|
|
276
|
+
return [];
|
|
277
|
+
}
|
|
278
|
+
return this.network
|
|
279
|
+
.getPeers()
|
|
280
|
+
.filter(peer => !this.peerId.equals(peer))
|
|
281
|
+
.map(peer => peer.toString());
|
|
282
|
+
}
|
|
273
283
|
}
|
|
274
284
|
|
|
275
285
|
/**
|
|
@@ -76,7 +76,7 @@ export class InMemoryTxPool extends EventEmitter implements TxPoolV2 {
|
|
|
76
76
|
return Promise.resolve({ accepted, ignored: [], rejected: [] });
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'
|
|
79
|
+
canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
|
|
80
80
|
const key = tx.getTxHash().toString();
|
|
81
81
|
if (this.txsByHash.has(key)) {
|
|
82
82
|
return Promise.resolve('ignored');
|
package/src/util.ts
CHANGED
|
@@ -23,7 +23,13 @@ export interface PubSubLibp2p extends Pick<Libp2p, 'status' | 'start' | 'stop' |
|
|
|
23
23
|
services: {
|
|
24
24
|
pubsub: Pick<
|
|
25
25
|
GossipSub,
|
|
26
|
-
|
|
26
|
+
| 'addEventListener'
|
|
27
|
+
| 'removeEventListener'
|
|
28
|
+
| 'publish'
|
|
29
|
+
| 'subscribe'
|
|
30
|
+
| 'reportMessageValidationResult'
|
|
31
|
+
| 'direct'
|
|
32
|
+
| 'getMeshPeers'
|
|
27
33
|
> & { score: Pick<GossipSub['score'], 'score'> };
|
|
28
34
|
};
|
|
29
35
|
}
|