Skip to main content

Verification (--verify)

Prove that your contracts hold using formal verification with an SMT solver.

The --verify flag runs the complete verification pipeline: source checking, Viper translation, and SMT solving via Silicon/Z3. Unlike --check, which stops before Viper generation and SMT solving, --verify attempts to prove that your requires, ensures, and invariant contracts hold for all inputs under Sector9's verifier model.

Basic Usage​

sector9 --verify file.sr9

On success, the command exits with code 0 after Silicon proves the obligations. On failure, it prints diagnostics describing source or proof failures and exits with a non-zero code.

What --verify Does​

The verification pipeline performs these steps:

  1. Source checking - All validations from --check
  2. MVIR lowering - Translates Sector9 source to the MVIR intermediate representation
  3. MVIR passes - Runs lowering and analysis passes including effect inference, permission scheduling, and async handling
  4. Viper generation - Converts MVIR to Viper verification language
  5. Silicon verification - Invokes the Viper/Silicon verifier
  6. SMT solving - Z3 solver proves or disproves proof obligations
  7. Diagnostics - Maps verification failures back to source locations

Verification Output​

Successful verification:

✓ verification succeeded

Failed verification with diagnostics:

✗ verification failed (1 issue)

[1] Postcondition might not hold
Assertion result == x + 1 might not hold.
at: counter.sr9:8:4
hint:
- Check that the function body establishes the postcondition.

Exit Codes​

CodeMeaning
0Verification succeeded - checked contracts proven
1Verification failed - one or more proof obligations not satisfied
2Invalid arguments - missing files or conflicting flags
124Timeout - verification exceeded time limit

Common Flags​

Timeout Control​

Set a wall-clock timeout for verification (in milliseconds):

# 30 second timeout
sector9 --verify --verify-timeout-ms 30000 file.sr9

# 2 minute timeout
sector9 --verify --verify-timeout-ms 120000 file.sr9

# No timeout; `0` disables the timeout
sector9 --verify --verify-timeout-ms 0 file.sr9

When verification times out, the process exits with code 124.

Parallelization​

Run verification with multiple worker threads:

# Use 4 cores
sector9 --verify --cores 4 file.sr9

# Use 8 cores
sector9 --verify --cores 8 file.sr9

The --cores N flag maps to Silicon's parallel verifier setting as --numberOfParallelVerifiers=N-1, while keeping one coordinating thread. More cores can speed up verification of programs with multiple independent methods.

Counterexamples​

Include counterexample values when verification fails:

sector9 --verify --counterexample file.sr9

When a proof fails, the counterexample shows concrete values that violate the contract:

✗ verification failed (1 issue)

[1] Postcondition might not hold
Assertion result > 0 might not hold.
at: example.sr9:5:4
counterexample:
x = 0

JSON Output​

Emit structured JSON diagnostics:

sector9 --verify --json file.sr9

This outputs machine-readable JSON with schema version 2, useful for IDE integration and CI pipelines. The JSON includes source locations, snippets, hints, and optional counterexamples. See JSON Output.

Intermediate Viper Output​

Save the generated Viper program for debugging:

sector9 --verify --verify-vpr-out output.vpr file.sr9

The .vpr file shows how Sector9 encodes your Sector9 program for verification. This is useful for understanding verification failures at the Viper level, especially alongside --viper.

Debugging Flags​

# Log Viper/Silicon invocation details
sector9 --verify --viper-verbose file.sr9

# Echo Silicon stdout/stderr even on success
sector9 --verify --viper-trace file.sr9

# Keep generated Viper files on success
sector9 --verify --viper-keep-vpr file.sr9

Integer Mode​

Verified code requires checked fixed-width integer semantics:

# Checked mode (default) - prove no overflow/underflow
sector9 --verify --int-mode checked file.sr9

--verify --int-mode unchecked and --verify --int-mode bitvec are rejected. See Integer Mode.

Deterministic Artifacts​

Enable deterministic Viper output for reproducible builds:

sector9 --verify --deterministic file.sr9

--verify vs --check​

Aspect--check--verify
Source/type checkingYesYes
Contract parsingYesYes
Viper generationNoYes
SMT solvingNoYes
Proof verificationNoYes
SpeedFast (seconds)Slower (depends on complexity)
Use caseDevelopment iterationPre-deployment validation

Use --check for rapid iteration during development. Use --verify when you need mathematical proof that contracts hold.

Environment Variables​

VariableEffect
XDG_CACHE_HOMEOverride cache directory for Viper files
VIPER_SERVERPath to custom viperserver.jar
SILICON_FLAGSAdditional flags passed to Silicon
SECTOR9C_VERIFY_KEEP_VPRKeep Viper files on success (non-empty = true)

Verification Outcomes​

Tests and source files use naming conventions to indicate expected outcomes:

SuffixMeaning
_satVerification should succeed
_unsatVerification should fail (expected counterexample)
_rejectType checking should fail before verification

For example:

  • counter_sat.sr9 - contracts should be proven
  • counter_unsat.sr9 - contains a deliberate bug, verification should fail
  • counter_reject.sr9 - has a type error, rejected before verification

Typical Workflow​

# 1. Fast iteration with type checking
sector9 --package core ./core/src --check my_actor.sr9

# 2. Fix any type or contract syntax errors

# 3. Run verification when --check passes
sector9 --package core ./core/src --verify my_actor.sr9

# 4. If verification fails, analyze the failure
sector9 --package core ./core/src --verify --counterexample my_actor.sr9

# 5. Debug complex failures with Viper output
sector9 --package core ./core/src --verify --verify-vpr-out debug.vpr my_actor.sr9

# 6. On verification success, proceed to deployment

CI/CD Integration​

For continuous integration, combine timeout and JSON output:

# CI-friendly verification with timeout and machine-readable output
sector9 --verify --json --verify-timeout-ms 300000 my_actor.sr9

Parse the JSON output to integrate with test reporters. The exit code indicates overall success or failure.

Performance Tips​

  1. Start with --check - Catch type errors before expensive verification
  2. Use --cores - Parallelize verification for programs with multiple methods
  3. Set timeouts - Prevent runaway verification in CI
  4. Minimize quantifiers - Complex forall/exists can slow verification
  5. Use triggers - Guide the SMT solver with forallWith triggers
  6. Modularize - Verify smaller modules independently
  7. Run --check first - It catches frontend and shared-boundary errors before Silicon starts

Troubleshooting​

Verification times out​

  • Increase --verify-timeout-ms for legitimate long proofs, or reduce it in CI to fail fast on regressions
  • Use --counterexample on failures where Silicon returns a model
  • Simplify quantifiers or add explicit triggers
  • Break large methods into smaller helpers

"Insufficient permission" errors​

  • Add missing reads or modifies clauses
  • Check that all accessed fields are declared in footprints

Postcondition might not hold​

  • Use --counterexample to see failing values
  • Add intermediate assert statements to isolate the issue
  • Strengthen preconditions to rule out impossible inputs

Verification succeeds but takes too long​

  • Use --cores for parallelization
  • Profile with --viper-trace to identify slow methods
  • Consider using trusted for expensive methods during development

Summary​

  • --verify proves contracts hold using SMT solving
  • Use --counterexample to debug failing verifications
  • Use --verify-timeout-ms and --cores for performance control
  • Use --json for CI/CD integration
  • Combine with --check for efficient development workflow