The public history carried kat/__pycache__/mlkem768_reference.cpython-314.pyc, a compiled Python artifact embedding the operator's absolute local path. Text secret scanners do not read compiled binaries, which is exactly how it slipped through, and removing it from the tip would have left it reachable through the old root commits. So this repository is republished from a single clean root. This root also carries, from the previously unpublished line of work: - corrected LICENSE year, LICENSING.md, VERIFY-POLICY.md, and CITATIONS-UNRESOLVED.md remeasured 2026-08-11 (101 paths, README aligned) - O-018: run_consensus_verification.py ran 19 of 29 models and reported PASS; it now runs all 29, and computemarket_smt.py gains resolveByTimeout / reclaimUnsettled cases plus a negative control - O-006: the word 'audited' removed from next to Bouncy Castle, twice, after a concurrent edit resurrected it - O-014: prior art named and dated - Algorand's native falcon_verify shipped about ten months before AERE's precompiles; the primacy claim is withdrawn where it was implied - bench/ scripts parametrized so they actually run for an outsider (the earlier textual sanitization left $STAGING unexpanded inside Python strings) - AIP-2/AIP-3 errata with measured figures, spec remeasurements at 2026-08-01, and the spec-zk-stack retractions (owner is an operational key, not the Foundation; 'maximally sound' withdrawn; aggregator V1 deprecated) The redacted bench-host environment files from the sanitized line are kept exactly as published; the unredacted local variants are not carried.
124 lines
4.2 KiB
Rust
124 lines
4.2 KiB
Rust
//! Deterministic, seedable workload generation. No external RNG crate: a small
|
|
//! SplitMix64 gives reproducible batches so a failing case can be replayed
|
|
//! exactly. `conflict` in [0,1] tunes how often a transaction touches the small
|
|
//! "hot" set (shared accounts / the shared counter / the shared AMM pool),
|
|
//! which is what drives the abort rate and destroys parallelism when high.
|
|
|
|
use crate::types::{Key, StateMap, TxKind, Txn, Value};
|
|
|
|
pub struct SplitMix64 {
|
|
state: u64,
|
|
}
|
|
|
|
impl SplitMix64 {
|
|
pub fn new(seed: u64) -> Self {
|
|
SplitMix64 { state: seed }
|
|
}
|
|
pub fn next_u64(&mut self) -> u64 {
|
|
self.state = self.state.wrapping_add(0x9E3779B97F4A7C15);
|
|
let mut z = self.state;
|
|
z = (z ^ (z >> 30)).wrapping_mul(0xBF58476D1CE4E5B9);
|
|
z = (z ^ (z >> 27)).wrapping_mul(0x94D049BB133111EB);
|
|
z ^ (z >> 31)
|
|
}
|
|
pub fn below(&mut self, n: u64) -> u64 {
|
|
if n == 0 {
|
|
0
|
|
} else {
|
|
self.next_u64() % n
|
|
}
|
|
}
|
|
/// probability p in [0,1] scaled to 1e6.
|
|
pub fn chance(&mut self, p_ppm: u64) -> bool {
|
|
self.below(1_000_000) < p_ppm
|
|
}
|
|
}
|
|
|
|
pub struct WorkloadConfig {
|
|
pub num_txns: usize,
|
|
pub num_accounts: u64,
|
|
pub num_hot_accounts: u64,
|
|
pub num_contracts: u64,
|
|
pub num_hot_slots: u64,
|
|
/// probability (0..1e6 ppm) that a given account/slot pick is from the hot set
|
|
pub conflict_ppm: u64,
|
|
/// simulated EVM execution cost per tx (keccak rounds). 0 = trivial tx.
|
|
pub gas: u32,
|
|
pub seed: u64,
|
|
}
|
|
|
|
/// Build the base state: every account funded, hot slots seeded, AMM pools seeded.
|
|
pub fn make_base_state(cfg: &WorkloadConfig) -> StateMap {
|
|
let mut s = StateMap::new();
|
|
for a in 0..cfg.num_accounts {
|
|
s.insert(Key::Balance(a), 1_000_000u128);
|
|
}
|
|
for c in 0..cfg.num_contracts {
|
|
// slot layout: 0..num_hot_slots = counters; then two AMM slots 1000,1001
|
|
for slot in 0..cfg.num_hot_slots {
|
|
s.insert(Key::Storage(c, slot), 0);
|
|
}
|
|
s.insert(Key::Storage(c, 1000), 1_000_000u128); // AMM reserve x
|
|
s.insert(Key::Storage(c, 1001), 1_000_000u128); // AMM reserve y
|
|
}
|
|
s
|
|
}
|
|
|
|
impl WorkloadConfig {
|
|
fn pick_account(&self, rng: &mut SplitMix64) -> u64 {
|
|
if self.num_hot_accounts > 0 && rng.chance(self.conflict_ppm) {
|
|
rng.below(self.num_hot_accounts)
|
|
} else {
|
|
self.num_hot_accounts + rng.below(self.num_accounts - self.num_hot_accounts)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Generate a batch. Mix: transfers, sweeps, increments, AMM swaps.
|
|
pub fn generate_batch(cfg: &WorkloadConfig) -> Vec<Txn> {
|
|
let mut rng = SplitMix64::new(cfg.seed);
|
|
let mut txns = Vec::with_capacity(cfg.num_txns);
|
|
for _ in 0..cfg.num_txns {
|
|
let roll = rng.below(100);
|
|
let kind = if roll < 60 {
|
|
// 60% transfers
|
|
let from = cfg.pick_account(&mut rng);
|
|
let mut to = cfg.pick_account(&mut rng);
|
|
if to == from {
|
|
to = (to + 1) % cfg.num_accounts;
|
|
}
|
|
let amount = 1 + rng.below(1000) as Value;
|
|
TxKind::Transfer { from, to, amount }
|
|
} else if roll < 75 {
|
|
// 15% sweeps
|
|
let from = cfg.pick_account(&mut rng);
|
|
let mut to = cfg.pick_account(&mut rng);
|
|
if to == from {
|
|
to = (to + 1) % cfg.num_accounts;
|
|
}
|
|
TxKind::Sweep { from, to }
|
|
} else if roll < 90 {
|
|
// 15% shared-counter increments (the serializability stressor)
|
|
let contract = rng.below(cfg.num_contracts.max(1));
|
|
let slot = if cfg.num_hot_slots > 0 {
|
|
rng.below(cfg.num_hot_slots)
|
|
} else {
|
|
0
|
|
};
|
|
TxKind::Increment { contract, slot }
|
|
} else {
|
|
// 10% AMM swaps against a shared pool
|
|
let contract = rng.below(cfg.num_contracts.max(1));
|
|
let dx = 1 + rng.below(10_000) as Value;
|
|
TxKind::AmmSwap {
|
|
contract,
|
|
x_slot: 1000,
|
|
y_slot: 1001,
|
|
dx,
|
|
}
|
|
};
|
|
txns.push(Txn { kind, gas: cfg.gas });
|
|
}
|
|
txns
|
|
}
|