@aztec/p2p 0.56.0 → 0.58.0
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/index.d.ts +6 -3
- package/dest/client/index.d.ts.map +1 -1
- package/dest/client/index.js +12 -6
- package/dest/client/p2p_client.d.ts +30 -12
- package/dest/client/p2p_client.d.ts.map +1 -1
- package/dest/client/p2p_client.js +375 -335
- package/dest/config.js +3 -3
- package/dest/index.d.ts +4 -3
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +5 -4
- package/dest/{attestation_pool → mem_pools/attestation_pool}/attestation_pool.d.ts +2 -1
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -0
- package/dest/{attestation_pool → mem_pools/attestation_pool}/attestation_pool.js +1 -1
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -0
- package/dest/{attestation_pool → mem_pools/attestation_pool}/index.js +1 -1
- package/dest/{attestation_pool → mem_pools/attestation_pool}/memory_attestation_pool.d.ts +6 -2
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +114 -0
- package/dest/{attestation_pool → mem_pools/attestation_pool}/mocks.d.ts +2 -1
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/mocks.js +31 -0
- package/dest/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts +7 -0
- package/dest/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.js +2 -0
- package/dest/mem_pools/epoch_proof_quote_pool/index.d.ts +4 -0
- package/dest/mem_pools/epoch_proof_quote_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/index.js +4 -0
- package/dest/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts +12 -0
- package/dest/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.js +30 -0
- package/dest/mem_pools/epoch_proof_quote_pool/test_utils.d.ts +8 -0
- package/dest/mem_pools/epoch_proof_quote_pool/test_utils.d.ts.map +1 -0
- package/dest/mem_pools/epoch_proof_quote_pool/test_utils.js +21 -0
- package/dest/mem_pools/index.d.ts +5 -0
- package/dest/mem_pools/index.d.ts.map +1 -0
- package/dest/mem_pools/index.js +2 -0
- package/dest/mem_pools/instrumentation.d.ts +25 -0
- package/dest/mem_pools/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/instrumentation.js +70 -0
- package/dest/mem_pools/interface.d.ts +12 -0
- package/dest/mem_pools/interface.d.ts.map +1 -0
- package/dest/mem_pools/interface.js +2 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -0
- package/dest/{tx_pool → mem_pools/tx_pool}/aztec_kv_tx_pool.js +9 -9
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -0
- package/dest/{tx_pool → mem_pools/tx_pool}/index.js +1 -1
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +111 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -0
- package/dest/{tx_pool → mem_pools/tx_pool}/tx_pool.js +1 -1
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +55 -0
- package/dest/service/libp2p_service.d.ts +12 -7
- package/dest/service/libp2p_service.d.ts.map +1 -1
- package/dest/service/libp2p_service.js +453 -381
- package/dest/service/reqresp/reqresp.d.ts +0 -1
- package/dest/service/reqresp/reqresp.d.ts.map +1 -1
- package/dest/service/reqresp/reqresp.js +7 -4
- package/package.json +10 -6
- package/src/client/index.ts +21 -8
- package/src/client/p2p_client.ts +77 -21
- package/src/config.ts +2 -2
- package/src/index.ts +4 -3
- package/src/{attestation_pool → mem_pools/attestation_pool}/attestation_pool.ts +2 -1
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -0
- package/src/{attestation_pool → mem_pools/attestation_pool}/mocks.ts +5 -2
- package/src/mem_pools/epoch_proof_quote_pool/epoch_proof_quote_pool.ts +7 -0
- package/src/mem_pools/epoch_proof_quote_pool/index.ts +3 -0
- package/src/mem_pools/epoch_proof_quote_pool/memory_epoch_proof_quote_pool.ts +42 -0
- package/src/mem_pools/epoch_proof_quote_pool/test_utils.ts +26 -0
- package/src/mem_pools/index.ts +4 -0
- package/src/mem_pools/instrumentation.ts +85 -0
- package/src/mem_pools/interface.ts +12 -0
- package/src/{tx_pool → mem_pools/tx_pool}/aztec_kv_tx_pool.ts +9 -9
- package/src/{tx_pool → mem_pools/tx_pool}/memory_tx_pool.ts +9 -9
- package/src/service/libp2p_service.ts +78 -20
- package/src/service/reqresp/reqresp.ts +9 -5
- package/dest/attestation_pool/attestation_pool.d.ts.map +0 -1
- package/dest/attestation_pool/index.d.ts.map +0 -1
- package/dest/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
- package/dest/attestation_pool/memory_attestation_pool.js +0 -57
- package/dest/attestation_pool/mocks.d.ts.map +0 -1
- package/dest/attestation_pool/mocks.js +0 -32
- package/dest/client/mocks.d.ts +0 -65
- package/dest/client/mocks.d.ts.map +0 -1
- package/dest/client/mocks.js +0 -106
- package/dest/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
- package/dest/tx_pool/index.d.ts.map +0 -1
- package/dest/tx_pool/instrumentation.d.ts +0 -25
- package/dest/tx_pool/instrumentation.d.ts.map +0 -1
- package/dest/tx_pool/instrumentation.js +0 -61
- package/dest/tx_pool/memory_tx_pool.d.ts.map +0 -1
- package/dest/tx_pool/memory_tx_pool.js +0 -111
- package/dest/tx_pool/tx_pool.d.ts.map +0 -1
- package/dest/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
- package/dest/tx_pool/tx_pool_test_suite.js +0 -55
- package/src/attestation_pool/memory_attestation_pool.ts +0 -71
- package/src/client/mocks.ts +0 -129
- package/src/tx_pool/instrumentation.ts +0 -73
- /package/dest/{attestation_pool → mem_pools/attestation_pool}/index.d.ts +0 -0
- /package/dest/{tx_pool → mem_pools/tx_pool}/aztec_kv_tx_pool.d.ts +0 -0
- /package/dest/{tx_pool → mem_pools/tx_pool}/index.d.ts +0 -0
- /package/dest/{tx_pool → mem_pools/tx_pool}/memory_tx_pool.d.ts +0 -0
- /package/dest/{tx_pool → mem_pools/tx_pool}/tx_pool.d.ts +0 -0
- /package/dest/{tx_pool → mem_pools/tx_pool}/tx_pool_test_suite.d.ts +0 -0
- /package/src/{attestation_pool → mem_pools/attestation_pool}/index.ts +0 -0
- /package/src/{tx_pool → mem_pools/tx_pool}/index.ts +0 -0
- /package/src/{tx_pool → mem_pools/tx_pool}/tx_pool.ts +0 -0
- /package/src/{tx_pool → mem_pools/tx_pool}/tx_pool_test_suite.ts +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __esDecorate, __runInitializers } from "tslib";
|
|
2
|
+
import { BlockAttestation, BlockProposal, EpochProofQuote, MerkleTreeId, TopicType, TopicTypeMap, Tx, TxHash, } from '@aztec/circuit-types';
|
|
2
3
|
import { Fr } from '@aztec/circuits.js';
|
|
3
4
|
import { createDebugLogger } from '@aztec/foundation/log';
|
|
4
5
|
import { SerialQueue } from '@aztec/foundation/queue';
|
|
5
6
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
7
|
+
import { Attributes, WithTracer, trackSpan } from '@aztec/telemetry-client';
|
|
6
8
|
import { gossipsub } from '@chainsafe/libp2p-gossipsub';
|
|
7
9
|
import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
|
|
8
10
|
import { noise } from '@chainsafe/libp2p-noise';
|
|
@@ -39,394 +41,464 @@ export async function createLibP2PPeerId(privateKey) {
|
|
|
39
41
|
/**
|
|
40
42
|
* Lib P2P implementation of the P2PService interface.
|
|
41
43
|
*/
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
peerId,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
closeServerOnMaxConnections: {
|
|
155
|
-
closeAbove: maxPeerCount ?? Infinity,
|
|
156
|
-
listenBelow: maxPeerCount ?? Infinity,
|
|
44
|
+
let LibP2PService = (() => {
|
|
45
|
+
var _a;
|
|
46
|
+
let _classSuper = WithTracer;
|
|
47
|
+
let _instanceExtraInitializers = [];
|
|
48
|
+
let _processAttestationFromPeer_decorators;
|
|
49
|
+
let _processBlockFromPeer_decorators;
|
|
50
|
+
let _broadcastAttestation_decorators;
|
|
51
|
+
return _a = class LibP2PService extends _classSuper {
|
|
52
|
+
constructor(config, node, peerDiscoveryService, mempools, l2BlockSource, proofVerifier, worldStateSynchronizer, telemetry, requestResponseHandlers = DEFAULT_SUB_PROTOCOL_HANDLERS, logger = createDebugLogger('aztec:libp2p_service')) {
|
|
53
|
+
// Instatntiate tracer
|
|
54
|
+
super(telemetry, 'LibP2PService');
|
|
55
|
+
this.config = (__runInitializers(this, _instanceExtraInitializers), config);
|
|
56
|
+
this.node = node;
|
|
57
|
+
this.peerDiscoveryService = peerDiscoveryService;
|
|
58
|
+
this.mempools = mempools;
|
|
59
|
+
this.l2BlockSource = l2BlockSource;
|
|
60
|
+
this.proofVerifier = proofVerifier;
|
|
61
|
+
this.worldStateSynchronizer = worldStateSynchronizer;
|
|
62
|
+
this.requestResponseHandlers = requestResponseHandlers;
|
|
63
|
+
this.logger = logger;
|
|
64
|
+
this.jobQueue = new SerialQueue();
|
|
65
|
+
this.peerManager = new PeerManager(node, peerDiscoveryService, config, logger);
|
|
66
|
+
this.node.services.pubsub.score.params.appSpecificScore = (peerId) => {
|
|
67
|
+
return this.peerManager.getPeerScore(peerId);
|
|
68
|
+
};
|
|
69
|
+
this.node.services.pubsub.score.params.appSpecificWeight = 10;
|
|
70
|
+
this.reqresp = new ReqResp(config, node, this.peerManager);
|
|
71
|
+
this.blockReceivedCallback = (block) => {
|
|
72
|
+
this.logger.verbose(`[WARNING] handler not yet registered: Block received callback not set. Received block ${block.p2pMessageIdentifier()} from peer.`);
|
|
73
|
+
return Promise.resolve(undefined);
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Starts the LibP2P service.
|
|
78
|
+
* @returns An empty promise.
|
|
79
|
+
*/
|
|
80
|
+
async start() {
|
|
81
|
+
// Check if service is already started
|
|
82
|
+
if (this.node.status === 'started') {
|
|
83
|
+
throw new Error('P2P service already started');
|
|
84
|
+
}
|
|
85
|
+
// Log listen & announce addresses
|
|
86
|
+
const { tcpListenAddress, tcpAnnounceAddress } = this.config;
|
|
87
|
+
this.logger.info(`Starting P2P node on ${tcpListenAddress}`);
|
|
88
|
+
if (!tcpAnnounceAddress) {
|
|
89
|
+
throw new Error('Announce address not provided.');
|
|
90
|
+
}
|
|
91
|
+
const announceTcpMultiaddr = convertToMultiaddr(tcpAnnounceAddress, 'tcp');
|
|
92
|
+
this.logger.info(`Announcing at ${announceTcpMultiaddr}`);
|
|
93
|
+
// Start job queue, peer discovery service and libp2p node
|
|
94
|
+
this.jobQueue.start();
|
|
95
|
+
await this.peerDiscoveryService.start();
|
|
96
|
+
await this.node.start();
|
|
97
|
+
this.logger.info(`Started P2P client with Peer ID ${this.node.peerId.toString()}`);
|
|
98
|
+
// Subscribe to standard GossipSub topics by default
|
|
99
|
+
for (const topic in TopicType) {
|
|
100
|
+
this.subscribeToTopic(TopicTypeMap[topic].p2pTopic);
|
|
101
|
+
}
|
|
102
|
+
// add GossipSub listener
|
|
103
|
+
this.node.services.pubsub.addEventListener('gossipsub:message', async (e) => {
|
|
104
|
+
const { msg, propagationSource: peerId } = e.detail;
|
|
105
|
+
this.logger.debug(`Received PUBSUB message.`);
|
|
106
|
+
await this.jobQueue.put(() => this.handleNewGossipMessage(msg, peerId));
|
|
107
|
+
});
|
|
108
|
+
// Start running promise for peer discovery
|
|
109
|
+
this.discoveryRunningPromise = new RunningPromise(() => {
|
|
110
|
+
this.peerManager.heartbeat();
|
|
111
|
+
}, this.config.peerCheckIntervalMS);
|
|
112
|
+
this.discoveryRunningPromise.start();
|
|
113
|
+
// Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
|
|
114
|
+
const reqrespSubProtocolValidators = {
|
|
115
|
+
...DEFAULT_SUB_PROTOCOL_VALIDATORS,
|
|
116
|
+
[TX_REQ_PROTOCOL]: this.validateRequestedTx.bind(this),
|
|
117
|
+
};
|
|
118
|
+
await this.reqresp.start(this.requestResponseHandlers, reqrespSubProtocolValidators);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Stops the LibP2P service.
|
|
122
|
+
* @returns An empty promise.
|
|
123
|
+
*/
|
|
124
|
+
async stop() {
|
|
125
|
+
this.logger.debug('Stopping job queue...');
|
|
126
|
+
await this.jobQueue.end();
|
|
127
|
+
this.logger.debug('Stopping running promise...');
|
|
128
|
+
await this.discoveryRunningPromise?.stop();
|
|
129
|
+
this.logger.debug('Stopping peer discovery service...');
|
|
130
|
+
await this.peerDiscoveryService.stop();
|
|
131
|
+
this.logger.debug('Request response service stopped...');
|
|
132
|
+
await this.reqresp.stop();
|
|
133
|
+
this.logger.debug('Stopping LibP2P...');
|
|
134
|
+
await this.stopLibP2P();
|
|
135
|
+
this.logger.info('LibP2P service stopped');
|
|
136
|
+
this.logger.debug('Stopping request response service...');
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Creates an instance of the LibP2P service.
|
|
140
|
+
* @param config - The configuration to use when creating the service.
|
|
141
|
+
* @param txPool - The transaction pool to be accessed by the service.
|
|
142
|
+
* @returns The new service.
|
|
143
|
+
*/
|
|
144
|
+
static async new(config, peerDiscoveryService, peerId, mempools, l2BlockSource, proofVerifier, worldStateSynchronizer, store, telemetry) {
|
|
145
|
+
const { tcpListenAddress, tcpAnnounceAddress, minPeerCount, maxPeerCount } = config;
|
|
146
|
+
const bindAddrTcp = convertToMultiaddr(tcpListenAddress, 'tcp');
|
|
147
|
+
// We know tcpAnnounceAddress cannot be null here because we set it or throw when setting up the service.
|
|
148
|
+
const announceAddrTcp = convertToMultiaddr(tcpAnnounceAddress, 'tcp');
|
|
149
|
+
const datastore = new AztecDatastore(store);
|
|
150
|
+
const node = await createLibp2p({
|
|
151
|
+
start: false,
|
|
152
|
+
peerId,
|
|
153
|
+
addresses: {
|
|
154
|
+
listen: [bindAddrTcp],
|
|
155
|
+
announce: [announceAddrTcp],
|
|
157
156
|
},
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
157
|
+
transports: [
|
|
158
|
+
tcp({
|
|
159
|
+
maxConnections: config.maxPeerCount,
|
|
160
|
+
// socket option: the maximum length of the queue of pending connections
|
|
161
|
+
// https://nodejs.org/dist/latest-v18.x/docs/api/net.html#serverlisten
|
|
162
|
+
// it's not safe if we increase this number
|
|
163
|
+
backlog: 5,
|
|
164
|
+
closeServerOnMaxConnections: {
|
|
165
|
+
closeAbove: maxPeerCount ?? Infinity,
|
|
166
|
+
listenBelow: maxPeerCount ?? Infinity,
|
|
167
|
+
},
|
|
168
|
+
}),
|
|
169
|
+
],
|
|
170
|
+
datastore,
|
|
171
|
+
streamMuxers: [yamux(), mplex()],
|
|
172
|
+
connectionEncryption: [noise()],
|
|
173
|
+
connectionManager: {
|
|
174
|
+
minConnections: minPeerCount,
|
|
175
|
+
maxConnections: maxPeerCount,
|
|
176
|
+
},
|
|
177
|
+
services: {
|
|
178
|
+
identify: identify({
|
|
179
|
+
protocolPrefix: 'aztec',
|
|
180
|
+
}),
|
|
181
|
+
pubsub: gossipsub({
|
|
182
|
+
allowPublishToZeroTopicPeers: true,
|
|
183
|
+
D: config.gossipsubD,
|
|
184
|
+
Dlo: config.gossipsubDlo,
|
|
185
|
+
Dhi: config.gossipsubDhi,
|
|
186
|
+
heartbeatInterval: config.gossipsubInterval,
|
|
187
|
+
mcacheLength: config.gossipsubMcacheLength,
|
|
188
|
+
mcacheGossip: config.gossipsubMcacheGossip,
|
|
189
|
+
scoreParams: createPeerScoreParams({
|
|
190
|
+
topics: {
|
|
191
|
+
[Tx.p2pTopic]: createTopicScoreParams({
|
|
192
|
+
topicWeight: 1,
|
|
193
|
+
invalidMessageDeliveriesWeight: -20,
|
|
194
|
+
invalidMessageDeliveriesDecay: 0.5,
|
|
195
|
+
}),
|
|
196
|
+
[BlockAttestation.p2pTopic]: createTopicScoreParams({
|
|
197
|
+
topicWeight: 1,
|
|
198
|
+
invalidMessageDeliveriesWeight: -20,
|
|
199
|
+
invalidMessageDeliveriesDecay: 0.5,
|
|
200
|
+
}),
|
|
201
|
+
[BlockAttestation.p2pTopic]: createTopicScoreParams({
|
|
202
|
+
topicWeight: 1,
|
|
203
|
+
invalidMessageDeliveriesWeight: -20,
|
|
204
|
+
invalidMessageDeliveriesDecay: 0.5,
|
|
205
|
+
}),
|
|
206
|
+
[EpochProofQuote.p2pTopic]: createTopicScoreParams({
|
|
207
|
+
topicWeight: 1,
|
|
208
|
+
invalidMessageDeliveriesWeight: -20,
|
|
209
|
+
invalidMessageDeliveriesDecay: 0.5,
|
|
210
|
+
}),
|
|
211
|
+
},
|
|
185
212
|
}),
|
|
186
|
-
},
|
|
187
|
-
}
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
213
|
+
}),
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
// Create request response protocol handlers
|
|
217
|
+
/**
|
|
218
|
+
* Handler for tx requests
|
|
219
|
+
* @param msg - the tx request message
|
|
220
|
+
* @returns the tx response message
|
|
221
|
+
*/
|
|
222
|
+
const txHandler = (msg) => {
|
|
223
|
+
const txHash = TxHash.fromBuffer(msg);
|
|
224
|
+
const foundTx = mempools.txPool.getTxByHash(txHash);
|
|
225
|
+
const asUint8Array = Uint8Array.from(foundTx ? foundTx.toBuffer() : Buffer.alloc(0));
|
|
226
|
+
return Promise.resolve(asUint8Array);
|
|
227
|
+
};
|
|
228
|
+
const requestResponseHandlers = {
|
|
229
|
+
[PING_PROTOCOL]: pingHandler,
|
|
230
|
+
[STATUS_PROTOCOL]: statusHandler,
|
|
231
|
+
[TX_REQ_PROTOCOL]: txHandler,
|
|
232
|
+
};
|
|
233
|
+
return new _a(config, node, peerDiscoveryService, mempools, l2BlockSource, proofVerifier, worldStateSynchronizer, telemetry, requestResponseHandlers);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Send Request via the ReqResp service
|
|
237
|
+
* The subprotocol defined will determine the request and response types
|
|
238
|
+
*
|
|
239
|
+
* See the subProtocolMap for the mapping of subprotocols to request/response types in `interface.ts`
|
|
240
|
+
*
|
|
241
|
+
* @param protocol The request response protocol to use
|
|
242
|
+
* @param request The request type to send
|
|
243
|
+
* @returns
|
|
244
|
+
*/
|
|
245
|
+
sendRequest(protocol, request) {
|
|
246
|
+
return this.reqresp.sendRequest(protocol, request);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get the ENR of the node
|
|
250
|
+
* @returns The ENR of the node
|
|
251
|
+
*/
|
|
252
|
+
getEnr() {
|
|
253
|
+
return this.peerDiscoveryService.getEnr();
|
|
254
|
+
}
|
|
255
|
+
registerBlockReceivedCallback(callback) {
|
|
256
|
+
this.blockReceivedCallback = callback;
|
|
257
|
+
this.logger.verbose('Block received callback registered');
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Subscribes to a topic.
|
|
261
|
+
* @param topic - The topic to subscribe to.
|
|
262
|
+
*/
|
|
263
|
+
subscribeToTopic(topic) {
|
|
264
|
+
if (!this.node.services.pubsub) {
|
|
265
|
+
throw new Error('Pubsub service not available.');
|
|
266
|
+
}
|
|
267
|
+
void this.node.services.pubsub.subscribe(topic);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Publishes data to a topic.
|
|
271
|
+
* @param topic - The topic to publish to.
|
|
272
|
+
* @param data - The data to publish.
|
|
273
|
+
* @returns The number of recipients the data was sent to.
|
|
274
|
+
*/
|
|
275
|
+
async publishToTopic(topic, data) {
|
|
276
|
+
if (!this.node.services.pubsub) {
|
|
277
|
+
throw new Error('Pubsub service not available.');
|
|
278
|
+
}
|
|
279
|
+
const result = await this.node.services.pubsub.publish(topic, data);
|
|
280
|
+
return result.recipients.length;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Handles a new gossip message that was received by the client.
|
|
284
|
+
* @param topic - The message's topic.
|
|
285
|
+
* @param data - The message data
|
|
286
|
+
*/
|
|
287
|
+
async handleNewGossipMessage(message, peerId) {
|
|
288
|
+
if (message.topic === Tx.p2pTopic) {
|
|
289
|
+
const tx = Tx.fromBuffer(Buffer.from(message.data));
|
|
290
|
+
await this.processTxFromPeer(tx, peerId);
|
|
291
|
+
}
|
|
292
|
+
if (message.topic === BlockAttestation.p2pTopic) {
|
|
293
|
+
const attestation = BlockAttestation.fromBuffer(Buffer.from(message.data));
|
|
294
|
+
await this.processAttestationFromPeer(attestation);
|
|
295
|
+
}
|
|
296
|
+
if (message.topic == BlockProposal.p2pTopic) {
|
|
297
|
+
const block = BlockProposal.fromBuffer(Buffer.from(message.data));
|
|
298
|
+
await this.processBlockFromPeer(block);
|
|
299
|
+
}
|
|
300
|
+
if (message.topic == EpochProofQuote.p2pTopic) {
|
|
301
|
+
const epochProofQuote = EpochProofQuote.fromBuffer(Buffer.from(message.data));
|
|
302
|
+
this.processEpochProofQuoteFromPeer(epochProofQuote);
|
|
303
|
+
}
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
/**Process Attestation From Peer
|
|
307
|
+
* When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
|
|
308
|
+
*
|
|
309
|
+
* @param attestation - The attestation to process.
|
|
310
|
+
*/
|
|
311
|
+
async processAttestationFromPeer(attestation) {
|
|
312
|
+
this.logger.debug(`Received attestation ${attestation.p2pMessageIdentifier()} from external peer.`);
|
|
313
|
+
await this.mempools.attestationPool.addAttestations([attestation]);
|
|
314
|
+
}
|
|
315
|
+
/**Process block from peer
|
|
316
|
+
*
|
|
317
|
+
* Pass the received block to the validator client
|
|
318
|
+
*
|
|
319
|
+
* @param block - The block to process.
|
|
320
|
+
*/
|
|
321
|
+
// REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
|
|
322
|
+
async processBlockFromPeer(block) {
|
|
323
|
+
this.logger.verbose(`Received block ${block.p2pMessageIdentifier()} from external peer.`);
|
|
324
|
+
const attestation = await this.blockReceivedCallback(block);
|
|
325
|
+
// TODO: fix up this pattern - the abstraction is not nice
|
|
326
|
+
// The attestation can be undefined if no handler is registered / the validator deems the block invalid
|
|
327
|
+
if (attestation != undefined) {
|
|
328
|
+
this.logger.verbose(`Broadcasting attestation ${attestation.p2pMessageIdentifier()}`);
|
|
329
|
+
this.broadcastAttestation(attestation);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Broadcast an attestation to all peers.
|
|
334
|
+
* @param attestation - The attestation to broadcast.
|
|
335
|
+
*/
|
|
336
|
+
broadcastAttestation(attestation) {
|
|
337
|
+
this.propagate(attestation);
|
|
338
|
+
}
|
|
339
|
+
processEpochProofQuoteFromPeer(epochProofQuote) {
|
|
340
|
+
this.logger.verbose(`Received epoch proof quote ${epochProofQuote.p2pMessageIdentifier()} from external peer.`);
|
|
341
|
+
this.mempools.epochProofQuotePool.addQuote(epochProofQuote);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Propagates provided message to peers.
|
|
345
|
+
* @param message - The message to propagate.
|
|
346
|
+
*/
|
|
347
|
+
propagate(message) {
|
|
348
|
+
this.logger.debug(`[${message.p2pMessageIdentifier()}] queued`);
|
|
349
|
+
void this.jobQueue.put(async () => {
|
|
350
|
+
await this.sendToPeers(message);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
async processTxFromPeer(tx, peerId) {
|
|
354
|
+
const txHash = tx.getTxHash();
|
|
355
|
+
const txHashString = txHash.toString();
|
|
356
|
+
this.logger.verbose(`Received tx ${txHashString} from external peer.`);
|
|
357
|
+
const isValidTx = await this.validatePropagatedTx(tx, peerId);
|
|
358
|
+
if (isValidTx) {
|
|
359
|
+
await this.mempools.txPool.addTxs([tx]);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Validate a tx that has been requested from a peer.
|
|
364
|
+
*
|
|
365
|
+
* The core component of this validator is that the tx hash MUST match the requested tx hash,
|
|
366
|
+
* In order to perform this check, the tx proof must be verified.
|
|
367
|
+
*
|
|
368
|
+
* Note: This function is called from within `ReqResp.sendRequest` as part of the
|
|
369
|
+
* TX_REQ_PROTOCOL subprotocol validation.
|
|
370
|
+
*
|
|
371
|
+
* @param requestedTxHash - The hash of the tx that was requested.
|
|
372
|
+
* @param responseTx - The tx that was received as a response to the request.
|
|
373
|
+
* @param peerId - The peer ID of the peer that sent the tx.
|
|
374
|
+
* @returns True if the tx is valid, false otherwise.
|
|
375
|
+
*/
|
|
376
|
+
async validateRequestedTx(requestedTxHash, responseTx, peerId) {
|
|
377
|
+
const proofValidator = new TxProofValidator(this.proofVerifier);
|
|
378
|
+
const validProof = await proofValidator.validateTx(responseTx);
|
|
379
|
+
// If the node returns the wrong data, we penalize it
|
|
380
|
+
if (!requestedTxHash.equals(responseTx.getTxHash())) {
|
|
381
|
+
// Returning the wrong data is a low tolerance error
|
|
382
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
if (!validProof) {
|
|
386
|
+
// If the proof is invalid, but the txHash is correct, then this is an active attack and we severly punish
|
|
387
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
async validatePropagatedTx(tx, peerId) {
|
|
393
|
+
const blockNumber = (await this.l2BlockSource.getBlockNumber()) + 1;
|
|
394
|
+
// basic data validation
|
|
395
|
+
const dataValidator = new DataTxValidator();
|
|
396
|
+
const validData = await dataValidator.validateTx(tx);
|
|
397
|
+
if (!validData) {
|
|
398
|
+
// penalize
|
|
399
|
+
this.node.services.pubsub.score.markInvalidMessageDelivery(peerId.toString(), Tx.p2pTopic);
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
// metadata validation
|
|
403
|
+
const metadataValidator = new MetadataTxValidator(new Fr(this.config.l1ChainId), new Fr(blockNumber));
|
|
404
|
+
const validMetadata = await metadataValidator.validateTx(tx);
|
|
405
|
+
if (!validMetadata) {
|
|
406
|
+
// penalize
|
|
407
|
+
this.node.services.pubsub.score.markInvalidMessageDelivery(peerId.toString(), Tx.p2pTopic);
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
// double spend validation
|
|
411
|
+
const doubleSpendValidator = new DoubleSpendTxValidator({
|
|
379
412
|
getNullifierIndex: async (nullifier) => {
|
|
380
|
-
const merkleTree = this.worldStateSynchronizer.
|
|
413
|
+
const merkleTree = this.worldStateSynchronizer.getCommitted();
|
|
381
414
|
const index = await merkleTree.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
382
415
|
return index;
|
|
383
416
|
},
|
|
384
417
|
});
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
418
|
+
const validDoubleSpend = await doubleSpendValidator.validateTx(tx);
|
|
419
|
+
if (!validDoubleSpend) {
|
|
420
|
+
// check if nullifier is older than 20 blocks
|
|
421
|
+
if (blockNumber - this.config.severePeerPenaltyBlockLength > 0) {
|
|
422
|
+
const snapshotValidator = new DoubleSpendTxValidator({
|
|
423
|
+
getNullifierIndex: async (nullifier) => {
|
|
424
|
+
const merkleTree = this.worldStateSynchronizer.getSnapshot(blockNumber - this.config.severePeerPenaltyBlockLength);
|
|
425
|
+
const index = await merkleTree.findLeafIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBuffer());
|
|
426
|
+
return index;
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
const validSnapshot = await snapshotValidator.validateTx(tx);
|
|
430
|
+
// High penalty if nullifier is older than 20 blocks
|
|
431
|
+
if (!validSnapshot) {
|
|
432
|
+
// penalize
|
|
433
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
388
437
|
// penalize
|
|
389
|
-
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.
|
|
438
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
|
|
390
439
|
return false;
|
|
391
440
|
}
|
|
441
|
+
// proof validation
|
|
442
|
+
const proofValidator = new TxProofValidator(this.proofVerifier);
|
|
443
|
+
const validProof = await proofValidator.validateTx(tx);
|
|
444
|
+
if (!validProof) {
|
|
445
|
+
// penalize
|
|
446
|
+
this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
return true;
|
|
392
450
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
}
|
|
432
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlicDJwX3NlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZS9saWJwMnBfc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsZ0JBQWdCLEVBQ2hCLGFBQWEsRUFJYixZQUFZLEVBRVosU0FBUyxFQUNULFlBQVksRUFDWixFQUFFLEVBQ0YsTUFBTSxHQUVQLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFJbkUsT0FBTyxFQUE0QyxTQUFTLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNsRyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNsRyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxPQUFPLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hGLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUt0QyxPQUFPLEVBQ0wsZUFBZSxFQUNmLHNCQUFzQixFQUN0QixtQkFBbUIsRUFDbkIsZ0JBQWdCLEdB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
|
|
451
|
+
getPeerScore(peerId) {
|
|
452
|
+
return this.node.services.pubsub.score.score(peerId.toString());
|
|
453
|
+
}
|
|
454
|
+
async sendToPeers(message) {
|
|
455
|
+
const parent = message.constructor;
|
|
456
|
+
const identifier = message.p2pMessageIdentifier().toString();
|
|
457
|
+
this.logger.verbose(`[${identifier}] sending`);
|
|
458
|
+
const recipientsNum = await this.publishToTopic(parent.p2pTopic, message.toBuffer());
|
|
459
|
+
this.logger.verbose(`[${identifier}] sent to ${recipientsNum} peers`);
|
|
460
|
+
}
|
|
461
|
+
// Libp2p seems to hang sometimes if new peers are initiating connections.
|
|
462
|
+
async stopLibP2P() {
|
|
463
|
+
const TIMEOUT_MS = 5000; // 5 seconds timeout
|
|
464
|
+
const timeout = new Promise((resolve, reject) => {
|
|
465
|
+
setTimeout(() => reject(new Error('Timeout during libp2p.stop()')), TIMEOUT_MS);
|
|
466
|
+
});
|
|
467
|
+
try {
|
|
468
|
+
await Promise.race([this.node.stop(), timeout]);
|
|
469
|
+
this.logger.debug('Libp2p stopped');
|
|
470
|
+
}
|
|
471
|
+
catch (error) {
|
|
472
|
+
this.logger.error('Error during stop or timeout:', error);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
(() => {
|
|
477
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
478
|
+
_processAttestationFromPeer_decorators = [trackSpan('Libp2pService.processAttestationFromPeer', attestation => ({
|
|
479
|
+
[Attributes.BLOCK_NUMBER]: attestation.payload.header.globalVariables.blockNumber.toNumber(),
|
|
480
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
|
|
481
|
+
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
482
|
+
[Attributes.P2P_ID]: attestation.p2pMessageIdentifier().toString(),
|
|
483
|
+
}))];
|
|
484
|
+
_processBlockFromPeer_decorators = [trackSpan('Libp2pService.processBlockFromPeer', block => ({
|
|
485
|
+
[Attributes.BLOCK_NUMBER]: block.payload.header.globalVariables.blockNumber.toNumber(),
|
|
486
|
+
[Attributes.SLOT_NUMBER]: block.payload.header.globalVariables.slotNumber.toNumber(),
|
|
487
|
+
[Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
|
|
488
|
+
[Attributes.P2P_ID]: block.p2pMessageIdentifier().toString(),
|
|
489
|
+
}))];
|
|
490
|
+
_broadcastAttestation_decorators = [trackSpan('Libp2pService.broadcastAttestation', attestation => ({
|
|
491
|
+
[Attributes.BLOCK_NUMBER]: attestation.payload.header.globalVariables.blockNumber.toNumber(),
|
|
492
|
+
[Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
|
|
493
|
+
[Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
|
|
494
|
+
[Attributes.P2P_ID]: attestation.p2pMessageIdentifier().toString(),
|
|
495
|
+
}))];
|
|
496
|
+
__esDecorate(_a, null, _processAttestationFromPeer_decorators, { kind: "method", name: "processAttestationFromPeer", static: false, private: false, access: { has: obj => "processAttestationFromPeer" in obj, get: obj => obj.processAttestationFromPeer }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
497
|
+
__esDecorate(_a, null, _processBlockFromPeer_decorators, { kind: "method", name: "processBlockFromPeer", static: false, private: false, access: { has: obj => "processBlockFromPeer" in obj, get: obj => obj.processBlockFromPeer }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
498
|
+
__esDecorate(_a, null, _broadcastAttestation_decorators, { kind: "method", name: "broadcastAttestation", static: false, private: false, access: { has: obj => "broadcastAttestation" in obj, get: obj => obj.broadcastAttestation }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
499
|
+
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
500
|
+
})(),
|
|
501
|
+
_a;
|
|
502
|
+
})();
|
|
503
|
+
export { LibP2PService };
|
|
504
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlicDJwX3NlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZS9saWJwMnBfc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixhQUFhLEVBRWIsZUFBZSxFQUdmLFlBQVksRUFFWixTQUFTLEVBQ1QsWUFBWSxFQUNaLEVBQUUsRUFDRixNQUFNLEdBRVAsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDeEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUVuRSxPQUFPLEVBQUUsVUFBVSxFQUF3QixVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFHbEcsT0FBTyxFQUE0QyxTQUFTLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNsRyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUNsRyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDaEQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUU1QyxPQUFPLGlCQUFpQixDQUFDO0FBQ3pCLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hGLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxFQUFFLFlBQVksRUFBRSxN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
|