@aztec/archiver 2.1.0-rc.1 → 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 +1 -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;AAEhE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAW,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAgC,mBAAmB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAErG,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,GAAG,EAKT,MAAM,
|
|
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;AAEhE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAC9C,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,KAAK,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAW,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE7C,OAAO,EAAgC,mBAAmB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAErG,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,GAAG,EAKT,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,EAAE,CAAC;IAChB,cAAc,EAAE,cAAc,CAAC;IAC/B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,IAAI,EAAE,IAAI,CAAC;IACX,EAAE,EAAE,eAAe,CAAC;IACpB,OAAO,EAAE,EAAE,CAAC;IACZ,OAAO,EAAE,EAAE,CAAC;IACZ,YAAY,EAAE,oBAAoB,EAAE,CAAC;CACtC,CAAC;AAEF,wBAAgB,gCAAgC,CAAC,cAAc,EAAE,gBAAgB,GAAG,gBAAgB,CAyCnG;AAED;;;;;;;;GAQG;AACH,wBAAsB,wBAAwB,CAC5C,MAAM,EAAE,qBAAqB,CAAC,OAAO,SAAS,EAAE,gBAAgB,CAAC,EACjE,YAAY,EAAE,gBAAgB,EAC9B,cAAc,EAAE,uBAAuB,EACvC,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,MAAM,EACtB,MAAM,GAAE,MAAiC,GACxC,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAuD7B;AA6DD,wBAAsB,cAAc,CAAC,YAAY,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGzG;AAqJD,iHAAiH;AACjH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,qBAAqB,CAAC,OAAO,QAAQ,EAAE,UAAU,CAAC,EACzD,IAAI,EAAE,EAAE,EACR,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAKnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,qBAAqB,CAAC,OAAO,QAAQ,EAAE,UAAU,CAAC,EACzD,gBAAgB,EAAE,MAAM,EACxB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,YAAY,EAAE,CAAC,CAgBzB;AAgBD,iEAAiE;AACjE,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,UAAU,EACzB,gBAAgB,EAAE,MAAM,EACxB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,EAAE,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,EAAE,CAAC,CAexF;AAED,yDAAyD;AACzD,wBAAsB,0BAA0B,CAC9C,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,UAAU,EACzB,gBAAgB,EAAE,MAAM,EACxB,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,aAAa,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,MAAM,EAAE,CAAA;CAAE,CAAC,CAAC,CAatG;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,EAAE,CAAC;IAChB,QAAQ,EAAE,EAAE,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,gBAAgB,EAC9B,MAAM,EAAE,KAAK,MAAM,EAAE,EACrB,gBAAgB,EAAE,EAAE,GACnB,OAAO,CAAC,gBAAgB,CAAC,CAmC3B"}
|
|
@@ -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.1.0-rc.
|
|
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.1.0-rc.
|
|
70
|
-
"@aztec/blob-sink": "2.1.0-rc.
|
|
71
|
-
"@aztec/constants": "2.1.0-rc.
|
|
72
|
-
"@aztec/epoch-cache": "2.1.0-rc.
|
|
73
|
-
"@aztec/ethereum": "2.1.0-rc.
|
|
74
|
-
"@aztec/foundation": "2.1.0-rc.
|
|
75
|
-
"@aztec/kv-store": "2.1.0-rc.
|
|
76
|
-
"@aztec/l1-artifacts": "2.1.0-rc.
|
|
77
|
-
"@aztec/noir-protocol-circuits-types": "2.1.0-rc.
|
|
78
|
-
"@aztec/protocol-contracts": "2.1.0-rc.
|
|
79
|
-
"@aztec/stdlib": "2.1.0-rc.
|
|
80
|
-
"@aztec/telemetry-client": "2.1.0-rc.
|
|
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';
|
|
@@ -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';
|