Skip to content

Commit

Permalink
[CLI] Make the number of validators configurable for sui genesis an…
Browse files Browse the repository at this point in the history
…d `sui start` (#20511)

## Description 

This PR enables `sui genesis` and `sui start` to pass the
`committee-size` argument specifying the number of validators that
should be started in the local network.

Note that if `sui start --committee-size 3` is executed with no `.sui`
or `genesis` data, on a subsequent run the `--committee-size` arg will
be ignored.

## Test plan 

Locally. Checked the number of generated config files for validators +
GraphQL query.

```
sui start --committee-size 3 --with-graphql

➜  sui_config ls -l
total 3104
-rw-r--r--  1 s    staff    5338 Dec  4 21:15 127.0.0.1-51144.yaml
-rw-r--r--  1 s    staff    5338 Dec  4 21:15 127.0.0.1-51158.yaml
-rw-r--r--  1 s    staff    5338 Dec  4 21:15 127.0.0.1-51172.yaml
drwxr-xr-x  5 s  staff     160 Dec  4 21:15 authorities_db/
---
```
```json
{
  "data": {
    "epoch": {
      "validatorSet": {
        "pendingActiveValidatorsSize": 0,
        "activeValidators": {
          "nodes": [
            {
              "address": {
                "address": "0xf6f511d0d450bfe2cc6cfabcc00024fcef2ede7a63b47eefcf0c086249fb4642"
              },
              "name": "validator-1",
              "description": ""
            },
            {
              "address": {
                "address": "0x478572ac85ffeba294d8cbbb87ae4c2b0c223a224ec34e9b75c45b5c210a9fe5"
              },
              "name": "validator-0",
              "description": ""
            },
            {
              "address": {
                "address": "0x7242e93071987c25454a64ae07f6640008d706647e2b9106ac61ac3d2e2d47af"
              },
              "name": "validator-2",
              "description": ""
            }
          ]
        },
        "totalStake": "0"
      }
    }
  }
}
```
## Release notes

Check each box that your changes affect. If none of the boxes relate to
your changes, release notes aren't required.

For each box you select, include information after the relevant heading
that describes the impact of your changes that a user might notice and
any actions they must take to implement updates.

- [ ] Protocol: 
- [ ] Nodes (Validators and Full nodes): 
- [ ] Indexer: 
- [ ] JSON-RPC: 
- [ ] GraphQL: 
- [x] CLI: Added the `--committee-size` argument to `sui start` and `sui
genesis` to configure the number of validators to start with the local
network / when generating a genesis.
- [ ] Rust SDK:
- [ ] REST API:
  • Loading branch information
stefan-mysten authored Dec 6, 2024
1 parent e0885ca commit 0d64196
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 12 deletions.
94 changes: 82 additions & 12 deletions crates/sui/src/sui_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ pub enum SuiCommand {
/// Start the network without a fullnode
#[clap(long = "no-full-node")]
no_full_node: bool,
/// Set the number of validators in the network. If a genesis was already generated with a
/// specific number of validators, this will not override it; the user should recreate the
/// genesis with the desired number of validators.
#[clap(long)]
committee_size: Option<usize>,
},
#[clap(name = "network")]
Network {
Expand Down Expand Up @@ -250,6 +255,9 @@ pub enum SuiCommand {
help = "Creates an extra faucet configuration for sui persisted runs."
)]
with_faucet: bool,
/// Set number of validators in the network.
#[clap(long)]
committee_size: Option<usize>,
},
GenesisCeremony(Ceremony),
/// Sui keystore tool.
Expand Down Expand Up @@ -378,6 +386,7 @@ impl SuiCommand {
data_ingestion_dir,
no_full_node,
epoch_duration_ms,
committee_size,
} => {
start(
config_dir.clone(),
Expand All @@ -388,6 +397,7 @@ impl SuiCommand {
fullnode_rpc_port,
data_ingestion_dir,
no_full_node,
committee_size,
)
.await?;

Expand All @@ -401,6 +411,7 @@ impl SuiCommand {
epoch_duration_ms,
benchmark_ips,
with_faucet,
committee_size,
} => {
genesis(
from_config,
Expand All @@ -410,6 +421,7 @@ impl SuiCommand {
epoch_duration_ms,
benchmark_ips,
with_faucet,
committee_size,
)
.await
}
Expand Down Expand Up @@ -612,6 +624,7 @@ async fn start(
fullnode_rpc_port: u16,
mut data_ingestion_dir: Option<PathBuf>,
no_full_node: bool,
committee_size: Option<usize>,
) -> Result<(), anyhow::Error> {
if force_regenesis {
ensure!(
Expand Down Expand Up @@ -656,8 +669,12 @@ async fn start(
// If this is set, then no data will be persisted between runs, and a new genesis will be
// generated each run.
let config_dir = if force_regenesis {
swarm_builder =
swarm_builder.committee_size(NonZeroUsize::new(DEFAULT_NUMBER_OF_AUTHORITIES).unwrap());
let committee_size = match committee_size {
Some(x) => NonZeroUsize::new(x),
None => NonZeroUsize::new(DEFAULT_NUMBER_OF_AUTHORITIES),
}
.ok_or_else(|| anyhow!("Committee size must be at least 1."))?;
swarm_builder = swarm_builder.committee_size(committee_size);
let genesis_config = GenesisConfig::custom_genesis(1, 100);
swarm_builder = swarm_builder.with_genesis_config(genesis_config);
let epoch_duration_ms = epoch_duration_ms.unwrap_or(DEFAULT_EPOCH_DURATION_MS);
Expand All @@ -674,30 +691,76 @@ async fn start(
.extension()
.is_some_and(|e| e == "yml" || e == "yaml") =>
{
if committee_size.is_some() {
eprintln!(
"{}",
"[warning] The committee-size arg wil be ignored as a network \
configuration already exists. To change the committee-size, you'll \
have to adjust the network configuration file or regenerate a genesis \
with the desired committee size. See `sui genesis --help` for more \
information."
.yellow()
.bold()
);
}
(config, sui_config_dir()?)
}

Some(config) => (config.join(SUI_NETWORK_CONFIG), config),
Some(config) => {
if committee_size.is_some() {
eprintln!(
"{}",
"[warning] The committee-size arg wil be ignored as a network \
configuration already exists. To change the committee-size, you'll \
have to adjust the network configuration file or regenerate a genesis \
with the desired committee size. See `sui genesis --help` for more \
information."
.yellow()
.bold()
);
}
(config.join(SUI_NETWORK_CONFIG), config)
}

None => {
let sui_config = sui_config_dir()?;
let network_config = sui_config.join(SUI_NETWORK_CONFIG);

if !network_config.exists() {
genesis(None, None, None, false, epoch_duration_ms, None, false)
.await
.map_err(|_| {
anyhow!(
"Cannot run genesis with non-empty Sui config directory: {}.\n\n\
genesis(
None,
None,
None,
false,
epoch_duration_ms,
None,
false,
committee_size,
)
.await
.map_err(|_| {
anyhow!(
"Cannot run genesis with non-empty Sui config directory: {}.\n\n\
If you are trying to run a local network without persisting the \
data (so a new genesis that is randomly generated and will not be \
saved once the network is shut down), use --force-regenesis flag.\n\
If you are trying to persist the network data and start from a new \
genesis, use sui genesis --help to see how to generate a new \
genesis.",
sui_config.display(),
)
})?;
sui_config.display(),
)
})?;
} else if committee_size.is_some() {
eprintln!(
"{}",
"[warning] The committee-size arg wil be ignored as a network \
configuration already exists. To change the committee-size, you'll \
have to adjust the network configuration file or regenerate a genesis \
with the desired committee size. See `sui genesis --help` for more \
information."
.yellow()
.bold()
);
}

(network_config, sui_config)
Expand Down Expand Up @@ -888,6 +951,7 @@ async fn genesis(
epoch_duration_ms: Option<u64>,
benchmark_ips: Option<Vec<String>>,
with_faucet: bool,
committee_size: Option<usize>,
) -> Result<(), anyhow::Error> {
let sui_config_dir = &match working_dir {
// if a directory is specified, it must exist (it
Expand Down Expand Up @@ -994,14 +1058,20 @@ async fn genesis(
if let Some(epoch_duration_ms) = epoch_duration_ms {
genesis_conf.parameters.epoch_duration_ms = epoch_duration_ms;
}
let committee_size = match committee_size {
Some(x) => NonZeroUsize::new(x),
None => NonZeroUsize::new(DEFAULT_NUMBER_OF_AUTHORITIES),
}
.ok_or_else(|| anyhow!("Committee size must be at least 1."))?;

let mut network_config = if let Some(validators) = validator_info {
builder
.with_genesis_config(genesis_conf)
.with_validators(validators)
.build()
} else {
builder
.committee_size(NonZeroUsize::new(DEFAULT_NUMBER_OF_AUTHORITIES).unwrap())
.committee_size(committee_size)
.with_genesis_config(genesis_conf)
.build()
};
Expand Down
3 changes: 3 additions & 0 deletions crates/sui/tests/cli_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ async fn test_genesis() -> Result<(), anyhow::Error> {
fullnode_rpc_port: 9000,
epoch_duration_ms: None,
no_full_node: false,
committee_size: None,
indexer_feature_args: IndexerArgs::for_testing(),
}
.execute()
Expand All @@ -90,6 +91,7 @@ async fn test_genesis() -> Result<(), anyhow::Error> {
epoch_duration_ms: None,
benchmark_ips: None,
with_faucet: false,
committee_size: None,
}
.execute()
.await?;
Expand Down Expand Up @@ -129,6 +131,7 @@ async fn test_genesis() -> Result<(), anyhow::Error> {
epoch_duration_ms: None,
benchmark_ips: None,
with_faucet: false,
committee_size: None,
}
.execute()
.await;
Expand Down

0 comments on commit 0d64196

Please sign in to comment.