47 lines
1.6 KiB
Rust
47 lines
1.6 KiB
Rust
use blake2::Blake2b512;
|
||
use digest::Digest;
|
||
|
||
/// Database of fixed-length records, packed as a `cells_per_record × n_records`
|
||
/// column-major matrix of mod-p cells (p = 256, so one byte = one cell).
|
||
pub struct Database {
|
||
/// Row-major: data[i * n_records + j] = record j's byte i.
|
||
data: Vec<u32>,
|
||
n_records: usize,
|
||
record_bytes: usize,
|
||
}
|
||
|
||
impl Database {
|
||
/// Pack `records` (each padded/truncated to `record_bytes`) into a query-ready matrix.
|
||
pub fn new(records: &[&[u8]], record_bytes: usize) -> Self {
|
||
let n_records = records.len();
|
||
let cells = record_bytes;
|
||
let mut data = vec![0u32; cells * n_records];
|
||
for (j, rec) in records.iter().enumerate() {
|
||
let len = rec.len().min(record_bytes);
|
||
for i in 0..len {
|
||
data[i * n_records + j] = rec[i] as u32;
|
||
}
|
||
}
|
||
Database { data, n_records, record_bytes }
|
||
}
|
||
|
||
pub fn data(&self) -> &[u32] { &self.data }
|
||
pub fn n_records(&self) -> usize { self.n_records }
|
||
pub fn record_bytes(&self) -> usize { self.record_bytes }
|
||
pub fn cells_per_record(&self) -> usize { self.record_bytes }
|
||
|
||
/// BLAKE2b-256 commitment over (n_records, record_bytes, all packed cells).
|
||
pub fn version(&self) -> [u8; 32] {
|
||
let mut h = Blake2b512::new();
|
||
h.update((self.n_records as u64).to_le_bytes());
|
||
h.update((self.record_bytes as u64).to_le_bytes());
|
||
for &val in &self.data {
|
||
h.update(val.to_le_bytes());
|
||
}
|
||
let digest = h.finalize();
|
||
let mut v = [0u8; 32];
|
||
v.copy_from_slice(&digest[..32]);
|
||
v
|
||
}
|
||
}
|