emp-tool's circuits are evaluated by a BooleanContext — a type with a cheap,
copyable Wire and value-return public_bit / and_gate / xor_gate /
not_gate. There is no global backend and no void* virtual dispatch: a context
is passed explicitly and the gate ops are statically dispatched and inlineable. See
circuits.md for the value layer, and the concept
(ir/context/concept.h) and the built-in analysis contexts (ClearCtx / CountCtx
/ DigestCtx / RecordCtx), all re-exported by ir/context/context.h.
A protocol provides two pieces. The context is pure circuit execution — only
the four gate ops, no I/O — like emp-sh2pc's SH2PCCtx, or the shared
ChunkRecorderCtx that emp-ag2pc / emp-agmpc expose as ctx_t:
- pick a
Wire(a garbled label, a wire id, …) that isstd::semiregular; - implement the four gate ops (eager crypto, or recording into an IR — whatever the
protocol does per gate); optionally
and_manyfor batched AND layers.
The session owns the clear↔circuit I/O boundary and the protocol state (IO,
party, OT/preprocessing, batching), wrapping a context — like emp-tool's
ClearSession (ir/session/clear_session.h):
- hold the context and expose
ctx()for value/context-level work (theDirectSessionconcept,ir/session/session.h); - expose
input<T>(owner, clear)(andinput_batchwhere applicable) /reveal(value, recipient), implemented over the value'sWireValuecodec (T::width()/T::encode/T::decode,ir/wire_value.h).revealreturnsstd::optional<clear_t>: the value on a party that learns it (every party forPUBLIC, the named recipient otherwise) andstd::nullopton a party that does not. A plaintextClearSessionalways populates it.
The context automatically works with the frontend — live run,
compile, and replay over any circuit value — and with the analysis contexts, with
no frontend changes. Pure circuit bodies take and return values and never touch
I/O; only the session does. That uniformity is the payoff of the seam.
The execution layer ships the per-gate garble/evaluate primitives a garbled context
builds on, as free functions over block labels (XOR/NOT are free; only AND needs
ciphertext):
- half_gate.h —
halfgates_garble/halfgates_eval(Zahur–Rosulek–Evans half-gates). - privacy_free.h —
privacy_free_garble/privacy_free_eval.
SH2PCCtx calls halfgates_garble/halfgates_eval directly inside its and_gate;
a new garbled context does the same. The OT that feeds private inputs lives in the
protocol libraries (emp-sh2pc / emp-ag2pc / emp-agmpc) over emp-ot.