Skip to content

Commit

Permalink
Merge pull request #3181 from AleoHQ/feat/puzzle
Browse files Browse the repository at this point in the history
[Feature] Updates the puzzle integration for development and testing
  • Loading branch information
howardwu authored Mar 22, 2024
2 parents 03e7928 + 225ee3a commit c5d4a58
Show file tree
Hide file tree
Showing 37 changed files with 509 additions and 549 deletions.
295 changes: 157 additions & 138 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ default-features = false

[workspace.dependencies.snarkvm]
git = "https://github.com/AleoHQ/snarkVM.git"
rev = "eefd27d"
rev = "81af174"
#version = "=0.16.18"
features = [ "circuit", "console", "rocks" ]

Expand Down
8 changes: 4 additions & 4 deletions node/bft/events/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ pub mod prop_tests {
};
use snarkvm::{
console::{network::Network, types::Field},
ledger::{coinbase::PuzzleCommitment, narwhal::TransmissionID},
ledger::{narwhal::TransmissionID, puzzle::SolutionID},
prelude::{FromBytes, Rng, ToBytes, Uniform},
};

Expand All @@ -282,8 +282,8 @@ pub mod prop_tests {
time::OffsetDateTime::now_utc().unix_timestamp()
}

pub fn any_puzzle_commitment() -> BoxedStrategy<PuzzleCommitment<CurrentNetwork>> {
Just(0).prop_perturb(|_, mut rng| PuzzleCommitment::from_g1_affine(rng.gen())).boxed()
pub fn any_solution_id() -> BoxedStrategy<SolutionID<CurrentNetwork>> {
Just(0).prop_perturb(|_, mut rng| rng.gen::<u64>().into()).boxed()
}

pub fn any_transaction_id() -> BoxedStrategy<<CurrentNetwork as Network>::TransactionID> {
Expand All @@ -295,7 +295,7 @@ pub mod prop_tests {
pub fn any_transmission_id() -> BoxedStrategy<TransmissionID<CurrentNetwork>> {
prop_oneof![
any_transaction_id().prop_map(TransmissionID::Transaction),
any_puzzle_commitment().prop_map(TransmissionID::Solution),
any_solution_id().prop_map(TransmissionID::Solution),
]
.boxed()
}
Expand Down
4 changes: 2 additions & 2 deletions node/bft/events/src/transmission_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl<N: Network> FromBytes for TransmissionRequest<N> {
#[cfg(test)]
pub mod prop_tests {
use crate::{
prop_tests::{any_puzzle_commitment, any_transaction_id},
prop_tests::{any_solution_id, any_transaction_id},
TransmissionRequest,
};
use snarkvm::{
Expand All @@ -78,7 +78,7 @@ pub mod prop_tests {

fn any_transmission_id() -> BoxedStrategy<TransmissionID<CurrentNetwork>> {
prop_oneof![
any_puzzle_commitment().prop_map(TransmissionID::Solution),
any_solution_id().prop_map(TransmissionID::Solution),
any_transaction_id().prop_map(TransmissionID::Transaction),
]
.boxed()
Expand Down
4 changes: 2 additions & 2 deletions node/bft/events/src/transmission_response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl<N: Network> FromBytes for TransmissionResponse<N> {
#[cfg(test)]
pub mod prop_tests {
use crate::{
prop_tests::{any_puzzle_commitment, any_transaction_id},
prop_tests::{any_solution_id, any_transaction_id},
TransmissionResponse,
};
use snarkvm::{
Expand All @@ -82,7 +82,7 @@ pub mod prop_tests {

pub fn any_transmission() -> BoxedStrategy<(TransmissionID<CurrentNetwork>, Transmission<CurrentNetwork>)> {
prop_oneof![
(any_puzzle_commitment(), collection::vec(any::<u8>(), 256..=256)).prop_map(|(pc, bytes)| (
(any_solution_id(), collection::vec(any::<u8>(), 256..=256)).prop_map(|(pc, bytes)| (
TransmissionID::Solution(pc),
Transmission::Solution(Data::Buffer(Bytes::from(bytes)))
)),
Expand Down
19 changes: 9 additions & 10 deletions node/bft/examples/simple_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ use snarkos_node_bft_storage_service::BFTMemoryService;
use snarkvm::{
ledger::{
block::Transaction,
coinbase::{ProverSolution, PuzzleCommitment},
committee::{Committee, MIN_VALIDATOR_STAKE},
narwhal::{BatchHeader, Data},
puzzle::{Solution, SolutionID},
},
prelude::{Field, Network, Uniform},
};
Expand Down Expand Up @@ -269,28 +269,27 @@ fn fire_unconfirmed_solutions(sender: &PrimarySender<CurrentNetwork>, node_id: u
// This RNG samples *different* fake solutions for each node.
let mut unique_rng = rand_chacha::ChaChaRng::seed_from_u64(node_id as u64);

// A closure to generate a commitment and solution.
fn sample(mut rng: impl Rng) -> (PuzzleCommitment<CurrentNetwork>, Data<ProverSolution<CurrentNetwork>>) {
// Sample a random fake puzzle commitment.
// TODO (howardwu): Use a mutex to bring in the real 'proof target' and change this sampling to a while loop.
let commitment = PuzzleCommitment::<CurrentNetwork>::from_g1_affine(rng.gen());
// A closure to generate a solution ID and solution.
fn sample(mut rng: impl Rng) -> (SolutionID<CurrentNetwork>, Data<Solution<CurrentNetwork>>) {
// Sample a random fake solution ID.
let solution_id = rng.gen::<u64>().into();
// Sample random fake solution bytes.
let solution = Data::Buffer(Bytes::from((0..1024).map(|_| rng.gen::<u8>()).collect::<Vec<_>>()));
// Return the ID and solution.
(commitment, solution)
(solution_id, solution)
}

// Initialize a counter.
let mut counter = 0;

loop {
// Sample a random fake puzzle commitment and solution.
let (commitment, solution) =
// Sample a random fake solution ID and solution.
let (solution_id, solution) =
if counter % 2 == 0 { sample(&mut shared_rng) } else { sample(&mut unique_rng) };
// Initialize a callback sender and receiver.
let (callback, callback_receiver) = oneshot::channel();
// Send the fake solution.
if let Err(e) = tx_unconfirmed_solution.send((commitment, solution, callback)).await {
if let Err(e) = tx_unconfirmed_solution.send((solution_id, solution, callback)).await {
error!("Failed to send unconfirmed solution: {e}");
}
let _ = callback_receiver.await;
Expand Down
47 changes: 20 additions & 27 deletions node/bft/ledger-service/src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::{fmt_id, spawn_blocking, LedgerService};
use snarkvm::{
ledger::{
block::{Block, Transaction},
coinbase::{CoinbaseVerifyingKey, ProverSolution, PuzzleCommitment},
committee::Committee,
narwhal::{BatchCertificate, Data, Subdag, Transmission, TransmissionID},
puzzle::{Solution, SolutionID},
store::ConsensusStorage,
Ledger,
},
Expand All @@ -37,14 +37,13 @@ use std::{
},
};

/// The capacity of the LRU holiding the recently queried committees.
/// The capacity of the LRU holding the recently queried committees.
const COMMITTEE_CACHE_SIZE: usize = 16;

/// A core ledger service.
#[allow(clippy::type_complexity)]
pub struct CoreLedgerService<N: Network, C: ConsensusStorage<N>> {
ledger: Ledger<N, C>,
coinbase_verifying_key: Arc<CoinbaseVerifyingKey<N>>,
committee_cache: Arc<Mutex<LruCache<u64, Committee<N>>>>,
latest_leader: Arc<RwLock<Option<(u64, Address<N>)>>>,
shutdown: Arc<AtomicBool>,
Expand All @@ -53,9 +52,8 @@ pub struct CoreLedgerService<N: Network, C: ConsensusStorage<N>> {
impl<N: Network, C: ConsensusStorage<N>> CoreLedgerService<N, C> {
/// Initializes a new core ledger service.
pub fn new(ledger: Ledger<N, C>, shutdown: Arc<AtomicBool>) -> Self {
let coinbase_verifying_key = Arc::new(ledger.coinbase_puzzle().coinbase_verifying_key().clone());
let committee_cache = Arc::new(Mutex::new(LruCache::new(COMMITTEE_CACHE_SIZE.try_into().unwrap())));
Self { ledger, coinbase_verifying_key, committee_cache, latest_leader: Default::default(), shutdown }
Self { ledger, committee_cache, latest_leader: Default::default(), shutdown }
}
}

Expand Down Expand Up @@ -125,7 +123,7 @@ impl<N: Network, C: ConsensusStorage<N>> LedgerService<N> for CoreLedgerService<
}

/// Returns the solution for the given solution ID.
fn get_solution(&self, solution_id: &PuzzleCommitment<N>) -> Result<ProverSolution<N>> {
fn get_solution(&self, solution_id: &SolutionID<N>) -> Result<Solution<N>> {
self.ledger.get_solution(solution_id)
}

Expand Down Expand Up @@ -203,7 +201,7 @@ impl<N: Network, C: ConsensusStorage<N>> LedgerService<N> for CoreLedgerService<
fn contains_transmission(&self, transmission_id: &TransmissionID<N>) -> Result<bool> {
match transmission_id {
TransmissionID::Ratification => Ok(false),
TransmissionID::Solution(puzzle_commitment) => self.ledger.contains_puzzle_commitment(puzzle_commitment),
TransmissionID::Solution(solution_id) => self.ledger.contains_solution_id(solution_id),
TransmissionID::Transaction(transaction_id) => self.ledger.contains_transaction_id(transaction_id),
}
}
Expand Down Expand Up @@ -241,14 +239,14 @@ impl<N: Network, C: ConsensusStorage<N>> LedgerService<N> for CoreLedgerService<
}
}
}
(TransmissionID::Solution(expected_commitment), Transmission::Solution(solution_data)) => {
(TransmissionID::Solution(expected_solution_id), Transmission::Solution(solution_data)) => {
match solution_data.clone().deserialize_blocking() {
Ok(solution) => {
if solution.commitment() != expected_commitment {
if solution.id() != expected_solution_id {
bail!(
"Received mismatching solution ID - expected {}, found {}",
fmt_id(expected_commitment),
fmt_id(solution.commitment()),
fmt_id(expected_solution_id),
fmt_id(solution.id()),
);
}

Expand All @@ -269,30 +267,25 @@ impl<N: Network, C: ConsensusStorage<N>> LedgerService<N> for CoreLedgerService<
}

/// Checks the given solution is well-formed.
async fn check_solution_basic(
&self,
puzzle_commitment: PuzzleCommitment<N>,
solution: Data<ProverSolution<N>>,
) -> Result<()> {
async fn check_solution_basic(&self, solution_id: SolutionID<N>, solution: Data<Solution<N>>) -> Result<()> {
// Deserialize the solution.
let solution = spawn_blocking!(solution.deserialize_blocking())?;
// Ensure the puzzle commitment matches in the solution.
if puzzle_commitment != solution.commitment() {
bail!("Invalid solution - expected {puzzle_commitment}, found {}", solution.commitment());
// Ensure the solution ID matches in the solution.
if solution_id != solution.id() {
bail!("Invalid solution - expected {solution_id}, found {}", solution.id());
}

// Retrieve the coinbase verifying key.
let coinbase_verifying_key = self.coinbase_verifying_key.clone();
// Compute the current epoch challenge.
let epoch_challenge = self.ledger.latest_epoch_challenge()?;
// Compute the current epoch hash.
let epoch_hash = self.ledger.latest_epoch_hash()?;
// Retrieve the current proof target.
let proof_target = self.ledger.latest_proof_target();

// Ensure that the prover solution is valid for the given epoch.
if !spawn_blocking!(solution.verify(&coinbase_verifying_key, &epoch_challenge, proof_target))? {
bail!("Invalid prover solution '{puzzle_commitment}' for the current epoch.");
// Ensure that the solution is valid for the given epoch.
let puzzle = self.ledger.puzzle().clone();
match spawn_blocking!(puzzle.check_solution(&solution, epoch_hash, proof_target)) {
Ok(()) => Ok(()),
Err(e) => bail!("Invalid solution '{}' for the current epoch - {e}", fmt_id(solution_id)),
}
Ok(())
}

/// Checks the given transaction is well-formed and unique.
Expand Down
12 changes: 4 additions & 8 deletions node/bft/ledger-service/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::{fmt_id, LedgerService};
use snarkvm::{
ledger::{
block::{Block, Transaction},
coinbase::{ProverSolution, PuzzleCommitment},
committee::Committee,
narwhal::{BatchCertificate, Data, Subdag, Transmission, TransmissionID},
puzzle::{Solution, SolutionID},
},
prelude::{bail, ensure, Address, Field, Network, Result},
};
Expand Down Expand Up @@ -127,7 +127,7 @@ impl<N: Network> LedgerService<N> for MockLedgerService<N> {
}

/// Returns the solution for the given solution ID.
fn get_solution(&self, _solution_id: &PuzzleCommitment<N>) -> Result<ProverSolution<N>> {
fn get_solution(&self, _solution_id: &SolutionID<N>) -> Result<Solution<N>> {
unreachable!("MockLedgerService does not support get_solution")
}

Expand Down Expand Up @@ -180,12 +180,8 @@ impl<N: Network> LedgerService<N> for MockLedgerService<N> {
}

/// Checks the given solution is well-formed.
async fn check_solution_basic(
&self,
puzzle_commitment: PuzzleCommitment<N>,
_solution: Data<ProverSolution<N>>,
) -> Result<()> {
trace!("[MockLedgerService] Check solution basic {:?} - Ok", fmt_id(puzzle_commitment));
async fn check_solution_basic(&self, solution_id: SolutionID<N>, _solution: Data<Solution<N>>) -> Result<()> {
trace!("[MockLedgerService] Check solution basic {:?} - Ok", fmt_id(solution_id));
Ok(())
}

Expand Down
10 changes: 3 additions & 7 deletions node/bft/ledger-service/src/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::LedgerService;
use snarkvm::{
ledger::{
block::{Block, Transaction},
coinbase::{ProverSolution, PuzzleCommitment},
committee::Committee,
narwhal::{BatchCertificate, Data, Subdag, Transmission, TransmissionID},
puzzle::{Solution, SolutionID},
},
prelude::{bail, Address, Field, Network, Result},
};
Expand Down Expand Up @@ -98,7 +98,7 @@ impl<N: Network> LedgerService<N> for ProverLedgerService<N> {
}

/// Returns the solution for the given solution ID.
fn get_solution(&self, solution_id: &PuzzleCommitment<N>) -> Result<ProverSolution<N>> {
fn get_solution(&self, solution_id: &SolutionID<N>) -> Result<Solution<N>> {
bail!("Solution '{solution_id}' does not exist in prover")
}

Expand Down Expand Up @@ -149,11 +149,7 @@ impl<N: Network> LedgerService<N> for ProverLedgerService<N> {
}

/// Checks the given solution is well-formed.
async fn check_solution_basic(
&self,
_puzzle_commitment: PuzzleCommitment<N>,
_solution: Data<ProverSolution<N>>,
) -> Result<()> {
async fn check_solution_basic(&self, _solution_id: SolutionID<N>, _solution: Data<Solution<N>>) -> Result<()> {
Ok(())
}

Expand Down
10 changes: 3 additions & 7 deletions node/bft/ledger-service/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
use snarkvm::{
ledger::{
block::{Block, Transaction},
coinbase::{ProverSolution, PuzzleCommitment},
committee::Committee,
narwhal::{BatchCertificate, Data, Subdag, Transmission, TransmissionID},
puzzle::{Solution, SolutionID},
},
prelude::{Address, Field, Network, Result},
};
Expand Down Expand Up @@ -62,7 +62,7 @@ pub trait LedgerService<N: Network>: Debug + Send + Sync {
fn get_blocks(&self, heights: Range<u32>) -> Result<Vec<Block<N>>>;

/// Returns the solution for the given solution ID.
fn get_solution(&self, solution_id: &PuzzleCommitment<N>) -> Result<ProverSolution<N>>;
fn get_solution(&self, solution_id: &SolutionID<N>) -> Result<Solution<N>>;

/// Returns the unconfirmed transaction for the given transaction ID.
fn get_unconfirmed_transaction(&self, transaction_id: N::TransactionID) -> Result<Transaction<N>>;
Expand Down Expand Up @@ -95,11 +95,7 @@ pub trait LedgerService<N: Network>: Debug + Send + Sync {
) -> Result<()>;

/// Checks the given solution is well-formed.
async fn check_solution_basic(
&self,
puzzle_commitment: PuzzleCommitment<N>,
solution: Data<ProverSolution<N>>,
) -> Result<()>;
async fn check_solution_basic(&self, solution_id: SolutionID<N>, solution: Data<Solution<N>>) -> Result<()>;

/// Checks the given transaction is well-formed and unique.
async fn check_transaction_basic(
Expand Down
10 changes: 3 additions & 7 deletions node/bft/ledger-service/src/translucent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use indexmap::IndexMap;
use snarkvm::{
ledger::{
block::{Block, Transaction},
coinbase::{ProverSolution, PuzzleCommitment},
committee::Committee,
narwhal::{Data, Subdag, Transmission, TransmissionID},
puzzle::{Solution, SolutionID},
store::ConsensusStorage,
Ledger,
},
Expand Down Expand Up @@ -109,7 +109,7 @@ impl<N: Network, C: ConsensusStorage<N>> LedgerService<N> for TranslucentLedgerS
}

/// Returns the solution for the given solution ID.
fn get_solution(&self, solution_id: &PuzzleCommitment<N>) -> Result<ProverSolution<N>> {
fn get_solution(&self, solution_id: &SolutionID<N>) -> Result<Solution<N>> {
self.inner.get_solution(solution_id)
}

Expand Down Expand Up @@ -159,11 +159,7 @@ impl<N: Network, C: ConsensusStorage<N>> LedgerService<N> for TranslucentLedgerS
}

/// Always succeeds.
async fn check_solution_basic(
&self,
_puzzle_commitment: PuzzleCommitment<N>,
_solution: Data<ProverSolution<N>>,
) -> Result<()> {
async fn check_solution_basic(&self, _solution_id: SolutionID<N>, _solution: Data<Solution<N>>) -> Result<()> {
Ok(())
}

Expand Down
4 changes: 2 additions & 2 deletions node/bft/src/bft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ use snarkvm::{
console::account::Address,
ledger::{
block::Transaction,
coinbase::{ProverSolution, PuzzleCommitment},
committee::Committee,
narwhal::{BatchCertificate, Data, Subdag, Transmission, TransmissionID},
puzzle::{Solution, SolutionID},
},
prelude::{bail, ensure, Field, Network, Result},
};
Expand Down Expand Up @@ -183,7 +183,7 @@ impl<N: Network> BFT<N> {
}

/// Returns the unconfirmed solutions.
pub fn unconfirmed_solutions(&self) -> impl '_ + Iterator<Item = (PuzzleCommitment<N>, Data<ProverSolution<N>>)> {
pub fn unconfirmed_solutions(&self) -> impl '_ + Iterator<Item = (SolutionID<N>, Data<Solution<N>>)> {
self.primary.unconfirmed_solutions()
}

Expand Down
Loading

0 comments on commit c5d4a58

Please sign in to comment.