|
| 1 | +use binius_circuits::{builder::ConstraintSystemBuilder, sha256::u32const_repeating}; |
| 2 | +use binius_core::{ |
| 3 | + constraint_system::validate::validate_witness, oracle::OracleId, |
| 4 | + transparent::constant::Constant, |
| 5 | +}; |
| 6 | +use binius_field::{arch::OptimalUnderlier, BinaryField128b, BinaryField1b, BinaryField32b}; |
| 7 | + |
| 8 | +type U = OptimalUnderlier; |
| 9 | +type F128 = BinaryField128b; |
| 10 | +type F32 = BinaryField32b; |
| 11 | +type F1 = BinaryField1b; |
| 12 | + |
| 13 | +const LOG_SIZE: usize = 4; |
| 14 | + |
| 15 | +// FIXME: Following gadgets are unconstrained. Only for demonstrative purpose, don't use in production |
| 16 | + |
| 17 | +fn constants_gadget( |
| 18 | + name: impl ToString, |
| 19 | + log_size: usize, |
| 20 | + builder: &mut ConstraintSystemBuilder<U, F128>, |
| 21 | + constant_value: u32, |
| 22 | +) -> OracleId { |
| 23 | + builder.push_namespace(name); |
| 24 | + |
| 25 | + let c = Constant::new(log_size, F32::new(constant_value)); |
| 26 | + |
| 27 | + let oracle = builder.add_transparent("constant", c).unwrap(); |
| 28 | + |
| 29 | + if let Some(witness) = builder.witness() { |
| 30 | + let mut oracle_witness = witness.new_column::<F32>(oracle); |
| 31 | + let values = oracle_witness.as_mut_slice::<u32>(); |
| 32 | + for v in values { |
| 33 | + *v = constant_value; |
| 34 | + } |
| 35 | + } |
| 36 | + |
| 37 | + builder.pop_namespace(); |
| 38 | + |
| 39 | + oracle |
| 40 | +} |
| 41 | + |
| 42 | +// Transparent column can also naturally be used for storing some constants (also available for verifier). |
| 43 | +// For example there is a 'u32const_repeating' function (in sha256 gadget) that does exactly this |
| 44 | +// using Transparent + Repeated columns. Alternatively one can use Constant abstraction to create equivalent |
| 45 | +// Transparent column. |
| 46 | +fn main() { |
| 47 | + let allocator = bumpalo::Bump::new(); |
| 48 | + let mut builder = ConstraintSystemBuilder::<U, F128>::new_with_witness(&allocator); |
| 49 | + |
| 50 | + pub const SHA256_INIT: [u32; 8] = [ |
| 51 | + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, |
| 52 | + 0x5be0cd19, |
| 53 | + ]; |
| 54 | + |
| 55 | + let oracles: [OracleId; 8] = |
| 56 | + SHA256_INIT.map(|c| u32const_repeating(LOG_SIZE, &mut builder, c, "INIT").unwrap()); |
| 57 | + if let Some(witness) = builder.witness() { |
| 58 | + for (index, oracle) in oracles.into_iter().enumerate() { |
| 59 | + let values = witness.get::<F1>(oracle).unwrap().as_slice::<u32>(); |
| 60 | + |
| 61 | + // every value in the column should match the expected one |
| 62 | + for value in values { |
| 63 | + assert_eq!(*value, SHA256_INIT[index]); |
| 64 | + } |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + let oracles: [OracleId; 8] = |
| 69 | + SHA256_INIT.map(|c| constants_gadget("constants_gadget", LOG_SIZE, &mut builder, c)); |
| 70 | + if let Some(witness) = builder.witness() { |
| 71 | + for (index, oracle) in oracles.into_iter().enumerate() { |
| 72 | + // The difference is here. With Constant we have to operate over F32, while |
| 73 | + // with Transparent + Repeated approach as in 'u32const_repeating' we operate over F1, |
| 74 | + // which can be more convenient in the bit-oriented computations |
| 75 | + let values = witness.get::<F32>(oracle).unwrap().as_slice::<u32>(); |
| 76 | + |
| 77 | + // every value in the column should match the expected one |
| 78 | + for value in values { |
| 79 | + assert_eq!(*value, SHA256_INIT[index]); |
| 80 | + } |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + let witness = builder.take_witness().unwrap(); |
| 85 | + let constraints_system = builder.build().unwrap(); |
| 86 | + |
| 87 | + validate_witness(&constraints_system, &[], &witness).unwrap(); |
| 88 | +} |
0 commit comments