Skip to content

Commit

Permalink
Merge pull request #1833 from AleoHQ/feat/profiler-coinbase
Browse files Browse the repository at this point in the history
Add profiler for `CoinbasePuzzle::verify`
  • Loading branch information
howardwu authored Aug 13, 2023
2 parents a6c5cf5 + 5bd3de8 commit 8a36895
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 4 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions ledger/coinbase/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ serial = [
"snarkvm-utilities/serial"
]
setup = [ ]
timer = [ "aleo-std/timer" ]
wasm = [
"console/wasm",
"snarkvm-algorithms/wasm",
Expand Down Expand Up @@ -72,6 +73,10 @@ path = "../../utilities"
version = "=0.14.6"
default-features = false

[dependencies.aleo-std]
version = "0.1.18"
default-features = false

[dependencies.anyhow]
version = "1.0.72"

Expand Down
21 changes: 18 additions & 3 deletions ledger/coinbase/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ use snarkvm_fields::{PrimeField, Zero};
use snarkvm_synthesizer_snark::UniversalSRS;
use snarkvm_utilities::cfg_zip_fold;

use aleo_std::prelude::*;

use std::sync::Arc;

#[cfg(feature = "serial")]
Expand Down Expand Up @@ -263,6 +265,8 @@ impl<N: Network> CoinbasePuzzle<N> {
epoch_challenge: &EpochChallenge<N>,
proof_target: u64,
) -> Result<bool> {
let timer = timer!("CoinbasePuzzle::verify");

// Ensure the solutions are not empty.
if coinbase_solution.is_empty() {
bail!("There are no solutions");
Expand All @@ -286,6 +290,7 @@ impl<N: Network> CoinbasePuzzle<N> {
if has_duplicates(coinbase_solution.puzzle_commitments()) {
bail!("The solutions contain duplicate puzzle commitments");
}
lap!(timer, "Perform initial checks");

// Compute the prover polynomials.
let prover_polynomials = cfg_iter!(coinbase_solution.partial_solutions())
Expand All @@ -296,6 +301,7 @@ impl<N: Network> CoinbasePuzzle<N> {
false => bail!("Prover puzzle does not meet the proof target requirements."),
})
.collect::<Result<Vec<_>>>()?;
lap!(timer, "Compute the prover polynomials");

// Compute the challenge points.
let mut challenge_points =
Expand All @@ -310,6 +316,7 @@ impl<N: Network> CoinbasePuzzle<N> {
Some(point) => point,
None => bail!("Missing the accumulator challenge point"),
};
lap!(timer, "Construct the accumulator point");

// Compute the accumulator evaluation.
let mut accumulator_evaluation = cfg_zip_fold!(
Expand All @@ -322,28 +329,36 @@ impl<N: Network> CoinbasePuzzle<N> {
_
);
accumulator_evaluation *= &epoch_challenge.epoch_polynomial().evaluate(accumulator_point);
lap!(timer, "Compute the accumulator evaluation");

// Compute the accumulator commitment.
let commitments: Vec<_> =
cfg_iter!(coinbase_solution.partial_solutions()).map(|solution| solution.commitment().0).collect();
let fs_challenges = challenge_points.into_iter().map(|f| f.to_bigint()).collect::<Vec<_>>();
let accumulator_commitment =
KZGCommitment::<N::PairingCurve>(VariableBase::msm(&commitments, &fs_challenges).into());
lap!(timer, "Compute the accumulator commitment");

// Retrieve the coinbase verifying key.
let coinbase_verifying_key = match self {
Self::Prover(coinbase_proving_key) => &coinbase_proving_key.verifying_key,
Self::Verifier(coinbase_verifying_key) => coinbase_verifying_key,
};

// Return the verification result.
Ok(KZG10::check(
// Verify the KZG10 proof.
let check = KZG10::check(
coinbase_verifying_key,
&accumulator_commitment,
accumulator_point,
accumulator_evaluation,
coinbase_solution.proof(),
)?)
)?;
lap!(timer, "Verify the KZG10 proof");

finish!(timer);

// Return the verification result.
Ok(check)
}

/// Returns the coinbase proving key.
Expand Down
46 changes: 45 additions & 1 deletion ledger/coinbase/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ fn test_edge_case_for_degree() {
let srs = CoinbasePuzzle::<Testnet3>::setup(max_config).unwrap();

// Generate PK and VK.
let degree = (1 << 13) - 1; // IF YOU ADD `- 1` THIS WILL PASS
let degree = (1 << 13) - 1;
let puzzle = CoinbasePuzzle::<Testnet3>::trim(&srs, PuzzleConfig { degree }).unwrap();

// Generate proof inputs
Expand All @@ -106,3 +106,47 @@ fn test_edge_case_for_degree() {
let (coinbase_solution, _) = puzzle.accumulate_unchecked(&epoch_challenge, &[prover_solution]).unwrap();
assert!(puzzle.verify(&coinbase_solution, &epoch_challenge, 0u64).unwrap());
}

/// Use `cargo test profiler --features timer` to run this test.
#[ignore]
#[test]
fn test_profiler() -> Result<()> {
fn sample_address_and_nonce(rng: &mut (impl CryptoRng + RngCore)) -> (Address<Testnet3>, u64) {
let private_key = PrivateKey::new(rng).unwrap();
let address = Address::try_from(private_key).unwrap();
let nonce = rng.next_u64();
(address, nonce)
}

let mut rng = rand::thread_rng();

// Generate srs.
let max_degree = 1 << 15;
let max_config = PuzzleConfig { degree: max_degree };
let universal_srs = CoinbasePuzzle::<Testnet3>::setup(max_config).unwrap();

// Generate PK and VK.
let degree = (1 << 13) - 1;
let config = PuzzleConfig { degree };
let puzzle = CoinbasePuzzle::trim(&universal_srs, config).unwrap();

// Generate proof inputs
let epoch_challenge = EpochChallenge::new(rng.next_u32(), Default::default(), degree).unwrap();

for batch_size in [10, 100, <Testnet3 as Network>::MAX_PROVER_SOLUTIONS] {
// Generate the solutions.
let solutions = (0..batch_size)
.map(|_| {
let (address, nonce) = sample_address_and_nonce(&mut rng);
puzzle.prove(&epoch_challenge, address, nonce, None).unwrap()
})
.collect::<Vec<_>>();
// Accumulate the solutions.
let (solution, _) = puzzle.accumulate_unchecked(&epoch_challenge, &solutions).unwrap();

// Verify the solution.
puzzle.verify(&solution, &epoch_challenge, 0u64).unwrap();
}

bail!("\n\nRemember to #[ignore] this test!\n\n")
}

0 comments on commit 8a36895

Please sign in to comment.