bitwright
Hash-consed fixed-width bit-vector expressions for Rust: exact evaluation, bit-level facts, and verified simplification.
bitwright is for tools that reason about machine integers: binary analyzers, deobfuscators, decompilers and lifters. It simplifies their expressions with predictable cost and without guessing: a rewrite preserves the value of the expression at every input, or it does not happen.
use Engine;
use ;
What it gives you
- Exact values of 1 to 512 bits. Every operator has total SMT-LIB QF_BV semantics, division by zero included, checked against an independent bit-serial reference evaluator.
- A hash-consed expression arena with canonicalization at construction, owned by a context. There is no global state, and the same input gives the same output on every run.
- Bit-level facts: known bits, unsigned and signed ranges, tri-state proofs, and constraints you assume (a path condition, an invariant), with the ones each result relies on reported back.
- A directed simplifier built from normal-form passes (linear arithmetic, xor forms, truth tables, comparison lattices, casts, demanded bits, linear MBA, bit shuffles) and a small rule corpus. Termination is guaranteed by construction, and every run is bounded by budgets you choose.
- Invertibility: proofs that an expression is an injective or bijective function of a subexpression (keyed mixers, xorshifts, T-functions), used to cancel and solve equalities, so a hash comparison becomes a plain one.
- A rule language (
.bwr) for your own rewrites, with a mandatory soundness check (exhaustive at small widths, sampled up to 512 bits) and proof ledgers. - Optional services: MBA simplification (a native solver for linear, semi-linear and polynomial MBA, pluggable backends, and answers bitwright proves itself), a bounded equality-saturation search, and SMT-LIB export and import, so any SMT solver can prove a rule at any width.
Installation
bitwright needs Rust 1.88 or later. Its only required dependency is hashbrown. Optional
features:
| Feature | Default | Adds |
|---|---|---|
check |
yes | the rule soundness checker, evidence and proof ledgers |
smtlib |
no | SMT-LIB export and import, rule obligations for any SMT solver |
mba |
no | the MBA service: lowering, the native normal-form solver, solver and prover traits, the evidence gate and its certificates |
cobra |
no | mba plus a backend over the cobra-mba crate |
eqsat |
no | a bounded equality-saturation search for alternative expressions |
Documentation
The bitwright book is the guide. Every example in it is compiled and run as a test. It reads fine on GitHub too:
| Part | Chapters |
|---|---|
| Basics | Introduction · Getting started · Semantics |
| Reasoning | Facts and proofs · Constraints · Extension operations |
| Simplifying | Simplifying · Deobfuscation and MBA · Invertibility |
| Rules | Writing rules · Checking rules · Rule catalog |
| Services | Equality saturation · SMT-LIB · The command line |
| Contracts | Stability |
- API reference on docs.rs, for the latest release.
- Design reference: the principles, semantics and contracts, and how each part is validated.
- Changelog.
Command line
The bitwright binary checks, lints and proves rule files, and simplifies expressions:
bitwright check rules.bwr --ledger rules.bwr.proof # soundness verdicts and the proof ledger
bitwright lint rules.bwr # every diagnostic, rendered
bitwright smt rules.bwr | z3 -in # prove every rule at 8, 32 and 64 bits (or `| bitwuzla`)
bitwright catalog > RULES.md # the built-in rules as Markdown
bitwright explain BW0302 # what a diagnostic means
bitwright simplify '(x | y) - (x & y)' --deobfuscate # x ^ y
bitwright simplify 'x * k == y * k' --assume '(k & 1) == 1' # x == y, relying on the assumption
Stability
bitwright is 0.x. A minor release may change the API and simplification results, and lists every change of results under Behavior changes in the changelog; a patch release changes results only to fix unsoundness. The minimum supported Rust version is 1.88. See the stability chapter for the full contract.
Development
Fuzz targets are in fuzz/ (cargo +nightly fuzz run simplify_dag),
docs/benchmarking.md explains how to compare a change against its
baseline, and compare/ compares bitwright with other symbolic engines (egg, CoBRA,
Triton, SMT solvers) on public MBA datasets.
License
PolyForm Noncommercial 1.0.0: free for any noncommercial purpose, including personal use, research, education, and use by charitable and public organizations. Commercial use needs a separate license from Emergentesombra Lda. (https://emergentelabs.com/).
Required Notice: Copyright 2026 Emergentesombra Lda., Porto, Portugal, PT 517806843 (https://emergentelabs.com/)