feat: sigagg#426
Conversation
|
@claude review |
|
Claude finished @mskrzypkows's task in 3m 58s —— View job Claude PR Review — SigaggReviewed the port of Charon's Todo
Functional correctness1. Silent #[allow(clippy::cast_possible_truncation)]
let bls_map: HashMap<u8, [u8; 96]> = bls_sigs
.iter()
.map(|(idx, sig)| (*idx as u8, *sig.as_ref()))
.collect();Dedup at line 133 happens in a let idx_u8 = u8::try_from(*idx).map_err(|_| SigAggError::InvalidShareIndex)?;2. Lost error context — pubkey not wrapped on per-validator failure ( return errors.Wrap(err, "threshold aggregate", z.Any("pubkey", pubkey))Rust just propagates the inner error. With multi-validator batches, the caller can't tell which validator failed. Consider wrapping with the pubkey, or at least logging it on the error path. 3. Template-selection loop diverges from Go in mixed-type edge case ( for _, parSig := range parSigs {
attVidx, ok := parSig.SignedData.(core.VersionedAttestation)
if !ok { break }
if attVidx.ValidatorIndex != nil { fullSig = attVidx; break }
}Rust uses 4. Subscriber semantics: no clone, immutable borrow ( 5. pub fn new_verifier() -> VerifyFn {
Arc::new(|_, _| Box::pin(async { Ok(()) }))
}Acknowledged in the TODO above, but this is security-critical — without verification, an aggregator will happily emit a "valid" aggregated signature for any input. Should not be wired into the production path until 6. Missing tracing spans Rust style / idioms7. Pin<Box<dyn Future<Output = Result<()>> + Send + Sync>>Futures rarely need 8.
9. Type alias 10. 11. Doc comment style — top-of-file //! SigAgg aggregates threshold partial BLS signatures...
TestsGood baseline coverage (12 tests), but a few important paths are uncovered. 12. No test for 13. No test for subscriber returning an error. Currently 14. No test for 15. No test for the 16. Nitpicks
VerdictSolid first pass. Main blockers before this can be considered production-ready:
Style/observability points (#2, #3, #6, #7-11) are easy follow-ups and don't need to block. |
No description provided.