Skip to content

feat: Add multisig e2e benchmark test#348

Open
zeljkoX wants to merge 2 commits into
mainfrom
multisig-e2e-benchmark
Open

feat: Add multisig e2e benchmark test#348
zeljkoX wants to merge 2 commits into
mainfrom
multisig-e2e-benchmark

Conversation

@zeljkoX

@zeljkoX zeljkoX commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Add multisig e2e benchmark test.

It uses real accounts and sends p2id notes between them.

Summary by CodeRabbit

  • New Features
    • Added an end-to-end multisig benchmarking tool with commands to prepare fixtures, run preflight checks, bootstrap accounts, execute benchmarks, and summarize reports.
    • Added configurable transfer and consume operations with retry handling, timing measurements, canonicalization tracking, and JSON/JSONL artifacts.
    • Added local testnet configuration and documentation covering setup, execution, outputs, and troubleshooting.
  • Documentation
    • Documented account funding, balance requirements, generated reports, and failure artifacts.

@zeljkoX
zeljkoX requested a review from haseebrabbani as a code owner July 23, 2026 08:25
@zeljkoX
zeljkoX requested a review from Copilot July 23, 2026 08:25
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0e889fc9-069d-4163-b3d3-5d56afcc504d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

Changes

Adds a new workspace-integrated Rust benchmark for Guardian multisig workflows. It supports fixture preparation, validated configuration, preflight and bootstrap operations, retries, canonicalization tracking, JSONL measurements, summaries, and documented local testnet execution.

Multisig E2E Benchmark

Layer / File(s) Summary
Configuration and fixture preparation
Cargo.toml, benchmarks/multisig-e2e/Cargo.toml, benchmarks/multisig-e2e/src/config.rs, benchmarks/multisig-e2e/src/fixture.rs, benchmarks/multisig-e2e/testnet.local.toml
Adds the benchmark crate, validated TOML settings, endpoint parsing, and persistent two-account fixture preparation with atomic writes and permissions handling.
Client runtime and canonicalization tracking
benchmarks/multisig-e2e/src/runtime.rs, benchmarks/multisig-e2e/src/canonicalization.rs
Loads multisig clients and Guardian observers, retries synchronization, computes balances, and records proposal canonicalization or discard outcomes.
CLI and benchmark execution
benchmarks/multisig-e2e/src/main.rs, benchmarks/multisig-e2e/src/runner.rs
Adds CLI commands for preparation, preflight, bootstrap, execution, and summarization, plus proposal retries, note polling, operation timing, and failure artifacts.
Reports and benchmark documentation
benchmarks/multisig-e2e/src/runner.rs, benchmarks/multisig-e2e/.gitignore, benchmarks/multisig-e2e/README.md
Adds JSONL report records, percentile summaries, generated-artifact ignores, and instructions for running and interpreting the benchmark.

Estimated code review effort: 5 (Critical) | ~90 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant BenchmarkRunner
  participant MultisigClient
  participant GuardianClient
  CLI->>BenchmarkRunner: run configured benchmark
  BenchmarkRunner->>MultisigClient: create and execute proposal
  BenchmarkRunner->>GuardianClient: poll proposal delta
  GuardianClient-->>BenchmarkRunner: canonicalization status
  BenchmarkRunner-->>CLI: write JSONL report and summary
Loading

Suggested labels: enhancement

Suggested reviewers: haseebrabbani

Poem

A rabbit hops through multisig gates,
Timing proposals, noting fates.
JSON carrots neatly line the trail,
Retries help each small hop prevail.
Guardian stars mark canonical light—
A benchmark bounds into the night!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.28% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a multisig end-to-end benchmark test.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch multisig-e2e-benchmark

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Rust workspace benchmark harness that runs an end-to-end multisig workflow against real Guardian + Miden endpoints, using two persistent 1-of-1 accounts and recording per-operation latency artifacts.

Changes:

  • Adds a new workspace member crate guardian-multisig-e2e-benchmark with CLI subcommands to prepare fixtures, preflight, bootstrap, run, and summarize.
  • Introduces a TOML-runner configuration and local README workflow, producing JSONL reports plus manifest/summary/canonicalization artifacts.
  • Implements retry handling for known transient Guardian/Miden sync races and collects deferred canonicalization observations.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated no comments.

Show a summary per file
File Description
Cargo.toml Registers benchmarks/multisig-e2e as a workspace member.
Cargo.lock Adds lock entries for the new benchmark crate and its dependencies.
benchmarks/multisig-e2e/Cargo.toml Defines the new benchmark crate, dependencies, and Tokio runtime setup.
benchmarks/multisig-e2e/README.md Documents the intended real-account workflow, artifacts, and interpretation.
benchmarks/multisig-e2e/testnet.local.toml Provides a sample local profile for testnet runs (ops/amount/intervals/timeouts/artifacts dir).
benchmarks/multisig-e2e/.gitignore Ignores generated benchmark report artifacts under reports/.
benchmarks/multisig-e2e/src/main.rs Implements the CLI entrypoint and subcommands wiring.
benchmarks/multisig-e2e/src/config.rs Adds TOML config loading/validation and Miden endpoint parsing.
benchmarks/multisig-e2e/src/fixture.rs Adds fixture generation/persistence for two persistent accounts (Alice/Bob).
benchmarks/multisig-e2e/src/runtime.rs Builds benchmark clients, pulls/syncs accounts, and connects an authenticated Guardian observer.
benchmarks/multisig-e2e/src/runner.rs Core benchmark runner: operation loop, retries, note waiting, report writing, and summary generation (with unit tests).
benchmarks/multisig-e2e/src/canonicalization.rs Deferred canonicalization tracking and post-run observation drain (with unit tests).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread benchmarks/multisig-e2e/src/main.rs Dismissed
Comment thread benchmarks/multisig-e2e/src/runner.rs Dismissed
Comment thread benchmarks/multisig-e2e/src/runner.rs Dismissed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (3)
benchmarks/multisig-e2e/src/runtime.rs (1)

43-74: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate MultisigClient builder chain across fixture.rs and runtime.rs. Both files build a MultisigClient via the identical miden_endpoint/guardian_endpoint/account_dir/with_secret_key/build sequence before diverging into create-vs-load logic; the shared root cause is no common construction helper.

  • benchmarks/multisig-e2e/src/runtime.rs#L43-L74: extract the builder chain (lines 52-59) into a shared helper (e.g. build_client(fixture, account, config) -> Result<(MultisigClient, TempDir)>) that both load_client and fixture::prepare can call, keeping each caller's post-build steps (pull_account/sync_with_retry here) separate.
  • benchmarks/multisig-e2e/src/fixture.rs#L69-L98: replace the builder chain (lines 74-81) with the same shared helper, keeping create_account/push_account as this call site's own follow-up steps.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/multisig-e2e/src/runtime.rs` around lines 43 - 74, Extract the
duplicated MultisigClient construction into a shared helper, such as
build_client(fixture, account, config), returning the client and TempDir while
preserving the existing endpoint, account directory, secret-key, and build
configuration. In benchmarks/multisig-e2e/src/runtime.rs lines 43-74, call the
helper from load_client and retain pull_account and sync_with_retry there; in
benchmarks/multisig-e2e/src/fixture.rs lines 69-98, call the same helper and
retain create_account and push_account there.
benchmarks/multisig-e2e/src/runner.rs (2)

504-514: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Retry classification depends on brittle substring matching of Guardian error text.

is_retryable_proposal_error classifies transient failures by checking for exact substrings like "conflict_pending_delta" and "There's already a pending change for this account" inside MultisigError::GuardianServer. If the Guardian server's wording changes, this silently stops retrying and previously-transient errors become hard failures.

Please confirm whether miden_multisig_client::MultisigError/the Guardian server response exposes a structured error code/kind for "pending delta conflict" that could replace this string match.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/multisig-e2e/src/runner.rs` around lines 504 - 514, Inspect
miden_multisig_client::MultisigError and the Guardian server response types for
a structured error code or kind representing a pending-delta conflict. Update
is_retryable_proposal_error to classify GuardianServer errors using that
structured value instead of matching message text, while preserving retry
behavior for GuardianConnection and MidenClient errors.

646-664: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate "required balance" formula (also in preflight, Line 135).

config.amount.saturating_mul(config.operations.div_ceil(2)) is computed identically here and in preflight (Line 135). Extract a shared helper to avoid the two copies drifting apart if the funding formula ever changes.

♻️ Proposed refactor
+fn required_balance(config: &RunConfig) -> u64 {
+    config.amount.saturating_mul(config.operations.div_ceil(2))
+}
+
 fn ensure_starting_balances(
     clients: &[BenchClient],
     faucet_id: AccountId,
     config: &RunConfig,
 ) -> Result<()> {
-    let required = config.amount.saturating_mul(config.operations.div_ceil(2));
+    let required = required_balance(config);

And in preflight (Line 135):

-    let required = config.amount.saturating_mul(config.operations.div_ceil(2));
+    let required = required_balance(config);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/multisig-e2e/src/runner.rs` around lines 646 - 664, Extract the
shared required-balance calculation from ensure_starting_balances and preflight
into a helper, using the existing config.amount and config.operations inputs.
Replace both inline config.amount.saturating_mul(config.operations.div_ceil(2))
expressions with that helper while preserving the current funding formula and
validation behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@benchmarks/multisig-e2e/src/canonicalization.rs`:
- Around line 118-152: Update finish so each queued observation gets its own
deadline anchored to queued.started plus self.timeout, instead of reusing one
Instant computed at finish entry. Remove the shared deadline and pass the
per-observation deadline to observe_delta, preserving the existing sequential
processing and elapsed-time reporting.

In `@benchmarks/multisig-e2e/src/fixture.rs`:
- Around line 125-136: Update the non-Unix `restrict_permissions` implementation
to return an explicit error instead of silently succeeding, so callers cannot
persist secret keys while assuming permissions were restricted. Keep the Unix
implementation unchanged and preserve the existing `Result<()>` contract.

In `@benchmarks/multisig-e2e/src/main.rs`:
- Around line 62-66: Update the network_id derivation in the fixture setup to
use an explicit network configuration value rather than inspecting
fixture.miden_endpoint. Map each supported network setting to its corresponding
NetworkId, including Mainnet, Testnet, and Devnet, and avoid defaulting unknown
endpoints to Devnet.

In `@benchmarks/multisig-e2e/src/runtime.rs`:
- Around line 95-102: Update is_miden_sync_tip_ahead to classify the retryable
sync-tip failure using the structured MultisigError variant or error code,
rather than matching text within MidenClient messages. Preserve the existing
behavior for the specific block-to versus chain-tip condition and return false
for unrelated errors.

---

Nitpick comments:
In `@benchmarks/multisig-e2e/src/runner.rs`:
- Around line 504-514: Inspect miden_multisig_client::MultisigError and the
Guardian server response types for a structured error code or kind representing
a pending-delta conflict. Update is_retryable_proposal_error to classify
GuardianServer errors using that structured value instead of matching message
text, while preserving retry behavior for GuardianConnection and MidenClient
errors.
- Around line 646-664: Extract the shared required-balance calculation from
ensure_starting_balances and preflight into a helper, using the existing
config.amount and config.operations inputs. Replace both inline
config.amount.saturating_mul(config.operations.div_ceil(2)) expressions with
that helper while preserving the current funding formula and validation
behavior.

In `@benchmarks/multisig-e2e/src/runtime.rs`:
- Around line 43-74: Extract the duplicated MultisigClient construction into a
shared helper, such as build_client(fixture, account, config), returning the
client and TempDir while preserving the existing endpoint, account directory,
secret-key, and build configuration. In benchmarks/multisig-e2e/src/runtime.rs
lines 43-74, call the helper from load_client and retain pull_account and
sync_with_retry there; in benchmarks/multisig-e2e/src/fixture.rs lines 69-98,
call the same helper and retain create_account and push_account there.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a612c448-a198-468e-af1d-d887e0cd8962

📥 Commits

Reviewing files that changed from the base of the PR and between 1636c9f and 7e07e7a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • Cargo.toml
  • benchmarks/multisig-e2e/.gitignore
  • benchmarks/multisig-e2e/Cargo.toml
  • benchmarks/multisig-e2e/README.md
  • benchmarks/multisig-e2e/src/canonicalization.rs
  • benchmarks/multisig-e2e/src/config.rs
  • benchmarks/multisig-e2e/src/fixture.rs
  • benchmarks/multisig-e2e/src/main.rs
  • benchmarks/multisig-e2e/src/runner.rs
  • benchmarks/multisig-e2e/src/runtime.rs
  • benchmarks/multisig-e2e/testnet.local.toml

Comment thread benchmarks/multisig-e2e/src/canonicalization.rs
Comment thread benchmarks/multisig-e2e/src/fixture.rs
Comment thread benchmarks/multisig-e2e/src/main.rs
Comment thread benchmarks/multisig-e2e/src/runtime.rs
@codecov-commenter

codecov-commenter commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@a30ffa4). Learn more about missing BASE report.
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #348   +/-   ##
=======================================
  Coverage        ?   78.04%           
=======================================
  Files           ?      167           
  Lines           ?    31904           
  Branches        ?        0           
=======================================
  Hits            ?    24900           
  Misses          ?     7004           
  Partials        ?        0           

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a30ffa4...f957fba. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

4 participants