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

fix: update simple_node #2787

Merged
merged 8 commits into from Mar 22, 2024
Merged
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
102 changes: 94 additions & 8 deletions node/bft/examples/simple_node.rs
Expand Up @@ -22,16 +22,21 @@ use snarkos_node_bft::{
BFT,
MEMORY_POOL_PORT,
};
use snarkos_node_bft_ledger_service::MockLedgerService;
use snarkos_node_bft_ledger_service::TranslucentLedgerService;
use snarkos_node_bft_storage_service::BFTMemoryService;
use snarkvm::{
console::{account::PrivateKey, algorithms::BHP256, types::Address},
ledger::{
block::Transaction,
committee::{Committee, MIN_VALIDATOR_STAKE},
narwhal::{BatchHeader, Data},
puzzle::{Solution, SolutionID},
store::{helpers::memory::ConsensusMemory, ConsensusStore},
Block,
Ledger,
},
prelude::{Field, Network, Uniform},
prelude::{Field, Hash, Network, Uniform, VM},
utilities::{to_bytes_le, FromBytes, TestRng, ToBits, ToBytes},
};

use ::bytes::Bytes;
Expand All @@ -46,8 +51,14 @@ use axum::{
use axum_extra::response::ErasedJson;
use clap::{Parser, ValueEnum};
use indexmap::IndexMap;
use rand::{Rng, SeedableRng};
use std::{collections::HashMap, net::SocketAddr, path::PathBuf, str::FromStr, sync::Arc};
use rand::{CryptoRng, Rng, SeedableRng};
use std::{
collections::HashMap,
net::SocketAddr,
path::PathBuf,
str::FromStr,
sync::{atomic::AtomicBool, Arc, Mutex, OnceLock},
};
use tokio::{net::TcpListener, sync::oneshot};
use tracing_subscriber::{
layer::{Layer, SubscriberExt},
Expand Down Expand Up @@ -108,8 +119,8 @@ pub async fn start_bft(
let (sender, receiver) = init_primary_channels();
// Initialize the components.
let (committee, account) = initialize_components(node_id, num_nodes)?;
// Initialize the mock ledger service.
let ledger = Arc::new(MockLedgerService::new(committee));
// Initialize the translucent ledger service.
let ledger = create_ledger(&account, num_nodes, committee, node_id);
// Initialize the storage.
let storage = Storage::new(
ledger.clone(),
Expand Down Expand Up @@ -149,8 +160,8 @@ pub async fn start_primary(
let (sender, receiver) = init_primary_channels();
// Initialize the components.
let (committee, account) = initialize_components(node_id, num_nodes)?;
// Initialize the mock ledger service.
let ledger = Arc::new(MockLedgerService::new(committee));
// Initialize the translucent ledger service.
let ledger = create_ledger(&account, num_nodes, committee, node_id);
// Initialize the storage.
let storage = Storage::new(
ledger.clone(),
Expand All @@ -174,6 +185,81 @@ pub async fn start_primary(
Ok((primary, sender))
}

/// Initialize the translucent ledger service.
fn create_ledger(
account: &Account<CurrentNetwork>,
num_nodes: u16,
committee: Committee<snarkvm::prelude::MainnetV0>,
node_id: u16,
) -> Arc<TranslucentLedgerService<snarkvm::prelude::MainnetV0, ConsensusMemory<snarkvm::prelude::MainnetV0>>> {
let gen_key = account.private_key();
let public_balance_per_validator =
(CurrentNetwork::STARTING_SUPPLY - (num_nodes as u64) * MIN_VALIDATOR_STAKE) / (num_nodes as u64);
let mut balances = IndexMap::<Address<CurrentNetwork>, u64>::new();
for address in committee.members().keys() {
balances.insert(*address, public_balance_per_validator);
}
let mut rng = TestRng::default();
let gen_ledger = genesis_ledger(*gen_key, committee.clone(), balances.clone(), node_id, &mut rng);
Arc::new(TranslucentLedgerService::new(gen_ledger, Arc::new(AtomicBool::new(false))))
}

pub type CurrentLedger = Ledger<CurrentNetwork, ConsensusMemory<CurrentNetwork>>;

fn genesis_cache() -> &'static Mutex<HashMap<Vec<u8>, Block<CurrentNetwork>>> {
static CACHE: OnceLock<Mutex<HashMap<Vec<u8>, Block<CurrentNetwork>>>> = OnceLock::new();
CACHE.get_or_init(|| Mutex::new(HashMap::new()))
}

fn genesis_block(
genesis_private_key: PrivateKey<CurrentNetwork>,
committee: Committee<CurrentNetwork>,
public_balances: IndexMap<Address<CurrentNetwork>, u64>,
rng: &mut (impl Rng + CryptoRng),
) -> Block<CurrentNetwork> {
// Initialize the store.
let store = ConsensusStore::<_, ConsensusMemory<_>>::open(None).unwrap();
// Initialize a new VM.
let vm = VM::from(store).unwrap();
// Initialize the genesis block.
let bonded_balances: IndexMap<_, _> =
committee.members().iter().map(|(address, (amount, _))| (*address, (*address, *address, *amount))).collect();
vm.genesis_quorum(&genesis_private_key, committee, public_balances, bonded_balances, rng).unwrap()
}

fn genesis_ledger(
genesis_private_key: PrivateKey<CurrentNetwork>,
committee: Committee<CurrentNetwork>,
public_balances: IndexMap<Address<CurrentNetwork>, u64>,
node_id: u16,
rng: &mut (impl Rng + CryptoRng),
) -> CurrentLedger {
let cache_key =
to_bytes_le![genesis_private_key, committee, public_balances.iter().collect::<Vec<(_, _)>>()].unwrap();
// Initialize the genesis block on the first call; other callers
// will wait for it on the mutex.
let block = genesis_cache()
.lock()
.unwrap()
.entry(cache_key.clone())
.or_insert_with(|| {
let hasher = BHP256::<CurrentNetwork>::setup("aleo.dev.block").unwrap();
let file_name = hasher.hash(&cache_key.to_bits_le()).unwrap().to_string() + ".genesis";
let file_path = std::env::temp_dir().join(file_name);
if file_path.exists() {
let buffer = std::fs::read(file_path).unwrap();
return Block::from_bytes_le(&buffer).unwrap();
}

let block = genesis_block(genesis_private_key, committee, public_balances, rng);
std::fs::write(&file_path, block.to_bytes_le().unwrap()).unwrap();
block
})
.clone();
// Initialize the ledger with the genesis block.
CurrentLedger::load(block, aleo_std::StorageMode::Development(node_id)).unwrap()
}

/// Initializes the components of the node.
fn initialize_components(node_id: u16, num_nodes: u16) -> Result<(Committee<CurrentNetwork>, Account<CurrentNetwork>)> {
// Ensure that the node ID is valid.
Expand Down