@aztec/p2p 0.0.1-commit.1142ef1 → 0.0.1-commit.1bea0213
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.js +1 -1
- package/dest/config.js +2 -2
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +20 -9
- package/dest/mem_pools/attestation_pool/mocks.d.ts +4 -2
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/mocks.js +8 -5
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +15 -10
- 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 +91 -50
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +19 -5
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +59 -3
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +79 -5
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +47 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +4 -4
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +2 -0
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +2 -2
- package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +3 -3
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +41 -10
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +11 -4
- package/dest/msg_validators/clock_tolerance.d.ts +21 -0
- package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
- package/dest/msg_validators/clock_tolerance.js +37 -0
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +3 -3
- package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator.js +52 -28
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +3 -3
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -1
- package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +93 -64
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
- package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
- package/dest/msg_validators/tx_validator/gas_validator.js +8 -14
- 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/size_validator.d.ts +6 -0
- package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/size_validator.js +20 -0
- package/dest/services/encoding.d.ts +1 -1
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +2 -3
- package/dest/services/libp2p/instrumentation.js +5 -5
- package/dest/services/libp2p/libp2p_service.d.ts +5 -5
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +26 -26
- package/dest/services/reqresp/constants.d.ts +12 -0
- package/dest/services/reqresp/constants.d.ts.map +1 -0
- package/dest/services/reqresp/constants.js +7 -0
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/block_txs/bitvector.js +7 -0
- package/dest/services/reqresp/protocols/status.d.ts +1 -1
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +2 -1
- package/dest/services/tx_collection/slow_tx_collection.d.ts +3 -3
- package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
- package/dest/services/tx_collection/tx_collection.d.ts +5 -5
- package/dest/services/tx_collection/tx_collection.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/testbench/p2p_client_testbench_worker.js +5 -6
- package/package.json +16 -16
- package/src/client/p2p_client.ts +6 -6
- package/src/config.ts +2 -2
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +17 -9
- package/src/mem_pools/attestation_pool/mocks.ts +6 -4
- package/src/mem_pools/tx_pool/README.md +28 -13
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +130 -75
- package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +66 -5
- package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +119 -4
- package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
- package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +4 -2
- package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -14
- package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +6 -6
- package/src/msg_validators/clock_tolerance.ts +51 -0
- package/src/msg_validators/proposal_validator/proposal_validator.ts +28 -28
- package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +91 -67
- package/src/msg_validators/tx_validator/block_header_validator.ts +3 -1
- package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
- package/src/msg_validators/tx_validator/gas_validator.ts +8 -25
- package/src/msg_validators/tx_validator/index.ts +1 -0
- package/src/msg_validators/tx_validator/size_validator.ts +18 -0
- package/src/services/encoding.ts +2 -3
- package/src/services/libp2p/instrumentation.ts +5 -5
- package/src/services/libp2p/libp2p_service.ts +39 -27
- package/src/services/reqresp/constants.ts +14 -0
- package/src/services/reqresp/protocols/block_txs/bitvector.ts +9 -0
- package/src/services/reqresp/protocols/status.ts +5 -3
- package/src/services/tx_collection/slow_tx_collection.ts +2 -2
- package/src/services/tx_collection/tx_collection.ts +4 -4
- package/src/services/tx_provider.ts +2 -2
- package/src/testbench/p2p_client_testbench_worker.ts +6 -10
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +0 -15
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +0 -1
- package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +0 -88
- package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +0 -108
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
type Gossipable,
|
|
21
21
|
P2PClientType,
|
|
22
22
|
P2PMessage,
|
|
23
|
+
type ValidationResult as P2PValidationResult,
|
|
23
24
|
PeerErrorSeverity,
|
|
24
25
|
TopicType,
|
|
25
26
|
createTopicString,
|
|
@@ -66,6 +67,7 @@ import {
|
|
|
66
67
|
CheckpointAttestationValidator,
|
|
67
68
|
CheckpointProposalValidator,
|
|
68
69
|
FishermanAttestationValidator,
|
|
70
|
+
SizeTxValidator,
|
|
69
71
|
} from '../../msg_validators/index.js';
|
|
70
72
|
import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
|
|
71
73
|
import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
|
|
@@ -923,7 +925,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
923
925
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointAttestation>> = async () => {
|
|
924
926
|
const attestation = CheckpointAttestation.fromBuffer(payloadData);
|
|
925
927
|
const pool = this.mempools.attestationPool;
|
|
926
|
-
const
|
|
928
|
+
const validationResult = await this.validateCheckpointAttestation(source, attestation);
|
|
929
|
+
const isValid = validationResult.result === 'accept';
|
|
927
930
|
const exists = isValid && (await pool.hasCheckpointAttestation(attestation));
|
|
928
931
|
|
|
929
932
|
let canAdd = true;
|
|
@@ -942,9 +945,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
942
945
|
[Attributes.P2P_ID]: source.toString(),
|
|
943
946
|
});
|
|
944
947
|
|
|
945
|
-
if (
|
|
948
|
+
if (validationResult.result === 'reject') {
|
|
946
949
|
return { result: TopicValidatorResult.Reject };
|
|
947
|
-
} else if (exists) {
|
|
950
|
+
} else if (validationResult.result === 'ignore' || exists) {
|
|
948
951
|
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
949
952
|
} else if (!canAdd) {
|
|
950
953
|
this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
|
|
@@ -985,7 +988,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
985
988
|
private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
986
989
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
|
|
987
990
|
const block = BlockProposal.fromBuffer(payloadData);
|
|
988
|
-
const
|
|
991
|
+
const validationResult = await this.validateBlockProposal(source, block);
|
|
992
|
+
const isValid = validationResult.result === 'accept';
|
|
989
993
|
const pool = this.mempools.attestationPool;
|
|
990
994
|
|
|
991
995
|
const exists = isValid && (await pool.hasBlockProposal(block));
|
|
@@ -999,9 +1003,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
999
1003
|
[Attributes.P2P_ID]: source.toString(),
|
|
1000
1004
|
});
|
|
1001
1005
|
|
|
1002
|
-
if (
|
|
1006
|
+
if (validationResult.result === 'reject') {
|
|
1003
1007
|
return { result: TopicValidatorResult.Reject };
|
|
1004
|
-
} else if (exists) {
|
|
1008
|
+
} else if (validationResult.result === 'ignore' || exists) {
|
|
1005
1009
|
return { result: TopicValidatorResult.Ignore, obj: block };
|
|
1006
1010
|
} else if (!canAdd) {
|
|
1007
1011
|
this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
|
|
@@ -1081,7 +1085,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1081
1085
|
// TODO(palla/mbps): This pattern is repeated across multiple message handlers, consider abstracting it.
|
|
1082
1086
|
const validationFunc: () => Promise<ReceivedMessageValidationResult<CheckpointProposal>> = async () => {
|
|
1083
1087
|
const checkpoint = CheckpointProposal.fromBuffer(payloadData);
|
|
1084
|
-
const
|
|
1088
|
+
const validationResult = await this.validateCheckpointProposal(source, checkpoint);
|
|
1089
|
+
const isValid = validationResult.result === 'accept';
|
|
1085
1090
|
const pool = this.mempools.attestationPool;
|
|
1086
1091
|
|
|
1087
1092
|
const exists = isValid && (await pool.hasCheckpointProposal(checkpoint));
|
|
@@ -1095,9 +1100,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1095
1100
|
[Attributes.P2P_ID]: source.toString(),
|
|
1096
1101
|
});
|
|
1097
1102
|
|
|
1098
|
-
if (
|
|
1103
|
+
if (validationResult.result === 'reject') {
|
|
1099
1104
|
return { result: TopicValidatorResult.Reject };
|
|
1100
|
-
} else if (exists) {
|
|
1105
|
+
} else if (validationResult.result === 'ignore' || exists) {
|
|
1101
1106
|
return { result: TopicValidatorResult.Ignore, obj: checkpoint };
|
|
1102
1107
|
} else if (!canAdd) {
|
|
1103
1108
|
this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
|
|
@@ -1370,6 +1375,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1370
1375
|
private createRequestedTxValidator(): TxValidator {
|
|
1371
1376
|
return new AggregateTxValidator(
|
|
1372
1377
|
new DataTxValidator(),
|
|
1378
|
+
new SizeTxValidator(),
|
|
1373
1379
|
new MetadataTxValidator({
|
|
1374
1380
|
l1ChainId: new Fr(this.config.l1ChainId),
|
|
1375
1381
|
rollupVersion: new Fr(this.config.rollupVersion),
|
|
@@ -1574,15 +1580,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1574
1580
|
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
1575
1581
|
[Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
|
|
1576
1582
|
}))
|
|
1577
|
-
public async validateCheckpointAttestation(
|
|
1578
|
-
|
|
1579
|
-
|
|
1583
|
+
public async validateCheckpointAttestation(
|
|
1584
|
+
peerId: PeerId,
|
|
1585
|
+
attestation: CheckpointAttestation,
|
|
1586
|
+
): Promise<P2PValidationResult> {
|
|
1587
|
+
const result = await this.checkpointAttestationValidator.validate(attestation);
|
|
1588
|
+
|
|
1589
|
+
if (result.result === 'reject') {
|
|
1580
1590
|
this.logger.debug(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
|
|
1581
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1582
|
-
return false;
|
|
1591
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1583
1592
|
}
|
|
1584
1593
|
|
|
1585
|
-
return
|
|
1594
|
+
return result;
|
|
1586
1595
|
}
|
|
1587
1596
|
|
|
1588
1597
|
/**
|
|
@@ -1594,15 +1603,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1594
1603
|
@trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
|
|
1595
1604
|
[Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
|
|
1596
1605
|
}))
|
|
1597
|
-
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<
|
|
1598
|
-
const
|
|
1599
|
-
|
|
1606
|
+
public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<P2PValidationResult> {
|
|
1607
|
+
const result = await this.blockProposalValidator.validate(block);
|
|
1608
|
+
|
|
1609
|
+
if (result.result === 'reject') {
|
|
1600
1610
|
this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
|
|
1601
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1602
|
-
return false;
|
|
1611
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1603
1612
|
}
|
|
1604
1613
|
|
|
1605
|
-
return
|
|
1614
|
+
return result;
|
|
1606
1615
|
}
|
|
1607
1616
|
|
|
1608
1617
|
/**
|
|
@@ -1614,15 +1623,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
1614
1623
|
@trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint) => ({
|
|
1615
1624
|
[Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
|
|
1616
1625
|
}))
|
|
1617
|
-
public async validateCheckpointProposal(
|
|
1618
|
-
|
|
1619
|
-
|
|
1626
|
+
public async validateCheckpointProposal(
|
|
1627
|
+
peerId: PeerId,
|
|
1628
|
+
checkpoint: CheckpointProposal,
|
|
1629
|
+
): Promise<P2PValidationResult> {
|
|
1630
|
+
const result = await this.checkpointProposalValidator.validate(checkpoint);
|
|
1631
|
+
|
|
1632
|
+
if (result.result === 'reject') {
|
|
1620
1633
|
this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
|
|
1621
|
-
this.peerManager.penalizePeer(peerId, severity);
|
|
1622
|
-
return false;
|
|
1634
|
+
this.peerManager.penalizePeer(peerId, result.severity);
|
|
1623
1635
|
}
|
|
1624
1636
|
|
|
1625
|
-
return
|
|
1637
|
+
return result;
|
|
1626
1638
|
}
|
|
1627
1639
|
|
|
1628
1640
|
public getPeerScore(peerId: PeerId): number {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for P2P message deserialization bounds checking.
|
|
3
|
+
* These constants define maximum allowed sizes during deserialization
|
|
4
|
+
* to prevent DoS attacks via maliciously crafted messages.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Max transactions per block for deserialization validation (~300x default of 32) */
|
|
8
|
+
export { MAX_TXS_PER_BLOCK } from '@aztec/stdlib/deserialization';
|
|
9
|
+
|
|
10
|
+
/** Max version string length (e.g., "1.0.0-alpha.123") */
|
|
11
|
+
export const MAX_VERSION_STRING_LENGTH = 64;
|
|
12
|
+
|
|
13
|
+
/** Max block hash string length (hex: 0x + 64 chars, with generous headroom) */
|
|
14
|
+
export const MAX_BLOCK_HASH_STRING_LENGTH = 128;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
2
2
|
|
|
3
|
+
import { MAX_TXS_PER_BLOCK } from '../../constants.js';
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
6
|
* BitVector helper class for representing and serializing bit vectors
|
|
5
7
|
*/
|
|
@@ -80,6 +82,13 @@ export class BitVector {
|
|
|
80
82
|
const reader = BufferReader.asReader(buffer);
|
|
81
83
|
const length = reader.readNumber();
|
|
82
84
|
|
|
85
|
+
if (length < 0) {
|
|
86
|
+
throw new Error(`BitVector length ${length} cannot be negative`);
|
|
87
|
+
}
|
|
88
|
+
if (length > MAX_TXS_PER_BLOCK) {
|
|
89
|
+
throw new Error(`BitVector length ${length} exceeds maximum ${MAX_TXS_PER_BLOCK}`);
|
|
90
|
+
}
|
|
91
|
+
|
|
83
92
|
const bitBuffer = reader.readBytes(BitVector.byteLength(length));
|
|
84
93
|
return new BitVector(bitBuffer, length);
|
|
85
94
|
}
|
|
@@ -7,6 +7,8 @@ import type { WorldStateSyncStatus, WorldStateSynchronizer } from '@aztec/stdlib
|
|
|
7
7
|
|
|
8
8
|
import type { PeerId } from '@libp2p/interface';
|
|
9
9
|
|
|
10
|
+
import { MAX_BLOCK_HASH_STRING_LENGTH, MAX_VERSION_STRING_LENGTH } from '../constants.js';
|
|
11
|
+
|
|
10
12
|
/*
|
|
11
13
|
* P2P Status Message
|
|
12
14
|
* It is used to establish Status handshake between to peers
|
|
@@ -32,12 +34,12 @@ export class StatusMessage {
|
|
|
32
34
|
static fromBuffer(buffer: Buffer | BufferReader): StatusMessage {
|
|
33
35
|
const reader = BufferReader.asReader(buffer);
|
|
34
36
|
return new StatusMessage(
|
|
35
|
-
reader.readString(), // compressedComponentsVersion
|
|
37
|
+
reader.readString(MAX_VERSION_STRING_LENGTH), // compressedComponentsVersion
|
|
36
38
|
BlockNumber(reader.readNumber()), // latestBlockNumber
|
|
37
|
-
reader.readString(), // latestBlockHash
|
|
39
|
+
reader.readString(MAX_BLOCK_HASH_STRING_LENGTH), // latestBlockHash
|
|
38
40
|
BlockNumber(reader.readNumber()), // finalizedBlockNumber
|
|
39
41
|
//TODO: add finalizedBlockHash
|
|
40
|
-
//reader.readString(), // finalizedBlockHash
|
|
42
|
+
//reader.readString(MAX_BLOCK_HASH_STRING_LENGTH), // finalizedBlockHash
|
|
41
43
|
);
|
|
42
44
|
}
|
|
43
45
|
|
|
@@ -4,7 +4,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
|
4
4
|
import { boundInclusive } from '@aztec/foundation/number';
|
|
5
5
|
import { RunningPromise } from '@aztec/foundation/promise';
|
|
6
6
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
7
|
-
import type {
|
|
7
|
+
import type { L2Block } from '@aztec/stdlib/block';
|
|
8
8
|
import { type L1RollupConstants, getEpochAtSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
9
9
|
import { type Tx, TxHash } from '@aztec/stdlib/tx';
|
|
10
10
|
|
|
@@ -76,7 +76,7 @@ export class SlowTxCollection {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/** Starts collecting the given tx hashes for the given L2Block in the slow loop */
|
|
79
|
-
public startCollecting(block:
|
|
79
|
+
public startCollecting(block: L2Block, txHashes: TxHash[]) {
|
|
80
80
|
const slot = block.header.getSlot();
|
|
81
81
|
const deadline = this.getDeadlineForSlot(slot);
|
|
82
82
|
if (+deadline < this.dateProvider.now()) {
|
|
@@ -3,7 +3,7 @@ import { compactArray } from '@aztec/foundation/collection';
|
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { type PromiseWithResolvers, RunningPromise } from '@aztec/foundation/promise';
|
|
5
5
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
6
|
-
import type {
|
|
6
|
+
import type { L2Block, L2BlockInfo } from '@aztec/stdlib/block';
|
|
7
7
|
import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
|
|
8
8
|
import type { BlockProposal } from '@aztec/stdlib/p2p';
|
|
9
9
|
import { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
@@ -25,7 +25,7 @@ export type CollectionMethod = 'fast-req-resp' | 'fast-node-rpc' | 'slow-req-res
|
|
|
25
25
|
export type MissingTxInfo = { blockNumber: BlockNumber; deadline: Date; readyForReqResp: boolean };
|
|
26
26
|
|
|
27
27
|
export type FastCollectionRequestInput =
|
|
28
|
-
| { type: 'block'; block:
|
|
28
|
+
| { type: 'block'; block: L2Block }
|
|
29
29
|
| { type: 'proposal'; blockProposal: BlockProposal; blockNumber: BlockNumber };
|
|
30
30
|
|
|
31
31
|
export type FastCollectionRequest = FastCollectionRequestInput & {
|
|
@@ -146,7 +146,7 @@ export class TxCollection {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/** Starts collecting the given tx hashes for the given L2Block in the slow loop */
|
|
149
|
-
public startCollecting(block:
|
|
149
|
+
public startCollecting(block: L2Block, txHashes: TxHash[]) {
|
|
150
150
|
return this.slowCollection.startCollecting(block, txHashes);
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -162,7 +162,7 @@ export class TxCollection {
|
|
|
162
162
|
|
|
163
163
|
/** Collects the set of txs for the given mined block as fast as possible */
|
|
164
164
|
public collectFastForBlock(
|
|
165
|
-
block:
|
|
165
|
+
block: L2Block,
|
|
166
166
|
txHashes: TxHash[] | string[],
|
|
167
167
|
opts: { deadline: Date; pinnedPeer?: PeerId },
|
|
168
168
|
) {
|
|
@@ -2,7 +2,7 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
|
|
|
2
2
|
import { compactArray } from '@aztec/foundation/collection';
|
|
3
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import { elapsed } from '@aztec/foundation/timer';
|
|
5
|
-
import type {
|
|
5
|
+
import type { L2Block, L2BlockInfo } from '@aztec/stdlib/block';
|
|
6
6
|
import type { ITxProvider } from '@aztec/stdlib/interfaces/server';
|
|
7
7
|
import type { BlockProposal } from '@aztec/stdlib/p2p';
|
|
8
8
|
import { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
@@ -68,7 +68,7 @@ export class TxProvider implements ITxProvider {
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/** Gathers txs from the tx pool, remote rpc nodes, and reqresp. */
|
|
71
|
-
public getTxsForBlock(block:
|
|
71
|
+
public getTxsForBlock(block: L2Block, opts: { deadline: Date }): Promise<{ txs: Tx[]; missingTxs: TxHash[] }> {
|
|
72
72
|
return this.getOrderedTxsFromAllSources(
|
|
73
73
|
{ type: 'block', block },
|
|
74
74
|
block.toBlockInfo(),
|
|
@@ -7,7 +7,6 @@ import { MockL2BlockSource } from '@aztec/archiver/test';
|
|
|
7
7
|
import type { EpochCacheInterface } from '@aztec/epoch-cache';
|
|
8
8
|
import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
9
9
|
import { SecretValue } from '@aztec/foundation/config';
|
|
10
|
-
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
11
10
|
import { createLogger } from '@aztec/foundation/log';
|
|
12
11
|
import { sleep } from '@aztec/foundation/sleep';
|
|
13
12
|
import type { DataStoreConfig } from '@aztec/kv-store/config';
|
|
@@ -88,17 +87,14 @@ function mockAttestationPool(): AttestationPool {
|
|
|
88
87
|
|
|
89
88
|
function mockEpochCache(): EpochCacheInterface {
|
|
90
89
|
return {
|
|
91
|
-
getCommittee: () => Promise.resolve({ committee: [], seed: 1n, epoch: EpochNumber.ZERO }),
|
|
90
|
+
getCommittee: () => Promise.resolve({ committee: [], seed: 1n, epoch: EpochNumber.ZERO, isEscapeHatchOpen: false }),
|
|
92
91
|
getProposerIndexEncoding: () => '0x' as `0x${string}`,
|
|
93
|
-
getEpochAndSlotNow: () => ({ epoch: EpochNumber.ZERO, slot: SlotNumber.ZERO, ts: 0n }),
|
|
92
|
+
getEpochAndSlotNow: () => ({ epoch: EpochNumber.ZERO, slot: SlotNumber.ZERO, ts: 0n, nowMs: 0n }),
|
|
94
93
|
computeProposerIndex: () => 0n,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
currentSlot: SlotNumber.ZERO,
|
|
100
|
-
nextSlot: SlotNumber.ZERO,
|
|
101
|
-
}),
|
|
94
|
+
getCurrentAndNextSlot: () => ({
|
|
95
|
+
currentSlot: SlotNumber.ZERO,
|
|
96
|
+
nextSlot: SlotNumber.ZERO,
|
|
97
|
+
}),
|
|
102
98
|
getProposerAttesterAddressInSlot: () => Promise.resolve(undefined),
|
|
103
99
|
getEpochAndSlotInNextL1Slot: () => ({ epoch: EpochNumber.ZERO, slot: SlotNumber.ZERO, ts: 0n, now: 0n }),
|
|
104
100
|
isInCommittee: () => Promise.resolve(false),
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { ReadonlyWorldStateAccess } from '@aztec/stdlib/interfaces/server';
|
|
2
|
-
import type { TxPoolOptions } from '../tx_pool.js';
|
|
3
|
-
import { type EvictionContext, type EvictionResult, type EvictionRule, type TxPoolOperations } from './eviction_strategy.js';
|
|
4
|
-
export declare class InsufficientFeePayerBalanceRule implements EvictionRule {
|
|
5
|
-
private worldState;
|
|
6
|
-
readonly name: string;
|
|
7
|
-
readonly reason: string;
|
|
8
|
-
constructor(worldState: ReadonlyWorldStateAccess);
|
|
9
|
-
private log;
|
|
10
|
-
evict(context: EvictionContext, txPool: TxPoolOperations): Promise<EvictionResult>;
|
|
11
|
-
private evictTxs;
|
|
12
|
-
private createGasTxValidator;
|
|
13
|
-
updateConfig(_config: TxPoolOptions): void;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zdWZmaWNpZW50X2ZlZV9wYXllcl9iYWxhbmNlX3J1bGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9tZW1fcG9vbHMvdHhfcG9vbC9ldmljdGlvbi9pbnN1ZmZpY2llbnRfZmVlX3BheWVyX2JhbGFuY2VfcnVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEtBQUssRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBS2hGLE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQ0wsS0FBSyxlQUFlLEVBRXBCLEtBQUssY0FBYyxFQUNuQixLQUFLLFlBQVksRUFFakIsS0FBSyxnQkFBZ0IsRUFDdEIsTUFBTSx3QkFBd0IsQ0FBQztBQUVoQyxxQkFBYSwrQkFBZ0MsWUFBVyxZQUFZO0lBSS9DLE9BQU8sQ0FBQyxVQUFVO0lBSHJDLFNBQWdCLElBQUksU0FBaUM7SUFDckQsU0FBZ0IsTUFBTSxTQUE0QjtJQUVsRCxZQUEyQixVQUFVLEVBQUUsd0JBQXdCLEVBQUk7SUFFbkUsT0FBTyxDQUFDLEdBQUcsQ0FBMkU7SUFFaEYsS0FBSyxDQUFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxFQUFFLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FrQ3ZGO1lBRWEsUUFBUTtJQXdDdEIsT0FBTyxDQUFDLG9CQUFvQjtJQUk1QixZQUFZLENBQUMsT0FBTyxFQUFFLGFBQWEsR0FBRyxJQUFJLENBQUc7Q0FDOUMifQ==
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"insufficient_fee_payer_balance_rule.d.ts","sourceRoot":"","sources":["../../../../src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAKhF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EACL,KAAK,eAAe,EAEpB,KAAK,cAAc,EACnB,KAAK,YAAY,EAEjB,KAAK,gBAAgB,EACtB,MAAM,wBAAwB,CAAC;AAEhC,qBAAa,+BAAgC,YAAW,YAAY;IAI/C,OAAO,CAAC,UAAU;IAHrC,SAAgB,IAAI,SAAiC;IACrD,SAAgB,MAAM,SAA4B;IAElD,YAA2B,UAAU,EAAE,wBAAwB,EAAI;IAEnE,OAAO,CAAC,GAAG,CAA2E;IAEhF,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,cAAc,CAAC,CAkCvF;YAEa,QAAQ;IAwCtB,OAAO,CAAC,oBAAoB;IAI5B,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAG;CAC9C"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
-
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
3
|
-
import { GasFees } from '@aztec/stdlib/gas';
|
|
4
|
-
import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
|
|
5
|
-
import { GasTxValidator } from '../../../msg_validators/index.js';
|
|
6
|
-
import { EvictionEvent } from './eviction_strategy.js';
|
|
7
|
-
export class InsufficientFeePayerBalanceRule {
|
|
8
|
-
worldState;
|
|
9
|
-
name;
|
|
10
|
-
reason;
|
|
11
|
-
constructor(worldState){
|
|
12
|
-
this.worldState = worldState;
|
|
13
|
-
this.name = 'InsufficientFeePayerBalance';
|
|
14
|
-
this.reason = 'insufficient_fee_juice';
|
|
15
|
-
this.log = createLogger('p2p:mempool:tx_pool:insufficient_fee_payer_balance_rule');
|
|
16
|
-
}
|
|
17
|
-
log;
|
|
18
|
-
async evict(context, txPool) {
|
|
19
|
-
try {
|
|
20
|
-
if (context.event === EvictionEvent.CHAIN_PRUNED) {
|
|
21
|
-
const affectedTxs = await txPool.getPendingTxInfos();
|
|
22
|
-
return this.evictTxs(affectedTxs, context.blockNumber, txPool);
|
|
23
|
-
}
|
|
24
|
-
if (context.event === EvictionEvent.BLOCK_MINED) {
|
|
25
|
-
const affectedTxs = await txPool.getPendingTxsWithFeePayer(context.minedFeePayers);
|
|
26
|
-
// TODO: fix this edge-case
|
|
27
|
-
// This can lead to a race condition if we are catching up in the p2p client.
|
|
28
|
-
// Let's say we have 3 txs for the same fee payer, which get mined in blocks 1, 2, 3.
|
|
29
|
-
// Tx1 consumes fee juice, tx2 increases it, tx3 consumes it again. We see block1 with tx1 first, run this rule, and evict tx3.
|
|
30
|
-
// But tx3 was valid (due to tx2) and mined on block3. And we have just removed from the mempool a tx we needed for proving/reexec.
|
|
31
|
-
// -----
|
|
32
|
-
// Proposed fix: evict only if node is synched
|
|
33
|
-
return this.evictTxs(affectedTxs, context.block.getBlockNumber(), txPool);
|
|
34
|
-
}
|
|
35
|
-
return {
|
|
36
|
-
reason: this.reason,
|
|
37
|
-
success: true,
|
|
38
|
-
txsEvicted: []
|
|
39
|
-
};
|
|
40
|
-
} catch (err) {
|
|
41
|
-
this.log.error('Failed to evict invalid transactions after mining', {
|
|
42
|
-
err
|
|
43
|
-
});
|
|
44
|
-
return {
|
|
45
|
-
reason: this.reason,
|
|
46
|
-
success: false,
|
|
47
|
-
txsEvicted: [],
|
|
48
|
-
error: new Error('Failed to evict invalid txs after mining', {
|
|
49
|
-
cause: err
|
|
50
|
-
})
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
async evictTxs(candidateTxs, blockNumber, txPool) {
|
|
55
|
-
const txsToEvict = [];
|
|
56
|
-
const gasValidator = this.createGasTxValidator(this.worldState.getSnapshot(blockNumber));
|
|
57
|
-
for (const { txHash, isEvictable } of candidateTxs){
|
|
58
|
-
if (!isEvictable) {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
const tx = await txPool.getTxByHash(txHash);
|
|
62
|
-
if (!tx) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
this.log.debug(`Validating tx balance ${txHash}`);
|
|
66
|
-
if ((await gasValidator.validateTxFee(tx)).result === 'invalid') {
|
|
67
|
-
this.log.verbose(`Evicting tx ${txHash} from pool due to an insufficient fee payer balance`);
|
|
68
|
-
txsToEvict.push(txHash);
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (txsToEvict.length > 0) {
|
|
73
|
-
await txPool.deleteTxs(txsToEvict);
|
|
74
|
-
}
|
|
75
|
-
this.log.verbose(`Evicted ${txsToEvict.length} invalid txs after block mined`, {
|
|
76
|
-
txsToEvict
|
|
77
|
-
});
|
|
78
|
-
return {
|
|
79
|
-
reason: this.reason,
|
|
80
|
-
success: true,
|
|
81
|
-
txsEvicted: txsToEvict
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
createGasTxValidator(db) {
|
|
85
|
-
return new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, GasFees.empty());
|
|
86
|
-
}
|
|
87
|
-
updateConfig(_config) {}
|
|
88
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
-
import { ProtocolContractAddress } from '@aztec/protocol-contracts';
|
|
3
|
-
import { GasFees } from '@aztec/stdlib/gas';
|
|
4
|
-
import type { ReadonlyWorldStateAccess } from '@aztec/stdlib/interfaces/server';
|
|
5
|
-
import { DatabasePublicStateSource, type MerkleTreeReadOperations } from '@aztec/stdlib/trees';
|
|
6
|
-
import type { TxHash } from '@aztec/stdlib/tx';
|
|
7
|
-
|
|
8
|
-
import { GasTxValidator } from '../../../msg_validators/index.js';
|
|
9
|
-
import type { TxPoolOptions } from '../tx_pool.js';
|
|
10
|
-
import {
|
|
11
|
-
type EvictionContext,
|
|
12
|
-
EvictionEvent,
|
|
13
|
-
type EvictionResult,
|
|
14
|
-
type EvictionRule,
|
|
15
|
-
type PendingTxInfo,
|
|
16
|
-
type TxPoolOperations,
|
|
17
|
-
} from './eviction_strategy.js';
|
|
18
|
-
|
|
19
|
-
export class InsufficientFeePayerBalanceRule implements EvictionRule {
|
|
20
|
-
public readonly name = 'InsufficientFeePayerBalance';
|
|
21
|
-
public readonly reason = 'insufficient_fee_juice';
|
|
22
|
-
|
|
23
|
-
public constructor(private worldState: ReadonlyWorldStateAccess) {}
|
|
24
|
-
|
|
25
|
-
private log = createLogger('p2p:mempool:tx_pool:insufficient_fee_payer_balance_rule');
|
|
26
|
-
|
|
27
|
-
async evict(context: EvictionContext, txPool: TxPoolOperations): Promise<EvictionResult> {
|
|
28
|
-
try {
|
|
29
|
-
if (context.event === EvictionEvent.CHAIN_PRUNED) {
|
|
30
|
-
const affectedTxs = await txPool.getPendingTxInfos();
|
|
31
|
-
return this.evictTxs(affectedTxs, context.blockNumber, txPool);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (context.event === EvictionEvent.BLOCK_MINED) {
|
|
35
|
-
const affectedTxs = await txPool.getPendingTxsWithFeePayer(context.minedFeePayers);
|
|
36
|
-
|
|
37
|
-
// TODO: fix this edge-case
|
|
38
|
-
// This can lead to a race condition if we are catching up in the p2p client.
|
|
39
|
-
// Let's say we have 3 txs for the same fee payer, which get mined in blocks 1, 2, 3.
|
|
40
|
-
// Tx1 consumes fee juice, tx2 increases it, tx3 consumes it again. We see block1 with tx1 first, run this rule, and evict tx3.
|
|
41
|
-
// But tx3 was valid (due to tx2) and mined on block3. And we have just removed from the mempool a tx we needed for proving/reexec.
|
|
42
|
-
// -----
|
|
43
|
-
// Proposed fix: evict only if node is synched
|
|
44
|
-
return this.evictTxs(affectedTxs, context.block.getBlockNumber(), txPool);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return {
|
|
48
|
-
reason: this.reason,
|
|
49
|
-
success: true,
|
|
50
|
-
txsEvicted: [],
|
|
51
|
-
};
|
|
52
|
-
} catch (err) {
|
|
53
|
-
this.log.error('Failed to evict invalid transactions after mining', { err });
|
|
54
|
-
return {
|
|
55
|
-
reason: this.reason,
|
|
56
|
-
success: false,
|
|
57
|
-
txsEvicted: [],
|
|
58
|
-
error: new Error('Failed to evict invalid txs after mining', { cause: err }),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private async evictTxs(
|
|
64
|
-
candidateTxs: PendingTxInfo[],
|
|
65
|
-
blockNumber: number,
|
|
66
|
-
txPool: TxPoolOperations,
|
|
67
|
-
): Promise<EvictionResult> {
|
|
68
|
-
const txsToEvict: TxHash[] = [];
|
|
69
|
-
const gasValidator = this.createGasTxValidator(this.worldState.getSnapshot(blockNumber));
|
|
70
|
-
|
|
71
|
-
for (const { txHash, isEvictable } of candidateTxs) {
|
|
72
|
-
if (!isEvictable) {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const tx = await txPool.getTxByHash(txHash);
|
|
77
|
-
if (!tx) {
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
this.log.debug(`Validating tx balance ${txHash}`);
|
|
82
|
-
|
|
83
|
-
if ((await gasValidator.validateTxFee(tx)).result === 'invalid') {
|
|
84
|
-
this.log.verbose(`Evicting tx ${txHash} from pool due to an insufficient fee payer balance`);
|
|
85
|
-
txsToEvict.push(txHash);
|
|
86
|
-
continue;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
if (txsToEvict.length > 0) {
|
|
91
|
-
await txPool.deleteTxs(txsToEvict);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
this.log.verbose(`Evicted ${txsToEvict.length} invalid txs after block mined`, { txsToEvict });
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
reason: this.reason,
|
|
98
|
-
success: true,
|
|
99
|
-
txsEvicted: txsToEvict,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
private createGasTxValidator(db: MerkleTreeReadOperations): GasTxValidator {
|
|
104
|
-
return new GasTxValidator(new DatabasePublicStateSource(db), ProtocolContractAddress.FeeJuice, GasFees.empty());
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
updateConfig(_config: TxPoolOptions): void {}
|
|
108
|
-
}
|