Skip to content

Commit 627b8f7

Browse files
authored
Merge branch 'main' into emlautarom1/frost_kryptology
2 parents 9830515 + 8836fb4 commit 627b8f7

File tree

17 files changed

+2872
-47
lines changed

17 files changed

+2872
-47
lines changed

.claude/skills/review-pr/SKILL.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
---
2+
name: review-pr
3+
description: >
4+
Full multi-agent code review for a Pluto PR. Spawns parallel agents covering
5+
functional correctness, security, Rust style, and code quality, then posts
6+
all findings as isolated GitHub review comments and submits a final
7+
approve/request-changes verdict. Invoke as `/review-pr <PR-number>` or
8+
`/review-pr <GitHub-PR-URL>`.
9+
---
10+
11+
# Review PR
12+
13+
You are orchestrating a thorough code review for a Pluto pull request.
14+
15+
## Input
16+
17+
The argument is either a PR number (e.g. `311`) or a full GitHub PR URL. The
18+
repository is always `NethermindEth/pluto`.
19+
20+
Resolve the PR number if a URL was given:
21+
```bash
22+
# From URL like https://github.com/NethermindEth/pluto/pull/311
23+
PR=311
24+
```
25+
26+
## Step 1 — Gather context
27+
28+
Run these in parallel:
29+
```bash
30+
gh pr view $PR --repo NethermindEth/pluto \
31+
--json title,body,files,additions,deletions,headRefName,commits
32+
gh pr diff $PR --repo NethermindEth/pluto
33+
```
34+
35+
Read every changed file from disk (the branch may already be checked out).
36+
If a file is not available locally, use the raw diff.
37+
38+
Also note the head commit SHA — you will need it for the review API call.
39+
40+
## Step 2 — Parallel agent review
41+
42+
Spawn **four agents in a single message** so they run concurrently. Give each
43+
agent the full diff and relevant file contents in its prompt.
44+
45+
| Agent | Skill | Focus |
46+
|---|---|---|
47+
| **pluto-review** | `/pluto-review` | Functional equivalence with Charon Go; parity matrix; test coverage gaps |
48+
| **security-review** || Auth bypass, resource exhaustion, key-material handling, DoS vectors |
49+
| **rust-style** | `/rust-style` | Idiomatic Rust; memory orderings; error handling patterns; naming |
50+
| **code-quality** || Concurrency correctness; state-machine completeness; resource lifecycle |
51+
52+
Each agent must return findings as JSON objects:
53+
```json
54+
{
55+
"file": "crates/foo/src/bar.rs",
56+
"line": 42,
57+
"severity": "bug|major|minor|nit",
58+
"title": "short title",
59+
"body": "detailed explanation with code snippets if helpful"
60+
}
61+
```
62+
63+
## Step 3 — Deduplicate and assess
64+
65+
Merge the four finding lists. For each finding:
66+
67+
- If the same issue is raised by multiple agents, merge into one finding
68+
(use the most detailed body).
69+
- Assign a final severity: `bug``major``minor``nit`.
70+
- Prefix the comment body with **`nit:`** if severity is `nit`.
71+
- Verify every `file` path and `line` number against the actual diff before
72+
posting — do not guess.
73+
74+
## Step 4 — Post inline comments via GitHub review API
75+
76+
Build a single JSON payload and post it in **one** API call:
77+
78+
```bash
79+
gh api repos/NethermindEth/pluto/pulls/$PR/reviews \
80+
--method POST \
81+
--input /tmp/review_payload.json \
82+
--jq '{id:.id, state:.state, url:.html_url}'
83+
```
84+
85+
Payload shape:
86+
```json
87+
{
88+
"commit_id": "<head-sha>",
89+
"body": "<overall-assessment — see Step 5>",
90+
"event": "APPROVE | REQUEST_CHANGES | COMMENT",
91+
"comments": [
92+
{
93+
"path": "crates/foo/src/bar.rs",
94+
"line": 42,
95+
"side": "RIGHT",
96+
"body": "comment text"
97+
}
98+
]
99+
}
100+
```
101+
102+
Rules for comments:
103+
- One comment per finding. Do not batch multiple issues into one comment.
104+
- Use `line` + `side: "RIGHT"` for new/modified lines (additions).
105+
- Use `side: "LEFT"` only for deleted lines.
106+
- If `line` is unavailable or ambiguous, omit it — the comment lands at the
107+
file level, which is still useful.
108+
- nit-level findings must start with **`nit:`** in the comment body.
109+
110+
## Step 5 — Overall assessment
111+
112+
Write a 3–5 sentence overall body for the review covering:
113+
1. What the PR does and overall quality signal.
114+
2. A numbered list of **bugs** (must-fix before merge).
115+
3. Summary of major/minor findings.
116+
4. Verdict rationale.
117+
118+
**Verdict rules:**
119+
120+
| Condition | Event |
121+
|---|---|
122+
| Any `bug` severity finding | `REQUEST_CHANGES` |
123+
| Any `major` severity finding | `REQUEST_CHANGES` |
124+
| Only `minor` / `nit` findings | `COMMENT` (leave open for author discretion) |
125+
| No findings or only `nit` | `APPROVE` |
126+
127+
## Output
128+
129+
After the API call succeeds, print:
130+
```
131+
Review posted: <html_url>
132+
Verdict: <APPROVE|REQUEST_CHANGES|COMMENT>
133+
Findings: <N bugs, M major, P minor, Q nits>
134+
```

.claude/skills/rust-style/SKILL.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,16 +61,25 @@ let x = a.checked_add(b).ok_or(Error::Overflow)?;
6161

6262
## Casts
6363

64-
No lossy or unchecked casts — use fallible conversions:
64+
**Never use `as` for numeric type conversions** — use fallible conversions with `try_from`:
6565

6666
```rust
67-
// Bad
67+
// Bad - will cause clippy errors
6868
let x = value as u32;
69+
let y = some_usize as u64;
6970

70-
// Good
71+
// Good - use try_from with proper error handling
7172
let x = u32::try_from(value)?;
73+
let y = u64::try_from(some_usize).expect("message explaining why this is safe");
7274
```
7375

76+
Rules:
77+
78+
- Always use `TryFrom`/`try_from` for numeric conversions between different types
79+
- Handle conversion failures explicitly (either with `?` or `expect` with justification)
80+
- The only acceptable use of `expect` is when the conversion is guaranteed to succeed (e.g., `usize` to `u64` on 64-bit platforms)
81+
- Clippy will error on unchecked `as` casts: `cast_possible_truncation`, `cast_possible_wrap`, `cast_sign_loss`
82+
7483
---
7584

7685
## Async / Tokio
@@ -158,3 +167,22 @@ mod tests {
158167
```
159168

160169
- For hashing/serialization parity, generate Go-derived test vectors and hardcode them as Rust fixtures.
170+
171+
---
172+
173+
## Pluto-Specific Checklist
174+
175+
Apply when reviewing or porting code:
176+
177+
- [ ] `Ordering::SeqCst` is justified; prefer `Relaxed`/`AcqRel` for
178+
standalone flags.
179+
- [ ] `Error::Io` wraps `std::io::Error` (not `String`) to preserve
180+
`ErrorKind`.
181+
- [ ] New public functions accept `impl AsRef<[u8]>` / `impl AsRef<str>`
182+
rather than concrete slice refs where appropriate.
183+
- [ ] No `unwrap()` / `expect()` / `panic!()` outside test code.
184+
- [ ] All arithmetic uses checked ops (`checked_add`, `checked_mul`, …).
185+
- [ ] Tests mirror the Go test names and shapes where applicable.
186+
- [ ] `use` declarations appear before all other items in each file.
187+
- [ ] No dead payload in error variants (every captured field appears in the
188+
`#[error("...")]` string).

.github/workflows/claude-code-review.yml

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,19 @@
11
name: Claude Code Review
22

33
on:
4-
pull_request:
5-
types: [review_requested]
6-
# Optional: Only run on specific file changes
7-
# paths:
8-
# - "src/**/*.ts"
9-
# - "src/**/*.tsx"
10-
# - "src/**/*.js"
11-
# - "src/**/*.jsx"
4+
issue_comment:
5+
types: [created]
126

137
jobs:
148
claude-review:
15-
# Only run when a specific reviewer is requested (e.g., "claude-code" or specific team)
169
if: |
17-
contains(github.event.pull_request.requested_reviewers.*.login, 'claude-code') ||
18-
contains(github.event.pull_request.requested_teams.*.slug, 'claude-code')
10+
github.event.issue.pull_request != null &&
11+
contains(github.event.comment.body, '/claude-review')
1912
2013
runs-on: ubuntu-latest
2114
permissions:
2215
contents: read
23-
pull-requests: read
16+
pull-requests: write
2417
issues: read
2518
id-token: write
2619

@@ -50,8 +43,4 @@ jobs:
5043
with:
5144
anthropic_api_key: ${{ secrets.CLAUDE_CODE_API_KEY }}
5245
track_progress: true
53-
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
54-
plugins: 'code-review@claude-code-plugins'
55-
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
56-
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
57-
# or https://code.claude.com/docs/en/cli-reference for available options
46+
prompt: '/review-pr ${{ github.event.pull_request.number || github.event.issue.number }}'

Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cli/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ humantime.workspace = true
1919
tokio.workspace = true
2020
pluto-app.workspace = true
2121
pluto-cluster.workspace = true
22+
pluto-crypto.workspace = true
2223
pluto-relay-server.workspace = true
2324
pluto-tracing.workspace = true
2425
pluto-core.workspace = true
2526
pluto-p2p.workspace = true
27+
pluto-eth1wrap.workspace = true
28+
pluto-eth2api.workspace = true
2629
pluto-eth2util.workspace = true
2730
pluto-k1util.workspace = true
2831
pluto-ssz.workspace = true
@@ -35,6 +38,8 @@ serde_with = { workspace = true, features = ["base64"] }
3538
rand.workspace = true
3639
tempfile.workspace = true
3740
reqwest.workspace = true
41+
url.workspace = true
42+
chrono.workspace = true
3843

3944
[dev-dependencies]
4045
tempfile.workspace = true

crates/cli/src/cli.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use clap::{Parser, Subcommand};
44

55
use crate::commands::{
6+
create_cluster::CreateClusterArgs,
67
create_enr::CreateEnrArgs,
78
enr::EnrArgs,
89
relay::RelayArgs,
@@ -40,7 +41,7 @@ pub enum Commands {
4041
about = "Create artifacts for a distributed validator cluster",
4142
long_about = "Create artifacts for a distributed validator cluster. These commands can be used to facilitate the creation of a distributed validator cluster between a group of operators by performing a distributed key generation ceremony, or they can be used to create a local cluster for single operator use cases."
4243
)]
43-
Create(CreateArgs),
44+
Create(Box<CreateArgs>),
4445

4546
#[command(about = "Print version and exit", long_about = "Output version info")]
4647
Version(VersionArgs),
@@ -135,4 +136,10 @@ pub enum CreateCommands {
135136
/// Create an Ethereum Node Record (ENR) private key to identify this charon
136137
/// client
137138
Enr(CreateEnrArgs),
139+
140+
#[command(
141+
about = "Create private keys and configuration files needed to run a distributed validator cluster locally",
142+
long_about = "Creates a local charon cluster configuration including validator keys, charon p2p keys, cluster-lock.json and deposit-data.json file(s). See flags for supported features."
143+
)]
144+
Cluster(Box<CreateClusterArgs>),
138145
}

0 commit comments

Comments
 (0)