pub trait ChipGadget: Hint {
// Required method
fn build(
&self,
builder: &CircuitBuilder,
dimensions: &[usize],
inputs: &[Wire],
) -> Vec<Wire>;
}Expand description
A gadget the builder emits either as inline gates or as a call to a chip.
The gadget is written once, in build, and where it lands is the building
circuit’s to decide: CircuitBuilder::build_gadget
emits the gates unless
CircuitBuilder::register_chip has made the gadget a
chip, in which case it emits a hint and a call constraining it.
The Hint half is what the chip path needs of a gadget beyond its gates. Its NAME and
dimensions name which gadget a registered chip serves; shape gives the arity
of the gates and of the chip’s interface alike; and execute computes the
outputs a call passes alongside its inputs.
So a Hint::execute and a build of the same gadget must agree on every input the circuit can
reach them with. Where they disagree, the chip instance recomputes a word the call did not name,
and only WitnessM4::verify reports it.
use binius_core::word::Word;
use binius_frontend::{ChipGadget, CircuitBuilder, Hint, Wire};
/// The bitwise conjunction of two words.
struct And;
impl Hint for And {
const NAME: &'static str = "doc.and";
fn shape(&self, _dimensions: &[usize]) -> (usize, usize) {
(2, 1)
}
fn execute(&self, _dimensions: &[usize], inputs: &[Word], outputs: &mut [Word]) {
outputs[0] = Word(inputs[0].as_u64() & inputs[1].as_u64());
}
}
impl ChipGadget for And {
fn build(&self, builder: &CircuitBuilder, _dims: &[usize], inputs: &[Wire]) -> Vec<Wire> {
vec![builder.band(inputs[0], inputs[1])]
}
}
// Without a chip the gadget is its gates, and the circuit builds as any other.
let builder = CircuitBuilder::new();
let (a, b) = (builder.add_inout(), builder.add_inout());
builder.build_gadget(And, &[], &[a, b]);
builder.build();
// Registering the gadget is the whole of the opt-in: the same call is now a chip call.
let builder = CircuitBuilder::new();
builder.register_chip(And, &[]);
let (a, b) = (builder.add_inout(), builder.add_inout());
builder.build_gadget(And, &[], &[a, b]);
builder.build_m4().validate().unwrap();Required Methods§
Sourcefn build(
&self,
builder: &CircuitBuilder,
dimensions: &[usize],
inputs: &[Wire],
) -> Vec<Wire>
fn build( &self, builder: &CircuitBuilder, dimensions: &[usize], inputs: &[Wire], ) -> Vec<Wire>
Emits the gadget’s gates, returning the outputs its
shape declares.
Each returned wire must be gate-created: a chip promotes them with
CircuitBuilder::mark_inout, which takes no other
kind. Returning an input or a constant unchanged is what that rules out.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".