@aztec/archiver 2.1.0-rc.10 → 2.1.0-rc.11

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.
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/archiver/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EAEzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,6BAA6B,CAAC;AAErF,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,cAAc,EAAE,gBAAgB,EAChC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,EACnD,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC,CAoF9B"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/archiver/validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EACL,KAAK,gBAAgB,EAErB,KAAK,mBAAmB,EAEzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,iBAAiB,EAAkB,MAAM,6BAA6B,CAAC;AAErF,YAAY,EAAE,mBAAmB,EAAE,CAAC;AAEpC;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,cAAc,EAAE,gBAAgB,EAChC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,EACnD,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,mBAAmB,CAAC,CA4E9B"}
@@ -1,12 +1,12 @@
1
1
  import { compactArray } from '@aztec/foundation/collection';
2
- import { getAttestationsFromPublishedL2Block } from '@aztec/stdlib/block';
2
+ import { getAttestationInfoFromPublishedL2Block } from '@aztec/stdlib/block';
3
3
  import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
4
4
  /**
5
5
  * Validates the attestations submitted for the given block.
6
6
  * Returns true if the attestations are valid and sufficient, false otherwise.
7
7
  */ export async function validateBlockAttestations(publishedBlock, epochCache, constants, logger) {
8
- const attestations = getAttestationsFromPublishedL2Block(publishedBlock);
9
- const attestors = compactArray(attestations.map((a)=>a?.tryGetSender()));
8
+ const attestorInfos = getAttestationInfoFromPublishedL2Block(publishedBlock);
9
+ const attestors = compactArray(attestorInfos.map((info)=>'address' in info ? info.address : undefined));
10
10
  const { block } = publishedBlock;
11
11
  const blockHash = await block.hash().then((hash)=>hash.toString());
12
12
  const archiveRoot = block.archive.root.toString();
@@ -22,8 +22,7 @@ import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
22
22
  };
23
23
  logger?.debug(`Validating attestations for block ${block.number} at slot ${slot} in epoch ${epoch}`, {
24
24
  committee: (committee ?? []).map((member)=>member.toString()),
25
- recoveredAttestors: attestors.map((member)=>member.toString()),
26
- invalidAttestations: attestations.filter((a)=>a !== undefined && a.tryGetSender() === undefined).map((a)=>a?.toInspect()),
25
+ recoveredAttestors: attestorInfos,
27
26
  postedAttestations: publishedBlock.attestations.map((a)=>(a.address.isZero() ? a.signature : a.address).toString()),
28
27
  ...logData
29
28
  });
@@ -35,58 +34,54 @@ import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
35
34
  }
36
35
  const committeeSet = new Set(committee.map((member)=>member.toString()));
37
36
  const requiredAttestationCount = Math.floor(committee.length * 2 / 3) + 1;
38
- for(let i = 0; i < attestations.length; i++){
39
- const attestation = attestations[i];
40
- // Skip empty signatures (undefined entries)
41
- if (attestation === undefined) {
42
- continue;
43
- }
44
- const signer = attestation.tryGetSender()?.toString();
45
- if (signer !== undefined && committeeSet.has(signer)) {
46
- continue;
47
- }
48
- if (signer === undefined) {
49
- logger?.warn(`Attestation with invalid signature at slot ${slot}`, {
50
- committee,
51
- ...logData
52
- });
53
- } else {
54
- logger?.warn(`Attestation from non-committee member ${signer} at slot ${slot}`, {
55
- committee,
56
- ...logData
57
- });
58
- }
59
- const reason = 'invalid-attestation';
60
- return {
37
+ const failedValidationResult = (reason)=>({
61
38
  valid: false,
62
39
  reason,
63
- invalidIndex: i,
64
40
  block: publishedBlock.block.toBlockInfo(),
65
41
  committee,
66
42
  seed,
67
43
  epoch,
68
44
  attestors,
69
45
  attestations: publishedBlock.attestations
70
- };
46
+ });
47
+ for(let i = 0; i < attestorInfos.length; i++){
48
+ const info = attestorInfos[i];
49
+ // Fail on invalid signatures (no address recovered)
50
+ if (info.status === 'invalid-signature' || info.status === 'empty') {
51
+ logger?.warn(`Attestation with empty or invalid signature at slot ${slot}`, {
52
+ committee,
53
+ invalidIndex: i,
54
+ ...logData
55
+ });
56
+ return {
57
+ ...failedValidationResult('invalid-attestation'),
58
+ invalidIndex: i
59
+ };
60
+ }
61
+ // Check if the attestor is in the committee
62
+ if (info.status === 'recovered-from-signature' || info.status === 'provided-as-address') {
63
+ const signer = info.address.toString();
64
+ if (!committeeSet.has(signer)) {
65
+ logger?.warn(`Attestation from non-committee member ${signer} at slot ${slot}`, {
66
+ committee,
67
+ invalidIndex: i,
68
+ ...logData
69
+ });
70
+ return {
71
+ ...failedValidationResult('invalid-attestation'),
72
+ invalidIndex: i
73
+ };
74
+ }
75
+ }
71
76
  }
72
- const validAttestationCount = compactArray(attestations).length;
77
+ const validAttestationCount = attestorInfos.filter((info)=>info.status === 'recovered-from-signature').length;
73
78
  if (validAttestationCount < requiredAttestationCount) {
74
79
  logger?.warn(`Insufficient attestations for block at slot ${slot}`, {
75
80
  requiredAttestations: requiredAttestationCount,
76
81
  actualAttestations: validAttestationCount,
77
82
  ...logData
78
83
  });
79
- const reason = 'insufficient-attestations';
80
- return {
81
- valid: false,
82
- reason,
83
- block: publishedBlock.block.toBlockInfo(),
84
- committee,
85
- seed,
86
- epoch,
87
- attestors,
88
- attestations: publishedBlock.attestations
89
- };
84
+ return failedValidationResult('insufficient-attestations');
90
85
  }
91
86
  logger?.debug(`Block attestations validated successfully for block ${block.number} at slot ${slot}`, logData);
92
87
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/archiver",
3
- "version": "2.1.0-rc.10",
3
+ "version": "2.1.0-rc.11",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -66,18 +66,18 @@
66
66
  ]
67
67
  },
68
68
  "dependencies": {
69
- "@aztec/blob-lib": "2.1.0-rc.10",
70
- "@aztec/blob-sink": "2.1.0-rc.10",
71
- "@aztec/constants": "2.1.0-rc.10",
72
- "@aztec/epoch-cache": "2.1.0-rc.10",
73
- "@aztec/ethereum": "2.1.0-rc.10",
74
- "@aztec/foundation": "2.1.0-rc.10",
75
- "@aztec/kv-store": "2.1.0-rc.10",
76
- "@aztec/l1-artifacts": "2.1.0-rc.10",
77
- "@aztec/noir-protocol-circuits-types": "2.1.0-rc.10",
78
- "@aztec/protocol-contracts": "2.1.0-rc.10",
79
- "@aztec/stdlib": "2.1.0-rc.10",
80
- "@aztec/telemetry-client": "2.1.0-rc.10",
69
+ "@aztec/blob-lib": "2.1.0-rc.11",
70
+ "@aztec/blob-sink": "2.1.0-rc.11",
71
+ "@aztec/constants": "2.1.0-rc.11",
72
+ "@aztec/epoch-cache": "2.1.0-rc.11",
73
+ "@aztec/ethereum": "2.1.0-rc.11",
74
+ "@aztec/foundation": "2.1.0-rc.11",
75
+ "@aztec/kv-store": "2.1.0-rc.11",
76
+ "@aztec/l1-artifacts": "2.1.0-rc.11",
77
+ "@aztec/noir-protocol-circuits-types": "2.1.0-rc.11",
78
+ "@aztec/protocol-contracts": "2.1.0-rc.11",
79
+ "@aztec/stdlib": "2.1.0-rc.11",
80
+ "@aztec/telemetry-client": "2.1.0-rc.11",
81
81
  "@spalladino/viem": "2.38.2-eip7594.0",
82
82
  "lodash.groupby": "^4.6.0",
83
83
  "lodash.omit": "^4.5.0",
@@ -3,8 +3,9 @@ import { compactArray } from '@aztec/foundation/collection';
3
3
  import type { Logger } from '@aztec/foundation/log';
4
4
  import {
5
5
  type PublishedL2Block,
6
+ type ValidateBlockNegativeResult,
6
7
  type ValidateBlockResult,
7
- getAttestationsFromPublishedL2Block,
8
+ getAttestationInfoFromPublishedL2Block,
8
9
  } from '@aztec/stdlib/block';
9
10
  import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
10
11
 
@@ -20,8 +21,8 @@ export async function validateBlockAttestations(
20
21
  constants: Pick<L1RollupConstants, 'epochDuration'>,
21
22
  logger?: Logger,
22
23
  ): Promise<ValidateBlockResult> {
23
- const attestations = getAttestationsFromPublishedL2Block(publishedBlock);
24
- const attestors = compactArray(attestations.map(a => a?.tryGetSender()));
24
+ const attestorInfos = getAttestationInfoFromPublishedL2Block(publishedBlock);
25
+ const attestors = compactArray(attestorInfos.map(info => ('address' in info ? info.address : undefined)));
25
26
  const { block } = publishedBlock;
26
27
  const blockHash = await block.hash().then(hash => hash.toString());
27
28
  const archiveRoot = block.archive.root.toString();
@@ -32,10 +33,7 @@ export async function validateBlockAttestations(
32
33
 
33
34
  logger?.debug(`Validating attestations for block ${block.number} at slot ${slot} in epoch ${epoch}`, {
34
35
  committee: (committee ?? []).map(member => member.toString()),
35
- recoveredAttestors: attestors.map(member => member.toString()),
36
- invalidAttestations: attestations
37
- .filter(a => a !== undefined && a.tryGetSender() === undefined)
38
- .map(a => a?.toInspect()),
36
+ recoveredAttestors: attestorInfos,
39
37
  postedAttestations: publishedBlock.attestations.map(a => (a.address.isZero() ? a.signature : a.address).toString()),
40
38
  ...logData,
41
39
  });
@@ -48,57 +46,52 @@ export async function validateBlockAttestations(
48
46
  const committeeSet = new Set(committee.map(member => member.toString()));
49
47
  const requiredAttestationCount = Math.floor((committee.length * 2) / 3) + 1;
50
48
 
51
- for (let i = 0; i < attestations.length; i++) {
52
- const attestation = attestations[i];
49
+ const failedValidationResult = <TReason extends ValidateBlockNegativeResult['reason']>(reason: TReason) => ({
50
+ valid: false as const,
51
+ reason,
52
+ block: publishedBlock.block.toBlockInfo(),
53
+ committee,
54
+ seed,
55
+ epoch,
56
+ attestors,
57
+ attestations: publishedBlock.attestations,
58
+ });
53
59
 
54
- // Skip empty signatures (undefined entries)
55
- if (attestation === undefined) {
56
- continue;
57
- }
60
+ for (let i = 0; i < attestorInfos.length; i++) {
61
+ const info = attestorInfos[i];
58
62
 
59
- const signer = attestation.tryGetSender()?.toString();
60
- if (signer !== undefined && committeeSet.has(signer)) {
61
- continue;
63
+ // Fail on invalid signatures (no address recovered)
64
+ if (info.status === 'invalid-signature' || info.status === 'empty') {
65
+ logger?.warn(`Attestation with empty or invalid signature at slot ${slot}`, {
66
+ committee,
67
+ invalidIndex: i,
68
+ ...logData,
69
+ });
70
+ return { ...failedValidationResult('invalid-attestation'), invalidIndex: i };
62
71
  }
63
72
 
64
- if (signer === undefined) {
65
- logger?.warn(`Attestation with invalid signature at slot ${slot}`, { committee, ...logData });
66
- } else {
67
- logger?.warn(`Attestation from non-committee member ${signer} at slot ${slot}`, { committee, ...logData });
73
+ // Check if the attestor is in the committee
74
+ if (info.status === 'recovered-from-signature' || info.status === 'provided-as-address') {
75
+ const signer = info.address.toString();
76
+ if (!committeeSet.has(signer)) {
77
+ logger?.warn(`Attestation from non-committee member ${signer} at slot ${slot}`, {
78
+ committee,
79
+ invalidIndex: i,
80
+ ...logData,
81
+ });
82
+ return { ...failedValidationResult('invalid-attestation'), invalidIndex: i };
83
+ }
68
84
  }
69
-
70
- const reason = 'invalid-attestation';
71
- return {
72
- valid: false,
73
- reason,
74
- invalidIndex: i,
75
- block: publishedBlock.block.toBlockInfo(),
76
- committee,
77
- seed,
78
- epoch,
79
- attestors,
80
- attestations: publishedBlock.attestations,
81
- };
82
85
  }
83
86
 
84
- const validAttestationCount = compactArray(attestations).length;
87
+ const validAttestationCount = attestorInfos.filter(info => info.status === 'recovered-from-signature').length;
85
88
  if (validAttestationCount < requiredAttestationCount) {
86
89
  logger?.warn(`Insufficient attestations for block at slot ${slot}`, {
87
90
  requiredAttestations: requiredAttestationCount,
88
91
  actualAttestations: validAttestationCount,
89
92
  ...logData,
90
93
  });
91
- const reason = 'insufficient-attestations';
92
- return {
93
- valid: false,
94
- reason,
95
- block: publishedBlock.block.toBlockInfo(),
96
- committee,
97
- seed,
98
- epoch,
99
- attestors,
100
- attestations: publishedBlock.attestations,
101
- };
94
+ return failedValidationResult('insufficient-attestations');
102
95
  }
103
96
 
104
97
  logger?.debug(`Block attestations validated successfully for block ${block.number} at slot ${slot}`, logData);