# Audit Diff Report 本地代码复核报告

## 结论

我已按用户指定，基于 `/root/ethauditorpub/code/` 下的 5 个本地仓库重新核查 `Audit_Diff_Report.md`。

这次复核不再依赖上游仓库路径，而是直接检查本地代码文件、对应行号和实际实现。**结论没有改变：报告不能支撑“已确认 25 个共识级漏洞”这一 headline。**

## 本地代码排查方法

1. 解析 `Audit_Diff_Report.json` 中全部 99 个条目；
2. 把每条 `evidence.file` 映射到 `/root/ethauditorpub/code/{client}/...`；
3. 检查本地文件是否存在、行号是否有效、是否落在 `test / mock / fixture / generator`；
4. 对 25 个 `VULN-*` 逐条阅读本地源码片段，判断是否真的构成漏洞。

## 本地排查统计

| 类别 | 数量 | 可保留 | 仅保留为线索/降级 | 不采信 |
|---|---:|---:|---:|---:|
| A-class | 44 | 2 | 13 | 29 |
| VULN | 25 | 0 | 3 | 22 |
| B-class | 30 | 11 | 7 | 12 |

本地 evidence 质量统计：

- `本地可定位`: 28
- `引用非生产代码`: 28
- `证据缺失`: 20
- `部分路径缺失`: 16
- `本地路径失效`: 7

按客户端看，报告中引用路径缺失最多的是：

- `prysm`: 6 处 missing path
- `lighthouse`: 15 处 missing path
- `grandine`: 25 处 missing path
- `teku`: 12 处 missing path
- `lodestar`: 5 处 missing path

## 关键代码观察

1. **Prysm attestation 顺序窗口真实存在**：`validator/client/attest.go` 里先 `signAtt()`，再调用 `db.SlashableAttestationCheck()`；而 `SlashableAttestationCheck()` 内部又会 `SaveAttestationForPubKey()`。这说明报告描述的“签名与落库之间存在窗口”并非空穴来风，但它更像原子性/健壮性风险。
2. **Grandine blob cache 不是“仅插入不清理”**：`fork_choice_store/src/blob_cache.rs` 里除了 `insert()`，还有 `on_slot()` 的 `retain(...)` 清理逻辑，因此报告把它直接定性为“无界缓存漏洞”并不成立。
3. **Lodestar checkpoint 读取并不支持 OOM 结论**：`packages/beacon-node/src/chain/chain.ts:getPersistedCheckpointState()` 只是从 datastore 读取最新或指定 checkpoint。
4. **Lodestar block archive 的证据不足以推出共识漏洞**：`blockArchive.ts` 的 `Promise.all` 只能说明并行写 block 和索引，不能自动推出“非原子写导致链分叉”。
5. **Lighthouse VULN-10 的证据其实在测试模块里**：`naive_aggregation_pool.rs` 中被引用的 `sign_attestation(...).expect(...)` 位于 `#[cfg(test)] mod tests`。
6. **Lighthouse VULN-14 直接引用测试生成器**：`validator_client/slashing_protection/src/bin/test_generator.rs` 明确不是生产路径。
7. **Lodestar VULN-12 引错函数**：报告引用的 `packages/validator/src/services/attestation.ts` 对应的是 `produceAndPublishAggregates()`，不是 `recording_slashing_db`。
8. **多条执行层 VULN 实际只落在普通 RPC 包装/状态查询上**：如 Teku `ExecutionClientHandlerImpl.engineNewPayload()`、Lodestar `isSyncing()`，这不足以支撑“执行层卡死/optimistic 漏洞”的结论。

## 25 个 VULN 的本地代码结论

> 注：下表“本地定位结果”取自报告原始 evidence 的本地映射汇总；若我在人工复核中补读了正确生产代码，会以“最终判断/说明”为准。

| 条目 | 本地定位结果 | 最终判断 | 说明 |
|---|---|---|---|
| VULN-1 | 本地路径失效 | 不采信 | 本地代码路径不存在，无法在本地仓库核对该结论。 |
| VULN-2 | 本地可定位 | 不采信 | `blob_cache.rs` 除了 `insert()` 外还有 `on_slot()` 清理逻辑，不能据此认定为无界缓存。 |
| VULN-3 | 本地路径失效 | 不采信 | 本地代码路径不存在，无法证成 optimistic depth 漏洞。 |
| VULN-4 | 证据缺失 | 不采信 | 报告没有给出任何本地 evidence。 |
| VULN-5 | 本地可定位 | 不采信 | `blockArchive.ts` 只是 `Promise.all` 写 block 和索引，不能直接推出“共识级归档损坏漏洞”。 |
| VULN-6 | 本地可定位 | 不采信 | 与 VULN-2 同源，只看到插入路径，没有看到无界性成立。 |
| VULN-7 | 本地可定位 | 不采信 | 对应代码是 `expect(...)` invariant，不足以直接推出外部可触发的节点崩溃漏洞。 |
| VULN-8 | 本地可定位 | 不采信 | `getPersistedCheckpointState()` 只是 datastore 读取，无法支持 `UnboundedMemoryAllocation` 结论。 |
| VULN-9 | 引用非生产代码 | 保留但降级 | Prysm 本地代码确有“先签名后做 slashing DB 检查/保存”的顺序窗口，但报告行号错误，且更像原子性风险。 |
| VULN-10 | 本地可定位 | 不采信 | 本地代码显示该 `expect("should sign attestation")` 位于 `#[cfg(test)] mod tests` 中，不是生产漏洞。 |
| VULN-11 | 引用非生产代码 | 不采信 | 本地代码文件不存在。 |
| VULN-12 | 引用非生产代码 | 不采信 | 报告给的 `attestation.ts` 行段实际是 `produceAndPublishAggregates()`，与 `recording_slashing_db` 不对应。 |
| VULN-13 | 引用非生产代码 | 不采信 | 本地代码只是 `debug_assert!(false, "Cannot aggregate base and electra attestations")`，更像调试断言，不是已证漏洞。 |
| VULN-14 | 引用非生产代码 | 不采信 | 引用的是 Lighthouse `validator_client/slashing_protection/src/bin/test_generator.rs`，明确属于测试生成器。 |
| VULN-15 | 本地可定位 | 不采信 | 对应代码只是 Lodestar 执行层状态错误映射入口，不能推出“会提议 optimistic 无效块”。 |
| VULN-16 | 本地可定位 | 保留但降级 | Prysm 本地代码明确先 `broadcastBlock` 再 `ReceiveBlock`，这是顺序差异，可保留为局部风险点。 |
| VULN-17 | 本地可定位 | 保留但降级 | Grandine 本地代码确有 `try_lock_for(timeout)` 失败路径，但更像局部 DoS/健壮性问题。 |
| VULN-18 | 证据缺失 | 不采信 | 报告没有给出任何本地 evidence。 |
| VULN-19 | 本地可定位 | 不采信 | 对应代码仅是 `push(aggregate)`，无法据此证明“无界 sync committee pool 漏洞”。 |
| VULN-20 | 本地可定位 | 不采信 | 本地文件存在，但报告不给行号，且未能在本地代码中定位其声称的漏洞分支。 |
| VULN-21 | 本地可定位 | 不采信 | 本地代码片段是普通 forkchoice reorg 判断，不支持“optimistic depth exceeded 漏洞”这一表述。 |
| VULN-22 | 本地可定位 | 不采信 | Teku/Lodestar 对应片段只是普通 engine RPC 包装与 sync 状态查询。 |
| VULN-23 | 本地路径失效 | 不采信 | 本地路径不存在。 |
| VULN-24 | 本地可定位 | 不采信 | 与 VULN-21 类似，本地代码片段不支持该漏洞结论。 |
| VULN-25 | 本地可定位 | 不采信 | 本地片段只显示 `engineNewPayload` 和 `isSyncing()`，不能证明 stuck optimistic 漏洞。 |

## A-class 全量结论（本地代码）

| 条目 | 处理结论 | 本地复核结果 | 对应项 |
|---|---|---|---|
| A-1 | 仅保留为模型线索 | 部分路径缺失 | regular_sync / multiple / HeadSlotLagExceedsThreshold |
| A-2 | 不采信为已验证结论 | 证据缺失 | regular_sync / multiple / GossipBlockReceived/GossipAttestationReceived |
| A-3 | 不采信为已验证结论 | 证据缺失 | regular_sync / multiple / BeaconNodeIsSynced/BeaconNodeApiIsReady |
| A-4 | 不采信为已验证结论 | 证据缺失 | regular_sync / multiple / KzgCommitmentsRequired / DenebForkIsActive && !AllBlobSidecarsAreAvailable / !AllBlobSidecarsAreAvailable |
| A-5 | 不采信为已验证结论 | 证据缺失 | regular_sync / multiple / PayloadRetrievalTimedOut / BlobSidecarRequestTimedOut |
| A-6 | 不采信为已验证结论 | 证据缺失 | regular_sync / multiple / AttestationIsTooOld / AttestationIsNotTooOld |
| A-7 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / start / CheckpointSyncRequired |
| A-8 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / start / CheckpointSyncRequired |
| A-9 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / fetch_checkpoint / CheckpointResponseIsValid |
| A-10 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / fetch_checkpoint / CheckpointResponseIsValid |
| A-11 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / fetch_checkpoint / ApiCheckpointSyncFailed |
| A-12 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / validate_checkpoint / CheckpointIsValid |
| A-13 | 仅保留为模型线索 | 本地路径失效 | checkpoint_sync / initialize_anchor_fork_choice / TRUE |
| A-14 | 仅保留为模型线索 | 本地路径失效 | checkpoint_sync / initialize_anchor_fork_choice / TRUE |
| A-15 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / forward_sync / SyncTargetReached |
| A-16 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / forward_sync / ShouldPerformBlobSidecarRangeSync |
| A-17 | 仅保留为模型线索 | 部分路径缺失 | checkpoint_sync / backfill_history / BackfillComplete |
| A-18 | 不采信为已验证结论 | 证据缺失 | attestation_generate / duty_processing / N/A |
| A-19 | 不采信为已验证结论 | 证据缺失 | attestation_generate / waiting_for_attestation_slot / N/A |
| A-20 | 不采信为已验证结论 | 证据缺失 | attestation_generate / fetching_beacon_state / N/A |
| A-21 | 不采信为已验证结论 | 证据缺失 | attestation_generate / preparing_attestation / N/A |
| A-22 | 不采信为已验证结论 | 证据缺失 | attestation_generate / checking_slashing_protection / N/A |
| A-23 | 不采信为已验证结论 | 证据缺失 | attestation_generate / signing / N/A |
| A-24 | 不采信为已验证结论 | 证据缺失 | attestation_generate / recording_slashing_protection / N/A |
| A-25 | 不采信为已验证结论 | 证据缺失 | attestation_generate / skipped_duty / N/A |
| A-26 | 不采信为已验证结论 | 证据缺失 | attestation_generate / complete / N/A |
| A-27 | 不采信为已验证结论 | 引用非生产代码 | attestation_generate / fetching_beacon_state / AttestationDataIsAvailable |
| A-28 | 不采信为已验证结论 | 引用非生产代码 | attestation_generate / slashing_protection_check / SlashingProtectionDBIsReady&&AttestationIsNotSlashable |
| A-29 | 不采信为已验证结论 | 引用非生产代码 | attestation_generate / various / true |
| A-30 | 仅保留为模型线索 | 部分路径缺失 | block_generate / BuildingLocalPayload / LocalPayloadIsAvailable |
| A-31 | 不采信为已验证结论 | 引用非生产代码 | aggregate / start_duty / ValidatorHasAttesterDuty |
| A-32 | 不采信为已验证结论 | 引用非生产代码 | aggregate / CheckingAggregatorDuty / SelectedAsAggregator |
| A-33 | 不采信为已验证结论 | 引用非生产代码 | aggregate / check_aggregator_duty / AggregatorNotSelected |
| A-34 | 不采信为已验证结论 | 引用非生产代码 | aggregate / wait_for_aggregation_window / EnoughTimeForAttestation |
| A-35 | 不采信为已验证结论 | 引用非生产代码 | aggregate / wait_for_aggregation_window / EnoughTimeForAttestation |
| A-36 | 不采信为已验证结论 | 引用非生产代码 | aggregate / collect_attestations / AttestationPoolContainsAggregatableAttestations |
| A-37 | 不采信为已验证结论 | 引用非生产代码 | aggregate / collect_attestations / AttestationPoolContainsAggregatableAttestations |
| A-38 | 不采信为已验证结论 | 引用非生产代码 | aggregate / collect_attestations / AttestationIsValidForPool |
| A-39 | 不采信为已验证结论 | 引用非生产代码 | aggregate / aggregate_signatures / true |
| A-40 | 不采信为已验证结论 | 引用非生产代码 | aggregate / prepare_aggregate_and_proof / true |
| A-41 | 不采信为已验证结论 | 引用非生产代码 | aggregate / record_slashing_protection / SlashingProtectionDBIsReady |
| A-42 | 不采信为已验证结论 | 引用非生产代码 | aggregate / PublishingAggregate / true |
| A-43 | 保留为模型差异 | 本地可定位 | execute_layer_relation / idle / ExecutionPayloadRequired |
| A-44 | 保留为模型差异 | 本地可定位 | execute_layer_relation / idle / BeaconNodeReadyForForkChoice |

## B-class 全量结论（本地代码）

| 条目 | 处理结论 | 本地复核结果 | 对应项 |
|---|---|---|---|
| B-1 | 仅保留为模型线索 | 本地路径失效 | initial_sync / FetchingCheckpoint / WeakSubjectivityCheckFailed |
| B-2 | 不采信为已验证结论 | 引用非生产代码 | regular_sync / multiple / GossipAttestationIsValid |
| B-3 | 不采信为已验证结论 | 证据缺失 | regular_sync / importing_block / BlockIsSlashable/BlockIsNotSlashable |
| B-4 | 保留为模型差异 | 本地可定位 | checkpoint_sync / validate_checkpoint / WeakSubjectivityPeriodNotConfigured |
| B-5 | 不采信为已验证结论 | 引用非生产代码 | attestation_generate / waiting_for_slot / NOT EnoughTimeForAttestation |
| B-6 | 保留为模型差异 | 本地可定位 | attestation_generate / building_attestation_data / NOT AttestationDataIsConsistentWithDuty |
| B-7 | 保留为模型差异 | 本地可定位 | block_generate / check_slashing_protection / BlockIsNotSlashable |
| B-8 | 保留为模型差异 | 本地可定位 | aggregate / check_aggregator_duty / AttesterDutyFetchFailed |
| B-9 | 不采信为已验证结论 | 引用非生产代码 | aggregate / collect_attestations / AttestationAggregationInternalError |
| B-10 | 不采信为已验证结论 | 引用非生产代码 | aggregate / sign_aggregate_and_proof / AggregateGenerationFailed |
| B-11 | 不采信为已验证结论 | 引用非生产代码 | aggregate / publish_aggregate / BeaconNodeIsDisconnected |
| B-12 | 仅保留为模型线索 | 部分路径缺失 | initial_sync / InitializingSync / CheckpointSyncRequired |
| B-13 | 保留为模型差异 | 本地可定位 | initial_sync / RangeSyncDownloading / MissingParentBlockRequestTimedOut |
| B-14 | 不采信为已验证结论 | 证据缺失 | initial_sync / ProcessingSyncData / ExecutionEngineDisconnected |
| B-15 | 仅保留为模型线索 | 部分路径缺失 | initial_sync / RangeSyncProcessing / ParentBlockIsMissing |
| B-16 | 保留为模型差异 | 本地可定位 | regular_sync / ImportingBlock / PayloadStatusIsSyncing && !OptimisticImportAllowed |
| B-17 | 仅保留为模型线索 | 部分路径缺失 | regular_sync / ApplyingForkChoice / ReorgDepthExceedsMaximumAllowed |
| B-18 | 仅保留为模型线索 | 部分路径缺失 | regular_sync / multiple / BlobSidecarIsValid |
| B-19 | 不采信为已验证结论 | 证据缺失 | regular_sync / multiple / SyncCommitteeMessageIsValid / SyncCommitteeContributionIsValid |
| B-20 | 保留为模型差异 | 本地可定位 | checkpoint_sync / initialize_anchor_fork_choice / InconsistentAnchorState |
| B-21 | 仅保留为模型线索 | 本地路径失效 | checkpoint_sync / forward_sync / ExecutionEngineDisconnected |
| B-22 | 保留为模型差异 | 本地可定位 | checkpoint_sync / validate_checkpoint / ConfigMismatchDetected |
| B-23 | 不采信为已验证结论 | 引用非生产代码 | attestation_generate / building_attestation / true |
| B-24 | 不采信为已验证结论 | 引用非生产代码 | block_generate / build_local_payload / ExecutionEngineTransientError |
| B-25 | 保留为模型差异 | 本地可定位 | block_generate / beacon_node_receive_proposed_block / BlockIsBlinded |
| B-26 | 保留为模型差异 | 本地可定位 | block_generate / assemble_block_components / BlockHasInvalidKzgCommitments |
| B-27 | 仅保留为模型线索 | 部分路径缺失 | execute_layer_relation / idle / ExecutionEngineDisconnected |
| B-28 | 不采信为已验证结论 | 证据缺失 | execute_layer_relation / N/A / N/A |
| B-29 | 不采信为已验证结论 | 引用非生产代码 | execute_layer_relation / awaiting_forkchoice_updated_response / PayloadStatusIsInvalid |
| B-30 | 保留为模型差异 | 本地可定位 | initial_sync / BackfillingToGenesis / BackfillDataAvailable |

## 最终结论

基于本地代码复核后，可以更明确地下结论：

1. 报告中大量条目并没有落到真实生产代码上，而是落在测试代码、错误路径或根本不存在的本地路径上。
2. 即便本地代码可定位，很多条目也只是“看到了某个分支或某个状态处理”，远不足以推出报告写的漏洞严重性。
3. 报告最有价值的部分仍然只是**跨客户端差异线索**，而不是“25 个已确认共识漏洞”的最终审计结论。
