diff --git a/Cargo.lock b/Cargo.lock index 3ff25b806d3a6..c97678f68f678 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5404,8 +5404,6 @@ dependencies = [ "bytes", "clap 3.1.18", "colored", - "config 0.1.0", - "crypto", "dirs", "ed25519-dalek", "futures", @@ -5692,6 +5690,7 @@ dependencies = [ "bincode", "bytes", "clap 3.1.18", + "crypto", "ed25519-dalek", "executor", "fdlimit", @@ -5706,6 +5705,7 @@ dependencies = [ "move-vm-types", "multiaddr", "mysten-network 0.1.0 (git+https://github.com/MystenLabs/mysten-infra?rev=7c247967e5a5abd59ecaa75bc62b05bcdf4503fe)", + "node", "once_cell", "parking_lot 0.12.0", "pretty_assertions", diff --git a/sui/Cargo.toml b/sui/Cargo.toml index bbd3c09fecd0f..6eb33568f2b4a 100644 --- a/sui/Cargo.toml +++ b/sui/Cargo.toml @@ -61,8 +61,6 @@ move-bytecode-utils = { git = "https://github.com/move-language/move", rev = "1b move-unit-test = { git = "https://github.com/move-language/move", rev = "1b2d3b4274345f5b4b6a1a1bde5aee452003ab5b" } narwhal-node = { git = "https://github.com/MystenLabs/narwhal", rev = "23745f48103656eae4a4205d0b3edd53ad8894de", package = "node" } -narwhal-config = { git = "https://github.com/MystenLabs/narwhal", rev = "23745f48103656eae4a4205d0b3edd53ad8894de", package = "config" } -narwhal-crypto = { git = "https://github.com/MystenLabs/narwhal", rev = "23745f48103656eae4a4205d0b3edd53ad8894de", package = "crypto" } once_cell = "1.10.0" diff --git a/sui/src/sui_commands.rs b/sui/src/sui_commands.rs index 3924f12faa88b..d30acae89cf64 100644 --- a/sui/src/sui_commands.rs +++ b/sui/src/sui_commands.rs @@ -10,25 +10,16 @@ use crate::{ use anyhow::{anyhow, bail}; use base64ct::{Base64, Encoding}; use clap::*; -use futures::future::join_all; use std::fs; +use std::num::NonZeroUsize; use std::path::PathBuf; -use std::sync::Arc; -use std::time::Duration; -use std::{collections::BTreeMap, num::NonZeroUsize}; +use sui_config::GenesisConfig; use sui_config::{builder::ConfigBuilder, NetworkConfig}; -use sui_config::{GenesisConfig, ValidatorConfig}; -use sui_core::authority::{AuthorityState, AuthorityStore}; -use sui_core::authority_active::ActiveAuthority; -use sui_core::authority_client::NetworkAuthorityClient; -use sui_core::authority_server::AuthorityServer; -use sui_core::authority_server::AuthorityServerHandle; -use sui_core::consensus_adapter::ConsensusListener; use sui_types::base_types::decode_bytes_hex; use sui_types::base_types::SuiAddress; -use sui_types::error::SuiResult; -use tokio::sync::mpsc::channel; -use tracing::{error, info}; +use tracing::info; + +pub use sui_core::make::{make_authority, make_server, make_server_with_genesis, SuiNetwork}; #[derive(Parser)] #[clap(rename_all = "kebab-case")] @@ -273,170 +264,3 @@ impl SuiCommand { } } } - -pub struct SuiNetwork { - pub spawned_authorities: Vec, -} - -impl SuiNetwork { - pub async fn start(config: &NetworkConfig) -> Result { - if config.validator_configs().is_empty() { - return Err(anyhow!( - "No authority configured for the network, please run genesis." - )); - } - - info!( - "Starting network with {} authorities", - config.validator_configs().len() - ); - - let mut spawned_authorities = Vec::new(); - for validator in config.validator_configs() { - let server = make_server_with_genesis(validator).await?; - spawned_authorities.push(server.spawn().await?); - } - info!("Started {} authorities", spawned_authorities.len()); - - Ok(Self { - spawned_authorities, - }) - } - - pub async fn kill(self) -> Result<(), anyhow::Error> { - for spawned_server in self.spawned_authorities { - spawned_server.kill().await?; - } - Ok(()) - } - - pub async fn wait_for_completion(self) -> Result<(), anyhow::Error> { - let mut handles = Vec::new(); - for spawned_server in self.spawned_authorities { - handles.push(async move { - if let Err(err) = spawned_server.join().await { - error!("Server ended with an error: {err}"); - } - }); - } - join_all(handles).await; - info!("All servers stopped."); - Ok(()) - } -} - -pub async fn make_server(validator_config: &ValidatorConfig) -> SuiResult { - let store = Arc::new(AuthorityStore::open(validator_config.db_path(), None)); - let name = validator_config.public_key(); - let state = AuthorityState::new_without_genesis( - validator_config.committee_config().committee(), - name, - Arc::pin(validator_config.key_pair().copy()), - store, - ) - .await; - - make_authority(validator_config, state).await -} - -pub async fn make_server_with_genesis( - validator_config: &ValidatorConfig, -) -> SuiResult { - let store = Arc::new(AuthorityStore::open(validator_config.db_path(), None)); - let name = validator_config.public_key(); - let state = AuthorityState::new_with_genesis( - validator_config.committee_config().committee(), - name, - Arc::pin(validator_config.key_pair().copy()), - store, - validator_config.genesis(), - ) - .await; - - make_authority(validator_config, state).await -} - -/// Spawn all the subsystems run by a Sui authority: a consensus node, a sui authority server, -/// and a consensus listener bridging the consensus node and the sui authority. -pub async fn make_authority( - validator_config: &ValidatorConfig, - state: AuthorityState, -) -> SuiResult { - let (tx_consensus_to_sui, rx_consensus_to_sui) = channel(1_000); - let (tx_sui_to_consensus, rx_sui_to_consensus) = channel(1_000); - - let authority_state = Arc::new(state); - - // Spawn the consensus node of this authority. - let consensus_keypair = validator_config.key_pair().make_narwhal_keypair(); - let consensus_name = consensus_keypair.name.clone(); - let consensus_store = - narwhal_node::NodeStorage::reopen(validator_config.consensus_config().db_path()); - narwhal_node::Node::spawn_primary( - consensus_keypair, - validator_config - .committee_config() - .narwhal_committee() - .to_owned(), - &consensus_store, - validator_config - .consensus_config() - .narwhal_config() - .to_owned(), - /* consensus */ true, // Indicate that we want to run consensus. - /* execution_state */ authority_state.clone(), - /* tx_confirmation */ tx_consensus_to_sui, - ) - .await?; - narwhal_node::Node::spawn_workers( - consensus_name, - /* ids */ vec![0], // We run a single worker with id '0'. - validator_config - .committee_config() - .narwhal_committee() - .to_owned(), - &consensus_store, - validator_config - .consensus_config() - .narwhal_config() - .to_owned(), - ); - - // Spawn a consensus listener. It listen for consensus outputs and notifies the - // authority server when a sequenced transaction is ready for execution. - ConsensusListener::spawn( - rx_sui_to_consensus, - rx_consensus_to_sui, - /* max_pending_transactions */ 1_000_000, - ); - - // If we have network information make authority clients - // to all authorities in the system. - let _active_authority: Option<()> = { - let mut authority_clients = BTreeMap::new(); - let mut config = mysten_network::config::Config::new(); - config.connect_timeout = Some(Duration::from_secs(5)); - config.request_timeout = Some(Duration::from_secs(5)); - for validator in validator_config.committee_config().validator_set() { - let channel = config.connect_lazy(validator.network_address()).unwrap(); - let client = NetworkAuthorityClient::new(channel); - authority_clients.insert(validator.public_key(), client); - } - - let _active_authority = ActiveAuthority::new(authority_state.clone(), authority_clients)?; - - // TODO: turn on to start the active part of validators - // - // let join_handle = active_authority.spawn_all_active_processes().await; - // Some(join_handle) - None - }; - - // Return new authority server. It listen to users transactions and send back replies. - Ok(AuthorityServer::new( - validator_config.network_address().to_owned(), - authority_state, - validator_config.consensus_config().address().to_owned(), - /* tx_consensus_listener */ tx_sui_to_consensus, - )) -} diff --git a/sui_core/Cargo.toml b/sui_core/Cargo.toml index 198fe369a7347..87484e694b17f 100644 --- a/sui_core/Cargo.toml +++ b/sui_core/Cargo.toml @@ -54,6 +54,8 @@ typed-store = { git = "https://github.com/MystenLabs/mysten-infra", rev = "7c247 narwhal-executor = { git = "https://github.com/MystenLabs/narwhal", rev = "23745f48103656eae4a4205d0b3edd53ad8894de", package = "executor" } narwhal-types = { git = "https://github.com/MystenLabs/narwhal", rev = "23745f48103656eae4a4205d0b3edd53ad8894de", package = "types" } +narwhal-node = { git = "https://github.com/MystenLabs/narwhal", rev = "23745f48103656eae4a4205d0b3edd53ad8894de", package = "node" } +narwhal-crypto = { git = "https://github.com/MystenLabs/narwhal", rev = "23745f48103656eae4a4205d0b3edd53ad8894de", package = "crypto" } [dev-dependencies] serde-reflection = "0.3.5" diff --git a/sui_core/src/lib.rs b/sui_core/src/lib.rs index ea7f1fc75d9d9..20372f674424e 100644 --- a/sui_core/src/lib.rs +++ b/sui_core/src/lib.rs @@ -11,6 +11,7 @@ pub mod consensus_adapter; pub mod execution_engine; pub mod gateway_state; pub mod gateway_types; +pub mod make; pub mod safe_client; pub mod sui_json; pub mod transaction_input_checker; diff --git a/sui_core/src/make.rs b/sui_core/src/make.rs new file mode 100644 index 0000000000000..f349f101d8307 --- /dev/null +++ b/sui_core/src/make.rs @@ -0,0 +1,185 @@ +// Copyright (c) 2022, Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use crate::authority::{AuthorityState, AuthorityStore}; +use crate::authority_active::ActiveAuthority; +use crate::authority_client::NetworkAuthorityClient; +use crate::authority_server::AuthorityServer; +use crate::authority_server::AuthorityServerHandle; +use crate::consensus_adapter::ConsensusListener; +use anyhow::{anyhow, Result}; +use futures::future::join_all; +use std::collections::BTreeMap; +use std::sync::Arc; +use std::time::Duration; +use sui_config::NetworkConfig; +use sui_config::ValidatorConfig; +use tokio::sync::mpsc::channel; +use tracing::{error, info}; + +pub struct SuiNetwork { + pub spawned_authorities: Vec, +} + +impl SuiNetwork { + pub async fn start(config: &NetworkConfig) -> Result { + if config.validator_configs().is_empty() { + return Err(anyhow!( + "No authority configured for the network, please run genesis." + )); + } + + info!( + "Starting network with {} authorities", + config.validator_configs().len() + ); + + let mut spawned_authorities = Vec::new(); + for validator in config.validator_configs() { + let server = make_server_with_genesis(validator).await?; + spawned_authorities.push(server.spawn().await?); + } + info!("Started {} authorities", spawned_authorities.len()); + + Ok(Self { + spawned_authorities, + }) + } + + pub async fn kill(self) -> Result<(), anyhow::Error> { + for spawned_server in self.spawned_authorities { + spawned_server.kill().await?; + } + Ok(()) + } + + pub async fn wait_for_completion(self) -> Result<(), anyhow::Error> { + let mut handles = Vec::new(); + for spawned_server in self.spawned_authorities { + handles.push(async move { + if let Err(err) = spawned_server.join().await { + error!("Server ended with an error: {err}"); + } + }); + } + join_all(handles).await; + info!("All servers stopped."); + Ok(()) + } +} + +pub async fn make_server(validator_config: &ValidatorConfig) -> Result { + let store = Arc::new(AuthorityStore::open(validator_config.db_path(), None)); + let name = validator_config.public_key(); + let state = AuthorityState::new_without_genesis( + validator_config.committee_config().committee(), + name, + Arc::pin(validator_config.key_pair().copy()), + store, + ) + .await; + + make_authority(validator_config, state).await +} + +pub async fn make_server_with_genesis( + validator_config: &ValidatorConfig, +) -> Result { + let store = Arc::new(AuthorityStore::open(validator_config.db_path(), None)); + let name = validator_config.public_key(); + let state = AuthorityState::new_with_genesis( + validator_config.committee_config().committee(), + name, + Arc::pin(validator_config.key_pair().copy()), + store, + validator_config.genesis(), + ) + .await; + + make_authority(validator_config, state).await +} + +/// Spawn all the subsystems run by a Sui authority: a consensus node, a sui authority server, +/// and a consensus listener bridging the consensus node and the sui authority. +pub async fn make_authority( + validator_config: &ValidatorConfig, + state: AuthorityState, +) -> Result { + let (tx_consensus_to_sui, rx_consensus_to_sui) = channel(1_000); + let (tx_sui_to_consensus, rx_sui_to_consensus) = channel(1_000); + + let authority_state = Arc::new(state); + + // Spawn the consensus node of this authority. + let consensus_keypair = validator_config.key_pair().make_narwhal_keypair(); + let consensus_name = consensus_keypair.name.clone(); + let consensus_store = + narwhal_node::NodeStorage::reopen(validator_config.consensus_config().db_path()); + narwhal_node::Node::spawn_primary( + consensus_keypair, + validator_config + .committee_config() + .narwhal_committee() + .to_owned(), + &consensus_store, + validator_config + .consensus_config() + .narwhal_config() + .to_owned(), + /* consensus */ true, // Indicate that we want to run consensus. + /* execution_state */ authority_state.clone(), + /* tx_confirmation */ tx_consensus_to_sui, + ) + .await?; + narwhal_node::Node::spawn_workers( + consensus_name, + /* ids */ vec![0], // We run a single worker with id '0'. + validator_config + .committee_config() + .narwhal_committee() + .to_owned(), + &consensus_store, + validator_config + .consensus_config() + .narwhal_config() + .to_owned(), + ); + + // Spawn a consensus listener. It listen for consensus outputs and notifies the + // authority server when a sequenced transaction is ready for execution. + ConsensusListener::spawn( + rx_sui_to_consensus, + rx_consensus_to_sui, + /* max_pending_transactions */ 1_000_000, + ); + + // If we have network information make authority clients + // to all authorities in the system. + let _active_authority: Option<()> = { + let mut authority_clients = BTreeMap::new(); + let mut config = mysten_network::config::Config::new(); + config.connect_timeout = Some(Duration::from_secs(5)); + config.request_timeout = Some(Duration::from_secs(5)); + for validator in validator_config.committee_config().validator_set() { + let channel = config.connect_lazy(validator.network_address()).unwrap(); + let client = NetworkAuthorityClient::new(channel); + authority_clients.insert(validator.public_key(), client); + } + + let _active_authority = ActiveAuthority::new(authority_state.clone(), authority_clients)?; + + // TODO: turn on to start the active part of validators + // + // let join_handle = active_authority.spawn_all_active_processes().await; + // Some(join_handle) + None + }; + + // Return new authority server. It listen to users transactions and send back replies. + Ok(AuthorityServer::new( + validator_config.network_address().to_owned(), + authority_state, + validator_config.consensus_config().address().to_owned(), + /* tx_consensus_listener */ tx_sui_to_consensus, + )) +}