@aztec/stdlib 2.1.0-rc.10 → 2.1.0-rc.12

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.
@@ -0,0 +1,30 @@
1
+ import type { EthAddress } from '@aztec/foundation/eth-address';
2
+ import type { L2Block } from './l2_block.js';
3
+ import type { CommitteeAttestation } from './proposal/committee_attestation.js';
4
+ /**
5
+ * Status indicating how the attestation address was determined
6
+ */
7
+ export type AttestationStatus = 'recovered-from-signature' | 'provided-as-address' | 'invalid-signature' | 'empty';
8
+ /**
9
+ * Information about an attestation extracted from a published block
10
+ */
11
+ export type AttestationInfo = {
12
+ /** The validator's address, undefined if signature recovery failed or empty */
13
+ address?: undefined;
14
+ /** How the attestation address was determined */
15
+ status: Extract<AttestationStatus, 'invalid-signature' | 'empty'>;
16
+ } | {
17
+ /** The validator's address */
18
+ address: EthAddress;
19
+ /** How the attestation address was determined */
20
+ status: Extract<AttestationStatus, 'provided-as-address' | 'recovered-from-signature'>;
21
+ };
22
+ /**
23
+ * Extracts attestation information from a published L2 block.
24
+ * Returns info for each attestation, preserving array indices.
25
+ */
26
+ export declare function getAttestationInfoFromPublishedL2Block(block: {
27
+ attestations: CommitteeAttestation[];
28
+ block: L2Block;
29
+ }): AttestationInfo[];
30
+ //# sourceMappingURL=attestation_info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attestation_info.d.ts","sourceRoot":"","sources":["../../src/block/attestation_info.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAIhE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAEhF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,0BAA0B,GAAG,qBAAqB,GAAG,mBAAmB,GAAG,OAAO,CAAC;AAEnH;;GAEG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,+EAA+E;IAC/E,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,iDAAiD;IACjD,MAAM,EAAE,OAAO,CAAC,iBAAiB,EAAE,mBAAmB,GAAG,OAAO,CAAC,CAAC;CACnE,GACD;IACE,8BAA8B;IAC9B,OAAO,EAAE,UAAU,CAAC;IACpB,iDAAiD;IACjD,MAAM,EAAE,OAAO,CAAC,iBAAiB,EAAE,qBAAqB,GAAG,0BAA0B,CAAC,CAAC;CACxF,CAAC;AAEN;;;GAGG;AACH,wBAAgB,sCAAsC,CAAC,KAAK,EAAE;IAC5D,YAAY,EAAE,oBAAoB,EAAE,CAAC;IACrC,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,eAAe,EAAE,CAwBpB"}
@@ -0,0 +1,39 @@
1
+ import { recoverAddress } from '@aztec/foundation/crypto';
2
+ import { ConsensusPayload } from '../p2p/consensus_payload.js';
3
+ import { SignatureDomainSeparator, getHashedSignaturePayloadEthSignedMessage } from '../p2p/signature_utils.js';
4
+ /**
5
+ * Extracts attestation information from a published L2 block.
6
+ * Returns info for each attestation, preserving array indices.
7
+ */ export function getAttestationInfoFromPublishedL2Block(block) {
8
+ const payload = ConsensusPayload.fromBlock(block.block);
9
+ const hashedPayload = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
10
+ return block.attestations.map((attestation)=>{
11
+ // If signature is empty, check if we have an address directly
12
+ if (attestation.signature.isEmpty()) {
13
+ if (attestation.address.isZero()) {
14
+ // No signature and no address - empty
15
+ return {
16
+ status: 'empty'
17
+ };
18
+ }
19
+ // Address provided without signature
20
+ return {
21
+ address: attestation.address,
22
+ status: 'provided-as-address'
23
+ };
24
+ }
25
+ // Try to recover address from signature
26
+ try {
27
+ const recoveredAddress = recoverAddress(hashedPayload, attestation.signature);
28
+ return {
29
+ address: recoveredAddress,
30
+ status: 'recovered-from-signature'
31
+ };
32
+ } catch {
33
+ // Signature present but recovery failed
34
+ return {
35
+ status: 'invalid-signature'
36
+ };
37
+ }
38
+ });
39
+ }
@@ -9,4 +9,5 @@ export * from './published_l2_block.js';
9
9
  export * from './proposal/index.js';
10
10
  export * from './validate_block_result.js';
11
11
  export * from './l2_block_info.js';
12
+ export * from './attestation_info.js';
12
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/block/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/block/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
@@ -9,3 +9,4 @@ export * from './published_l2_block.js';
9
9
  export * from './proposal/index.js';
10
10
  export * from './validate_block_result.js';
11
11
  export * from './l2_block_info.js';
12
+ export * from './attestation_info.js';
@@ -1,7 +1,6 @@
1
1
  import { BufferReader } from '@aztec/foundation/serialize';
2
2
  import type { FieldsOf } from '@aztec/foundation/types';
3
3
  import { z } from 'zod';
4
- import { BlockAttestation } from '../p2p/block_attestation.js';
5
4
  import { L2Block } from './l2_block.js';
6
5
  import { CommitteeAttestation } from './proposal/committee_attestation.js';
7
6
  export declare class L1PublishedData {
@@ -141,9 +140,4 @@ export declare class PublishedL2Block {
141
140
  static fromFields(fields: FieldsOf<PublishedL2Block>): PublishedL2Block;
142
141
  toBuffer(): Buffer;
143
142
  }
144
- /**
145
- * Extracts block attestations from a published L2 block.
146
- * Returns undefined for attestations with empty signatures, preserving array indices.
147
- */
148
- export declare function getAttestationsFromPublishedL2Block(block: Pick<PublishedL2Block, 'attestations' | 'block'>): (BlockAttestation | undefined)[];
149
143
  //# sourceMappingURL=published_l2_block.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"published_l2_block.d.ts","sourceRoot":"","sources":["../../src/block/published_l2_block.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAE3E,qBAAa,eAAe;IAEjB,WAAW,EAAE,MAAM;IACnB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;gBAFjB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM;IAG1B,MAAM,KAAK,MAAM;;;;;;;;;;;;OAMhB;IAED,MAAM,CAAC,MAAM;IAQb,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC;CAGpD;AAED,qBAAa,gBAAgB;IAElB,KAAK,EAAE,OAAO;IACd,EAAE,EAAE,eAAe;IACnB,YAAY,EAAE,oBAAoB,EAAE;gBAFpC,KAAK,EAAE,OAAO,EACd,EAAE,EAAE,eAAe,EACnB,YAAY,EAAE,oBAAoB,EAAE;IAG7C,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAQhB;IAED,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY,GAAG,gBAAgB;IAU1E,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC;IAI7C,QAAQ,IAAI,MAAM;CAU1B;AAED;;;GAGG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,cAAc,GAAG,OAAO,CAAC,GACtD,CAAC,gBAAgB,GAAG,SAAS,CAAC,EAAE,CAOlC"}
1
+ {"version":3,"file":"published_l2_block.d.ts","sourceRoot":"","sources":["../../src/block/published_l2_block.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAExD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAE3E,qBAAa,eAAe;IAEjB,WAAW,EAAE,MAAM;IACnB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;gBAFjB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM;IAG1B,MAAM,KAAK,MAAM;;;;;;;;;;;;OAMhB;IAED,MAAM,CAAC,MAAM;IAQb,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC;CAGpD;AAED,qBAAa,gBAAgB;IAElB,KAAK,EAAE,OAAO;IACd,EAAE,EAAE,eAAe;IACnB,YAAY,EAAE,oBAAoB,EAAE;gBAFpC,KAAK,EAAE,OAAO,EACd,EAAE,EAAE,eAAe,EACnB,YAAY,EAAE,oBAAoB,EAAE;IAG7C,MAAM,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAQhB;IAED,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,MAAM,GAAG,YAAY,GAAG,gBAAgB;IAU1E,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC;IAI7C,QAAQ,IAAI,MAAM;CAU1B"}
@@ -4,8 +4,6 @@ import { randomBigInt } from '@aztec/foundation/crypto';
4
4
  import { schemas } from '@aztec/foundation/schemas';
5
5
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
6
6
  import { z } from 'zod';
7
- import { BlockAttestation } from '../p2p/block_attestation.js';
8
- import { ConsensusPayload } from '../p2p/consensus_payload.js';
9
7
  import { L2Block } from './l2_block.js';
10
8
  import { CommitteeAttestation } from './proposal/committee_attestation.js';
11
9
  export class L1PublishedData {
@@ -63,10 +61,3 @@ export class PublishedL2Block {
63
61
  return serializeToBuffer(this.block, this.l1.blockNumber, this.l1.blockHash, this.l1.timestamp, this.attestations.length, this.attestations);
64
62
  }
65
63
  }
66
- /**
67
- * Extracts block attestations from a published L2 block.
68
- * Returns undefined for attestations with empty signatures, preserving array indices.
69
- */ export function getAttestationsFromPublishedL2Block(block) {
70
- const payload = ConsensusPayload.fromBlock(block.block);
71
- return block.attestations.map((attestation)=>attestation.signature.isEmpty() ? undefined : new BlockAttestation(block.block.number, payload, attestation.signature));
72
- }
@@ -48,6 +48,8 @@ export interface P2PApiWithAttestations extends P2PApiWithoutAttestations {
48
48
  * @returns BlockAttestations
49
49
  */
50
50
  getAttestationsForSlot(slot: bigint, proposalId?: string): Promise<BlockAttestation[]>;
51
+ /** Deletes a given attestation manually from the p2p client attestation pool. */
52
+ deleteAttestation(attestation: BlockAttestation): Promise<void>;
51
53
  }
52
54
  export interface P2PClient extends P2PApiWithAttestations {
53
55
  /** Manually adds an attestation to the p2p client attestation pool. */
@@ -1 +1 @@
1
- {"version":3,"file":"p2p.d.ts","sourceRoot":"","sources":["../../src/interfaces/p2p.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,MAAM,MAAM,QAAQ,GAChB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1E;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAc7F,qCAAqC;AACrC,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAE7D,4DAA4D;IAC5D,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAErC;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE7C;;OAEG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,sBAAuB,SAAQ,yBAAyB;IACvE;;;;;;OAMG;IACH,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CACxF;AAED,MAAM,WAAW,SAAU,SAAQ,sBAAsB;IACvD,uEAAuE;IACvE,eAAe,CAAC,YAAY,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,CAAC,IAAI,IAAI,CAAC,SAAS,aAAa,CAAC,IAAI,GAC3F,sBAAsB,GACtB,yBAAyB,CAAC;AAE9B,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,CAAC,IAAI,IAAI,CAAC,SAAS,aAAa,CAAC,IAAI,GAC/F,sBAAsB,GAAG,SAAS,GAClC,yBAAyB,CAAC;AAE9B,eAAO,MAAM,YAAY,EAAE,YAAY,CAAC,MAAM,CAa7C,CAAC"}
1
+ {"version":3,"file":"p2p.d.ts","sourceRoot":"","sources":["../../src/interfaces/p2p.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,KAAK,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,MAAM,MAAM,QAAQ,GAChB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1E;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC;AAc7F,qCAAqC;AACrC,MAAM,WAAW,yBAAyB;IACxC;;;;;OAKG;IACH,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAE7D,4DAA4D;IAC5D,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAErC;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAE7C;;OAEG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,sBAAuB,SAAQ,yBAAyB;IACvE;;;;;;OAMG;IACH,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAEvF,iFAAiF;IACjF,iBAAiB,CAAC,WAAW,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE;AAED,MAAM,WAAW,SAAU,SAAQ,sBAAsB;IACvD,uEAAuE;IACvE,eAAe,CAAC,YAAY,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED,MAAM,MAAM,MAAM,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,CAAC,IAAI,IAAI,CAAC,SAAS,aAAa,CAAC,IAAI,GAC3F,sBAAsB,GACtB,yBAAyB,CAAC;AAE9B,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,CAAC,IAAI,IAAI,CAAC,SAAS,aAAa,CAAC,IAAI,GAC/F,sBAAsB,GAAG,SAAS,GAClC,yBAAyB,CAAC;AAE9B,eAAO,MAAM,YAAY,EAAE,YAAY,CAAC,MAAM,CAc7C,CAAC"}
@@ -29,5 +29,6 @@ export const P2PApiSchema = {
29
29
  getPendingTxs: z.function().args(optional(z.number().gte(1).lte(MAX_RPC_TXS_LEN).default(MAX_RPC_TXS_LEN)), optional(TxHash.schema)).returns(z.array(Tx.schema)),
30
30
  getPendingTxCount: z.function().returns(schemas.Integer),
31
31
  getEncodedEnr: z.function().returns(z.string().optional()),
32
- getPeers: z.function().args(optional(z.boolean())).returns(z.array(PeerInfoSchema))
32
+ getPeers: z.function().args(optional(z.boolean())).returns(z.array(PeerInfoSchema)),
33
+ deleteAttestation: z.function().args(BlockAttestation.schema).returns(z.void())
33
34
  };
@@ -24,15 +24,20 @@ export declare class BlockAttestation extends Gossipable {
24
24
  readonly payload: ConsensusPayload;
25
25
  /** The signature of the block attester */
26
26
  readonly signature: Signature;
27
+ /** The signature from the block proposer */
28
+ readonly proposerSignature: Signature;
27
29
  static p2pTopic: TopicType;
28
30
  private sender;
31
+ private proposer;
29
32
  constructor(
30
33
  /** The block number of the attestation. */
31
34
  blockNumber: UInt32,
32
35
  /** The payload of the message, and what the signature is over */
33
36
  payload: ConsensusPayload,
34
37
  /** The signature of the block attester */
35
- signature: Signature);
38
+ signature: Signature,
39
+ /** The signature from the block proposer */
40
+ proposerSignature: Signature);
36
41
  static get schema(): ZodFor<BlockAttestation>;
37
42
  generateP2PMessageIdentifier(): Promise<Buffer32>;
38
43
  get archive(): Fr;
@@ -47,6 +52,11 @@ export declare class BlockAttestation extends Gossipable {
47
52
  * @returns The sender of the attestation or undefined if it fails during recovery
48
53
  */
49
54
  tryGetSender(): EthAddress | undefined;
55
+ /**
56
+ * Lazily evaluate and cache the proposer of the block
57
+ * @returns The proposer of the block
58
+ */
59
+ getProposer(): EthAddress;
50
60
  getPayload(): Buffer;
51
61
  toBuffer(): Buffer;
52
62
  static fromBuffer(buf: Buffer | BufferReader): BlockAttestation;
@@ -82,6 +92,7 @@ export declare class BlockAttestation extends Gossipable {
82
92
  };
83
93
  };
84
94
  signature: `0x${string}`;
95
+ proposerSignature: `0x${string}`;
85
96
  };
86
97
  }
87
98
  //# sourceMappingURL=block_attestation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"block_attestation.d.ts","sourceRoot":"","sources":["../../src/p2p/block_attestation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AAI9E,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,IAAI,EAAE,MAAM;CAGzB;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAM5C,2CAA2C;aAC3B,WAAW,EAAE,MAAM;IAEnC,iEAAiE;aACjD,OAAO,EAAE,gBAAgB;IAEzC,0CAA0C;aAC1B,SAAS,EAAE,SAAS;IAZtC,OAAgB,QAAQ,YAA+B;IAEvD,OAAO,CAAC,MAAM,CAAyB;;IAGrC,2CAA2C;IAC3B,WAAW,EAAE,MAAM;IAEnC,iEAAiE;IACjD,OAAO,EAAE,gBAAgB;IAEzC,0CAA0C;IAC1B,SAAS,EAAE,SAAS;IAKtC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAQ5C;IAEQ,4BAA4B,IAAI,OAAO,CAAC,QAAQ,CAAC;IAI1D,IAAI,OAAO,IAAI,EAAE,CAEhB;IAED,IAAI,UAAU,IAAI,EAAE,CAEnB;IAED;;;OAGG;IACH,SAAS,IAAI,UAAU;IAWvB;;;OAGG;IACH,YAAY,IAAI,UAAU,GAAG,SAAS;IAQtC,UAAU,IAAI,MAAM;IAIpB,QAAQ,IAAI,MAAM;IAIlB,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,gBAAgB;IAK/D,MAAM,CAAC,KAAK,IAAI,gBAAgB;IAIhC,MAAM,CAAC,MAAM,IAAI,gBAAgB;IAIjC,OAAO,IAAI,MAAM;IAIjB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOV"}
1
+ {"version":3,"file":"block_attestation.d.ts","sourceRoot":"","sources":["../../src/p2p/block_attestation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAC5D,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAqB,MAAM,6BAA6B,CAAC;AAI9E,OAAO,EAAE,KAAK,MAAM,EAAW,MAAM,qBAAqB,CAAC;AAC3D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,qBAAa,oBAAqB,SAAQ,QAAQ;gBACpC,IAAI,EAAE,MAAM;CAGzB;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAO5C,2CAA2C;aAC3B,WAAW,EAAE,MAAM;IAEnC,iEAAiE;aACjD,OAAO,EAAE,gBAAgB;IAEzC,0CAA0C;aAC1B,SAAS,EAAE,SAAS;IAEpC,4CAA4C;aAC5B,iBAAiB,EAAE,SAAS;IAhB9C,OAAgB,QAAQ,YAA+B;IAEvD,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,QAAQ,CAAyB;;IAGvC,2CAA2C;IAC3B,WAAW,EAAE,MAAM;IAEnC,iEAAiE;IACjD,OAAO,EAAE,gBAAgB;IAEzC,0CAA0C;IAC1B,SAAS,EAAE,SAAS;IAEpC,4CAA4C;IAC5B,iBAAiB,EAAE,SAAS;IAK9C,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAS5C;IAEQ,4BAA4B,IAAI,OAAO,CAAC,QAAQ,CAAC;IAI1D,IAAI,OAAO,IAAI,EAAE,CAEhB;IAED,IAAI,UAAU,IAAI,EAAE,CAEnB;IAED;;;OAGG;IACH,SAAS,IAAI,UAAU;IAWvB;;;OAGG;IACH,YAAY,IAAI,UAAU,GAAG,SAAS;IAQtC;;;OAGG;IACH,WAAW,IAAI,UAAU;IAWzB,UAAU,IAAI,MAAM;IAIpB,QAAQ,IAAI,MAAM;IAIlB,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,GAAG,gBAAgB;IAU/D,MAAM,CAAC,KAAK,IAAI,gBAAgB;IAIhC,MAAM,CAAC,MAAM,IAAI,gBAAgB;IASjC,OAAO,IAAI,MAAM;IAIjB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQV"}
@@ -22,17 +22,20 @@ export class BlockAttestationHash extends Buffer32 {
22
22
  blockNumber;
23
23
  payload;
24
24
  signature;
25
+ proposerSignature;
25
26
  static p2pTopic = TopicType.block_attestation;
26
27
  sender;
27
- constructor(/** The block number of the attestation. */ blockNumber, /** The payload of the message, and what the signature is over */ payload, /** The signature of the block attester */ signature){
28
- super(), this.blockNumber = blockNumber, this.payload = payload, this.signature = signature;
28
+ proposer;
29
+ constructor(/** The block number of the attestation. */ blockNumber, /** The payload of the message, and what the signature is over */ payload, /** The signature of the block attester */ signature, /** The signature from the block proposer */ proposerSignature){
30
+ super(), this.blockNumber = blockNumber, this.payload = payload, this.signature = signature, this.proposerSignature = proposerSignature;
29
31
  }
30
32
  static get schema() {
31
33
  return z.object({
32
34
  blockNumber: schemas.UInt32,
33
35
  payload: ConsensusPayload.schema,
34
- signature: Signature.schema
35
- }).transform((obj)=>new BlockAttestation(obj.blockNumber, obj.payload, obj.signature));
36
+ signature: Signature.schema,
37
+ proposerSignature: Signature.schema
38
+ }).transform((obj)=>new BlockAttestation(obj.blockNumber, obj.payload, obj.signature, obj.proposerSignature));
36
39
  }
37
40
  generateP2PMessageIdentifier() {
38
41
  return Promise.resolve(new BlockAttestationHash(keccak256(this.signature.toBuffer())));
@@ -65,6 +68,18 @@ export class BlockAttestationHash extends Buffer32 {
65
68
  return undefined;
66
69
  }
67
70
  }
71
+ /**
72
+ * Lazily evaluate and cache the proposer of the block
73
+ * @returns The proposer of the block
74
+ */ getProposer() {
75
+ if (!this.proposer) {
76
+ // Recover the proposer from the proposal signature
77
+ const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockProposal);
78
+ // Cache the proposer for later use
79
+ this.proposer = recoverAddress(hashed, this.proposerSignature);
80
+ }
81
+ return this.proposer;
82
+ }
68
83
  getPayload() {
69
84
  return this.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation);
70
85
  }
@@ -72,27 +87,29 @@ export class BlockAttestationHash extends Buffer32 {
72
87
  return serializeToBuffer([
73
88
  this.blockNumber,
74
89
  this.payload,
75
- this.signature
90
+ this.signature,
91
+ this.proposerSignature
76
92
  ]);
77
93
  }
78
94
  static fromBuffer(buf) {
79
95
  const reader = BufferReader.asReader(buf);
80
- return new BlockAttestation(reader.readNumber(), reader.readObject(ConsensusPayload), reader.readObject(Signature));
96
+ return new BlockAttestation(reader.readNumber(), reader.readObject(ConsensusPayload), reader.readObject(Signature), reader.readObject(Signature));
81
97
  }
82
98
  static empty() {
83
- return new BlockAttestation(0, ConsensusPayload.empty(), Signature.empty());
99
+ return new BlockAttestation(0, ConsensusPayload.empty(), Signature.empty(), Signature.empty());
84
100
  }
85
101
  static random() {
86
- return new BlockAttestation(Math.floor(Math.random() * 1000) + 1, ConsensusPayload.random(), Signature.random());
102
+ return new BlockAttestation(Math.floor(Math.random() * 1000) + 1, ConsensusPayload.random(), Signature.random(), Signature.random());
87
103
  }
88
104
  getSize() {
89
- return 4 /* blockNumber */ + this.payload.getSize() + this.signature.getSize();
105
+ return 4 /* blockNumber */ + this.payload.getSize() + this.signature.getSize() + this.proposerSignature.getSize();
90
106
  }
91
107
  toInspect() {
92
108
  return {
93
109
  blockNumber: this.blockNumber,
94
110
  payload: this.payload.toInspect(),
95
- signature: this.signature.toString()
111
+ signature: this.signature.toString(),
112
+ proposerSignature: this.proposerSignature.toString()
96
113
  };
97
114
  }
98
115
  }
@@ -43,6 +43,8 @@ export declare const randomDeployedContract: () => Promise<{
43
43
  }>;
44
44
  export interface MakeConsensusPayloadOptions {
45
45
  signer?: Secp256k1Signer;
46
+ attesterSigner?: Secp256k1Signer;
47
+ proposerSigner?: Secp256k1Signer;
46
48
  header?: BlockHeader;
47
49
  archive?: Fr;
48
50
  stateReference?: StateReference;
@@ -52,7 +54,7 @@ export interface MakeConsensusPayloadOptions {
52
54
  export declare const makeAndSignCommitteeAttestationsAndSigners: (attestationsAndSigners: CommitteeAttestationsAndSigners, signer?: Secp256k1Signer) => import("../block/index.js").Signature;
53
55
  export declare const makeBlockProposal: (options?: MakeConsensusPayloadOptions) => BlockProposal;
54
56
  export declare const makeBlockAttestation: (options?: MakeConsensusPayloadOptions) => BlockAttestation;
55
- export declare const makeBlockAttestationFromBlock: (block: L2Block, signer?: Secp256k1Signer) => BlockAttestation;
57
+ export declare const makeBlockAttestationFromBlock: (block: L2Block, attesterSigner?: Secp256k1Signer, proposerSigner?: Secp256k1Signer) => BlockAttestation;
56
58
  export declare function randomPublishedL2Block(l2BlockNumber: number, opts?: {
57
59
  signers?: Secp256k1Signer[];
58
60
  }): Promise<PublishedL2Block>;
@@ -1 +1 @@
1
- {"version":3,"file":"mocks.d.ts","sourceRoot":"","sources":["../../src/tests/mocks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mocks.d.ts","sourceRoot":"","sources":["../../src/tests/mocks.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAe,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAE9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,+CAA+C,CAAC;AACrG,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAIlE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAS7C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGzD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EACL,WAAW,EAIX,cAAc,EACd,EAAE,EACH,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAiC,MAAM,uBAAuB,CAAC;AAE1F,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAG1C,eAAO,MAAM,YAAY,QAAO,MAAyB,CAAC;AAE1D,eAAO,MAAM,kBAAkB,GAAU,6DAMtC,OAAO,CAAC,YAAY,CAAM,0BAQ5B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAU,wEAOpC,OAAO,CAAC,UAAU,CAAM,wBAS1B,CAAC;AAEF,eAAO,MAAM,MAAM,GACjB,aAAQ,EACR,8QAaG;IACD,uCAAuC,CAAC,EAAE,MAAM,CAAC;IACjD,oCAAoC,CAAC,EAAE,MAAM,CAAC;IAC9C,4BAA4B,CAAC,EAAE,MAAM,CAAC;IACtC,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,OAAO,CAAC,EAAE,EAAE,CAAC;IACb,OAAO,CAAC,EAAE,EAAE,CAAC;IACb,UAAU,CAAC,EAAE,EAAE,CAAC;IAChB,wBAAwB,CAAC,EAAE,EAAE,CAAC;CAC1B,gBAiEP,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,aAAQ,EAAE,OAAM,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAM,gBAC+B,CAAC;AAmBjH,eAAO,MAAM,eAAe,GAAU,aAAQ,gCAgB7C,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAO,gBAUxC,CAAC;AAEH,eAAO,MAAM,iCAAiC,GAC5C,OAAM;IAAE,eAAe,CAAC,EAAE,EAAE,CAAA;CAAO,EACnC,UAAU,YAAY,KACrB,OAAO,CAAC,2BAA2B,CAUrC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;EAIlC,CAAC;AAEF,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,cAAc,CAAC,EAAE,eAAe,CAAC;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,EAAE,CAAC;IACb,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC;CACZ;AAqBD,eAAO,MAAM,0CAA0C,GACrD,wBAAwB,+BAA+B,EACvD,SAAQ,eAA0C,0CAOnD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,UAAU,2BAA2B,KAAG,aAOzE,CAAC;AAGF,eAAO,MAAM,oBAAoB,GAAI,UAAU,2BAA2B,KAAG,gBAyB5E,CAAC;AAEF,eAAO,MAAM,6BAA6B,GACxC,OAAO,OAAO,EACd,iBAAiB,eAAe,EAChC,iBAAiB,eAAe,KAC/B,gBAsBF,CAAC;AAEF,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,MAAM,EACrB,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,eAAe,EAAE,CAAA;CAAO,GACzC,OAAO,CAAC,gBAAgB,CAAC,CAc3B"}
@@ -166,17 +166,39 @@ export const makeBlockProposal = (options)=>{
166
166
  };
167
167
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8028)
168
168
  export const makeBlockAttestation = (options)=>{
169
- const { blockNumber, payload, signature } = makeAndSignConsensusPayload(SignatureDomainSeparator.blockAttestation, options);
170
- return new BlockAttestation(blockNumber, payload, signature);
169
+ const header = options?.header ?? makeHeader(1);
170
+ const { signer, attesterSigner = signer ?? Secp256k1Signer.random(), proposerSigner = signer ?? Secp256k1Signer.random(), archive = Fr.random(), stateReference = header.state } = options ?? {};
171
+ const payload = ConsensusPayload.fromFields({
172
+ header: header.toPropose(),
173
+ archive,
174
+ stateReference
175
+ });
176
+ // Sign as attester
177
+ const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
178
+ const attestationSignature = attesterSigner.sign(attestationHash);
179
+ // Sign as proposer
180
+ const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
181
+ const proposerSignature = proposerSigner.sign(proposalHash);
182
+ return new BlockAttestation(header.globalVariables.blockNumber, payload, attestationSignature, proposerSignature);
171
183
  };
172
- export const makeBlockAttestationFromBlock = (block, signer)=>{
173
- return makeBlockAttestation({
174
- signer,
175
- header: block.header,
176
- archive: block.archive.root,
177
- stateReference: block.header.state,
178
- txHashes: block.body.txEffects.map((tx)=>tx.txHash)
184
+ export const makeBlockAttestationFromBlock = (block, attesterSigner, proposerSigner)=>{
185
+ const header = block.header;
186
+ const archive = block.archive.root;
187
+ const stateReference = block.header.state;
188
+ const payload = ConsensusPayload.fromFields({
189
+ header: header.toPropose(),
190
+ archive,
191
+ stateReference
179
192
  });
193
+ // Sign as attester
194
+ const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
195
+ const attestationSigner = attesterSigner ?? Secp256k1Signer.random();
196
+ const attestationSignature = attestationSigner.sign(attestationHash);
197
+ // Sign as proposer
198
+ const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
199
+ const proposalSignerToUse = proposerSigner ?? Secp256k1Signer.random();
200
+ const proposerSignature = proposalSignerToUse.sign(proposalHash);
201
+ return new BlockAttestation(header.globalVariables.blockNumber, payload, attestationSignature, proposerSignature);
180
202
  };
181
203
  export async function randomPublishedL2Block(l2BlockNumber, opts = {}) {
182
204
  const block = await L2Block.random(l2BlockNumber);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/stdlib",
3
- "version": "2.1.0-rc.10",
3
+ "version": "2.1.0-rc.12",
4
4
  "type": "module",
5
5
  "inherits": [
6
6
  "../package.common.json",
@@ -70,13 +70,13 @@
70
70
  },
71
71
  "dependencies": {
72
72
  "@aws-sdk/client-s3": "^3.892.0",
73
- "@aztec/bb.js": "2.1.0-rc.10",
74
- "@aztec/blob-lib": "2.1.0-rc.10",
75
- "@aztec/constants": "2.1.0-rc.10",
76
- "@aztec/ethereum": "2.1.0-rc.10",
77
- "@aztec/foundation": "2.1.0-rc.10",
78
- "@aztec/l1-artifacts": "2.1.0-rc.10",
79
- "@aztec/noir-noirc_abi": "2.1.0-rc.10",
73
+ "@aztec/bb.js": "2.1.0-rc.12",
74
+ "@aztec/blob-lib": "2.1.0-rc.12",
75
+ "@aztec/constants": "2.1.0-rc.12",
76
+ "@aztec/ethereum": "2.1.0-rc.12",
77
+ "@aztec/foundation": "2.1.0-rc.12",
78
+ "@aztec/l1-artifacts": "2.1.0-rc.12",
79
+ "@aztec/noir-noirc_abi": "2.1.0-rc.12",
80
80
  "@google-cloud/storage": "^7.15.0",
81
81
  "@spalladino/viem": "2.38.2-eip7594.0",
82
82
  "axios": "^1.12.0",
@@ -0,0 +1,62 @@
1
+ import { recoverAddress } from '@aztec/foundation/crypto';
2
+ import type { EthAddress } from '@aztec/foundation/eth-address';
3
+
4
+ import { ConsensusPayload } from '../p2p/consensus_payload.js';
5
+ import { SignatureDomainSeparator, getHashedSignaturePayloadEthSignedMessage } from '../p2p/signature_utils.js';
6
+ import type { L2Block } from './l2_block.js';
7
+ import type { CommitteeAttestation } from './proposal/committee_attestation.js';
8
+
9
+ /**
10
+ * Status indicating how the attestation address was determined
11
+ */
12
+ export type AttestationStatus = 'recovered-from-signature' | 'provided-as-address' | 'invalid-signature' | 'empty';
13
+
14
+ /**
15
+ * Information about an attestation extracted from a published block
16
+ */
17
+ export type AttestationInfo =
18
+ | {
19
+ /** The validator's address, undefined if signature recovery failed or empty */
20
+ address?: undefined;
21
+ /** How the attestation address was determined */
22
+ status: Extract<AttestationStatus, 'invalid-signature' | 'empty'>;
23
+ }
24
+ | {
25
+ /** The validator's address */
26
+ address: EthAddress;
27
+ /** How the attestation address was determined */
28
+ status: Extract<AttestationStatus, 'provided-as-address' | 'recovered-from-signature'>;
29
+ };
30
+
31
+ /**
32
+ * Extracts attestation information from a published L2 block.
33
+ * Returns info for each attestation, preserving array indices.
34
+ */
35
+ export function getAttestationInfoFromPublishedL2Block(block: {
36
+ attestations: CommitteeAttestation[];
37
+ block: L2Block;
38
+ }): AttestationInfo[] {
39
+ const payload = ConsensusPayload.fromBlock(block.block);
40
+ const hashedPayload = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
41
+
42
+ return block.attestations.map(attestation => {
43
+ // If signature is empty, check if we have an address directly
44
+ if (attestation.signature.isEmpty()) {
45
+ if (attestation.address.isZero()) {
46
+ // No signature and no address - empty
47
+ return { status: 'empty' as const };
48
+ }
49
+ // Address provided without signature
50
+ return { address: attestation.address, status: 'provided-as-address' as const };
51
+ }
52
+
53
+ // Try to recover address from signature
54
+ try {
55
+ const recoveredAddress = recoverAddress(hashedPayload, attestation.signature);
56
+ return { address: recoveredAddress, status: 'recovered-from-signature' as const };
57
+ } catch {
58
+ // Signature present but recovery failed
59
+ return { status: 'invalid-signature' as const };
60
+ }
61
+ });
62
+ }
@@ -9,3 +9,4 @@ export * from './published_l2_block.js';
9
9
  export * from './proposal/index.js';
10
10
  export * from './validate_block_result.js';
11
11
  export * from './l2_block_info.js';
12
+ export * from './attestation_info.js';
@@ -7,8 +7,6 @@ import type { FieldsOf } from '@aztec/foundation/types';
7
7
 
8
8
  import { z } from 'zod';
9
9
 
10
- import { BlockAttestation } from '../p2p/block_attestation.js';
11
- import { ConsensusPayload } from '../p2p/consensus_payload.js';
12
10
  import { L2Block } from './l2_block.js';
13
11
  import { CommitteeAttestation } from './proposal/committee_attestation.js';
14
12
 
@@ -82,18 +80,3 @@ export class PublishedL2Block {
82
80
  );
83
81
  }
84
82
  }
85
-
86
- /**
87
- * Extracts block attestations from a published L2 block.
88
- * Returns undefined for attestations with empty signatures, preserving array indices.
89
- */
90
- export function getAttestationsFromPublishedL2Block(
91
- block: Pick<PublishedL2Block, 'attestations' | 'block'>,
92
- ): (BlockAttestation | undefined)[] {
93
- const payload = ConsensusPayload.fromBlock(block.block);
94
- return block.attestations.map(attestation =>
95
- attestation.signature.isEmpty()
96
- ? undefined
97
- : new BlockAttestation(block.block.number, payload, attestation.signature),
98
- );
99
- }
@@ -57,6 +57,9 @@ export interface P2PApiWithAttestations extends P2PApiWithoutAttestations {
57
57
  * @returns BlockAttestations
58
58
  */
59
59
  getAttestationsForSlot(slot: bigint, proposalId?: string): Promise<BlockAttestation[]>;
60
+
61
+ /** Deletes a given attestation manually from the p2p client attestation pool. */
62
+ deleteAttestation(attestation: BlockAttestation): Promise<void>;
60
63
  }
61
64
 
62
65
  export interface P2PClient extends P2PApiWithAttestations {
@@ -85,4 +88,5 @@ export const P2PApiSchema: ApiSchemaFor<P2PApi> = {
85
88
  getPendingTxCount: z.function().returns(schemas.Integer),
86
89
  getEncodedEnr: z.function().returns(z.string().optional()),
87
90
  getPeers: z.function().args(optional(z.boolean())).returns(z.array(PeerInfoSchema)),
91
+ deleteAttestation: z.function().args(BlockAttestation.schema).returns(z.void()),
88
92
  };
@@ -30,6 +30,7 @@ export class BlockAttestation extends Gossipable {
30
30
  static override p2pTopic = TopicType.block_attestation;
31
31
 
32
32
  private sender: EthAddress | undefined;
33
+ private proposer: EthAddress | undefined;
33
34
 
34
35
  constructor(
35
36
  /** The block number of the attestation. */
@@ -40,6 +41,9 @@ export class BlockAttestation extends Gossipable {
40
41
 
41
42
  /** The signature of the block attester */
42
43
  public readonly signature: Signature,
44
+
45
+ /** The signature from the block proposer */
46
+ public readonly proposerSignature: Signature,
43
47
  ) {
44
48
  super();
45
49
  }
@@ -50,8 +54,9 @@ export class BlockAttestation extends Gossipable {
50
54
  blockNumber: schemas.UInt32,
51
55
  payload: ConsensusPayload.schema,
52
56
  signature: Signature.schema,
57
+ proposerSignature: Signature.schema,
53
58
  })
54
- .transform(obj => new BlockAttestation(obj.blockNumber, obj.payload, obj.signature));
59
+ .transform(obj => new BlockAttestation(obj.blockNumber, obj.payload, obj.signature, obj.proposerSignature));
55
60
  }
56
61
 
57
62
  override generateP2PMessageIdentifier(): Promise<Buffer32> {
@@ -93,29 +98,54 @@ export class BlockAttestation extends Gossipable {
93
98
  }
94
99
  }
95
100
 
101
+ /**
102
+ * Lazily evaluate and cache the proposer of the block
103
+ * @returns The proposer of the block
104
+ */
105
+ getProposer(): EthAddress {
106
+ if (!this.proposer) {
107
+ // Recover the proposer from the proposal signature
108
+ const hashed = getHashedSignaturePayloadEthSignedMessage(this.payload, SignatureDomainSeparator.blockProposal);
109
+ // Cache the proposer for later use
110
+ this.proposer = recoverAddress(hashed, this.proposerSignature);
111
+ }
112
+
113
+ return this.proposer;
114
+ }
115
+
96
116
  getPayload(): Buffer {
97
117
  return this.payload.getPayloadToSign(SignatureDomainSeparator.blockAttestation);
98
118
  }
99
119
 
100
120
  toBuffer(): Buffer {
101
- return serializeToBuffer([this.blockNumber, this.payload, this.signature]);
121
+ return serializeToBuffer([this.blockNumber, this.payload, this.signature, this.proposerSignature]);
102
122
  }
103
123
 
104
124
  static fromBuffer(buf: Buffer | BufferReader): BlockAttestation {
105
125
  const reader = BufferReader.asReader(buf);
106
- return new BlockAttestation(reader.readNumber(), reader.readObject(ConsensusPayload), reader.readObject(Signature));
126
+ return new BlockAttestation(
127
+ reader.readNumber(),
128
+ reader.readObject(ConsensusPayload),
129
+ reader.readObject(Signature),
130
+ reader.readObject(Signature),
131
+ );
107
132
  }
108
133
 
109
134
  static empty(): BlockAttestation {
110
- return new BlockAttestation(0, ConsensusPayload.empty(), Signature.empty());
135
+ return new BlockAttestation(0, ConsensusPayload.empty(), Signature.empty(), Signature.empty());
111
136
  }
112
137
 
113
138
  static random(): BlockAttestation {
114
- return new BlockAttestation(Math.floor(Math.random() * 1000) + 1, ConsensusPayload.random(), Signature.random());
139
+ return new BlockAttestation(
140
+ Math.floor(Math.random() * 1000) + 1,
141
+ ConsensusPayload.random(),
142
+ Signature.random(),
143
+ Signature.random(),
144
+ );
115
145
  }
116
146
 
117
147
  getSize(): number {
118
- return 4 /* blockNumber */ + this.payload.getSize() + this.signature.getSize();
148
+ return 4 /* blockNumber */ + this.payload.getSize() + this.signature.getSize() + this.proposerSignature.getSize();
119
149
  }
120
150
 
121
151
  toInspect() {
@@ -123,6 +153,7 @@ export class BlockAttestation extends Gossipable {
123
153
  blockNumber: this.blockNumber,
124
154
  payload: this.payload.toInspect(),
125
155
  signature: this.signature.toString(),
156
+ proposerSignature: this.proposerSignature.toString(),
126
157
  };
127
158
  }
128
159
  }
@@ -248,6 +248,8 @@ export const randomDeployedContract = async () => {
248
248
 
249
249
  export interface MakeConsensusPayloadOptions {
250
250
  signer?: Secp256k1Signer;
251
+ attesterSigner?: Secp256k1Signer;
252
+ proposerSigner?: Secp256k1Signer;
251
253
  header?: BlockHeader;
252
254
  archive?: Fr;
253
255
  stateReference?: StateReference;
@@ -296,21 +298,58 @@ export const makeBlockProposal = (options?: MakeConsensusPayloadOptions): BlockP
296
298
 
297
299
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/8028)
298
300
  export const makeBlockAttestation = (options?: MakeConsensusPayloadOptions): BlockAttestation => {
299
- const { blockNumber, payload, signature } = makeAndSignConsensusPayload(
300
- SignatureDomainSeparator.blockAttestation,
301
- options,
302
- );
303
- return new BlockAttestation(blockNumber, payload, signature);
301
+ const header = options?.header ?? makeHeader(1);
302
+ const {
303
+ signer,
304
+ attesterSigner = signer ?? Secp256k1Signer.random(),
305
+ proposerSigner = signer ?? Secp256k1Signer.random(),
306
+ archive = Fr.random(),
307
+ stateReference = header.state,
308
+ } = options ?? {};
309
+
310
+ const payload = ConsensusPayload.fromFields({
311
+ header: header.toPropose(),
312
+ archive,
313
+ stateReference,
314
+ });
315
+
316
+ // Sign as attester
317
+ const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
318
+ const attestationSignature = attesterSigner.sign(attestationHash);
319
+
320
+ // Sign as proposer
321
+ const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
322
+ const proposerSignature = proposerSigner.sign(proposalHash);
323
+
324
+ return new BlockAttestation(header.globalVariables.blockNumber, payload, attestationSignature, proposerSignature);
304
325
  };
305
326
 
306
- export const makeBlockAttestationFromBlock = (block: L2Block, signer?: Secp256k1Signer): BlockAttestation => {
307
- return makeBlockAttestation({
308
- signer,
309
- header: block.header,
310
- archive: block.archive.root,
311
- stateReference: block.header.state,
312
- txHashes: block.body.txEffects.map(tx => tx.txHash),
327
+ export const makeBlockAttestationFromBlock = (
328
+ block: L2Block,
329
+ attesterSigner?: Secp256k1Signer,
330
+ proposerSigner?: Secp256k1Signer,
331
+ ): BlockAttestation => {
332
+ const header = block.header;
333
+ const archive = block.archive.root;
334
+ const stateReference = block.header.state;
335
+
336
+ const payload = ConsensusPayload.fromFields({
337
+ header: header.toPropose(),
338
+ archive,
339
+ stateReference,
313
340
  });
341
+
342
+ // Sign as attester
343
+ const attestationHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockAttestation);
344
+ const attestationSigner = attesterSigner ?? Secp256k1Signer.random();
345
+ const attestationSignature = attestationSigner.sign(attestationHash);
346
+
347
+ // Sign as proposer
348
+ const proposalHash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
349
+ const proposalSignerToUse = proposerSigner ?? Secp256k1Signer.random();
350
+ const proposerSignature = proposalSignerToUse.sign(proposalHash);
351
+
352
+ return new BlockAttestation(header.globalVariables.blockNumber, payload, attestationSignature, proposerSignature);
314
353
  };
315
354
 
316
355
  export async function randomPublishedL2Block(