@aztec/p2p 0.87.7 → 1.0.0-nightly.20250605
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/interface.d.ts +4 -3
- package/dest/client/interface.d.ts.map +1 -1
- package/dest/client/p2p_client.d.ts +5 -5
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +10 -9
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +1 -1
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +1 -1
- 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 +3 -2
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +1 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +2 -1
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
- package/dest/msg_validators/attestation_validator/attestation_validator.js +1 -1
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +1 -1
- package/dest/msg_validators/tx_validator/data_validator.js +4 -4
- package/dest/services/dummy_service.d.ts +3 -3
- package/dest/services/dummy_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
- package/dest/services/libp2p/libp2p_service.js +15 -12
- package/dest/services/peer-manager/peer_manager.d.ts +16 -3
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
- package/dest/services/peer-manager/peer_manager.js +42 -2
- package/dest/services/reqresp/interface.d.ts.map +1 -1
- package/dest/services/reqresp/interface.js +3 -2
- package/dest/services/reqresp/protocols/status.d.ts +35 -4
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
- package/dest/services/reqresp/protocols/status.js +59 -5
- package/dest/services/service.d.ts +1 -1
- package/dest/services/service.d.ts.map +1 -1
- package/dest/services/tx_collector.d.ts +4 -2
- package/dest/services/tx_collector.d.ts.map +1 -1
- package/dest/services/tx_collector.js +41 -48
- package/dest/test-helpers/make-test-p2p-clients.d.ts +21 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
- package/dest/test-helpers/make-test-p2p-clients.js +47 -2
- package/dest/test-helpers/reqresp-nodes.js +2 -2
- package/dest/testbench/p2p_client_testbench_worker.js +16 -3
- package/package.json +12 -12
- package/src/client/interface.ts +4 -3
- package/src/client/p2p_client.ts +12 -11
- package/src/mem_pools/attestation_pool/attestation_pool.ts +1 -1
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +10 -3
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +2 -2
- package/src/mem_pools/tx_pool/tx_pool.ts +2 -1
- package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +1 -1
- package/src/msg_validators/tx_validator/data_validator.ts +4 -4
- package/src/services/dummy_service.ts +8 -5
- package/src/services/libp2p/libp2p_service.ts +25 -15
- package/src/services/peer-manager/peer_manager.ts +48 -2
- package/src/services/reqresp/interface.ts +3 -2
- package/src/services/reqresp/protocols/status.ts +91 -5
- package/src/services/service.ts +4 -1
- package/src/services/tx_collector.ts +65 -67
- package/src/test-helpers/make-test-p2p-clients.ts +61 -3
- package/src/test-helpers/reqresp-nodes.ts +2 -2
- package/src/testbench/p2p_client_testbench_worker.ts +18 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import { L2Block } from '@aztec/stdlib/block';
|
|
3
3
|
import { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
4
|
+
import { StatusMessage } from './protocols/status.js';
|
|
4
5
|
/*
|
|
5
6
|
* Request Response Sub Protocols
|
|
6
7
|
*/ export const PING_PROTOCOL = '/aztec/req/ping/0.1.0';
|
|
@@ -66,8 +67,8 @@ export const DEFAULT_SUB_PROTOCOL_VALIDATORS = {
|
|
|
66
67
|
response: RequestableBuffer
|
|
67
68
|
},
|
|
68
69
|
[ReqRespSubProtocol.STATUS]: {
|
|
69
|
-
request:
|
|
70
|
-
response:
|
|
70
|
+
request: StatusMessage,
|
|
71
|
+
response: StatusMessage
|
|
71
72
|
},
|
|
72
73
|
[ReqRespSubProtocol.TX]: {
|
|
73
74
|
request: TxHash,
|
|
@@ -1,7 +1,38 @@
|
|
|
1
|
+
import { BufferReader } from '@aztec/foundation/serialize';
|
|
2
|
+
import type { WorldStateSyncStatus, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
|
|
3
|
+
import type { PeerId } from '@libp2p/interface';
|
|
4
|
+
export declare class StatusMessage {
|
|
5
|
+
readonly compressedComponentsVersion: string;
|
|
6
|
+
readonly latestBlockNumber: number;
|
|
7
|
+
readonly latestBlockHash: string;
|
|
8
|
+
readonly finalisedBlockNumber: number;
|
|
9
|
+
constructor(compressedComponentsVersion: string, latestBlockNumber: number, latestBlockHash: string, finalisedBlockNumber: number);
|
|
10
|
+
/**
|
|
11
|
+
* Deserializes the StatusMessage object from a Buffer.
|
|
12
|
+
* @param buffer - Buffer or BufferReader object to deserialize.
|
|
13
|
+
* @returns An instance of StatusMessage.
|
|
14
|
+
*/
|
|
15
|
+
static fromBuffer(buffer: Buffer | BufferReader): StatusMessage;
|
|
16
|
+
/**
|
|
17
|
+
* Serializes the StatusMessage object into a Buffer.
|
|
18
|
+
* @returns Buffer representation of the StatusMessage object.
|
|
19
|
+
*/
|
|
20
|
+
toBuffer(): Buffer<ArrayBufferLike>;
|
|
21
|
+
/**
|
|
22
|
+
* Builds Status message
|
|
23
|
+
* @param version - Compressed Components Version
|
|
24
|
+
* @param worldStateSyncStatus - Info about the current sync status
|
|
25
|
+
* @returns StatusMessage instance
|
|
26
|
+
*/
|
|
27
|
+
static fromWorldStateSyncStatus(version: string, syncStatus: WorldStateSyncStatus): StatusMessage;
|
|
28
|
+
validate(peerStatus: StatusMessage): boolean;
|
|
29
|
+
}
|
|
1
30
|
/**
|
|
2
|
-
* Handles the status request.
|
|
3
|
-
* @param
|
|
4
|
-
* @
|
|
31
|
+
* Handles the status request. By immediately responding with the current node status.
|
|
32
|
+
* @param compressedComponentsVersion - Compressed Components Version
|
|
33
|
+
* @param worldStateSynchronizer - World State Synchronizer to fetch the sync status from.
|
|
34
|
+
* Note the WorldStateSynchronizer must be injected to fetch the fresh sync status, we cannot pass in pre-built StatusMessage.
|
|
35
|
+
* @returns Status message handler
|
|
5
36
|
*/
|
|
6
|
-
export declare function
|
|
37
|
+
export declare function reqRespStatusHandler(compressedComponentsVersion: string, worldStateSynchronizer: WorldStateSynchronizer): (_peerId: PeerId, _msg: Buffer) => Promise<Buffer<ArrayBufferLike>>;
|
|
7
38
|
//# sourceMappingURL=status.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../../src/services/reqresp/protocols/status.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../../src/services/reqresp/protocols/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AAC9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEpG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAQhD,qBAAa,aAAa;IAEtB,QAAQ,CAAC,2BAA2B,EAAE,MAAM;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,MAAM;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM;IAChC,QAAQ,CAAC,oBAAoB,EAAE,MAAM;gBAH5B,2BAA2B,EAAE,MAAM,EACnC,iBAAiB,EAAE,MAAM,EACzB,eAAe,EAAE,MAAM,EACvB,oBAAoB,EAAE,MAAM;IAKvC;;;;OAIG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,aAAa;IAY/D;;;OAGG;IACH,QAAQ;IAWR;;;;;OAKG;IACH,MAAM,CAAC,wBAAwB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,oBAAoB,GAAG,aAAa;IAUjG,QAAQ,CAAC,UAAU,EAAE,aAAa,GAAG,OAAO;CAI7C;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,2BAA2B,EAAE,MAAM,EACnC,sBAAsB,EAAE,sBAAsB,IAEhC,SAAS,MAAM,EAAE,MAAM,MAAM,sCAO5C"}
|
|
@@ -1,7 +1,61 @@
|
|
|
1
|
+
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
2
|
+
/*
|
|
3
|
+
* P2P Status Message
|
|
4
|
+
* It is used to establish Status handshake between to peers
|
|
5
|
+
* By validating Status handshake we ensure peers are on the same Blockchain fork
|
|
6
|
+
* And get peer sync status
|
|
7
|
+
*/ export class StatusMessage {
|
|
8
|
+
compressedComponentsVersion;
|
|
9
|
+
latestBlockNumber;
|
|
10
|
+
latestBlockHash;
|
|
11
|
+
finalisedBlockNumber;
|
|
12
|
+
constructor(compressedComponentsVersion, latestBlockNumber, latestBlockHash, finalisedBlockNumber){
|
|
13
|
+
this.compressedComponentsVersion = compressedComponentsVersion;
|
|
14
|
+
this.latestBlockNumber = latestBlockNumber;
|
|
15
|
+
this.latestBlockHash = latestBlockHash;
|
|
16
|
+
this.finalisedBlockNumber = finalisedBlockNumber;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Deserializes the StatusMessage object from a Buffer.
|
|
20
|
+
* @param buffer - Buffer or BufferReader object to deserialize.
|
|
21
|
+
* @returns An instance of StatusMessage.
|
|
22
|
+
*/ static fromBuffer(buffer) {
|
|
23
|
+
const reader = BufferReader.asReader(buffer);
|
|
24
|
+
return new StatusMessage(reader.readString(), reader.readNumber(), reader.readString(), reader.readNumber());
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Serializes the StatusMessage object into a Buffer.
|
|
28
|
+
* @returns Buffer representation of the StatusMessage object.
|
|
29
|
+
*/ toBuffer() {
|
|
30
|
+
return serializeToBuffer([
|
|
31
|
+
this.compressedComponentsVersion,
|
|
32
|
+
this.latestBlockNumber,
|
|
33
|
+
this.latestBlockHash,
|
|
34
|
+
this.finalisedBlockNumber
|
|
35
|
+
]);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Builds Status message
|
|
39
|
+
* @param version - Compressed Components Version
|
|
40
|
+
* @param worldStateSyncStatus - Info about the current sync status
|
|
41
|
+
* @returns StatusMessage instance
|
|
42
|
+
*/ static fromWorldStateSyncStatus(version, syncStatus) {
|
|
43
|
+
return new StatusMessage(version, syncStatus.latestBlockNumber, syncStatus.latestBlockHash, syncStatus.finalisedBlockNumber);
|
|
44
|
+
}
|
|
45
|
+
validate(peerStatus) {
|
|
46
|
+
// TODO: Validate other fields as well
|
|
47
|
+
return this.compressedComponentsVersion === peerStatus.compressedComponentsVersion;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
1
50
|
/**
|
|
2
|
-
* Handles the status request.
|
|
3
|
-
* @param
|
|
4
|
-
* @
|
|
5
|
-
|
|
6
|
-
|
|
51
|
+
* Handles the status request. By immediately responding with the current node status.
|
|
52
|
+
* @param compressedComponentsVersion - Compressed Components Version
|
|
53
|
+
* @param worldStateSynchronizer - World State Synchronizer to fetch the sync status from.
|
|
54
|
+
* Note the WorldStateSynchronizer must be injected to fetch the fresh sync status, we cannot pass in pre-built StatusMessage.
|
|
55
|
+
* @returns Status message handler
|
|
56
|
+
*/ export function reqRespStatusHandler(compressedComponentsVersion, worldStateSynchronizer) {
|
|
57
|
+
return async (_peerId, _msg)=>{
|
|
58
|
+
const status = StatusMessage.fromWorldStateSyncStatus(compressedComponentsVersion, (await worldStateSynchronizer.status()).syncSummary);
|
|
59
|
+
return Promise.resolve(status.toBuffer());
|
|
60
|
+
};
|
|
7
61
|
}
|
|
@@ -9,7 +9,7 @@ export declare enum PeerDiscoveryState {
|
|
|
9
9
|
RUNNING = "running",
|
|
10
10
|
STOPPED = "stopped"
|
|
11
11
|
}
|
|
12
|
-
export type P2PBlockReceivedCallback = (block: BlockProposal, sender: PeerId) => Promise<BlockAttestation | undefined>;
|
|
12
|
+
export type P2PBlockReceivedCallback = (block: BlockProposal, sender: PeerId) => Promise<BlockAttestation[] | undefined>;
|
|
13
13
|
/**
|
|
14
14
|
* The interface for a P2P service implementation.
|
|
15
15
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/services/service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACrF,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAE3C,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,KAAK,YAAY,MAAM,QAAQ,CAAC;AAEvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEjF,oBAAY,kBAAkB;IAC5B,OAAO,YAAY;IACnB,OAAO,YAAY;CACpB;AAED,MAAM,MAAM,wBAAwB,GAAG,
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/services/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { type Logger } from '@aztec/foundation/log';
|
|
2
2
|
import type { BlockProposal } from '@aztec/stdlib/p2p';
|
|
3
3
|
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
4
|
+
import type { PeerId } from '@libp2p/interface';
|
|
4
5
|
import type { P2PClient } from '../client/p2p_client.js';
|
|
5
6
|
export declare class TxCollector {
|
|
6
7
|
private p2pClient;
|
|
7
8
|
private log;
|
|
8
|
-
constructor(p2pClient: Pick<P2PClient, 'getTxsByHashFromPool' | 'hasTxsInPool' | 'getTxsByHash' | 'validate' | 'requestTxsByHash'>, log?: Logger);
|
|
9
|
-
|
|
9
|
+
constructor(p2pClient: Pick<P2PClient, 'getTxsByHashFromPool' | 'hasTxsInPool' | 'getTxsByHash' | 'validate' | 'requestTxsByHash' | 'addTxsToPool'>, log?: Logger);
|
|
10
|
+
private collectFromProposal;
|
|
11
|
+
collectForBlockProposal(proposal: BlockProposal, peerWhoSentTheProposal: PeerId | undefined): Promise<{
|
|
10
12
|
txs: Tx[];
|
|
11
13
|
missing?: TxHash[];
|
|
12
14
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tx_collector.d.ts","sourceRoot":"","sources":["../../src/services/tx_collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,qBAAa,WAAW;IAEpB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;gBAJH,SAAS,EAAE,IAAI,CACrB,SAAS,EACT,sBAAsB,GAAG,cAAc,GAAG,cAAc,GAAG,UAAU,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"tx_collector.d.ts","sourceRoot":"","sources":["../../src/services/tx_collector.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,qBAAa,WAAW;IAEpB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,GAAG;gBAJH,SAAS,EAAE,IAAI,CACrB,SAAS,EACT,sBAAsB,GAAG,cAAc,GAAG,cAAc,GAAG,UAAU,GAAG,kBAAkB,GAAG,cAAc,CAC5G,EACO,GAAG,GAAE,MAAyC;YAI1C,mBAAmB;IAqD3B,uBAAuB,CAC3B,QAAQ,EAAE,aAAa,EACvB,sBAAsB,EAAE,MAAM,GAAG,SAAS,GACzC,OAAO,CAAC;QAAE,GAAG,EAAE,EAAE,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAyB9C"}
|
|
@@ -7,6 +7,42 @@ export class TxCollector {
|
|
|
7
7
|
this.p2pClient = p2pClient;
|
|
8
8
|
this.log = log;
|
|
9
9
|
}
|
|
10
|
+
// Checks the proposal for transactions we don't already have, validates them and adds them to our pool
|
|
11
|
+
async collectFromProposal(proposal) {
|
|
12
|
+
// Does this proposal have any transactions?
|
|
13
|
+
if (!proposal.txs || proposal.txs.length === 0) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const proposalHashes = new Set((proposal.payload.txHashes ?? []).map((txHash)=>txHash.toString()));
|
|
17
|
+
// Get the transactions from the proposal and their hashes
|
|
18
|
+
// also, we are only interested in txs that are part of the proposal
|
|
19
|
+
const txsFromProposal = compactArray(await Promise.all(proposal.txs.map((tx)=>tx === undefined ? Promise.resolve(undefined) : tx.getTxHash().then((hash)=>({
|
|
20
|
+
txHash: hash,
|
|
21
|
+
tx
|
|
22
|
+
}))))).filter((tx)=>proposalHashes.has(tx.txHash.toString()));
|
|
23
|
+
// Of the transactions from the proposal, retrieve those that we have in the pool already
|
|
24
|
+
const txsToValidate = [];
|
|
25
|
+
const txsWeAlreadyHave = await this.p2pClient.getTxsByHashFromPool(txsFromProposal.map((tx)=>tx.txHash));
|
|
26
|
+
// Txs we already have will have holes where we did not find them
|
|
27
|
+
// Where that is the case we need to validate the tx in the proposal
|
|
28
|
+
for(let i = 0; i < txsWeAlreadyHave.length; i++){
|
|
29
|
+
if (txsWeAlreadyHave[i] === undefined) {
|
|
30
|
+
txsToValidate.push(txsFromProposal[i].tx);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Now validate all the transactions from the proposal that we don't have
|
|
34
|
+
// This will throw if any of the transactions are invalid, this is probably correct, if someone sends us a proposal with invalid
|
|
35
|
+
// transactions we probably shouldn't spend any more effort on it
|
|
36
|
+
try {
|
|
37
|
+
await this.p2pClient.validate(txsToValidate);
|
|
38
|
+
} catch (err) {
|
|
39
|
+
this.log.error(`Received proposal with invalid transactions, skipping`);
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
// Now store these transactions in our pool, provided these are the txs in proposal.payload.txHashes they will be pinned already
|
|
43
|
+
await this.p2pClient.addTxsToPool(txsToValidate);
|
|
44
|
+
this.log.info(`Received proposal with ${proposal.txs.length} transactions, ${txsToValidate.length} of which were new`);
|
|
45
|
+
}
|
|
10
46
|
async collectForBlockProposal(proposal, peerWhoSentTheProposal) {
|
|
11
47
|
if (proposal.payload.txHashes.length === 0) {
|
|
12
48
|
this.log.verbose(`Received block proposal with no transactions, skipping transaction availability check`);
|
|
@@ -14,60 +50,17 @@ export class TxCollector {
|
|
|
14
50
|
txs: []
|
|
15
51
|
};
|
|
16
52
|
}
|
|
17
|
-
//
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.log.info(`Using new style proposal with ${proposal.txs.length} transactions`);
|
|
21
|
-
// Request from the pool based on the signed hashes in the payload
|
|
22
|
-
const hashesFromPayload = proposal.payload.txHashes;
|
|
23
|
-
const txsToUse = await this.p2pClient.getTxsByHashFromPool(hashesFromPayload);
|
|
24
|
-
const missingTxs = txsToUse.filter((tx)=>tx === undefined).length;
|
|
25
|
-
if (missingTxs > 0) {
|
|
26
|
-
this.log.verbose(`Missing ${missingTxs}/${hashesFromPayload.length} transactions in the tx pool, will attempt to take from the proposal`);
|
|
27
|
-
}
|
|
28
|
-
let usedFromProposal = 0;
|
|
29
|
-
// Fill any holes with txs in the proposal, provided their hash matches the hash in the payload
|
|
30
|
-
for(let i = 0; i < txsToUse.length; i++){
|
|
31
|
-
if (txsToUse[i] === undefined) {
|
|
32
|
-
// We don't have the transaction, take from the proposal, provided the hash is the same
|
|
33
|
-
const hashOfTxInProposal = await proposal.txs[i].getTxHash();
|
|
34
|
-
if (hashOfTxInProposal.equals(hashesFromPayload[i])) {
|
|
35
|
-
// Hash is equal, we can use the tx from the proposal
|
|
36
|
-
txsToUse[i] = proposal.txs[i];
|
|
37
|
-
usedFromProposal++;
|
|
38
|
-
} else {
|
|
39
|
-
this.log.warn(`Unable to take tx: ${hashOfTxInProposal.toString()} from the proposal, it does not match payload hash: ${hashesFromPayload[i].toString()}`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
// See if we still have any holes, if there are then we were not successful and will try the old method
|
|
44
|
-
if (txsToUse.some((tx)=>tx === undefined)) {
|
|
45
|
-
this.log.warn(`Failed to use transactions from proposal. Falling back to old proposal logic`);
|
|
46
|
-
} else {
|
|
47
|
-
this.log.info(`Successfully used ${usedFromProposal}/${hashesFromPayload.length} transactions from the proposal`);
|
|
48
|
-
await this.p2pClient.validate(txsToUse);
|
|
49
|
-
return {
|
|
50
|
-
txs: txsToUse
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
this.log.info(`Using old style proposal with ${proposal.payload.txHashes.length} transactions`);
|
|
55
|
-
// Old style proposal, we will perform a request by hash from pool
|
|
56
|
-
// This will request from network any txs that are missing
|
|
53
|
+
// Take txs from the proposal if there are any
|
|
54
|
+
await this.collectFromProposal(proposal);
|
|
55
|
+
// Now get the txs we need, either from the pool or the p2p network
|
|
57
56
|
const txHashes = proposal.payload.txHashes;
|
|
58
|
-
// This part is just for logging that we are requesting from the network
|
|
59
|
-
const availability = await this.p2pClient.hasTxsInPool(txHashes);
|
|
60
|
-
const notAvailable = availability.filter((availability)=>availability === false);
|
|
61
|
-
if (notAvailable.length) {
|
|
62
|
-
this.log.verbose(`Missing ${notAvailable.length} transactions in the tx pool, will need to request from the network`);
|
|
63
|
-
}
|
|
64
57
|
// This will request from the network any txs that are missing
|
|
65
58
|
// NOTE: this could still return missing txs so we need to (1) be careful to handle undefined and (2) keep the txs in the correct order for re-execution
|
|
66
59
|
const maybeRetrievedTxs = await this.p2pClient.getTxsByHash(txHashes, peerWhoSentTheProposal);
|
|
60
|
+
// Get the txs that we didn't get from the network, if any. This will be empty if we got them al
|
|
67
61
|
const missingTxs = compactArray(maybeRetrievedTxs.map((tx, index)=>tx === undefined ? txHashes[index] : undefined));
|
|
68
|
-
// if we found all txs, this is a noop. If we didn't find all txs then
|
|
62
|
+
// if we found all txs, this is a noop. If we didn't find all txs then tell the validator to skip attestations because missingTxs.length > 0
|
|
69
63
|
const retrievedTxs = compactArray(maybeRetrievedTxs);
|
|
70
|
-
await this.p2pClient.validate(retrievedTxs);
|
|
71
64
|
return {
|
|
72
65
|
txs: retrievedTxs,
|
|
73
66
|
missing: missingTxs
|
|
@@ -16,6 +16,15 @@ interface MakeTestP2PClientOptions {
|
|
|
16
16
|
p2pConfigOverrides?: Partial<P2PConfig>;
|
|
17
17
|
logger?: Logger;
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates a single P2P client and immediately starts it for testing purposes.
|
|
21
|
+
* @param peerIdPrivateKey - The private key of the peer.
|
|
22
|
+
* @param port - The port to run the client on.
|
|
23
|
+
* @param peers - The peers to connect to.
|
|
24
|
+
* @param options - The options for the client.
|
|
25
|
+
* @returns The created and already started client.
|
|
26
|
+
*/
|
|
27
|
+
export declare function makeAndStartTestP2PClient(peerIdPrivateKey: string, port: number, peers: string[], options: MakeTestP2PClientOptions): Promise<P2PClient<P2PClientType.Full>>;
|
|
19
28
|
/**
|
|
20
29
|
* Creates a single P2P client for testing purposes.
|
|
21
30
|
* @param peerIdPrivateKey - The private key of the peer.
|
|
@@ -25,6 +34,18 @@ interface MakeTestP2PClientOptions {
|
|
|
25
34
|
* @returns The created client.
|
|
26
35
|
*/
|
|
27
36
|
export declare function makeTestP2PClient(peerIdPrivateKey: string, port: number, peers: string[], { alwaysTrueVerifier, p2pBaseConfig, p2pConfigOverrides, mockAttestationPool, mockTxPool, mockEpochCache, mockWorldState, logger, }: MakeTestP2PClientOptions): Promise<P2PClient<P2PClientType.Full>>;
|
|
37
|
+
/**
|
|
38
|
+
* Creates a number of P2P clients and immediately starts them for testing purposes.
|
|
39
|
+
* @param numberOfPeers - The number of clients to create.
|
|
40
|
+
* @param options - The options for the clients.
|
|
41
|
+
* @returns The created and started clients.
|
|
42
|
+
*/
|
|
43
|
+
export declare function makeAndStartTestP2PClients(numberOfPeers: number, testConfig: MakeTestP2PClientOptions): Promise<{
|
|
44
|
+
client: P2PClient<P2PClientType.Full>;
|
|
45
|
+
peerPrivateKey: string;
|
|
46
|
+
port: number;
|
|
47
|
+
enr: string;
|
|
48
|
+
}[]>;
|
|
28
49
|
/**
|
|
29
50
|
* Creates a number of P2P clients for testing purposes.
|
|
30
51
|
* @param numberOfPeers - The number of clients to create.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"make-test-p2p-clients.d.ts","sourceRoot":"","sources":["../../src/test-helpers/make-test-p2p-clients.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAIlE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AACzF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAM5D,UAAU,wBAAwB;IAChC,mBAAmB,EAAE,eAAe,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,UAAU,CAAC;IAC3B,cAAc,EAAE,sBAAsB,CAAC;IACvC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,EAAE,SAAS,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,gBAAgB,EAAE,MAAM,EACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EAAE,EACf,EACE,kBAAyB,EACzB,aAAa,EACb,kBAAuB,EACvB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,cAAc,EACd,MAAwC,GACzC,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"make-test-p2p-clients.d.ts","sourceRoot":"","sources":["../../src/test-helpers/make-test-p2p-clients.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAIlE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGlD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mDAAmD,CAAC;AACzF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,+BAA+B,CAAC;AAM5D,UAAU,wBAAwB;IAChC,mBAAmB,EAAE,eAAe,CAAC;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,UAAU,CAAC;IAC3B,cAAc,EAAE,sBAAsB,CAAC;IACvC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,EAAE,SAAS,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,yBAAyB,CAC7C,gBAAgB,EAAE,MAAM,EACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,wBAAwB,0CAMlC;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,gBAAgB,EAAE,MAAM,EACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EAAE,EACf,EACE,kBAAyB,EACzB,aAAa,EACb,kBAAuB,EACvB,mBAAmB,EACnB,UAAU,EACV,cAAc,EACd,cAAc,EACd,MAAwC,GACzC,EAAE,wBAAwB,0CAyC5B;AAED;;;;;GAKG;AACH,wBAAsB,0BAA0B,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,wBAAwB;;;;;KAiC3G;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,wBAAwB;;;;;KAgCnG"}
|
|
@@ -8,6 +8,18 @@ import { generatePeerIdPrivateKeys } from '../test-helpers/generate-peer-id-priv
|
|
|
8
8
|
import { getPorts } from './get-ports.js';
|
|
9
9
|
import { makeEnrs } from './make-enrs.js';
|
|
10
10
|
import { AlwaysFalseCircuitVerifier, AlwaysTrueCircuitVerifier } from './reqresp-nodes.js';
|
|
11
|
+
/**
|
|
12
|
+
* Creates a single P2P client and immediately starts it for testing purposes.
|
|
13
|
+
* @param peerIdPrivateKey - The private key of the peer.
|
|
14
|
+
* @param port - The port to run the client on.
|
|
15
|
+
* @param peers - The peers to connect to.
|
|
16
|
+
* @param options - The options for the client.
|
|
17
|
+
* @returns The created and already started client.
|
|
18
|
+
*/ export async function makeAndStartTestP2PClient(peerIdPrivateKey, port, peers, options) {
|
|
19
|
+
const client = await makeTestP2PClient(peerIdPrivateKey, port, peers, options);
|
|
20
|
+
await client.start();
|
|
21
|
+
return client;
|
|
22
|
+
}
|
|
11
23
|
/**
|
|
12
24
|
* Creates a single P2P client for testing purposes.
|
|
13
25
|
* @param peerIdPrivateKey - The private key of the peer.
|
|
@@ -41,9 +53,43 @@ import { AlwaysFalseCircuitVerifier, AlwaysTrueCircuitVerifier } from './reqresp
|
|
|
41
53
|
logger
|
|
42
54
|
};
|
|
43
55
|
const client = await createP2PClient(P2PClientType.Full, config, l2BlockSource, proofVerifier, mockWorldState, mockEpochCache, 'test-p2p-client', undefined, deps);
|
|
44
|
-
await client.start();
|
|
45
56
|
return client;
|
|
46
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Creates a number of P2P clients and immediately starts them for testing purposes.
|
|
60
|
+
* @param numberOfPeers - The number of clients to create.
|
|
61
|
+
* @param options - The options for the clients.
|
|
62
|
+
* @returns The created and started clients.
|
|
63
|
+
*/ export async function makeAndStartTestP2PClients(numberOfPeers, testConfig) {
|
|
64
|
+
const clients = [];
|
|
65
|
+
const peerIdPrivateKeys = generatePeerIdPrivateKeys(numberOfPeers);
|
|
66
|
+
let ports = [];
|
|
67
|
+
while(true){
|
|
68
|
+
try {
|
|
69
|
+
ports = await getPorts(numberOfPeers);
|
|
70
|
+
break;
|
|
71
|
+
} catch {
|
|
72
|
+
await sleep(1000);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const peerEnrs = await makeEnrs(peerIdPrivateKeys, ports, testConfig.p2pBaseConfig);
|
|
76
|
+
for(let i = 0; i < numberOfPeers; i++){
|
|
77
|
+
const client = await makeAndStartTestP2PClient(peerIdPrivateKeys[i], ports[i], peerEnrs, {
|
|
78
|
+
...testConfig,
|
|
79
|
+
logger: createLogger(`p2p:${i}`)
|
|
80
|
+
});
|
|
81
|
+
clients.push(client);
|
|
82
|
+
}
|
|
83
|
+
await Promise.all(clients.map((client)=>client.isReady()));
|
|
84
|
+
return clients.map((client, index)=>{
|
|
85
|
+
return {
|
|
86
|
+
client,
|
|
87
|
+
peerPrivateKey: peerIdPrivateKeys[index],
|
|
88
|
+
port: ports[index],
|
|
89
|
+
enr: peerEnrs[index]
|
|
90
|
+
};
|
|
91
|
+
});
|
|
92
|
+
}
|
|
47
93
|
/**
|
|
48
94
|
* Creates a number of P2P clients for testing purposes.
|
|
49
95
|
* @param numberOfPeers - The number of clients to create.
|
|
@@ -69,7 +115,6 @@ import { AlwaysFalseCircuitVerifier, AlwaysTrueCircuitVerifier } from './reqresp
|
|
|
69
115
|
});
|
|
70
116
|
clients.push(client);
|
|
71
117
|
}
|
|
72
|
-
await Promise.all(clients.map((client)=>client.isReady()));
|
|
73
118
|
return clients.map((client, index)=>{
|
|
74
119
|
return {
|
|
75
120
|
client,
|
|
@@ -17,7 +17,7 @@ import { BootstrapNode } from '../bootstrap/bootstrap.js';
|
|
|
17
17
|
import { DiscV5Service } from '../services/discv5/discV5_service.js';
|
|
18
18
|
import { LibP2PService } from '../services/libp2p/libp2p_service.js';
|
|
19
19
|
import { ReqRespSubProtocol, noopValidator } from '../services/reqresp/interface.js';
|
|
20
|
-
import { pingHandler
|
|
20
|
+
import { pingHandler } from '../services/reqresp/protocols/index.js';
|
|
21
21
|
import { ReqResp } from '../services/reqresp/reqresp.js';
|
|
22
22
|
import { convertToMultiaddr, createLibP2PPeerIdFromPrivateKey } from '../util.js';
|
|
23
23
|
/**
|
|
@@ -95,7 +95,7 @@ import { convertToMultiaddr, createLibP2PPeerIdFromPrivateKey } from '../util.js
|
|
|
95
95
|
// Mock sub protocol handlers
|
|
96
96
|
export const MOCK_SUB_PROTOCOL_HANDLERS = {
|
|
97
97
|
[ReqRespSubProtocol.PING]: pingHandler,
|
|
98
|
-
[ReqRespSubProtocol.STATUS]:
|
|
98
|
+
[ReqRespSubProtocol.STATUS]: (_msg)=>Promise.resolve(Buffer.from('status')),
|
|
99
99
|
[ReqRespSubProtocol.TX]: (_msg)=>Promise.resolve(Buffer.from('tx')),
|
|
100
100
|
[ReqRespSubProtocol.GOODBYE]: (_msg)=>Promise.resolve(Buffer.from('goodbye')),
|
|
101
101
|
[ReqRespSubProtocol.BLOCK]: (_msg)=>Promise.resolve(Buffer.from('block'))
|
|
@@ -19,7 +19,7 @@ function mockTxPool() {
|
|
|
19
19
|
// Mock all methods
|
|
20
20
|
return {
|
|
21
21
|
isEmpty: ()=>Promise.resolve(false),
|
|
22
|
-
addTxs: ()=>Promise.resolve(),
|
|
22
|
+
addTxs: ()=>Promise.resolve(1),
|
|
23
23
|
getTxByHash: ()=>Promise.resolve(undefined),
|
|
24
24
|
getArchivedTxByHash: ()=>Promise.resolve(undefined),
|
|
25
25
|
markAsMined: ()=>Promise.resolve(),
|
|
@@ -63,7 +63,7 @@ function mockEpochCache() {
|
|
|
63
63
|
ts: 0n
|
|
64
64
|
}),
|
|
65
65
|
computeProposerIndex: ()=>0n,
|
|
66
|
-
|
|
66
|
+
getProposerAttesterAddressInCurrentOrNextSlot: ()=>Promise.resolve({
|
|
67
67
|
currentProposer: EthAddress.ZERO,
|
|
68
68
|
nextProposer: EthAddress.ZERO,
|
|
69
69
|
currentSlot: 0n,
|
|
@@ -72,6 +72,19 @@ function mockEpochCache() {
|
|
|
72
72
|
isInCommittee: ()=>Promise.resolve(false)
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
|
+
function mockWorldStateSynchronizer() {
|
|
76
|
+
return {
|
|
77
|
+
status: ()=>Promise.resolve({
|
|
78
|
+
syncSummary: {
|
|
79
|
+
latestBlockNumber: 0,
|
|
80
|
+
latestBlockHash: '',
|
|
81
|
+
finalisedBlockNumber: 0,
|
|
82
|
+
treesAreSynched: false,
|
|
83
|
+
oldestHistoricBlockNumber: 0
|
|
84
|
+
}
|
|
85
|
+
})
|
|
86
|
+
};
|
|
87
|
+
}
|
|
75
88
|
class TestLibP2PService extends LibP2PService {
|
|
76
89
|
disableTxValidation;
|
|
77
90
|
gossipMessageCount = 0;
|
|
@@ -117,7 +130,7 @@ process.on('message', async (msg)=>{
|
|
|
117
130
|
const txPool = mockTxPool();
|
|
118
131
|
const attestationPool = mockAttestationPool();
|
|
119
132
|
const epochCache = mockEpochCache();
|
|
120
|
-
const worldState =
|
|
133
|
+
const worldState = mockWorldStateSynchronizer();
|
|
121
134
|
const l2BlockSource = new MockL2BlockSource();
|
|
122
135
|
const proofVerifier = new AlwaysTrueCircuitVerifier();
|
|
123
136
|
const kvStore = await openTmpStore(`test-${clientIndex}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/p2p",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-nightly.20250605",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -63,16 +63,16 @@
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@aztec/constants": "0.
|
|
67
|
-
"@aztec/epoch-cache": "0.
|
|
68
|
-
"@aztec/foundation": "0.
|
|
69
|
-
"@aztec/kv-store": "0.
|
|
70
|
-
"@aztec/noir-contracts.js": "0.
|
|
71
|
-
"@aztec/noir-protocol-circuits-types": "0.
|
|
72
|
-
"@aztec/protocol-contracts": "0.
|
|
73
|
-
"@aztec/simulator": "0.
|
|
74
|
-
"@aztec/stdlib": "0.
|
|
75
|
-
"@aztec/telemetry-client": "0.
|
|
66
|
+
"@aztec/constants": "1.0.0-nightly.20250605",
|
|
67
|
+
"@aztec/epoch-cache": "1.0.0-nightly.20250605",
|
|
68
|
+
"@aztec/foundation": "1.0.0-nightly.20250605",
|
|
69
|
+
"@aztec/kv-store": "1.0.0-nightly.20250605",
|
|
70
|
+
"@aztec/noir-contracts.js": "1.0.0-nightly.20250605",
|
|
71
|
+
"@aztec/noir-protocol-circuits-types": "1.0.0-nightly.20250605",
|
|
72
|
+
"@aztec/protocol-contracts": "1.0.0-nightly.20250605",
|
|
73
|
+
"@aztec/simulator": "1.0.0-nightly.20250605",
|
|
74
|
+
"@aztec/stdlib": "1.0.0-nightly.20250605",
|
|
75
|
+
"@aztec/telemetry-client": "1.0.0-nightly.20250605",
|
|
76
76
|
"@chainsafe/discv5": "9.0.0",
|
|
77
77
|
"@chainsafe/enr": "3.0.0",
|
|
78
78
|
"@chainsafe/libp2p-gossipsub": "13.0.0",
|
|
@@ -101,7 +101,7 @@
|
|
|
101
101
|
"xxhash-wasm": "^1.1.0"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@aztec/archiver": "0.
|
|
104
|
+
"@aztec/archiver": "1.0.0-nightly.20250605",
|
|
105
105
|
"@jest/globals": "^29.5.0",
|
|
106
106
|
"@types/jest": "^29.5.0",
|
|
107
107
|
"@types/node": "^22.15.17",
|
package/src/client/interface.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { L2BlockId } from '@aztec/stdlib/block';
|
|
2
|
-
import type {
|
|
2
|
+
import type { P2PApiFull } from '@aztec/stdlib/interfaces/server';
|
|
3
3
|
import type { BlockProposal, P2PClientType } from '@aztec/stdlib/p2p';
|
|
4
4
|
import type { Tx, TxHash } from '@aztec/stdlib/tx';
|
|
5
5
|
|
|
@@ -36,7 +36,7 @@ export interface P2PSyncState {
|
|
|
36
36
|
/**
|
|
37
37
|
* Interface of a P2P client.
|
|
38
38
|
**/
|
|
39
|
-
export type P2P<T extends P2PClientType = P2PClientType.Full> =
|
|
39
|
+
export type P2P<T extends P2PClientType = P2PClientType.Full> = P2PApiFull<T> & {
|
|
40
40
|
/**
|
|
41
41
|
* Broadcasts a block proposal to other peers.
|
|
42
42
|
*
|
|
@@ -77,8 +77,9 @@ export type P2P<T extends P2PClientType = P2PClientType.Full> = P2PApi<T> & {
|
|
|
77
77
|
/**
|
|
78
78
|
* Adds transactions to the pool. Does not send to peers or validate the tx.
|
|
79
79
|
* @param txs - The transactions.
|
|
80
|
+
* @returns The number of txs added to the pool. Note if the transaction already exists, it will not be added again.
|
|
80
81
|
**/
|
|
81
|
-
|
|
82
|
+
addTxsToPool(txs: Tx[]): Promise<number>;
|
|
82
83
|
|
|
83
84
|
/**
|
|
84
85
|
* Deletes 'txs' from the pool, given hashes.
|
package/src/client/p2p_client.ts
CHANGED
|
@@ -31,7 +31,7 @@ import type { AttestationPool } from '../mem_pools/attestation_pool/attestation_
|
|
|
31
31
|
import type { MemPools } from '../mem_pools/interface.js';
|
|
32
32
|
import type { TxPool } from '../mem_pools/tx_pool/index.js';
|
|
33
33
|
import { ReqRespSubProtocol } from '../services/reqresp/interface.js';
|
|
34
|
-
import type { P2PService } from '../services/service.js';
|
|
34
|
+
import type { P2PBlockReceivedCallback, P2PService } from '../services/service.js';
|
|
35
35
|
import { TxCollector } from '../services/tx_collector.js';
|
|
36
36
|
import { type P2P, P2PClientState, type P2PSyncState } from './interface.js';
|
|
37
37
|
|
|
@@ -331,15 +331,13 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
331
331
|
);
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
public
|
|
335
|
-
return this.attestationPool?.addAttestations(
|
|
334
|
+
public addAttestations(attestations: BlockAttestation[]): Promise<void> {
|
|
335
|
+
return this.attestationPool?.addAttestations(attestations) ?? Promise.resolve();
|
|
336
336
|
}
|
|
337
337
|
|
|
338
338
|
// REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
339
339
|
// ^ This pattern is not my favorite (md)
|
|
340
|
-
public registerBlockProposalHandler(
|
|
341
|
-
handler: (block: BlockProposal, sender: any) => Promise<BlockAttestation | undefined>,
|
|
342
|
-
): void {
|
|
340
|
+
public registerBlockProposalHandler(handler: P2PBlockReceivedCallback): void {
|
|
343
341
|
this.p2pService.registerBlockReceivedCallback(handler);
|
|
344
342
|
}
|
|
345
343
|
|
|
@@ -444,7 +442,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
444
442
|
/**
|
|
445
443
|
* Returns transactions in the transaction pool by hash.
|
|
446
444
|
* @param txHashes - Hashes of the transactions to look for.
|
|
447
|
-
* @returns The txs found,
|
|
445
|
+
* @returns The txs found, in the same order as the requested hashes. If a tx is not found, it will be undefined.
|
|
448
446
|
*/
|
|
449
447
|
getTxsByHashFromPool(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
|
|
450
448
|
return this.txPool.getTxsByHash(txHashes);
|
|
@@ -527,17 +525,20 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
|
|
|
527
525
|
* @returns Empty promise.
|
|
528
526
|
**/
|
|
529
527
|
public async sendTx(tx: Tx): Promise<void> {
|
|
530
|
-
await this.
|
|
531
|
-
|
|
528
|
+
const addedCount = await this.addTxsToPool([tx]);
|
|
529
|
+
const txAddedSuccessfully = addedCount === 1;
|
|
530
|
+
if (txAddedSuccessfully) {
|
|
531
|
+
await this.p2pService.propagate(tx);
|
|
532
|
+
}
|
|
532
533
|
}
|
|
533
534
|
|
|
534
535
|
/**
|
|
535
536
|
* Adds transactions to the pool. Does not send to peers or validate the txs.
|
|
536
537
|
* @param txs - The transactions.
|
|
537
538
|
**/
|
|
538
|
-
public async
|
|
539
|
+
public async addTxsToPool(txs: Tx[]): Promise<number> {
|
|
539
540
|
this.#assertIsReady();
|
|
540
|
-
await this.txPool.addTxs(txs);
|
|
541
|
+
return await this.txPool.addTxs(txs);
|
|
541
542
|
}
|
|
542
543
|
|
|
543
544
|
/**
|