From 18a50cf1ee5ba366e7c24655c979d8f329dc00f0 Mon Sep 17 00:00:00 2001 From: Howard Wu <9260812+howardwu@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:43:00 -0700 Subject: [PATCH 1/3] Removes current_committee from the Ledger struct --- ledger/src/check_next_block.rs | 25 ++++++++++++++------ ledger/src/check_transaction_basic.rs | 3 ++- ledger/src/get.rs | 22 +++++++++++++----- ledger/src/lib.rs | 33 ++++++++++----------------- synthesizer/src/vm/mod.rs | 7 ++++++ 5 files changed, 55 insertions(+), 35 deletions(-) diff --git a/ledger/src/check_next_block.rs b/ledger/src/check_next_block.rs index fa9eebe96c..eb709789a0 100644 --- a/ledger/src/check_next_block.rs +++ b/ledger/src/check_next_block.rs @@ -242,22 +242,33 @@ impl> Ledger { /* Authority */ - // Ensure the block is signed by a validator in the committee. - let signer = block.authority().to_address(); - if !self.current_committee.read().contains(&signer) { - bail!("Block {} ({}) is signed by an unauthorized account ({signer})", block.height(), block.hash()); - } - // Verify the block authority. match block.authority() { Authority::Beacon(signature) => { + // Retrieve the signer. + let signer = signature.to_address(); + + // Ensure the block is signed by a validator in the committee. + if signer != self.genesis_block.authority().to_address() { + bail!( + "Block {} ({}) is signed by an unauthorized account ({signer})", + block.height(), + block.hash() + ); + } // Check the signature. if !signature.verify(&signer, &[*block.hash()]) { bail!("Invalid signature for block {} ({})", block.height(), block.hash()); } } // TODO: Check the certificates of the quorum. - Authority::Quorum(_certificates) => (), + Authority::Quorum(_certificates) => { + // // Ensure the block is signed by a validator in the committee. + // let signer = block.authority().to_address(); + // if !self.current_committee.read().contains(&signer) { + // bail!("Block {} ({}) is signed by an unauthorized account ({signer})", block.height(), block.hash()); + // } + } } /* Transactions */ diff --git a/ledger/src/check_transaction_basic.rs b/ledger/src/check_transaction_basic.rs index 505242a1ab..5baa3a1c01 100644 --- a/ledger/src/check_transaction_basic.rs +++ b/ledger/src/check_transaction_basic.rs @@ -31,6 +31,7 @@ impl> Ledger { } } + // TODO (howardwu): DEPRECATE THIS - Remove support for `mint` altogether. // Ensure the mint transaction is attributed to a validator in the committee. if transaction.is_mint() { // Retrieve the execution. @@ -42,7 +43,7 @@ impl> Ledger { // Retrieve the address that minted. let address = mint_address(transition)?; // Check if the address is in the current committee. - if !self.current_committee.read().contains(address) { + if *address != self.genesis_block.authority().to_address() { bail!("Mint transaction ({transaction_id}) is from an unauthorized account ({address})") } } diff --git a/ledger/src/get.rs b/ledger/src/get.rs index 6f78a2f667..5c307bd1c3 100644 --- a/ledger/src/get.rs +++ b/ledger/src/get.rs @@ -15,6 +15,16 @@ use super::*; impl> Ledger { + /// Returns the committee for the given `block height`. + pub fn get_committee(&self, block_height: u32) -> Result>> { + self.vm.committee_store().get_committee(block_height) + } + + /// Returns the committee for the given `round`. + pub fn get_committee_for_round(&self, round: u64) -> Result>> { + self.vm.committee_store().get_committee_for_round(round) + } + /// Returns the state root that contains the given `block height`. pub fn get_state_root(&self, block_height: u32) -> Result> { self.vm.block_store().get_state_root(block_height) @@ -41,7 +51,7 @@ impl> Ledger { pub fn get_block(&self, height: u32) -> Result> { // If the height is 0, return the genesis block. if height == 0 { - return Ok(self.genesis.clone()); + return Ok(self.genesis_block.clone()); } // Retrieve the block hash. let block_hash = match self.vm.block_store().get_block_hash(height)? { @@ -82,7 +92,7 @@ impl> Ledger { pub fn get_hash(&self, height: u32) -> Result { // If the height is 0, return the genesis block hash. if height == 0 { - return Ok(self.genesis.hash()); + return Ok(self.genesis_block.hash()); } match self.vm.block_store().get_block_hash(height)? { Some(block_hash) => Ok(block_hash), @@ -106,7 +116,7 @@ impl> Ledger { pub fn get_header(&self, height: u32) -> Result> { // If the height is 0, return the genesis block header. if height == 0 { - return Ok(*self.genesis.header()); + return Ok(*self.genesis_block.header()); } // Retrieve the block hash. let block_hash = match self.vm.block_store().get_block_hash(height)? { @@ -124,7 +134,7 @@ impl> Ledger { pub fn get_transactions(&self, height: u32) -> Result> { // If the height is 0, return the genesis block transactions. if height == 0 { - return Ok(self.genesis.transactions().clone()); + return Ok(self.genesis_block.transactions().clone()); } // Retrieve the block hash. let block_hash = match self.vm.block_store().get_block_hash(height)? { @@ -168,7 +178,7 @@ impl> Ledger { pub fn get_coinbase(&self, height: u32) -> Result>> { // If the height is 0, return the genesis block solutions. if height == 0 { - return Ok(self.genesis.coinbase().cloned()); + return Ok(self.genesis_block.coinbase().cloned()); } // Retrieve the block hash. let block_hash = match self.vm.block_store().get_block_hash(height)? { @@ -183,7 +193,7 @@ impl> Ledger { pub fn get_authority(&self, height: u32) -> Result> { // If the height is 0, return the genesis block authority. if height == 0 { - return Ok(self.genesis.authority().clone()); + return Ok(self.genesis_block.authority().clone()); } // Retrieve the block hash. let block_hash = match self.vm.block_store().get_block_hash(height)? { diff --git a/ledger/src/lib.rs b/ledger/src/lib.rs index 9d21b83a17..77dd4d78e1 100644 --- a/ledger/src/lib.rs +++ b/ledger/src/lib.rs @@ -21,6 +21,7 @@ extern crate tracing; pub use ledger_authority as authority; pub use ledger_block as block; pub use ledger_coinbase as coinbase; +pub use ledger_committee as committee; pub use ledger_narwhal as narwhal; pub use ledger_query as query; pub use ledger_store as store; @@ -61,6 +62,7 @@ use console::{ use ledger_authority::Authority; use ledger_block::{Block, ConfirmedTransaction, Header, Metadata, Ratify, Transaction, Transactions}; use ledger_coinbase::{CoinbasePuzzle, CoinbaseSolution, EpochChallenge, ProverSolution, PuzzleCommitment}; +use ledger_committee::Committee; use ledger_narwhal::{Subdag, Transmission, TransmissionID}; use ledger_query::Query; use ledger_store::{ConsensusStorage, ConsensusStore}; @@ -102,26 +104,24 @@ pub struct Ledger> { /// The VM state. vm: VM, /// The genesis block. - genesis: Block, + genesis_block: Block, /// The coinbase puzzle. coinbase_puzzle: CoinbasePuzzle, /// The current block. current_block: Arc>>, /// The current epoch challenge. current_epoch_challenge: Arc>>>, - /// The current committee. - current_committee: Arc>>>, } impl> Ledger { /// Loads the ledger from storage. - pub fn load(genesis: Block, dev: Option) -> Result { + pub fn load(genesis_block: Block, dev: Option) -> Result { let timer = timer!("Ledger::load"); // Retrieve the genesis hash. - let genesis_hash = genesis.hash(); + let genesis_hash = genesis_block.hash(); // Initialize the ledger. - let ledger = Self::load_unchecked(genesis, dev)?; + let ledger = Self::load_unchecked(genesis_block, dev)?; // Ensure the ledger contains the correct genesis block. if !ledger.contains_block_hash(&genesis_hash)? { @@ -147,7 +147,7 @@ impl> Ledger { } /// Loads the ledger from storage, without performing integrity checks. - pub fn load_unchecked(genesis: Block, dev: Option) -> Result { + pub fn load_unchecked(genesis_block: Block, dev: Option) -> Result { let timer = timer!("Ledger::load_unchecked"); // Initialize the consensus store. @@ -164,20 +164,16 @@ impl> Ledger { // Initialize the ledger. let mut ledger = Self { vm, - genesis: genesis.clone(), + genesis_block: genesis_block.clone(), coinbase_puzzle: CoinbasePuzzle::::load()?, - current_block: Arc::new(RwLock::new(genesis.clone())), + current_block: Arc::new(RwLock::new(genesis_block.clone())), current_epoch_challenge: Default::default(), - current_committee: Default::default(), }; - // Add the genesis validator to the committee. - ledger.current_committee.write().insert(genesis.authority().to_address()); - // If the block store is empty, initialize the genesis block. if ledger.vm.block_store().heights().max().is_none() { // Add the genesis block. - ledger.advance_to_next_block(&genesis)?; + ledger.advance_to_next_block(&genesis_block)?; } lap!(timer, "Initialize genesis"); @@ -199,11 +195,6 @@ impl> Ledger { Ok(ledger) } - /// TODO: Delete this after testing for snarkOS team. - pub fn insert_committee_member(&self, address: Address) { - self.current_committee.write().insert(address); - } - /// Returns the VM. pub const fn vm(&self) -> &VM { &self.vm @@ -215,8 +206,8 @@ impl> Ledger { } /// Returns the latest committee. - pub fn latest_committee(&self) -> IndexSet> { - self.current_committee.read().clone() + pub fn latest_committee(&self) -> Result> { + self.vm.committee_store().current_committee() } /// Returns the latest state root. diff --git a/synthesizer/src/vm/mod.rs b/synthesizer/src/vm/mod.rs index fc2dfc10c1..f0f5ea7217 100644 --- a/synthesizer/src/vm/mod.rs +++ b/synthesizer/src/vm/mod.rs @@ -34,6 +34,7 @@ use ledger_query::Query; use ledger_store::{ atomic_finalize, BlockStore, + CommitteeStore, ConsensusStorage, ConsensusStore, FinalizeMode, @@ -145,6 +146,12 @@ impl> VM { } impl> VM { + /// Returns the committee store. + #[inline] + pub fn committee_store(&self) -> &CommitteeStore { + self.store.committee_store() + } + /// Returns the finalize store. #[inline] pub fn finalize_store(&self) -> &FinalizeStore { From c7813e5bff715cef7ef34d4ffd2a31ac2f7ec537 Mon Sep 17 00:00:00 2001 From: Howard Wu <9260812+howardwu@users.noreply.github.com> Date: Mon, 31 Jul 2023 14:43:44 -0700 Subject: [PATCH 2/3] Clippy --- ledger/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ledger/src/lib.rs b/ledger/src/lib.rs index 77dd4d78e1..f84b74fd4a 100644 --- a/ledger/src/lib.rs +++ b/ledger/src/lib.rs @@ -74,7 +74,7 @@ use synthesizer::{ use aleo_std::prelude::{finish, lap, timer}; use anyhow::Result; use core::ops::Range; -use indexmap::{IndexMap, IndexSet}; +use indexmap::IndexMap; use parking_lot::RwLock; use rand::{prelude::IteratorRandom, rngs::OsRng}; use std::{borrow::Cow, sync::Arc}; From adb32046120676d7fd827395b5a9d98c8a0d989e Mon Sep 17 00:00:00 2001 From: Howard Wu <9260812+howardwu@users.noreply.github.com> Date: Mon, 31 Jul 2023 15:54:47 -0700 Subject: [PATCH 3/3] Minor reorder nit --- ledger/src/lib.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ledger/src/lib.rs b/ledger/src/lib.rs index f84b74fd4a..2a5635d051 100644 --- a/ledger/src/lib.rs +++ b/ledger/src/lib.rs @@ -107,10 +107,10 @@ pub struct Ledger> { genesis_block: Block, /// The coinbase puzzle. coinbase_puzzle: CoinbasePuzzle, - /// The current block. - current_block: Arc>>, /// The current epoch challenge. current_epoch_challenge: Arc>>>, + /// The current block. + current_block: Arc>>, } impl> Ledger { @@ -166,8 +166,8 @@ impl> Ledger { vm, genesis_block: genesis_block.clone(), coinbase_puzzle: CoinbasePuzzle::::load()?, - current_block: Arc::new(RwLock::new(genesis_block.clone())), current_epoch_challenge: Default::default(), + current_block: Arc::new(RwLock::new(genesis_block.clone())), }; // If the block store is empty, initialize the genesis block. @@ -215,6 +215,19 @@ impl> Ledger { self.vm.block_store().current_state_root() } + /// Returns the latest epoch number. + pub fn latest_epoch_number(&self) -> u32 { + self.current_block.read().height() / N::NUM_BLOCKS_PER_EPOCH + } + + /// Returns the latest epoch challenge. + pub fn latest_epoch_challenge(&self) -> Result> { + match self.current_epoch_challenge.read().as_ref() { + Some(challenge) => Ok(challenge.clone()), + None => self.get_epoch_challenge(self.latest_height()), + } + } + /// Returns the latest block. pub fn latest_block(&self) -> Block { self.current_block.read().clone() @@ -289,19 +302,6 @@ impl> Ledger { pub fn latest_transactions(&self) -> Transactions { self.current_block.read().transactions().clone() } - - /// Returns the latest epoch number. - pub fn latest_epoch_number(&self) -> u32 { - self.current_block.read().height() / N::NUM_BLOCKS_PER_EPOCH - } - - /// Returns the latest epoch challenge. - pub fn latest_epoch_challenge(&self) -> Result> { - match self.current_epoch_challenge.read().as_ref() { - Some(challenge) => Ok(challenge.clone()), - None => self.get_epoch_challenge(self.latest_height()), - } - } } impl> Ledger {