@aztec/archiver 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/archiver/archiver.js +1 -1
- package/dest/archiver/data_retrieval.d.ts +1 -1
- package/dest/archiver/data_retrieval.d.ts.map +1 -1
- package/dest/archiver/data_retrieval.js +1 -1
- package/dest/archiver/validation.d.ts.map +1 -1
- package/dest/archiver/validation.js +36 -20
- package/package.json +15 -15
- package/src/archiver/archiver.ts +1 -1
- package/src/archiver/data_retrieval.ts +3 -1
- package/src/archiver/validation.ts +38 -22
|
@@ -21,9 +21,9 @@ import { L2BlockSourceEvents } from '@aztec/stdlib/block';
|
|
|
21
21
|
import { computePublicBytecodeCommitment, isValidPrivateFunctionMembershipProof, isValidUtilityFunctionMembershipProof } from '@aztec/stdlib/contract';
|
|
22
22
|
import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
23
23
|
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
24
|
+
import { createPublicClient, fallback, http } from '@spalladino/viem';
|
|
24
25
|
import { EventEmitter } from 'events';
|
|
25
26
|
import groupBy from 'lodash.groupby';
|
|
26
|
-
import { createPublicClient, fallback, http } from 'viem';
|
|
27
27
|
import { retrieveBlocksFromRollup, retrieveL1ToL2Message, retrieveL1ToL2Messages, retrievedBlockToPublishedL2Block } from './data_retrieval.js';
|
|
28
28
|
import { InitialBlockNumberNotSequentialError, NoBlobBodiesFoundError } from './errors.js';
|
|
29
29
|
import { ArchiverInstrumentation } from './instrumentation.js';
|
|
@@ -7,7 +7,7 @@ import { type InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
|
7
7
|
import { Body, CommitteeAttestation, PublishedL2Block } from '@aztec/stdlib/block';
|
|
8
8
|
import { Proof } from '@aztec/stdlib/proofs';
|
|
9
9
|
import { ProposedBlockHeader, StateReference } from '@aztec/stdlib/tx';
|
|
10
|
-
import { type GetContractReturnType, type Hex } from 'viem';
|
|
10
|
+
import { type GetContractReturnType, type Hex } from '@spalladino/viem';
|
|
11
11
|
import type { DataRetrieval } from './structs/data_retrieval.js';
|
|
12
12
|
import type { InboxMessage } from './structs/inbox_message.js';
|
|
13
13
|
import type { L1PublishedData } from './structs/published.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data_retrieval.d.ts","sourceRoot":"","sources":["../../src/archiver/data_retrieval.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,KAAK,EAEV,UAAU,EAGV,gBAAgB,EAEjB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"data_retrieval.d.ts","sourceRoot":"","sources":["../../src/archiver/data_retrieval.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ import { Body, CommitteeAttestation, L2Block, PublishedL2Block } from '@aztec/st
|
|
|
8
8
|
import { Proof } from '@aztec/stdlib/proofs';
|
|
9
9
|
import { AppendOnlyTreeSnapshot } from '@aztec/stdlib/trees';
|
|
10
10
|
import { BlockHeader, GlobalVariables, ProposedBlockHeader, StateReference } from '@aztec/stdlib/tx';
|
|
11
|
-
import { decodeFunctionData, getAbiItem, hexToBytes, multicall3Abi } from 'viem';
|
|
11
|
+
import { decodeFunctionData, getAbiItem, hexToBytes, multicall3Abi } from '@spalladino/viem';
|
|
12
12
|
import { NoBlobBodiesFoundError } from './errors.js';
|
|
13
13
|
export function retrievedBlockToPublishedL2Block(retrievedBlock) {
|
|
14
14
|
const { l2BlockNumber, archiveRoot, stateReference, header: proposedHeader, body, l1, chainId, version, attestations } = retrievedBlock;
|
|
@@ -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;
|
|
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,3 +1,4 @@
|
|
|
1
|
+
import { compactArray } from '@aztec/foundation/collection';
|
|
1
2
|
import { getAttestationsFromPublishedL2Block } from '@aztec/stdlib/block';
|
|
2
3
|
import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
3
4
|
/**
|
|
@@ -5,7 +6,7 @@ import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
|
5
6
|
* Returns true if the attestations are valid and sufficient, false otherwise.
|
|
6
7
|
*/ export async function validateBlockAttestations(publishedBlock, epochCache, constants, logger) {
|
|
7
8
|
const attestations = getAttestationsFromPublishedL2Block(publishedBlock);
|
|
8
|
-
const attestors = attestations.map((a)=>a
|
|
9
|
+
const attestors = compactArray(attestations.map((a)=>a?.tryGetSender()));
|
|
9
10
|
const { block } = publishedBlock;
|
|
10
11
|
const blockHash = await block.hash().then((hash)=>hash.toString());
|
|
11
12
|
const archiveRoot = block.archive.root.toString();
|
|
@@ -21,8 +22,9 @@ import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
|
21
22
|
};
|
|
22
23
|
logger?.debug(`Validating attestations for block ${block.number} at slot ${slot} in epoch ${epoch}`, {
|
|
23
24
|
committee: (committee ?? []).map((member)=>member.toString()),
|
|
24
|
-
recoveredAttestors:
|
|
25
|
-
|
|
25
|
+
recoveredAttestors: attestors.map((member)=>member.toString()),
|
|
26
|
+
invalidAttestations: attestations.filter((a)=>a !== undefined && a.tryGetSender() === undefined).map((a)=>a?.toInspect()),
|
|
27
|
+
postedAttestations: publishedBlock.attestations.map((a)=>(a.address.isZero() ? a.signature : a.address).toString()),
|
|
26
28
|
...logData
|
|
27
29
|
});
|
|
28
30
|
if (!committee || committee.length === 0) {
|
|
@@ -35,29 +37,43 @@ import { getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
|
35
37
|
const requiredAttestationCount = Math.floor(committee.length * 2 / 3) + 1;
|
|
36
38
|
for(let i = 0; i < attestations.length; i++){
|
|
37
39
|
const attestation = attestations[i];
|
|
38
|
-
|
|
39
|
-
if (
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
42
52
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
valid: false,
|
|
46
|
-
reason,
|
|
47
|
-
invalidIndex: i,
|
|
48
|
-
block: publishedBlock.block.toBlockInfo(),
|
|
53
|
+
} else {
|
|
54
|
+
logger?.warn(`Attestation from non-committee member ${signer} at slot ${slot}`, {
|
|
49
55
|
committee,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
attestors,
|
|
53
|
-
attestations: publishedBlock.attestations
|
|
54
|
-
};
|
|
56
|
+
...logData
|
|
57
|
+
});
|
|
55
58
|
}
|
|
59
|
+
const reason = 'invalid-attestation';
|
|
60
|
+
return {
|
|
61
|
+
valid: false,
|
|
62
|
+
reason,
|
|
63
|
+
invalidIndex: i,
|
|
64
|
+
block: publishedBlock.block.toBlockInfo(),
|
|
65
|
+
committee,
|
|
66
|
+
seed,
|
|
67
|
+
epoch,
|
|
68
|
+
attestors,
|
|
69
|
+
attestations: publishedBlock.attestations
|
|
70
|
+
};
|
|
56
71
|
}
|
|
57
|
-
|
|
72
|
+
const validAttestationCount = compactArray(attestations).length;
|
|
73
|
+
if (validAttestationCount < requiredAttestationCount) {
|
|
58
74
|
logger?.warn(`Insufficient attestations for block at slot ${slot}`, {
|
|
59
75
|
requiredAttestations: requiredAttestationCount,
|
|
60
|
-
actualAttestations:
|
|
76
|
+
actualAttestations: validAttestationCount,
|
|
61
77
|
...logData
|
|
62
78
|
});
|
|
63
79
|
const reason = 'insufficient-attestations';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/archiver",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-rc.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -66,23 +66,23 @@
|
|
|
66
66
|
]
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
-
"@aztec/blob-lib": "2.0.
|
|
70
|
-
"@aztec/blob-sink": "2.0.
|
|
71
|
-
"@aztec/constants": "2.0.
|
|
72
|
-
"@aztec/epoch-cache": "2.0.
|
|
73
|
-
"@aztec/ethereum": "2.0.
|
|
74
|
-
"@aztec/foundation": "2.0.
|
|
75
|
-
"@aztec/kv-store": "2.0.
|
|
76
|
-
"@aztec/l1-artifacts": "2.0.
|
|
77
|
-
"@aztec/noir-protocol-circuits-types": "2.0.
|
|
78
|
-
"@aztec/protocol-contracts": "2.0.
|
|
79
|
-
"@aztec/stdlib": "2.0.
|
|
80
|
-
"@aztec/telemetry-client": "2.0.
|
|
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",
|
|
81
|
+
"@spalladino/viem": "2.38.2-eip7594.0",
|
|
81
82
|
"lodash.groupby": "^4.6.0",
|
|
82
83
|
"lodash.omit": "^4.5.0",
|
|
83
84
|
"tsc-watch": "^6.0.0",
|
|
84
|
-
"tslib": "^2.5.0"
|
|
85
|
-
"viem": "2.23.7"
|
|
85
|
+
"tslib": "^2.5.0"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
88
|
"@jest/globals": "^30.0.0",
|
package/src/archiver/archiver.ts
CHANGED
|
@@ -72,9 +72,9 @@ import {
|
|
|
72
72
|
trackSpan,
|
|
73
73
|
} from '@aztec/telemetry-client';
|
|
74
74
|
|
|
75
|
+
import { type GetContractReturnType, createPublicClient, fallback, http } from '@spalladino/viem';
|
|
75
76
|
import { EventEmitter } from 'events';
|
|
76
77
|
import groupBy from 'lodash.groupby';
|
|
77
|
-
import { type GetContractReturnType, createPublicClient, fallback, http } from 'viem';
|
|
78
78
|
|
|
79
79
|
import type { ArchiverDataStore, ArchiverL1SynchPoint } from './archiver_store.js';
|
|
80
80
|
import type { ArchiverConfig } from './config.js';
|
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
12
12
|
import { Buffer16, Buffer32 } from '@aztec/foundation/buffer';
|
|
13
13
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
14
|
+
import type { ViemSignature } from '@aztec/foundation/eth-signature';
|
|
14
15
|
import { Fr } from '@aztec/foundation/fields';
|
|
15
16
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
16
17
|
import { type InboxAbi, RollupAbi } from '@aztec/l1-artifacts';
|
|
@@ -27,7 +28,7 @@ import {
|
|
|
27
28
|
getAbiItem,
|
|
28
29
|
hexToBytes,
|
|
29
30
|
multicall3Abi,
|
|
30
|
-
} from 'viem';
|
|
31
|
+
} from '@spalladino/viem';
|
|
31
32
|
|
|
32
33
|
import { NoBlobBodiesFoundError } from './errors.js';
|
|
33
34
|
import type { DataRetrieval } from './structs/data_retrieval.js';
|
|
@@ -319,6 +320,7 @@ async function getBlockFromRollupTx(
|
|
|
319
320
|
},
|
|
320
321
|
ViemCommitteeAttestations,
|
|
321
322
|
Hex[],
|
|
323
|
+
ViemSignature,
|
|
322
324
|
Hex,
|
|
323
325
|
];
|
|
324
326
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EpochCache } from '@aztec/epoch-cache';
|
|
2
|
+
import { compactArray } from '@aztec/foundation/collection';
|
|
2
3
|
import type { Logger } from '@aztec/foundation/log';
|
|
3
4
|
import {
|
|
4
5
|
type PublishedL2Block,
|
|
@@ -20,7 +21,7 @@ export async function validateBlockAttestations(
|
|
|
20
21
|
logger?: Logger,
|
|
21
22
|
): Promise<ValidateBlockResult> {
|
|
22
23
|
const attestations = getAttestationsFromPublishedL2Block(publishedBlock);
|
|
23
|
-
const attestors = attestations.map(a => a
|
|
24
|
+
const attestors = compactArray(attestations.map(a => a?.tryGetSender()));
|
|
24
25
|
const { block } = publishedBlock;
|
|
25
26
|
const blockHash = await block.hash().then(hash => hash.toString());
|
|
26
27
|
const archiveRoot = block.archive.root.toString();
|
|
@@ -31,10 +32,11 @@ export async function validateBlockAttestations(
|
|
|
31
32
|
|
|
32
33
|
logger?.debug(`Validating attestations for block ${block.number} at slot ${slot} in epoch ${epoch}`, {
|
|
33
34
|
committee: (committee ?? []).map(member => member.toString()),
|
|
34
|
-
recoveredAttestors:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
recoveredAttestors: attestors.map(member => member.toString()),
|
|
36
|
+
invalidAttestations: attestations
|
|
37
|
+
.filter(a => a !== undefined && a.tryGetSender() === undefined)
|
|
38
|
+
.map(a => a?.toInspect()),
|
|
39
|
+
postedAttestations: publishedBlock.attestations.map(a => (a.address.isZero() ? a.signature : a.address).toString()),
|
|
38
40
|
...logData,
|
|
39
41
|
});
|
|
40
42
|
|
|
@@ -48,28 +50,42 @@ export async function validateBlockAttestations(
|
|
|
48
50
|
|
|
49
51
|
for (let i = 0; i < attestations.length; i++) {
|
|
50
52
|
const attestation = attestations[i];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
};
|
|
53
|
+
|
|
54
|
+
// Skip empty signatures (undefined entries)
|
|
55
|
+
if (attestation === undefined) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const signer = attestation.tryGetSender()?.toString();
|
|
60
|
+
if (signer !== undefined && committeeSet.has(signer)) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
|
|
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 });
|
|
66
68
|
}
|
|
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
|
+
};
|
|
67
82
|
}
|
|
68
83
|
|
|
69
|
-
|
|
84
|
+
const validAttestationCount = compactArray(attestations).length;
|
|
85
|
+
if (validAttestationCount < requiredAttestationCount) {
|
|
70
86
|
logger?.warn(`Insufficient attestations for block at slot ${slot}`, {
|
|
71
87
|
requiredAttestations: requiredAttestationCount,
|
|
72
|
-
actualAttestations:
|
|
88
|
+
actualAttestations: validAttestationCount,
|
|
73
89
|
...logData,
|
|
74
90
|
});
|
|
75
91
|
const reason = 'insufficient-attestations';
|