// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the snarkOS library.
// The snarkOS library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The snarkOS library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the snarkOS library. If not, see .
use snarkos_storage::{storage::rocksdb::RocksDB, LedgerState};
use snarkvm::{dpc::testnet2::Testnet2, prelude::Block, traits::Network};
use criterion::{criterion_group, criterion_main, Criterion};
use rand::{prelude::SliceRandom, thread_rng, Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
use std::fs;
const NUM_BLOCKS: usize = 1_000;
fn lookups(c: &mut Criterion) {
// Prepare the test ledger.
let temp_dir = tempfile::tempdir().expect("Failed to open temporary directory").into_path();
let ledger = LedgerState::open_writer_with_increment::(temp_dir, 1).expect("Failed to initialize ledger");
// Read the test blocks; note: they don't include the genesis block, as it's always available when creating a ledger.
// note: the `blocks_100` and `blocks_1000` files were generated on a testnet2 storage using `LedgerState::dump_blocks`.
let test_blocks = fs::read(format!("benches/blocks_{}", NUM_BLOCKS)).unwrap_or_else(|_| panic!("Missing the test blocks file"));
let blocks: Vec> = bincode::deserialize(&test_blocks).expect("Failed to deserialize a block dump");
assert_eq!(blocks.len(), NUM_BLOCKS - 1);
// Prepare the collections for block component ids.
let mut block_hashes = Vec::with_capacity(NUM_BLOCKS);
block_hashes.push(Testnet2::genesis_block().hash());
let mut ledger_roots = Vec::with_capacity(NUM_BLOCKS);
let mut tx_ids = Vec::with_capacity(NUM_BLOCKS);
for tx_id in Testnet2::genesis_block().transactions().transaction_ids() {
tx_ids.push(tx_id);
}
let mut tx_commitments = Vec::with_capacity(NUM_BLOCKS);
for tx_commitment in Testnet2::genesis_block().transactions().commitments() {
tx_commitments.push(tx_commitment);
}
let mut tx_serial_numbers = Vec::with_capacity(NUM_BLOCKS);
for tx_serial_number in Testnet2::genesis_block().transactions().serial_numbers() {
tx_serial_numbers.push(tx_serial_number);
}
// Load the test blocks into the ledger and register their components along the way.
for block in &blocks {
ledger.add_next_block(block).expect("Failed to add a test block");
block_hashes.push(block.hash());
ledger_roots.push(ledger.latest_ledger_root());
tx_ids.extend(block.transactions().transaction_ids());
tx_commitments.extend(block.commitments());
tx_serial_numbers.extend(block.serial_numbers());
}
assert_eq!(block_hashes.len(), NUM_BLOCKS);
// Seed a fast random number generator.
let seed: u64 = thread_rng().gen();
let mut rng = XorShiftRng::seed_from_u64(seed);
c.bench_function("ledger_roots_lookup", |b| {
b.iter(|| {
let root = ledger_roots.choose(&mut rng).unwrap();
ledger.contains_ledger_root(root).expect("Lookup by ledger root failed");
})
});
c.bench_function("blocks_lookup_by_height", |b| {
b.iter(|| {
let height = rng.gen_range(0..NUM_BLOCKS as u32);
ledger.contains_block_height(height).expect("Lookup by block height failed");
})
});
c.bench_function("blocks_lookup_by_hash", |b| {
b.iter(|| {
let hash = block_hashes.choose(&mut rng).unwrap();
ledger.contains_block_hash(hash).expect("Lookup by block hash failed");
})
});
c.bench_function("txs_lookup_by_id", |b| {
b.iter(|| {
let id = tx_ids.choose(&mut rng).unwrap();
ledger.contains_transaction(id).expect("Lookup by tx id failed");
})
});
c.bench_function("txs_lookup_by_commitment", |b| {
b.iter(|| {
let id = tx_commitments.choose(&mut rng).unwrap();
ledger.contains_commitment(id).expect("Lookup by commitment failed");
})
});
c.bench_function("txs_lookup_by_serial_number", |b| {
b.iter(|| {
let id = tx_serial_numbers.choose(&mut rng).unwrap();
ledger.contains_serial_number(id).expect("Lookup by serial number failed");
})
});
}
criterion_group!(benches, lookups);
criterion_main!(benches);