Skip to main content
This guide covers practical tips for writing efficient, debuggable, and testable Arcis circuits.
Use this page when you are optimizing circuit performance, debugging an issue, or setting up tests.

Understanding execution flow

For conceptual background on why MPC circuits work differently (e.g., why both if/else branches execute), see Thinking in MPC.

Performance optimization

Operation costs

See Thinking in MPC - Cost Model for the full cost breakdown.

Optimization tips

Batch encrypted outputs when possible:
Reuse comparison results:
Prefer public constants over secret-dependent values:
In MPC, values known before the computation (public inputs and constants) can be handled more efficiently than values computed during secure execution.

Debugging

Arcis provides familiar debugging macros that work during circuit development.
Print macros do not change circuit behavior. They are for development only. Output appears during circuit execution on Arx nodes.

Debug assertions

Use assertions to verify invariants during development:
debug_assert macros are for development verification only. They do not enforce constraints in production: use explicit conditionals for actual validation logic.

Common debugging patterns

Trace loop iterations:
Check intermediate values:

Testing

What can be unit tested

You can test:
  • Helper functions (non-#[instruction] functions)
  • #[arcis_circuit] functions (builtin circuits)
  • Pure logic extracted into testable units
You cannot directly unit test:
  • #[instruction] functions (require MPC runtime)

Testing strategy

Extract testable logic into helper functions:

Integration testing

#[instruction] functions cannot be unit-tested in isolation: they require the full MPC runtime. For end-to-end testing, use the TypeScript SDK to invoke deployed circuits on a test cluster. See the JavaScript Client documentation and the Hello World tutorial for integration testing setup.

Common pitfalls

Conditionals don’t guard execution

When a condition is not a compile-time constant, both branches execute. The condition selects which result to keep, but Arx nodes perform work for both paths. See Thinking in MPC for the full explanation.

Reveal and encryption placement

.reveal() and .from_arcis() cannot appear inside conditional blocks. See Thinking in MPC for the correct pattern.

Error handling

Compile-time vs runtime

Division by secret values: If your divisor could be zero based on secret inputs, add explicit validation:
Best practices:
  1. Use constant array sizes where possible
  2. Validate divisors before division when they depend on secret inputs
  3. Keep floats within the supported range [-2^75, 2^75)

What’s next?

For the operation cost breakdown, see Thinking in MPC - Cost Model.

Quick reference

Keep this open while coding for fast syntax lookup.

Thinking in MPC

Understand MPC constraints and the cost model.