Skip to content

Commit

Permalink
SuiNode/Authority state are now aware of what protocol versions they …
Browse files Browse the repository at this point in the history
…support. (MystenLabs#8378)

Also, some basic testing infrastructure, and a simple panic test for
when the validator encounters an unsupported protocol.
  • Loading branch information
mystenmark authored Feb 17, 2023
1 parent a6387e8 commit 024711e
Show file tree
Hide file tree
Showing 17 changed files with 175 additions and 23 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions crates/sui-config/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::{
num::NonZeroUsize,
path::{Path, PathBuf},
};
use sui_protocol_config::SupportedProtocolVersions;
use sui_types::committee::ProtocolVersion;
use sui_types::crypto::{
generate_proof_of_possession, get_key_pair_from_rng, AccountKeyPair, AuthorityKeyPair,
Expand Down Expand Up @@ -116,6 +117,11 @@ impl<R> ConfigBuilder<R> {
self
}

pub fn with_protocol_version(mut self, protocol_version: ProtocolVersion) -> Self {
self.protocol_version = protocol_version;
self
}

pub fn rng<N: rand::RngCore + rand::CryptoRng>(self, rng: N) -> ConfigBuilder<N> {
ConfigBuilder {
rng: Some(rng),
Expand Down Expand Up @@ -277,14 +283,16 @@ impl<R: rand::RngCore + rand::CryptoRng> ConfigBuilder<R> {
})
.collect::<Vec<_>>();

let initial_accounts_config = self
let mut initial_accounts_config = self
.initial_accounts_config
.unwrap_or_else(GenesisConfig::for_local_testing);

initial_accounts_config.parameters.protocol_version = self.protocol_version;

let (account_keys, objects) = initial_accounts_config.generate_accounts(&mut rng).unwrap();

let genesis = {
let mut builder = genesis::Builder::new()
.with_protocol_version(self.protocol_version)
.with_parameters(initial_accounts_config.parameters)
.add_objects(objects)
.add_objects(self.additional_objects);
Expand Down Expand Up @@ -381,6 +389,7 @@ impl<R: rand::RngCore + rand::CryptoRng> ConfigBuilder<R> {
end_of_epoch_broadcast_channel_capacity:
default_end_of_epoch_broadcast_channel_capacity(),
checkpoint_executor_config: Default::default(),
supported_protocol_versions: Some(SupportedProtocolVersions::SYSTEM_DEFAULT),
}
})
.collect();
Expand Down
7 changes: 7 additions & 0 deletions crates/sui-config/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::usize;
use sui_keys::keypair_file::{read_authority_keypair_from_file, read_keypair_from_file};
use sui_protocol_config::SupportedProtocolVersions;
use sui_types::base_types::SuiAddress;
use sui_types::committee::StakeUnit;
use sui_types::crypto::AuthorityPublicKeyBytes;
Expand Down Expand Up @@ -89,6 +90,12 @@ pub struct NodeConfig {

#[serde(default)]
pub checkpoint_executor_config: CheckpointExecutorConfig,

/// In a `sui-node` binary, this is set to SupportedProtocolVersions::SYSTEM_DEFAULT
/// in sui-node/src/main.rs. It is present in the config so that it can be changed by tests in
/// order to test protocol upgrades.
#[serde(skip)]
pub supported_protocol_versions: Option<SupportedProtocolVersions>,
}

fn default_authority_store_pruning_config() -> AuthorityStorePruningConfig {
Expand Down
2 changes: 2 additions & 0 deletions crates/sui-config/src/swarm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use serde_with::serde_as;
use std::net::{IpAddr, SocketAddr};
use std::num::NonZeroUsize;
use std::path::{Path, PathBuf};
use sui_protocol_config::SupportedProtocolVersions;
use sui_types::committee::Committee;
use sui_types::crypto::{
get_key_pair_from_rng, AccountKeyPair, AuthorityKeyPair, NetworkKeyPair, SuiKeyPair,
Expand Down Expand Up @@ -239,6 +240,7 @@ impl<'a> FullnodeConfigBuilder<'a> {
end_of_epoch_broadcast_channel_capacity:
default_end_of_epoch_broadcast_channel_capacity(),
checkpoint_executor_config: Default::default(),
supported_protocol_versions: Some(SupportedProtocolVersions::SYSTEM_DEFAULT),
})
}
}
2 changes: 2 additions & 0 deletions crates/sui-config/tests/snapshot_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use sui_types::crypto::{
};

#[test]
#[cfg_attr(msim, ignore)]
fn genesis_config_snapshot_matches() {
// Test creating fake SuiAddress from PublicKeyBytes.
let keypair: AuthorityKeyPair = get_key_pair_from_rng(&mut StdRng::from_seed([0; 32])).1;
Expand All @@ -51,6 +52,7 @@ fn genesis_config_snapshot_matches() {
}

#[test]
#[cfg_attr(msim, ignore)]
fn populated_genesis_snapshot_matches() {
let genesis_config = GenesisConfig::for_local_testing();
let (_account_keys, objects) = genesis_config
Expand Down
25 changes: 24 additions & 1 deletion crates/sui-core/src/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ use sui_json_rpc_types::{
SuiTransactionEffects,
};
use sui_macros::nondeterministic;
use sui_protocol_config::SupportedProtocolVersions;
use sui_storage::indexes::{ObjectIndexChanges, MAX_GET_OWNED_OBJECT_SIZE};
use sui_storage::write_ahead_log::WriteAheadLog;
use sui_storage::{
Expand Down Expand Up @@ -1435,12 +1436,26 @@ impl AuthorityState {
})
}

fn check_protocol_version(
supported_protocol_versions: SupportedProtocolVersions,
current_version: ProtocolVersion,
) {
info!("current protocol version is now {:?}", current_version);
info!("supported versions are: {:?}", supported_protocol_versions);
if !supported_protocol_versions.is_version_supported(current_version) {
panic!(
"Unsupported protocol version. The network is at {:?}, but this SuiNode only supports: {:?}",
current_version, supported_protocol_versions,
);
}
}
// TODO: This function takes both committee and genesis as parameter.
// Technically genesis already contains committee information. Could consider merging them.
#[allow(clippy::disallowed_methods)] // allow unbounded_channel()
pub async fn new(
name: AuthorityName,
secret: StableSyncAuthoritySigner,
supported_protocol_versions: SupportedProtocolVersions,
store: Arc<AuthorityStore>,
epoch_store: Arc<AuthorityPerEpochStore>,
committee_store: Arc<CommitteeStore>,
Expand All @@ -1451,6 +1466,11 @@ impl AuthorityState {
pruning_config: &AuthorityStorePruningConfig,
genesis_objects: &[Object],
) -> Arc<Self> {
Self::check_protocol_version(
supported_protocol_versions,
epoch_store.committee().protocol_version,
);

let native_functions =
sui_framework::natives::all_natives(MOVE_STDLIB_ADDRESS, SUI_FRAMEWORK_ADDRESS);
let move_vm = Arc::new(
Expand Down Expand Up @@ -1572,10 +1592,10 @@ impl AuthorityState {
let checkpoint_store = CheckpointStore::new(&path.join("checkpoints"));
let index_store = Some(Arc::new(IndexStore::new(path.join("indexes"))));

// add the object_basics module
let state = AuthorityState::new(
secret.public().into(),
secret.clone(),
SupportedProtocolVersions::SYSTEM_DEFAULT,
store,
epoch_store,
epochs,
Expand Down Expand Up @@ -1691,9 +1711,12 @@ impl AuthorityState {
pub async fn reconfigure(
&self,
cur_epoch_store: &AuthorityPerEpochStore,
supported_protocol_versions: SupportedProtocolVersions,
new_committee: Committee,
sui_system_state: SuiSystemState,
) -> SuiResult<Arc<AuthorityPerEpochStore>> {
Self::check_protocol_version(supported_protocol_versions, new_committee.protocol_version);

self.committee_store.insert_new_committee(&new_committee)?;
let db = self.db();
let mut execution_lock = db.execution_lock_for_reconfiguration().await;
Expand Down
2 changes: 2 additions & 0 deletions crates/sui-core/src/checkpoints/checkpoint_executor/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use tempfile::tempdir;
use std::{sync::Arc, time::Duration};

use broadcast::{Receiver, Sender};
use sui_protocol_config::SupportedProtocolVersions;
use sui_types::committee::ProtocolVersion;
use sui_types::messages_checkpoint::VerifiedCheckpoint;
use tokio::{sync::broadcast, time::timeout};
Expand Down Expand Up @@ -178,6 +179,7 @@ pub async fn test_checkpoint_executor_cross_epoch() {
let new_epoch_store = authority_state
.reconfigure(
&authority_state.epoch_store_for_testing(),
SupportedProtocolVersions::SYSTEM_DEFAULT,
second_committee.committee().clone(),
sui_system_state,
)
Expand Down
3 changes: 2 additions & 1 deletion crates/sui-core/src/unit_tests/authority_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ use sui_types::{SUI_CLOCK_OBJECT_ID, SUI_CLOCK_OBJECT_SHARED_VERSION, SUI_FRAMEW
use crate::epoch::epoch_metrics::EpochMetrics;
use std::{convert::TryInto, env};
use sui_macros::sim_test;
use sui_protocol_config::ProtocolConfig;
use sui_protocol_config::{ProtocolConfig, SupportedProtocolVersions};
use sui_types::dynamic_field::DynamicFieldType;
use sui_types::object::Data;
use sui_types::{
Expand Down Expand Up @@ -2660,6 +2660,7 @@ async fn test_authority_persist() {
AuthorityState::new(
name,
secrete,
SupportedProtocolVersions::SYSTEM_DEFAULT,
store,
epoch_store,
committee_store,
Expand Down
27 changes: 21 additions & 6 deletions crates/sui-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use sui_network::api::ValidatorServer;
use sui_network::discovery;
use sui_network::{state_sync, DEFAULT_CONNECT_TIMEOUT_SEC, DEFAULT_HTTP2_KEEPALIVE_SEC};

use sui_protocol_config::ProtocolConfig;
use sui_protocol_config::{ProtocolConfig, SupportedProtocolVersions};

use sui_storage::{
event_store::{EventStoreType, SqlEventStore},
Expand Down Expand Up @@ -122,6 +122,15 @@ impl SuiNode {
config: &NodeConfig,
registry_service: RegistryService,
) -> Result<Arc<SuiNode>> {
let mut config = config.clone();
if config.supported_protocol_versions.is_none() {
info!(
"populating config.supported_protocol_versions with default {:?}",
SupportedProtocolVersions::SYSTEM_DEFAULT
);
config.supported_protocol_versions = Some(SupportedProtocolVersions::SYSTEM_DEFAULT);
}

// TODO: maybe have a config enum that takes care of this for us.
let is_validator = config.consensus_config().is_some();
let is_full_node = !is_validator;
Expand Down Expand Up @@ -211,11 +220,12 @@ impl SuiNode {
};

let (p2p_network, discovery_handle, state_sync_handle) =
Self::create_p2p_network(config, state_sync_store, &prometheus_registry)?;
Self::create_p2p_network(&config, state_sync_store, &prometheus_registry)?;

let state = AuthorityState::new(
config.protocol_public_key(),
secret,
config.supported_protocol_versions.unwrap(),
store,
epoch_store.clone(),
committee_store.clone(),
Expand Down Expand Up @@ -266,14 +276,14 @@ impl SuiNode {
let json_rpc_service = build_server(
state.clone(),
&transaction_orchestrator.clone(),
config,
&config,
&prometheus_registry,
)
.await?;

let validator_components = if state.is_validator(&epoch_store) {
let components = Self::construct_validator_components(
config,
&config,
state.clone(),
epoch_store.clone(),
checkpoint_store.clone(),
Expand All @@ -289,7 +299,7 @@ impl SuiNode {
};

let node = Self {
config: config.clone(),
config,
validator_components: Mutex::new(validator_components),
_json_rpc_service: json_rpc_service,
state,
Expand Down Expand Up @@ -854,7 +864,12 @@ impl SuiNode {
let next_epoch = next_epoch_committee.epoch();
let new_epoch_store = self
.state
.reconfigure(cur_epoch_store, next_epoch_committee, sui_system_state)
.reconfigure(
cur_epoch_store,
self.config.supported_protocol_versions.unwrap(),
next_epoch_committee,
sui_system_state,
)
.await
.expect("Reconfigure authority state cannot fail");
info!(next_epoch, "Validator State has been reconfigured");
Expand Down
13 changes: 11 additions & 2 deletions crates/sui-node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::path::PathBuf;
use std::time::Duration;
use sui_config::{Config, NodeConfig};
use sui_node::metrics;
use sui_protocol_config::ProtocolConfig;
use sui_protocol_config::{ProtocolConfig, SupportedProtocolVersions};
use sui_telemetry::send_telemetry_event;
use tokio::task;
use tokio::time::sleep;
Expand Down Expand Up @@ -45,11 +45,16 @@ struct Args {

#[tokio::main]
async fn main() -> Result<()> {
// Ensure that a validator never calls get_for_min_version.
// Ensure that a validator never calls get_for_min_version/get_for_max_version.
ProtocolConfig::poison_get_for_min_version();

let args = Args::parse();
let mut config = NodeConfig::load(&args.config_path)?;
assert!(
config.supported_protocol_versions.is_none(),
"supported_protocol_versions cannot be read from the config file"
);
config.supported_protocol_versions = Some(SupportedProtocolVersions::SYSTEM_DEFAULT);

let registry_service = metrics::start_prometheus_server(config.metrics_address);
let prometheus_registry = registry_service.default_registry();
Expand All @@ -64,6 +69,10 @@ async fn main() -> Result<()> {
.init();

info!("Sui Node version: {VERSION}");
info!(
"Supported protocol versions: {:?}",
config.supported_protocol_versions
);

info!(
"Started Prometheus HTTP endpoint at {}",
Expand Down
2 changes: 1 addition & 1 deletion crates/sui-proc-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ syn = "1.0.104"
workspace-hack = { version = "0.1", path = "../workspace-hack" }

[target.'cfg(msim)'.dependencies]
msim-macros = { git = "https://github.com/MystenLabs/mysten-sim.git", rev = "95269e60b8570411e0b09ffbd8ac95a506259bdb", package = "msim-macros" }
msim-macros = { git = "https://github.com/MystenLabs/mysten-sim.git", rev = "d9f001161fb8c8362c8644013bb7dc1572bbeb45", package = "msim-macros" }
Loading

0 comments on commit 024711e

Please sign in to comment.