@aztec/aztec-node 0.85.0-alpha-testnet.3 → 0.85.0-alpha-testnet.5

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.
@@ -17,7 +17,11 @@ export declare class Sentinel implements L2BlockStreamEventHandler {
17
17
  protected l2TipsStore: L2TipsStore;
18
18
  protected initialSlot: bigint | undefined;
19
19
  protected lastProcessedSlot: bigint | undefined;
20
- protected slotNumberToArchive: Map<bigint, string>;
20
+ protected slotNumberToBlock: Map<bigint, {
21
+ blockNumber: number;
22
+ archive: string;
23
+ attestors: EthAddress[];
24
+ }>;
21
25
  constructor(epochCache: EpochCache, archiver: L2BlockSource, p2p: P2PClient, store: SentinelStore, logger?: import("@aztec/foundation/log").Logger);
22
26
  start(): Promise<void>;
23
27
  /** Loads initial slot and initializes blockstream. We will not process anything at or before the initial slot. */
@@ -1 +1 @@
1
- {"version":3,"file":"sentinel.d.ts","sourceRoot":"","sources":["../../src/sentinel/sentinel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC/B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,qBAAa,QAAS,YAAW,yBAAyB;IAUtD,SAAS,CAAC,UAAU,EAAE,UAAU;IAChC,SAAS,CAAC,QAAQ,EAAE,aAAa;IACjC,SAAS,CAAC,GAAG,EAAE,SAAS;IACxB,SAAS,CAAC,KAAK,EAAE,aAAa;IAC9B,SAAS,CAAC,MAAM;IAblB,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IACzC,SAAS,CAAC,WAAW,EAAG,aAAa,CAAC;IACtC,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,SAAS,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,SAAS,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;gBAGnD,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,aAAa,EACpB,MAAM,yCAAgC;IAOrC,KAAK;IAKlB,kHAAkH;cAClG,IAAI;IAOb,IAAI;IAIE,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB7E;;;;OAIG;IACU,IAAI;IAmBjB;;;;OAIG;cACa,gBAAgB,CAAC,WAAW,EAAE,MAAM;IAkCpD;;;OAGG;cACa,WAAW,CAAC,IAAI,EAAE,MAAM;IAexC,0CAA0C;cAC1B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE;;;IAmD1G,wDAAwD;IACxD,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAIxG,0DAA0D;IAC7C,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC;IAiBrD,SAAS,CAAC,wBAAwB,CAChC,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,UAAU,EAAE,sBAAsB,EAClC,QAAQ,CAAC,EAAE,MAAM,GAChB,cAAc;IAejB,SAAS,CAAC,aAAa,CACrB,OAAO,EAAE,sBAAsB,EAC/B,iBAAiB,EAAE,mBAAmB,EACtC,MAAM,EAAE,qBAAqB;;;;;IAW/B,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;;;;;CAOnD"}
1
+ {"version":3,"file":"sentinel.d.ts","sourceRoot":"","sources":["../../src/sentinel/sentinel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EACL,KAAK,aAAa,EAClB,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAE/B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,qBAAa,QAAS,YAAW,yBAAyB;IAWtD,SAAS,CAAC,UAAU,EAAE,UAAU;IAChC,SAAS,CAAC,QAAQ,EAAE,aAAa;IACjC,SAAS,CAAC,GAAG,EAAE,SAAS;IACxB,SAAS,CAAC,KAAK,EAAE,aAAa;IAC9B,SAAS,CAAC,MAAM;IAdlB,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC;IACzC,SAAS,CAAC,WAAW,EAAG,aAAa,CAAC;IACtC,SAAS,CAAC,WAAW,EAAE,WAAW,CAAC;IAEnC,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,SAAS,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAC/F;gBAGA,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,SAAS,EACd,KAAK,EAAE,aAAa,EACpB,MAAM,yCAAgC;IAOrC,KAAK;IAKlB,kHAAkH;cAClG,IAAI;IAOb,IAAI;IAIE,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB7E;;;;OAIG;IACU,IAAI;IAmBjB;;;;OAIG;cACa,gBAAgB,CAAC,WAAW,EAAE,MAAM;IAkCpD;;;OAGG;cACa,WAAW,CAAC,IAAI,EAAE,MAAM;IAexC,0CAA0C;cAC1B,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE;;;IAwD1G,wDAAwD;IACxD,SAAS,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,MAAM,EAAE,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAIxG,0DAA0D;IAC7C,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC;IAiBrD,SAAS,CAAC,wBAAwB,CAChC,OAAO,EAAE,KAAK,MAAM,EAAE,EACtB,UAAU,EAAE,sBAAsB,EAClC,QAAQ,CAAC,EAAE,MAAM,GAChB,cAAc;IAejB,SAAS,CAAC,aAAa,CACrB,OAAO,EAAE,sBAAsB,EAC/B,iBAAiB,EAAE,mBAAmB,EACtC,MAAM,EAAE,qBAAqB;;;;;IAW/B,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS;;;;;CAOnD"}
@@ -3,7 +3,7 @@ import { EthAddress } from '@aztec/foundation/eth-address';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import { RunningPromise } from '@aztec/foundation/running-promise';
5
5
  import { L2TipsMemoryStore } from '@aztec/kv-store/stores';
6
- import { L2BlockStream } from '@aztec/stdlib/block';
6
+ import { L2BlockStream, getAttestationsFromPublishedL2Block } from '@aztec/stdlib/block';
7
7
  import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
8
8
  export class Sentinel {
9
9
  epochCache;
@@ -16,14 +16,14 @@ export class Sentinel {
16
16
  l2TipsStore;
17
17
  initialSlot;
18
18
  lastProcessedSlot;
19
- slotNumberToArchive;
19
+ slotNumberToBlock;
20
20
  constructor(epochCache, archiver, p2p, store, logger = createLogger('node:sentinel')){
21
21
  this.epochCache = epochCache;
22
22
  this.archiver = archiver;
23
23
  this.p2p = p2p;
24
24
  this.store = store;
25
25
  this.logger = logger;
26
- this.slotNumberToArchive = new Map();
26
+ this.slotNumberToBlock = new Map();
27
27
  this.l2TipsStore = new L2TipsMemoryStore();
28
28
  const interval = epochCache.getL1Constants().ethereumSlotDuration * 1000 / 4;
29
29
  this.runningPromise = new RunningPromise(this.work.bind(this), logger, interval);
@@ -46,16 +46,20 @@ export class Sentinel {
46
46
  async handleBlockStreamEvent(event) {
47
47
  await this.l2TipsStore.handleBlockStreamEvent(event);
48
48
  if (event.type === 'blocks-added') {
49
- // Store mapping from slot to archive
49
+ // Store mapping from slot to archive, block number, and attestors
50
50
  for (const block of event.blocks){
51
- this.slotNumberToArchive.set(block.block.header.getSlot(), block.block.archive.root.toString());
51
+ this.slotNumberToBlock.set(block.block.header.getSlot(), {
52
+ blockNumber: block.block.number,
53
+ archive: block.block.archive.root.toString(),
54
+ attestors: await Promise.all(getAttestationsFromPublishedL2Block(block).map((att)=>att.getSender()))
55
+ });
52
56
  }
53
57
  // Prune the archive map to only keep at most N entries
54
58
  const historyLength = this.store.getHistoryLength();
55
- if (this.slotNumberToArchive.size > historyLength) {
56
- const toDelete = Array.from(this.slotNumberToArchive.keys()).sort((a, b)=>Number(a - b)).slice(0, this.slotNumberToArchive.size - historyLength);
59
+ if (this.slotNumberToBlock.size > historyLength) {
60
+ const toDelete = Array.from(this.slotNumberToBlock.keys()).sort((a, b)=>Number(a - b)).slice(0, this.slotNumberToBlock.size - historyLength);
57
61
  for (const key of toDelete){
58
- this.slotNumberToArchive.delete(key);
62
+ this.slotNumberToBlock.delete(key);
59
63
  }
60
64
  }
61
65
  }
@@ -147,16 +151,21 @@ export class Sentinel {
147
151
  // Check if there is an L2 block in L1 for this L2 slot
148
152
  // Here we get all attestations for the block mined at the given slot,
149
153
  // or all attestations for all proposals in the slot if no block was mined.
150
- const archive = this.slotNumberToArchive.get(slot);
151
- const attested = await this.p2p.getAttestationsForSlot(slot, archive);
152
- const attestors = new Set(await Promise.all(attested.map((a)=>a.getSender().then((a)=>a.toString()))));
154
+ // We gather from both p2p (contains the ones seen on the p2p layer) and archiver
155
+ // (contains the ones synced from mined blocks, which we may have missed from p2p).
156
+ const block = this.slotNumberToBlock.get(slot);
157
+ const p2pAttested = await this.p2p.getAttestationsForSlot(slot, block?.archive);
158
+ const attestors = new Set([
159
+ ...await Promise.all(p2pAttested.map((a)=>a.getSender().then((s)=>s.toString()))),
160
+ ...block?.attestors.map((a)=>a.toString()) ?? []
161
+ ]);
153
162
  // We assume that there was a block proposal if at least one of the validators attested to it.
154
163
  // It could be the case that every single validator failed, and we could differentiate it by having
155
164
  // this node re-execute every block proposal it sees and storing it in the attestation pool.
156
165
  // But we'll leave that corner case out to reduce pressure on the node.
157
- const blockStatus = archive ? 'mined' : attestors.size > 0 ? 'proposed' : 'missed';
166
+ const blockStatus = block ? 'mined' : attestors.size > 0 ? 'proposed' : 'missed';
158
167
  this.logger.debug(`Block for slot ${slot} was ${blockStatus}`, {
159
- archive,
168
+ ...block,
160
169
  slot
161
170
  });
162
171
  // Get attestors that failed their duties for this block, but only if there was a block proposed
@@ -164,7 +173,7 @@ export class Sentinel {
164
173
  this.logger.debug(`Retrieved ${attestors.size} attestors out of ${committee.length} for slot ${slot}`, {
165
174
  blockStatus,
166
175
  proposer: proposer.toString(),
167
- archive,
176
+ ...block,
168
177
  slot,
169
178
  attestors: [
170
179
  ...attestors
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/aztec-node",
3
- "version": "0.85.0-alpha-testnet.3",
3
+ "version": "0.85.0-alpha-testnet.5",
4
4
  "main": "dest/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -63,26 +63,27 @@
63
63
  ]
64
64
  },
65
65
  "dependencies": {
66
- "@aztec/archiver": "0.85.0-alpha-testnet.3",
67
- "@aztec/bb-prover": "0.85.0-alpha-testnet.3",
68
- "@aztec/blob-sink": "0.85.0-alpha-testnet.3",
69
- "@aztec/constants": "0.85.0-alpha-testnet.3",
70
- "@aztec/epoch-cache": "0.85.0-alpha-testnet.3",
71
- "@aztec/ethereum": "0.85.0-alpha-testnet.3",
72
- "@aztec/foundation": "0.85.0-alpha-testnet.3",
73
- "@aztec/kv-store": "0.85.0-alpha-testnet.3",
74
- "@aztec/l1-artifacts": "0.85.0-alpha-testnet.3",
75
- "@aztec/merkle-tree": "0.85.0-alpha-testnet.3",
76
- "@aztec/node-lib": "0.85.0-alpha-testnet.3",
77
- "@aztec/p2p": "0.85.0-alpha-testnet.3",
78
- "@aztec/protocol-contracts": "0.85.0-alpha-testnet.3",
79
- "@aztec/prover-client": "0.85.0-alpha-testnet.3",
80
- "@aztec/sequencer-client": "0.85.0-alpha-testnet.3",
81
- "@aztec/simulator": "0.85.0-alpha-testnet.3",
82
- "@aztec/stdlib": "0.85.0-alpha-testnet.3",
83
- "@aztec/telemetry-client": "0.85.0-alpha-testnet.3",
84
- "@aztec/validator-client": "0.85.0-alpha-testnet.3",
85
- "@aztec/world-state": "0.85.0-alpha-testnet.3",
66
+ "@aztec/archiver": "0.85.0-alpha-testnet.5",
67
+ "@aztec/bb-prover": "0.85.0-alpha-testnet.5",
68
+ "@aztec/blob-sink": "0.85.0-alpha-testnet.5",
69
+ "@aztec/constants": "0.85.0-alpha-testnet.5",
70
+ "@aztec/epoch-cache": "0.85.0-alpha-testnet.5",
71
+ "@aztec/ethereum": "0.85.0-alpha-testnet.5",
72
+ "@aztec/foundation": "0.85.0-alpha-testnet.5",
73
+ "@aztec/kv-store": "0.85.0-alpha-testnet.5",
74
+ "@aztec/l1-artifacts": "0.85.0-alpha-testnet.5",
75
+ "@aztec/merkle-tree": "0.85.0-alpha-testnet.5",
76
+ "@aztec/node-lib": "0.85.0-alpha-testnet.5",
77
+ "@aztec/noir-protocol-circuits-types": "0.85.0-alpha-testnet.5",
78
+ "@aztec/p2p": "0.85.0-alpha-testnet.5",
79
+ "@aztec/protocol-contracts": "0.85.0-alpha-testnet.5",
80
+ "@aztec/prover-client": "0.85.0-alpha-testnet.5",
81
+ "@aztec/sequencer-client": "0.85.0-alpha-testnet.5",
82
+ "@aztec/simulator": "0.85.0-alpha-testnet.5",
83
+ "@aztec/stdlib": "0.85.0-alpha-testnet.5",
84
+ "@aztec/telemetry-client": "0.85.0-alpha-testnet.5",
85
+ "@aztec/validator-client": "0.85.0-alpha-testnet.5",
86
+ "@aztec/world-state": "0.85.0-alpha-testnet.5",
86
87
  "koa": "^2.16.1",
87
88
  "koa-router": "^12.0.0",
88
89
  "tslib": "^2.4.0",
@@ -10,6 +10,7 @@ import {
10
10
  L2BlockStream,
11
11
  type L2BlockStreamEvent,
12
12
  type L2BlockStreamEventHandler,
13
+ getAttestationsFromPublishedL2Block,
13
14
  } from '@aztec/stdlib/block';
14
15
  import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
15
16
  import type {
@@ -29,7 +30,8 @@ export class Sentinel implements L2BlockStreamEventHandler {
29
30
 
30
31
  protected initialSlot: bigint | undefined;
31
32
  protected lastProcessedSlot: bigint | undefined;
32
- protected slotNumberToArchive: Map<bigint, string> = new Map();
33
+ protected slotNumberToBlock: Map<bigint, { blockNumber: number; archive: string; attestors: EthAddress[] }> =
34
+ new Map();
33
35
 
34
36
  constructor(
35
37
  protected epochCache: EpochCache,
@@ -63,19 +65,23 @@ export class Sentinel implements L2BlockStreamEventHandler {
63
65
  public async handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void> {
64
66
  await this.l2TipsStore.handleBlockStreamEvent(event);
65
67
  if (event.type === 'blocks-added') {
66
- // Store mapping from slot to archive
68
+ // Store mapping from slot to archive, block number, and attestors
67
69
  for (const block of event.blocks) {
68
- this.slotNumberToArchive.set(block.block.header.getSlot(), block.block.archive.root.toString());
70
+ this.slotNumberToBlock.set(block.block.header.getSlot(), {
71
+ blockNumber: block.block.number,
72
+ archive: block.block.archive.root.toString(),
73
+ attestors: await Promise.all(getAttestationsFromPublishedL2Block(block).map(att => att.getSender())),
74
+ });
69
75
  }
70
76
 
71
77
  // Prune the archive map to only keep at most N entries
72
78
  const historyLength = this.store.getHistoryLength();
73
- if (this.slotNumberToArchive.size > historyLength) {
74
- const toDelete = Array.from(this.slotNumberToArchive.keys())
79
+ if (this.slotNumberToBlock.size > historyLength) {
80
+ const toDelete = Array.from(this.slotNumberToBlock.keys())
75
81
  .sort((a, b) => Number(a - b))
76
- .slice(0, this.slotNumberToArchive.size - historyLength);
82
+ .slice(0, this.slotNumberToBlock.size - historyLength);
77
83
  for (const key of toDelete) {
78
- this.slotNumberToArchive.delete(key);
84
+ this.slotNumberToBlock.delete(key);
79
85
  }
80
86
  }
81
87
  }
@@ -171,16 +177,21 @@ export class Sentinel implements L2BlockStreamEventHandler {
171
177
 
172
178
  // Here we get all attestations for the block mined at the given slot,
173
179
  // or all attestations for all proposals in the slot if no block was mined.
174
- const archive = this.slotNumberToArchive.get(slot);
175
- const attested = await this.p2p.getAttestationsForSlot(slot, archive);
176
- const attestors = new Set(await Promise.all(attested.map(a => a.getSender().then(a => a.toString()))));
180
+ // We gather from both p2p (contains the ones seen on the p2p layer) and archiver
181
+ // (contains the ones synced from mined blocks, which we may have missed from p2p).
182
+ const block = this.slotNumberToBlock.get(slot);
183
+ const p2pAttested = await this.p2p.getAttestationsForSlot(slot, block?.archive);
184
+ const attestors = new Set([
185
+ ...(await Promise.all(p2pAttested.map(a => a.getSender().then(s => s.toString())))),
186
+ ...(block?.attestors.map(a => a.toString()) ?? []),
187
+ ]);
177
188
 
178
189
  // We assume that there was a block proposal if at least one of the validators attested to it.
179
190
  // It could be the case that every single validator failed, and we could differentiate it by having
180
191
  // this node re-execute every block proposal it sees and storing it in the attestation pool.
181
192
  // But we'll leave that corner case out to reduce pressure on the node.
182
- const blockStatus = archive ? 'mined' : attestors.size > 0 ? 'proposed' : 'missed';
183
- this.logger.debug(`Block for slot ${slot} was ${blockStatus}`, { archive, slot });
193
+ const blockStatus = block ? 'mined' : attestors.size > 0 ? 'proposed' : 'missed';
194
+ this.logger.debug(`Block for slot ${slot} was ${blockStatus}`, { ...block, slot });
184
195
 
185
196
  // Get attestors that failed their duties for this block, but only if there was a block proposed
186
197
  const missedAttestors = new Set(
@@ -192,7 +203,7 @@ export class Sentinel implements L2BlockStreamEventHandler {
192
203
  this.logger.debug(`Retrieved ${attestors.size} attestors out of ${committee.length} for slot ${slot}`, {
193
204
  blockStatus,
194
205
  proposer: proposer.toString(),
195
- archive,
206
+ ...block,
196
207
  slot,
197
208
  attestors: [...attestors],
198
209
  missedAttestors: [...missedAttestors],