Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Updates the puzzle integration for development and testing #3181

Merged
merged 5 commits into from Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
295 changes: 157 additions & 138 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
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
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
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
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
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
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
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
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
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
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
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