@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.
- package/dest/block/in_block.d.ts +5 -5
- package/dest/block/in_block.d.ts.map +1 -1
- package/dest/block/proposal/attestations_and_signers.d.ts +48 -0
- package/dest/block/proposal/attestations_and_signers.d.ts.map +1 -0
- package/dest/block/proposal/attestations_and_signers.js +99 -0
- package/dest/block/proposal/committee_attestation.d.ts +1 -0
- package/dest/block/proposal/committee_attestation.d.ts.map +1 -1
- package/dest/block/proposal/committee_attestation.js +3 -0
- package/dest/block/proposal/index.d.ts +1 -0
- package/dest/block/proposal/index.d.ts.map +1 -1
- package/dest/block/proposal/index.js +1 -0
- package/dest/block/published_l2_block.d.ts +5 -1
- package/dest/block/published_l2_block.d.ts.map +1 -1
- package/dest/block/published_l2_block.js +5 -2
- package/dest/contract/interfaces/contract_class.d.ts +3 -3
- package/dest/epoch-helpers/index.d.ts +2 -0
- package/dest/epoch-helpers/index.d.ts.map +1 -1
- package/dest/epoch-helpers/index.js +3 -0
- package/dest/file-store/factory.d.ts.map +1 -1
- package/dest/file-store/factory.js +18 -0
- package/dest/file-store/interface.d.ts +8 -2
- package/dest/file-store/interface.d.ts.map +1 -1
- package/dest/file-store/s3.d.ts +26 -0
- package/dest/file-store/s3.d.ts.map +1 -0
- package/dest/file-store/s3.js +252 -0
- package/dest/interfaces/aztec-node-admin.d.ts +16 -7
- package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
- package/dest/interfaces/block-builder.d.ts +1 -0
- package/dest/interfaces/block-builder.d.ts.map +1 -1
- package/dest/interfaces/configs.d.ts +5 -0
- package/dest/interfaces/configs.d.ts.map +1 -1
- package/dest/interfaces/configs.js +2 -1
- package/dest/interfaces/proving-job.d.ts +6 -6
- package/dest/interfaces/slasher.d.ts +4 -0
- package/dest/interfaces/slasher.d.ts.map +1 -1
- package/dest/interfaces/slasher.js +1 -0
- package/dest/interfaces/validator.d.ts +9 -2
- package/dest/interfaces/validator.d.ts.map +1 -1
- package/dest/interfaces/validator.js +2 -1
- package/dest/l1-contracts/slash_factory.d.ts +1 -1
- package/dest/l1-contracts/slash_factory.d.ts.map +1 -1
- package/dest/l1-contracts/slash_factory.js +1 -1
- package/dest/p2p/block_attestation.d.ts +35 -0
- package/dest/p2p/block_attestation.d.ts.map +1 -1
- package/dest/p2p/block_attestation.js +17 -0
- package/dest/p2p/consensus_payload.d.ts +27 -0
- package/dest/p2p/consensus_payload.d.ts.map +1 -1
- package/dest/p2p/consensus_payload.js +11 -1
- package/dest/p2p/gossipable.d.ts +2 -4
- package/dest/p2p/gossipable.d.ts.map +1 -1
- package/dest/p2p/gossipable.js +5 -14
- package/dest/p2p/signature_utils.d.ts +2 -1
- package/dest/p2p/signature_utils.d.ts.map +1 -1
- package/dest/p2p/signature_utils.js +1 -0
- package/dest/slashing/types.d.ts +1 -0
- package/dest/slashing/types.d.ts.map +1 -1
- package/dest/slashing/types.js +22 -0
- package/dest/snapshots/download.d.ts.map +1 -1
- package/dest/snapshots/download.js +58 -2
- package/dest/snapshots/upload.d.ts.map +1 -1
- package/dest/snapshots/upload.js +1 -0
- package/dest/tests/mocks.d.ts +2 -0
- package/dest/tests/mocks.d.ts.map +1 -1
- package/dest/tests/mocks.js +4 -0
- package/dest/tx/indexed_tx_effect.d.ts +3 -3
- package/dest/tx/proposed_block_header.d.ts +1 -0
- package/dest/tx/proposed_block_header.d.ts.map +1 -1
- package/dest/tx/proposed_block_header.js +3 -0
- package/dest/tx/state_reference.js +1 -1
- package/dest/tx/tx.d.ts +0 -7
- package/dest/tx/tx.d.ts.map +1 -1
- package/dest/tx/tx.js +0 -8
- package/package.json +11 -10
- package/src/block/proposal/attestations_and_signers.ts +121 -0
- package/src/block/proposal/committee_attestation.ts +4 -0
- package/src/block/proposal/index.ts +1 -0
- package/src/block/published_l2_block.ts +10 -4
- package/src/epoch-helpers/index.ts +8 -0
- package/src/file-store/factory.ts +15 -0
- package/src/file-store/interface.ts +8 -2
- package/src/file-store/s3.ts +254 -0
- package/src/interfaces/block-builder.ts +1 -0
- package/src/interfaces/configs.ts +3 -0
- package/src/interfaces/slasher.ts +2 -0
- package/src/interfaces/validator.ts +12 -2
- package/src/l1-contracts/slash_factory.ts +1 -1
- package/src/p2p/block_attestation.ts +20 -0
- package/src/p2p/consensus_payload.ts +17 -1
- package/src/p2p/gossipable.ts +6 -16
- package/src/p2p/signature_utils.ts +1 -0
- package/src/slashing/types.ts +23 -0
- package/src/snapshots/download.ts +66 -2
- package/src/snapshots/upload.ts +1 -0
- package/src/tests/mocks.ts +12 -0
- package/src/tx/proposed_block_header.ts +13 -0
- package/src/tx/state_reference.ts +1 -1
- package/src/tx/tx.ts +0 -10
package/src/p2p/gossipable.ts
CHANGED
|
@@ -1,33 +1,23 @@
|
|
|
1
1
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
2
|
-
import { BufferReader,
|
|
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
|
|
14
|
-
return new P2PMessage(
|
|
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(
|
|
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
|
|
package/src/slashing/types.ts
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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
|
}
|
package/src/snapshots/upload.ts
CHANGED
|
@@ -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;
|
package/src/tests/mocks.ts
CHANGED
|
@@ -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.
|
|
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();
|