@aztec/p2p 3.0.0-nightly.20251026 → 3.0.0-nightly.20251031
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/mem_pools/attestation_pool/attestation_pool.d.ts +15 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +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 +32 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +2 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +16 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +2 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +22 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +1 -0
- 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 +8 -2
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +1 -0
- 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 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +6 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/services/encoding.d.ts +24 -3
- package/dest/services/encoding.d.ts.map +1 -1
- package/dest/services/encoding.js +73 -5
- package/dest/services/libp2p/libp2p_service.d.ts +15 -8
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +78 -26
- package/dest/services/reqresp/reqresp.js +2 -2
- package/dest/testbench/p2p_client_testbench_worker.js +4 -1
- package/dest/testbench/testbench.js +2 -2
- package/package.json +14 -14
- package/src/mem_pools/attestation_pool/attestation_pool.ts +17 -0
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +37 -0
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +21 -0
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +28 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +7 -2
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +5 -0
- package/src/mem_pools/tx_pool/tx_pool.ts +7 -0
- package/src/services/encoding.ts +80 -5
- package/src/services/libp2p/libp2p_service.ts +75 -24
- package/src/services/reqresp/reqresp.ts +2 -2
- package/src/testbench/p2p_client_testbench_worker.ts +3 -0
- package/src/testbench/testbench.ts +2 -2
|
@@ -107,6 +107,11 @@ interface ValidationResult {
|
|
|
107
107
|
|
|
108
108
|
type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
|
|
109
109
|
|
|
110
|
+
// REFACTOR: Unify with the type above
|
|
111
|
+
type ReceivedMessageValidationResult<T> =
|
|
112
|
+
| { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject> }
|
|
113
|
+
| { obj?: undefined; result: TopicValidatorResult.Reject };
|
|
114
|
+
|
|
110
115
|
/**
|
|
111
116
|
* Lib P2P implementation of the P2PService interface.
|
|
112
117
|
*/
|
|
@@ -615,6 +620,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
615
620
|
return result.recipients.length;
|
|
616
621
|
}
|
|
617
622
|
|
|
623
|
+
/**
|
|
624
|
+
* Checks if this message has already been seen, based on its msgId computed from hashing the message data.
|
|
625
|
+
* Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
|
|
626
|
+
* messages to avoid tx echoes across the network.
|
|
627
|
+
*/
|
|
618
628
|
protected preValidateReceivedMessage(
|
|
619
629
|
msg: Message,
|
|
620
630
|
msgId: string,
|
|
@@ -678,42 +688,57 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
678
688
|
}
|
|
679
689
|
|
|
680
690
|
protected async validateReceivedMessage<T>(
|
|
681
|
-
validationFunc: () => Promise<
|
|
691
|
+
validationFunc: () => Promise<ReceivedMessageValidationResult<T>>,
|
|
682
692
|
msgId: string,
|
|
683
693
|
source: PeerId,
|
|
684
694
|
topicType: TopicType,
|
|
685
|
-
): Promise<
|
|
686
|
-
let resultAndObj:
|
|
695
|
+
): Promise<ReceivedMessageValidationResult<T>> {
|
|
696
|
+
let resultAndObj: ReceivedMessageValidationResult<T> = { result: TopicValidatorResult.Reject };
|
|
687
697
|
const timer = new Timer();
|
|
688
698
|
try {
|
|
689
699
|
resultAndObj = await validationFunc();
|
|
690
700
|
} catch (err) {
|
|
691
|
-
this.logger.error(`Error deserializing and validating message
|
|
701
|
+
this.logger.error(`Error deserializing and validating gossipsub message`, err, {
|
|
702
|
+
msgId,
|
|
703
|
+
source: source.toString(),
|
|
704
|
+
topicType,
|
|
705
|
+
});
|
|
692
706
|
}
|
|
693
707
|
|
|
694
|
-
if (resultAndObj.result) {
|
|
708
|
+
if (resultAndObj.result === TopicValidatorResult.Accept) {
|
|
695
709
|
this.instrumentation.recordMessageValidation(topicType, timer);
|
|
696
710
|
}
|
|
697
711
|
|
|
698
|
-
this.node.services.pubsub.reportMessageValidationResult(
|
|
699
|
-
msgId,
|
|
700
|
-
source.toString(),
|
|
701
|
-
resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject,
|
|
702
|
-
);
|
|
712
|
+
this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
|
|
703
713
|
return resultAndObj;
|
|
704
714
|
}
|
|
705
715
|
|
|
706
716
|
protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
|
|
707
|
-
const validationFunc = async () => {
|
|
717
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
|
|
708
718
|
const tx = Tx.fromBuffer(payloadData);
|
|
709
|
-
const
|
|
710
|
-
|
|
719
|
+
const isValid = await this.validatePropagatedTx(tx, source);
|
|
720
|
+
const exists = isValid && (await this.mempools.txPool.hasTx(tx.getTxHash()));
|
|
721
|
+
|
|
722
|
+
this.logger.trace(`Validate propagated tx`, {
|
|
723
|
+
isValid,
|
|
724
|
+
exists,
|
|
725
|
+
[Attributes.P2P_ID]: source.toString(),
|
|
726
|
+
});
|
|
727
|
+
|
|
728
|
+
if (!isValid) {
|
|
729
|
+
return { result: TopicValidatorResult.Reject };
|
|
730
|
+
} else if (exists) {
|
|
731
|
+
return { result: TopicValidatorResult.Ignore, obj: tx };
|
|
732
|
+
} else {
|
|
733
|
+
return { result: TopicValidatorResult.Accept, obj: tx };
|
|
734
|
+
}
|
|
711
735
|
};
|
|
712
736
|
|
|
713
737
|
const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source, TopicType.tx);
|
|
714
|
-
if (
|
|
738
|
+
if (result !== TopicValidatorResult.Accept || !tx) {
|
|
715
739
|
return;
|
|
716
740
|
}
|
|
741
|
+
|
|
717
742
|
const txHash = tx.getTxHash();
|
|
718
743
|
const txHashString = txHash.toString();
|
|
719
744
|
this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
|
|
@@ -722,7 +747,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
722
747
|
});
|
|
723
748
|
|
|
724
749
|
if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
|
|
725
|
-
this.logger.
|
|
750
|
+
this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
|
|
726
751
|
return;
|
|
727
752
|
}
|
|
728
753
|
|
|
@@ -736,14 +761,25 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
736
761
|
* @param attestation - The attestation to process.
|
|
737
762
|
*/
|
|
738
763
|
private async processAttestationFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
739
|
-
const validationFunc = async () => {
|
|
764
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockAttestation>> = async () => {
|
|
740
765
|
const attestation = BlockAttestation.fromBuffer(payloadData);
|
|
741
|
-
const
|
|
742
|
-
this.
|
|
766
|
+
const isValid = await this.validateAttestation(source, attestation);
|
|
767
|
+
const exists = isValid && (await this.mempools.attestationPool!.hasAttestation(attestation));
|
|
768
|
+
|
|
769
|
+
this.logger.trace(`Validate propagated block attestation`, {
|
|
770
|
+
isValid,
|
|
771
|
+
exists,
|
|
743
772
|
[Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
|
|
744
773
|
[Attributes.P2P_ID]: source.toString(),
|
|
745
774
|
});
|
|
746
|
-
|
|
775
|
+
|
|
776
|
+
if (!isValid) {
|
|
777
|
+
return { result: TopicValidatorResult.Reject };
|
|
778
|
+
} else if (exists) {
|
|
779
|
+
return { result: TopicValidatorResult.Ignore, obj: attestation };
|
|
780
|
+
} else {
|
|
781
|
+
return { result: TopicValidatorResult.Accept, obj: attestation };
|
|
782
|
+
}
|
|
747
783
|
};
|
|
748
784
|
|
|
749
785
|
const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
|
|
@@ -752,9 +788,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
752
788
|
source,
|
|
753
789
|
TopicType.block_attestation,
|
|
754
790
|
);
|
|
755
|
-
|
|
791
|
+
|
|
792
|
+
if (result !== TopicValidatorResult.Accept || !attestation) {
|
|
756
793
|
return;
|
|
757
794
|
}
|
|
795
|
+
|
|
758
796
|
this.logger.debug(
|
|
759
797
|
`Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`,
|
|
760
798
|
{
|
|
@@ -764,18 +802,30 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
764
802
|
source: source.toString(),
|
|
765
803
|
},
|
|
766
804
|
);
|
|
805
|
+
|
|
767
806
|
await this.mempools.attestationPool!.addAttestations([attestation]);
|
|
768
807
|
}
|
|
769
808
|
|
|
770
809
|
private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
|
|
771
|
-
const validationFunc = async () => {
|
|
810
|
+
const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
|
|
772
811
|
const block = BlockProposal.fromBuffer(payloadData);
|
|
773
|
-
const
|
|
774
|
-
this.
|
|
812
|
+
const isValid = await this.validateBlockProposal(source, block);
|
|
813
|
+
const exists = isValid && (await this.mempools.attestationPool!.hasBlockProposal(block));
|
|
814
|
+
|
|
815
|
+
this.logger.trace(`Validate propagated block proposal`, {
|
|
816
|
+
isValid,
|
|
817
|
+
exists,
|
|
775
818
|
[Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
|
|
776
819
|
[Attributes.P2P_ID]: source.toString(),
|
|
777
820
|
});
|
|
778
|
-
|
|
821
|
+
|
|
822
|
+
if (!isValid) {
|
|
823
|
+
return { result: TopicValidatorResult.Reject };
|
|
824
|
+
} else if (exists) {
|
|
825
|
+
return { result: TopicValidatorResult.Ignore, obj: block };
|
|
826
|
+
} else {
|
|
827
|
+
return { result: TopicValidatorResult.Accept, obj: block };
|
|
828
|
+
}
|
|
779
829
|
};
|
|
780
830
|
|
|
781
831
|
const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
|
|
@@ -784,6 +834,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
|
|
|
784
834
|
source,
|
|
785
835
|
TopicType.block_proposal,
|
|
786
836
|
);
|
|
837
|
+
|
|
787
838
|
if (!result || !block) {
|
|
788
839
|
return;
|
|
789
840
|
}
|
|
@@ -489,7 +489,7 @@ export class ReqResp implements ReqRespInterface {
|
|
|
489
489
|
}
|
|
490
490
|
|
|
491
491
|
const messageData = Buffer.concat(chunks);
|
|
492
|
-
const message: Buffer = this.snappyTransform.
|
|
492
|
+
const message: Buffer = this.snappyTransform.inboundTransformData(messageData);
|
|
493
493
|
|
|
494
494
|
return {
|
|
495
495
|
status: status ?? ReqRespStatus.UNKNOWN,
|
|
@@ -618,7 +618,7 @@ export class ReqResp implements ReqRespInterface {
|
|
|
618
618
|
stream.metadata.written = true; // Mark the stream as written to;
|
|
619
619
|
|
|
620
620
|
yield SUCCESS;
|
|
621
|
-
yield snappy.
|
|
621
|
+
yield snappy.outboundTransformData(response);
|
|
622
622
|
}
|
|
623
623
|
},
|
|
624
624
|
stream.sink,
|
|
@@ -52,6 +52,7 @@ function mockTxPool(): TxPool {
|
|
|
52
52
|
getTxStatus: () => Promise.resolve(TxStatus.PENDING),
|
|
53
53
|
getTxsByHash: () => Promise.resolve([]),
|
|
54
54
|
hasTxs: () => Promise.resolve([]),
|
|
55
|
+
hasTx: () => Promise.resolve(false),
|
|
55
56
|
updateConfig: () => {},
|
|
56
57
|
markTxsAsNonEvictable: () => Promise.resolve(),
|
|
57
58
|
cleanupDeletedMinedTxs: () => Promise.resolve(0),
|
|
@@ -71,6 +72,8 @@ function mockAttestationPool(): AttestationPool {
|
|
|
71
72
|
getAttestationsForSlotAndProposal: () => Promise.resolve([]),
|
|
72
73
|
addBlockProposal: () => Promise.resolve(),
|
|
73
74
|
getBlockProposal: () => Promise.resolve(undefined),
|
|
75
|
+
hasBlockProposal: () => Promise.resolve(false),
|
|
76
|
+
hasAttestation: () => Promise.resolve(false),
|
|
74
77
|
};
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
2
|
import { sleep } from '@aztec/foundation/sleep';
|
|
3
|
-
import {
|
|
3
|
+
import { ChonkProof } from '@aztec/stdlib/proofs';
|
|
4
4
|
import { mockTx } from '@aztec/stdlib/testing';
|
|
5
5
|
|
|
6
6
|
import assert from 'assert';
|
|
@@ -35,7 +35,7 @@ async function main() {
|
|
|
35
35
|
|
|
36
36
|
// Send tx from client 0
|
|
37
37
|
const tx = await mockTx(1, {
|
|
38
|
-
|
|
38
|
+
chonkProof: ChonkProof.random(),
|
|
39
39
|
});
|
|
40
40
|
|
|
41
41
|
workerClientManager.processes[0].send({ type: 'SEND_TX', tx: tx.toBuffer() });
|