Skip to content

Commit f2981fe

Browse files
authored
Use Hint Bridge for Constraining HintLoad (#39)
* hint bridge * progress * optional writeback * hint bridge * hint bridge * fix stale data * hint provider gpu * resolve native sumcheck gpu trace fill problem * cuda adjust * fix compilation * fix compilation * account for empty gpu trace * constraints * column structure * adjust degree * remove debug flag * Adjust hint constraints
1 parent 373367e commit f2981fe

26 files changed

Lines changed: 806 additions & 190 deletions

File tree

crates/vm/src/arch/testing/cpu.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,17 @@ use crate::{
3737
testing::{
3838
execution::air::ExecutionDummyAir,
3939
program::{air::ProgramDummyAir, ProgramTester},
40-
ExecutionTester, MemoryTester, TestBuilder, TestChipHarness, EXECUTION_BUS, MEMORY_BUS,
41-
MEMORY_MERKLE_BUS, POSEIDON2_DIRECT_BUS, RANGE_CHECKER_BUS, READ_INSTRUCTION_BUS,
40+
ExecutionTester, MemoryTester, TestBuilder, TestChipHarness, EXECUTION_BUS, HINT_BUS,
41+
MEMORY_BUS, MEMORY_MERKLE_BUS, POSEIDON2_DIRECT_BUS, RANGE_CHECKER_BUS,
42+
READ_INSTRUCTION_BUS,
4243
},
4344
vm_poseidon2_config, Arena, ExecutionBridge, ExecutionBus, ExecutionState,
4445
MatrixRecordArena, MemoryConfig, PreflightExecutor, Streams, VmStateMut,
4546
},
4647
system::{
4748
memory::{
4849
adapter::records::arena_size_bound,
49-
offline_checker::{MemoryBridge, MemoryBus},
50+
offline_checker::{HintBridge, HintBus, MemoryBridge, MemoryBus},
5051
online::TracingMemory,
5152
MemoryAirInventory, MemoryController, SharedMemoryHelper, CHUNK,
5253
},
@@ -258,10 +259,13 @@ impl<F: PrimeField32> VmChipTestBuilder<F> {
258259
}
259260

260261
pub fn system_port(&self) -> SystemPort {
262+
let hint_bus = HintBus::new(HINT_BUS);
263+
let hint_bridge = HintBridge::new(hint_bus);
261264
SystemPort {
262265
execution_bus: self.execution.bus,
263266
program_bus: self.program.bus,
264267
memory_bridge: self.memory_bridge(),
268+
hint_bridge,
265269
}
266270
}
267271

crates/vm/src/arch/testing/cuda.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::{
5050
execution::{air::ExecutionDummyAir, DeviceExecutionTester},
5151
memory::DeviceMemoryTester,
5252
program::{air::ProgramDummyAir, DeviceProgramTester},
53-
TestBuilder, TestChipHarness, EXECUTION_BUS, MEMORY_BUS, MEMORY_MERKLE_BUS,
53+
TestBuilder, TestChipHarness, EXECUTION_BUS, HINT_BUS, MEMORY_BUS, MEMORY_MERKLE_BUS,
5454
POSEIDON2_DIRECT_BUS, READ_INSTRUCTION_BUS,
5555
},
5656
Arena, DenseRecordArena, ExecutionBridge, ExecutionBus, ExecutionState, MatrixRecordArena,
@@ -59,7 +59,7 @@ use crate::{
5959
system::{
6060
cuda::{poseidon2::Poseidon2PeripheryChipGPU, DIGEST_WIDTH},
6161
memory::{
62-
offline_checker::{MemoryBridge, MemoryBus},
62+
offline_checker::{HintBridge, HintBus, MemoryBridge, MemoryBus},
6363
MemoryAirInventory, SharedMemoryHelper,
6464
},
6565
poseidon2::air::Poseidon2PeripheryAir,
@@ -393,8 +393,14 @@ impl GpuChipTestBuilder {
393393
execution_bus: self.execution_bus(),
394394
program_bus: self.program_bus(),
395395
memory_bridge: self.memory_bridge(),
396+
hint_bridge: self.hint_bridge(),
396397
}
397398
}
399+
400+
pub fn hint_bridge(&self) -> HintBridge {
401+
let hint_bus = HintBus::new(HINT_BUS);
402+
HintBridge::new(hint_bus)
403+
}
398404
pub fn execution_bridge(&self) -> ExecutionBridge {
399405
ExecutionBridge::new(self.execution.bus(), self.program.bus())
400406
}

crates/vm/src/arch/testing/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub const BITWISE_OP_LOOKUP_BUS: BusIndex = 9;
2929
pub const BYTE_XOR_BUS: BusIndex = 10;
3030
pub const RANGE_TUPLE_CHECKER_BUS: BusIndex = 11;
3131
pub const MEMORY_MERKLE_BUS: BusIndex = 12;
32+
pub const HINT_BUS: BusIndex = 13;
3233

3334
pub const RANGE_CHECKER_BUS: BusIndex = 4;
3435

crates/vm/src/system/memory/offline_checker/bridge.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use openvm_stark_backend::{
1010
interaction::InteractionBuilder, p3_air::AirBuilder, p3_field::FieldAlgebra,
1111
};
1212

13-
use super::bus::MemoryBus;
13+
use super::bus::{HintBus, MemoryBus};
1414
use crate::system::memory::{
1515
offline_checker::columns::{
1616
MemoryBaseAuxCols, MemoryReadAuxCols, MemoryReadOrImmediateAuxCols, MemoryWriteAuxCols,
@@ -326,3 +326,52 @@ impl MemoryOfflineChecker {
326326
.eval(builder, enabled);
327327
}
328328
}
329+
330+
/// The [HintBridge] is used to constrain hint space lookups.
331+
/// Consumer chips call `lookup` to verify that values they read from hint_space
332+
/// match what was originally loaded via the hint bus lookup table.
333+
#[derive(Clone, Copy, Debug)]
334+
pub struct HintBridge {
335+
hint_bus: HintBus,
336+
}
337+
338+
impl HintBridge {
339+
/// Create a new [HintBridge] with the provided hint bus.
340+
pub fn new(hint_bus: HintBus) -> Self {
341+
Self { hint_bus }
342+
}
343+
344+
pub fn hint_bus(&self) -> HintBus {
345+
self.hint_bus
346+
}
347+
348+
/// Perform a lookup on the hint bus for a single element.
349+
///
350+
/// Constrains that `(hint_id, offset, value)` exists in the hint lookup table.
351+
/// Caller must constrain that `enabled` is boolean.
352+
pub fn lookup<AB: InteractionBuilder>(
353+
&self,
354+
builder: &mut AB,
355+
hint_id: impl Into<AB::Expr>,
356+
offset: impl Into<AB::Expr>,
357+
value: impl Into<AB::Expr>,
358+
enabled: impl Into<AB::Expr>,
359+
) {
360+
self.hint_bus.lookup(builder, hint_id, offset, value, enabled);
361+
}
362+
363+
/// Add a key to the hint lookup table.
364+
///
365+
/// Provider chips call this to register that `(hint_id, offset, value)` is available.
366+
pub fn provide<AB: InteractionBuilder>(
367+
&self,
368+
builder: &mut AB,
369+
hint_id: impl Into<AB::Expr>,
370+
offset: impl Into<AB::Expr>,
371+
value: impl Into<AB::Expr>,
372+
num_lookups: impl Into<AB::Expr>,
373+
) {
374+
self.hint_bus
375+
.provide(builder, hint_id, offset, value, num_lookups);
376+
}
377+
}

crates/vm/src/system/memory/offline_checker/bus.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::iter;
22

33
use openvm_stark_backend::{
4-
interaction::{BusIndex, InteractionBuilder, PermutationCheckBus},
4+
interaction::{BusIndex, InteractionBuilder, LookupBus, PermutationCheckBus},
55
p3_field::FieldAlgebra,
66
};
77

@@ -101,3 +101,65 @@ impl<T: FieldAlgebra> MemoryBusInteraction<T> {
101101
}
102102
}
103103
}
104+
105+
/// Represents a hint bus identified by a unique bus index.
106+
/// Used as a lookup table to constrain values read from hint space.
107+
///
108+
/// Consumer chips (e.g. NativeSumcheck) perform lookups to verify that
109+
/// hint_space values match what was originally loaded.
110+
/// Provider chips (e.g. a hint loader) add keys to the lookup table.
111+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
112+
pub struct HintBus {
113+
pub inner: LookupBus,
114+
}
115+
116+
impl HintBus {
117+
pub const fn new(index: BusIndex) -> Self {
118+
Self {
119+
inner: LookupBus::new(index),
120+
}
121+
}
122+
123+
#[inline(always)]
124+
pub fn index(&self) -> BusIndex {
125+
self.inner.index
126+
}
127+
128+
/// Performs a lookup on the hint bus.
129+
///
130+
/// Asserts that `(hint_id, offset, value)` is present in the hint lookup table.
131+
/// Caller must constrain that `enabled` is boolean.
132+
pub fn lookup<AB: InteractionBuilder>(
133+
&self,
134+
builder: &mut AB,
135+
hint_id: impl Into<AB::Expr>,
136+
offset: impl Into<AB::Expr>,
137+
value: impl Into<AB::Expr>,
138+
enabled: impl Into<AB::Expr>,
139+
) {
140+
self.inner.lookup_key(
141+
builder,
142+
[hint_id.into(), offset.into(), value.into()],
143+
enabled,
144+
);
145+
}
146+
147+
/// Adds a key to the hint lookup table.
148+
///
149+
/// The `num_lookups` parameter should equal the number of enabled lookups performed
150+
/// for this key.
151+
pub fn provide<AB: InteractionBuilder>(
152+
&self,
153+
builder: &mut AB,
154+
hint_id: impl Into<AB::Expr>,
155+
offset: impl Into<AB::Expr>,
156+
value: impl Into<AB::Expr>,
157+
num_lookups: impl Into<AB::Expr>,
158+
) {
159+
self.inner.add_key_with_lookups(
160+
builder,
161+
[hint_id.into(), offset.into(), value.into()],
162+
num_lookups,
163+
);
164+
}
165+
}

crates/vm/src/system/memory/offline_checker/columns.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ impl<T> AsMut<MemoryBaseAuxCols<T>> for MemoryReadOrImmediateAuxCols<T> {
122122
fn as_mut(&mut self) -> &mut MemoryBaseAuxCols<T> {
123123
&mut self.base
124124
}
125-
}
125+
}

crates/vm/src/system/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use crate::{
3636
connector::VmConnectorChip,
3737
memory::{
3838
interface::MemoryInterfaceAirs,
39-
offline_checker::{MemoryBridge, MemoryBus},
39+
offline_checker::{HintBridge, HintBus, MemoryBridge, MemoryBus},
4040
online::GuestMemory,
4141
MemoryAirInventory, MemoryController, TimestampedEquipartition, CHUNK,
4242
},
@@ -149,13 +149,15 @@ pub struct SystemPort {
149149
pub execution_bus: ExecutionBus,
150150
pub program_bus: ProgramBus,
151151
pub memory_bridge: MemoryBridge,
152+
pub hint_bridge: HintBridge,
152153
}
153154

154155
#[derive(Clone)]
155156
pub struct SystemAirInventory<SC: StarkGenericConfig> {
156157
pub program: ProgramAir,
157158
pub connector: VmConnectorAir,
158159
pub memory: MemoryAirInventory<SC>,
160+
pub hint_bridge: HintBridge,
159161
/// Public values AIR exists if and only if continuations is disabled and `num_public_values`
160162
/// is greater than 0.
161163
pub public_values: Option<PublicValuesAir>,
@@ -171,6 +173,7 @@ impl<SC: StarkGenericConfig> SystemAirInventory<SC> {
171173
execution_bus,
172174
program_bus,
173175
memory_bridge,
176+
hint_bridge,
174177
} = port;
175178
let range_bus = memory_bridge.range_bus();
176179
let program = ProgramAir::new(program_bus);
@@ -212,6 +215,7 @@ impl<SC: StarkGenericConfig> SystemAirInventory<SC> {
212215
program,
213216
connector,
214217
memory,
218+
hint_bridge,
215219
public_values,
216220
}
217221
}
@@ -221,6 +225,7 @@ impl<SC: StarkGenericConfig> SystemAirInventory<SC> {
221225
memory_bridge: self.memory.bridge,
222226
program_bus: self.program.bus,
223227
execution_bus: self.connector.execution_bus,
228+
hint_bridge: self.hint_bridge,
224229
}
225230
}
226231

@@ -300,10 +305,13 @@ impl<SC: StarkGenericConfig> VmCircuitConfig<SC> for SystemConfig {
300305
};
301306
let memory_bridge =
302307
MemoryBridge::new(memory_bus, self.memory_config.timestamp_max_bits, range_bus);
308+
let hint_bus = HintBus::new(bus_idx_mgr.new_bus_idx());
309+
let hint_bridge = HintBridge::new(hint_bus);
303310
let system_port = SystemPort {
304311
execution_bus,
305312
program_bus,
306313
memory_bridge,
314+
hint_bridge,
307315
};
308316
let system = SystemAirInventory::new(self, system_port, merkle_compression_buses);
309317

extensions/algebra/circuit/src/extension/fp2.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ impl<SC: StarkGenericConfig> VmCircuitExtension<SC> for Fp2Extension {
175175
execution_bus,
176176
program_bus,
177177
memory_bridge,
178+
hint_bridge: _,
178179
} = inventory.system().port();
179180

180181
let exec_bridge = ExecutionBridge::new(execution_bus, program_bus);

extensions/algebra/circuit/src/extension/modular.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ impl<SC: StarkGenericConfig> VmCircuitExtension<SC> for ModularExtension {
231231
execution_bus,
232232
program_bus,
233233
memory_bridge,
234+
hint_bridge: _,
234235
} = inventory.system().port();
235236

236237
let exec_bridge = ExecutionBridge::new(execution_bus, program_bus);

extensions/bigint/circuit/src/extension/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ impl<SC: StarkGenericConfig> VmCircuitExtension<SC> for Int256 {
143143
execution_bus,
144144
program_bus,
145145
memory_bridge,
146+
hint_bridge: _,
146147
} = inventory.system().port();
147148

148149
let exec_bridge = ExecutionBridge::new(execution_bus, program_bus);

0 commit comments

Comments
 (0)