@aztec/stdlib 2.0.3 → 2.1.0-rc.10

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.
Files changed (97) hide show
  1. package/dest/block/in_block.d.ts +5 -5
  2. package/dest/block/in_block.d.ts.map +1 -1
  3. package/dest/block/proposal/attestations_and_signers.d.ts +48 -0
  4. package/dest/block/proposal/attestations_and_signers.d.ts.map +1 -0
  5. package/dest/block/proposal/attestations_and_signers.js +99 -0
  6. package/dest/block/proposal/committee_attestation.d.ts +1 -0
  7. package/dest/block/proposal/committee_attestation.d.ts.map +1 -1
  8. package/dest/block/proposal/committee_attestation.js +3 -0
  9. package/dest/block/proposal/index.d.ts +1 -0
  10. package/dest/block/proposal/index.d.ts.map +1 -1
  11. package/dest/block/proposal/index.js +1 -0
  12. package/dest/block/published_l2_block.d.ts +5 -1
  13. package/dest/block/published_l2_block.d.ts.map +1 -1
  14. package/dest/block/published_l2_block.js +5 -2
  15. package/dest/contract/interfaces/contract_class.d.ts +3 -3
  16. package/dest/epoch-helpers/index.d.ts +2 -0
  17. package/dest/epoch-helpers/index.d.ts.map +1 -1
  18. package/dest/epoch-helpers/index.js +3 -0
  19. package/dest/file-store/factory.d.ts.map +1 -1
  20. package/dest/file-store/factory.js +18 -0
  21. package/dest/file-store/interface.d.ts +8 -2
  22. package/dest/file-store/interface.d.ts.map +1 -1
  23. package/dest/file-store/s3.d.ts +26 -0
  24. package/dest/file-store/s3.d.ts.map +1 -0
  25. package/dest/file-store/s3.js +252 -0
  26. package/dest/interfaces/aztec-node-admin.d.ts +16 -7
  27. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  28. package/dest/interfaces/block-builder.d.ts +1 -0
  29. package/dest/interfaces/block-builder.d.ts.map +1 -1
  30. package/dest/interfaces/configs.d.ts +5 -0
  31. package/dest/interfaces/configs.d.ts.map +1 -1
  32. package/dest/interfaces/configs.js +2 -1
  33. package/dest/interfaces/proving-job.d.ts +6 -6
  34. package/dest/interfaces/slasher.d.ts +4 -0
  35. package/dest/interfaces/slasher.d.ts.map +1 -1
  36. package/dest/interfaces/slasher.js +1 -0
  37. package/dest/interfaces/validator.d.ts +9 -2
  38. package/dest/interfaces/validator.d.ts.map +1 -1
  39. package/dest/interfaces/validator.js +2 -1
  40. package/dest/l1-contracts/slash_factory.d.ts +1 -1
  41. package/dest/l1-contracts/slash_factory.d.ts.map +1 -1
  42. package/dest/l1-contracts/slash_factory.js +1 -1
  43. package/dest/p2p/block_attestation.d.ts +35 -0
  44. package/dest/p2p/block_attestation.d.ts.map +1 -1
  45. package/dest/p2p/block_attestation.js +17 -0
  46. package/dest/p2p/consensus_payload.d.ts +27 -0
  47. package/dest/p2p/consensus_payload.d.ts.map +1 -1
  48. package/dest/p2p/consensus_payload.js +11 -1
  49. package/dest/p2p/gossipable.d.ts +2 -4
  50. package/dest/p2p/gossipable.d.ts.map +1 -1
  51. package/dest/p2p/gossipable.js +5 -14
  52. package/dest/p2p/signature_utils.d.ts +2 -1
  53. package/dest/p2p/signature_utils.d.ts.map +1 -1
  54. package/dest/p2p/signature_utils.js +1 -0
  55. package/dest/slashing/types.d.ts +1 -0
  56. package/dest/slashing/types.d.ts.map +1 -1
  57. package/dest/slashing/types.js +22 -0
  58. package/dest/snapshots/download.d.ts.map +1 -1
  59. package/dest/snapshots/download.js +58 -2
  60. package/dest/snapshots/upload.d.ts.map +1 -1
  61. package/dest/snapshots/upload.js +1 -0
  62. package/dest/tests/mocks.d.ts +2 -0
  63. package/dest/tests/mocks.d.ts.map +1 -1
  64. package/dest/tests/mocks.js +4 -0
  65. package/dest/tx/indexed_tx_effect.d.ts +3 -3
  66. package/dest/tx/proposed_block_header.d.ts +1 -0
  67. package/dest/tx/proposed_block_header.d.ts.map +1 -1
  68. package/dest/tx/proposed_block_header.js +3 -0
  69. package/dest/tx/state_reference.js +1 -1
  70. package/dest/tx/tx.d.ts +0 -7
  71. package/dest/tx/tx.d.ts.map +1 -1
  72. package/dest/tx/tx.js +0 -8
  73. package/package.json +11 -10
  74. package/src/block/proposal/attestations_and_signers.ts +121 -0
  75. package/src/block/proposal/committee_attestation.ts +4 -0
  76. package/src/block/proposal/index.ts +1 -0
  77. package/src/block/published_l2_block.ts +10 -4
  78. package/src/epoch-helpers/index.ts +8 -0
  79. package/src/file-store/factory.ts +15 -0
  80. package/src/file-store/interface.ts +8 -2
  81. package/src/file-store/s3.ts +254 -0
  82. package/src/interfaces/block-builder.ts +1 -0
  83. package/src/interfaces/configs.ts +3 -0
  84. package/src/interfaces/slasher.ts +2 -0
  85. package/src/interfaces/validator.ts +12 -2
  86. package/src/l1-contracts/slash_factory.ts +1 -1
  87. package/src/p2p/block_attestation.ts +20 -0
  88. package/src/p2p/consensus_payload.ts +17 -1
  89. package/src/p2p/gossipable.ts +6 -16
  90. package/src/p2p/signature_utils.ts +1 -0
  91. package/src/slashing/types.ts +23 -0
  92. package/src/snapshots/download.ts +66 -2
  93. package/src/snapshots/upload.ts +1 -0
  94. package/src/tests/mocks.ts +12 -0
  95. package/src/tx/proposed_block_header.ts +13 -0
  96. package/src/tx/state_reference.ts +1 -1
  97. package/src/tx/tx.ts +0 -10
@@ -1,33 +1,23 @@
1
1
  import { Buffer32 } from '@aztec/foundation/buffer';
2
- import { BufferReader, bigintToUInt64BE, serializeToBuffer } from '@aztec/foundation/serialize';
2
+ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
3
3
 
4
4
  import type { TopicType } from './topic_type.js';
5
5
 
6
6
  export class P2PMessage {
7
- constructor(
8
- public readonly publishTime: Date,
9
- public readonly id: Buffer32,
10
- public readonly payload: Buffer,
11
- ) {}
7
+ constructor(public readonly payload: Buffer) {}
12
8
 
13
- static async fromGossipable(message: Gossipable): Promise<P2PMessage> {
14
- return new P2PMessage(new Date(), await message.p2pMessageIdentifier(), message.toBuffer());
9
+ static fromGossipable(message: Gossipable): P2PMessage {
10
+ return new P2PMessage(message.toBuffer());
15
11
  }
16
12
 
17
13
  static fromMessageData(messageData: Buffer): P2PMessage {
18
14
  const reader = new BufferReader(messageData);
19
- const publishTime = reader.readUInt64();
20
- const id = Buffer32.fromBuffer(reader);
21
15
  const payload = reader.readBuffer();
22
- return new P2PMessage(new Date(Number(publishTime)), id, payload);
16
+ return new P2PMessage(payload);
23
17
  }
24
18
 
25
19
  toMessageData(): Buffer {
26
- return serializeToBuffer([
27
- bigintToUInt64BE(BigInt(this.publishTime.getTime())),
28
- this.id,
29
- serializeToBuffer(this.payload.length, this.payload),
30
- ]);
20
+ return serializeToBuffer([serializeToBuffer(this.payload.length, this.payload)]);
31
21
  }
32
22
  }
33
23
 
@@ -4,6 +4,7 @@ import { keccak256, makeEthSignDigest } from '@aztec/foundation/crypto';
4
4
  export enum SignatureDomainSeparator {
5
5
  blockProposal = 0,
6
6
  blockAttestation = 1,
7
+ attestationsAndSigners = 2,
7
8
  }
8
9
 
9
10
  export interface Signable {
@@ -22,6 +22,29 @@ export enum OffenseType {
22
22
  ATTESTED_DESCENDANT_OF_INVALID = 7,
23
23
  }
24
24
 
25
+ export function getOffenseTypeName(offense: OffenseType) {
26
+ switch (offense) {
27
+ case OffenseType.UNKNOWN:
28
+ return 'unknown';
29
+ case OffenseType.DATA_WITHHOLDING:
30
+ return 'data_withholding';
31
+ case OffenseType.VALID_EPOCH_PRUNED:
32
+ return 'valid_epoch_pruned';
33
+ case OffenseType.INACTIVITY:
34
+ return 'inactivity';
35
+ case OffenseType.BROADCASTED_INVALID_BLOCK_PROPOSAL:
36
+ return 'broadcasted_invalid_block_proposal';
37
+ case OffenseType.PROPOSED_INSUFFICIENT_ATTESTATIONS:
38
+ return 'proposed_insufficient_attestations';
39
+ case OffenseType.PROPOSED_INCORRECT_ATTESTATIONS:
40
+ return 'proposed_incorrect_attestations';
41
+ case OffenseType.ATTESTED_DESCENDANT_OF_INVALID:
42
+ return 'attested_descendant_of_invalid';
43
+ default:
44
+ throw new Error(`Unknown offense type: ${offense}`);
45
+ }
46
+ }
47
+
25
48
  export const OffenseTypeSchema = z.nativeEnum(OffenseType);
26
49
 
27
50
  export const OffenseToBigInt: Record<OffenseType, bigint> = {
@@ -2,6 +2,12 @@ import { fromEntries, getEntries, maxBy } from '@aztec/foundation/collection';
2
2
  import { jsonParseWithSchema } from '@aztec/foundation/json-rpc';
3
3
  import type { ReadOnlyFileStore } from '@aztec/stdlib/file-store';
4
4
 
5
+ import { createReadStream, createWriteStream } from 'fs';
6
+ import fs from 'fs/promises';
7
+ import pathMod from 'path';
8
+ import { pipeline } from 'stream/promises';
9
+ import { createGunzip, gunzipSync } from 'zlib';
10
+
5
11
  import {
6
12
  SnapshotDataKeys,
7
13
  type SnapshotDataUrls,
@@ -20,7 +26,8 @@ export async function getSnapshotIndex(
20
26
  try {
21
27
  if (await store.exists(snapshotIndexPath)) {
22
28
  const snapshotIndexData = await store.read(snapshotIndexPath);
23
- return jsonParseWithSchema(snapshotIndexData.toString(), SnapshotsIndexSchema);
29
+ const buf = maybeGunzip(snapshotIndexData);
30
+ return jsonParseWithSchema(buf.toString('utf-8'), SnapshotsIndexSchema);
24
31
  } else {
25
32
  return undefined;
26
33
  }
@@ -50,10 +57,67 @@ export function makeSnapshotPaths(baseDir: string): SnapshotDataUrls {
50
57
  return fromEntries(SnapshotDataKeys.map(key => [key, `${baseDir}/${key}.db`]));
51
58
  }
52
59
 
60
+ function isGzipMagic(data: Buffer): boolean {
61
+ return data.length >= 2 && data[0] === 0x1f && data[1] === 0x8b;
62
+ }
63
+
64
+ function maybeGunzip(data: Buffer): Buffer {
65
+ const magicNumberIndicatesGzip = isGzipMagic(data);
66
+
67
+ if (magicNumberIndicatesGzip) {
68
+ try {
69
+ const out = gunzipSync(data);
70
+ return out;
71
+ } catch (err) {
72
+ throw new Error(`Decompression of gzipped data failed: ${(err as Error).message}`);
73
+ }
74
+ }
75
+ return data;
76
+ }
77
+
78
+ async function detectGzip(localFilePathToPeek: string): Promise<boolean> {
79
+ // Peek the actual bytes we downloaded.
80
+ try {
81
+ const fd = await fs.open(localFilePathToPeek, 'r');
82
+ try {
83
+ const header = Buffer.alloc(2);
84
+ const { bytesRead } = await fd.read(header, 0, 2, 0);
85
+ return bytesRead >= 2 && isGzipMagic(header);
86
+ } finally {
87
+ await fd.close();
88
+ }
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+
53
94
  export async function downloadSnapshot(
54
95
  snapshot: Pick<SnapshotMetadata, 'dataUrls'>,
55
96
  localPaths: Record<SnapshotDataKeys, string>,
56
97
  store: ReadOnlyFileStore,
57
98
  ): Promise<void> {
58
- await Promise.all(getEntries(localPaths).map(([key, path]) => store.download(snapshot.dataUrls[key], path)));
99
+ await Promise.all(
100
+ getEntries(localPaths).map(async ([key, path]) => {
101
+ await fs.mkdir(pathMod.dirname(path), { recursive: true });
102
+
103
+ const tmpPath = `${path}.download`;
104
+ try {
105
+ const url = snapshot.dataUrls[key];
106
+ await store.download(url, tmpPath);
107
+
108
+ const isGzip = await detectGzip(tmpPath);
109
+
110
+ const read = createReadStream(tmpPath);
111
+ const write = createWriteStream(path);
112
+ if (isGzip) {
113
+ const gunzip = createGunzip();
114
+ await pipeline(read, gunzip, write);
115
+ } else {
116
+ await pipeline(read, write);
117
+ }
118
+ } finally {
119
+ await fs.unlink(tmpPath).catch(() => undefined);
120
+ }
121
+ }),
122
+ );
59
123
  }
@@ -48,6 +48,7 @@ export async function uploadSnapshotToIndex(
48
48
 
49
49
  await store.save(getSnapshotIndexPath(metadata), Buffer.from(jsonStringify(snapshotsIndex, true)), {
50
50
  public: true, // Make the index publicly accessible
51
+ compress: false, // Ensure index.json is not gzipped
51
52
  metadata: { ['Cache-control']: 'no-store' }, // Do not cache object versions
52
53
  });
53
54
  return newSnapshotMetadata;
@@ -8,6 +8,7 @@ import type { ContractArtifact } from '../abi/abi.js';
8
8
  import { AztecAddress } from '../aztec-address/index.js';
9
9
  import { CommitteeAttestation, L1PublishedData } from '../block/index.js';
10
10
  import { L2Block } from '../block/l2_block.js';
11
+ import type { CommitteeAttestationsAndSigners } from '../block/proposal/attestations_and_signers.js';
11
12
  import { PublishedL2Block } from '../block/published_l2_block.js';
12
13
  import { computeContractAddressFromInstance } from '../contract/contract_address.js';
13
14
  import { getContractClassFromArtifact } from '../contract/contract_class.js';
@@ -273,6 +274,17 @@ const makeAndSignConsensusPayload = (
273
274
  return { blockNumber: header.globalVariables.blockNumber, payload, signature };
274
275
  };
275
276
 
277
+ export const makeAndSignCommitteeAttestationsAndSigners = (
278
+ attestationsAndSigners: CommitteeAttestationsAndSigners,
279
+ signer: Secp256k1Signer = Secp256k1Signer.random(),
280
+ ) => {
281
+ const hash = getHashedSignaturePayloadEthSignedMessage(
282
+ attestationsAndSigners,
283
+ SignatureDomainSeparator.attestationsAndSigners,
284
+ );
285
+ return signer.sign(hash);
286
+ };
287
+
276
288
  export const makeBlockProposal = (options?: MakeConsensusPayloadOptions): BlockProposal => {
277
289
  const { blockNumber, payload, signature } = makeAndSignConsensusPayload(
278
290
  SignatureDomainSeparator.blockProposal,
@@ -84,6 +84,19 @@ export class ProposedBlockHeader {
84
84
  );
85
85
  }
86
86
 
87
+ equals(other: ProposedBlockHeader): boolean {
88
+ return (
89
+ this.lastArchiveRoot.equals(other.lastArchiveRoot) &&
90
+ this.contentCommitment.equals(other.contentCommitment) &&
91
+ this.slotNumber.equals(other.slotNumber) &&
92
+ this.timestamp === other.timestamp &&
93
+ this.coinbase.equals(other.coinbase) &&
94
+ this.feeRecipient.equals(other.feeRecipient) &&
95
+ this.gasFees.equals(other.gasFees) &&
96
+ this.totalManaUsed.equals(other.totalManaUsed)
97
+ );
98
+ }
99
+
87
100
  toBuffer() {
88
101
  // Note: The order here must match the order in the ProposedHeaderLib solidity library.
89
102
  return serializeToBuffer([
@@ -137,6 +137,6 @@ export class StateReference {
137
137
  }
138
138
 
139
139
  public equals(other: this): boolean {
140
- return this.l1ToL2MessageTree.root.equals(other.l1ToL2MessageTree.root) && this.partial.equals(other.partial);
140
+ return this.l1ToL2MessageTree.equals(other.l1ToL2MessageTree) && this.partial.equals(other.partial);
141
141
  }
142
142
  }
package/src/tx/tx.ts CHANGED
@@ -207,16 +207,6 @@ export class Tx extends Gossipable {
207
207
  return this.txHash;
208
208
  }
209
209
 
210
- /**
211
- * Allows setting the hash of the Tx.
212
- * Use this when you want to skip computing it from the original data.
213
- * Don't set a Tx hash received from an untrusted source.
214
- * @param hash - The hash to set.
215
- */
216
- setTxHash(_hash: TxHash) {
217
- return this;
218
- }
219
-
220
210
  getCalldataMap(): Map<string, Fr[]> {
221
211
  if (!this.calldataMap) {
222
212
  const calldataMap = new Map();