Skip to content

Commit

Permalink
[cli] Added default Sui configuration directory (MystenLabs#1057)
Browse files Browse the repository at this point in the history
* [cli] Added default Sui configuration directory

* Fixed tests

* Addressed review comments

* Updated docs to reflect new location of the Sui config files

* Fixed a typo
  • Loading branch information
awelc authored Mar 25, 2022
1 parent 82862d5 commit 5b112c5
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 116 deletions.
69 changes: 29 additions & 40 deletions doc/src/build/wallet.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,10 @@ interface, *Wallet CLI*.

## Set up

1. Follow the instructions to [install Sui binaries](install.md).

1. Create a `sui_instance` subdirectory in your desired Sui-specific
directory. Assuming you followed recommended setup, run:
```shell
cd "$SUI_ROOT"
mkdir sui_instance
```
Follow the instructions to [install Sui binaries](install.md).

## Genesis

1. Navigate to that new directory:
```shell
cd "$SUI_ROOT"/sui_instance
```
1. Optionally, set `RUST_LOG=debug` for verbose logging.
1. Initiate `genesis`:
```shell
Expand All @@ -41,10 +30,21 @@ arbitrarily; the process of generating the genesis state can be
customized with additional accounts, objects, code, etc. as described
in [Genesis customization](#customize-genesis).

The network configuration is stored in `network.conf` and
can be used subsequently to start the network. The `wallet.conf` and `wallet.key` are
also created to be used by the Sui wallet to manage the
newly created accounts.
The network configuration is stored in `network.conf` and can be used
subsequently to start the network. The `wallet.conf` and `wallet.key`
are also created to be used by the Sui wallet to manage the newly
created accounts. By default, these files will be stored in the
`~/.sui/sui_config` directory, but you can override this location by
providing an alternative path:

```shell
sui genesis --working-dir /path/to/sui/config/files
```
### Recreating Genesis

To recreate Sui genesis state in the same location, which will remove
existing configuration files, use the `--force` option to the `sui
genesis` command.

## Wallet configuration
The genesis process creates a configuration file `wallet.conf`, and a keystore file `wallet.key` for the
Expand Down Expand Up @@ -123,15 +123,16 @@ implement more secure key management and support hardware signing in a future re
Run the following command to start the local Sui network:

```shell
cd "$SUI_ROOT"/sui_instance
sui start
```

You can also run this command in any directory if you provide a path
to the directory where Sui configuration files are stored:
This command will by default look for Sui network coinfiguration file
(`network.conf`) in the `~/.sui/sui_config` directory, but you can
override this setting by providing a path to the directory where this
file are stored:

```shell
sui start --config "$SUI_ROOT"/sui_instance
sui start --config /path/to/sui/network/config/file
```

Executing any of these two commands in a terminal window will result
Expand All @@ -140,15 +141,9 @@ instance (it will not return the command prompt).

NOTE: For logs, set `RUST_LOG=debug` before invoking `sui start`.

The network config file path defaults to `./network.conf` if not
specified.

If you see errors when trying to start Sui network, particularly if
you did not start with a fresh `"$SUI_ROOT"/sui_instance` (e.g, did
[custom wallet configuration](#wallet-configuration) or
started/restarted Sui instance multiple time), you should remove
`"$SUI_ROOT"/sui_instance` directory containing configuration files
and recreate [Sui genesis state](#genesis).
If you see errors when trying to start Sui network, particularly if you made some custom changes
(e.g,
[customized wallet configuration](#wallet-configuration)), you should [recreate Sui genesis state](#recreating-genesis).

## Using the wallet
The following commands are supported by the wallet:
Expand All @@ -174,20 +169,18 @@ The wallet can be started in two modes: interactive shell or command line interf
To start the interactive shell, execute the following (in a different terminal window than one used to execute `sui start`):

```shell
cd "$SUI_ROOT"/sui_instance
wallet
```

You can also run this command in any directory if you provide a path
to the directory where Sui configuration files are stored:
This command will by default look for wallet coinfiguration file
(`wallet.conf`) in the `~/.sui/sui_config` directory, but you can
override this setting by providing a path to the directory where this
file are stored:

```shell
wallet --config "$SUI_ROOT"/sui_instance
wallet --config /path/to/wallet/config/file
```

The wallet config file path defaults to `./wallet.conf` if not
specified.

The Sui interactive wallet supports the following shell functionality:
* Command History
The `history` command can be used to print the interactive shell's command history;
Expand All @@ -206,10 +199,6 @@ The wallet can also be used without the interactive shell, which can be useful i
you want to pipe the output of the wallet to another application or invoke wallet
commands using scripts.

**For the remainder of this tutorial we will assume that you are
executing the `wallet` command in a directory where the Sui
configuration files are stored (`"$SUI_ROOT"/sui_instance`).**

```shell
USAGE:
wallet --no-shell [SUBCOMMAND]
Expand Down
33 changes: 13 additions & 20 deletions doc/src/explore/tutorials.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,9 @@ the `wallet` command used in the remainder of this tutorial in your path.
Simply leave the terminal with Sui running and start a new terminal for the
remainder of this tutorial.

We will follow the same convention as the one described in the [Sui
setup instructions](../build/wallet.md#setup) and assume that Sui
configuration files generated during Sui genesis state creation are
stored in the `"$SUI_ROOT"/sui_instance` directory.

*IMPORTANT*: For the remainder of this tutorial, we will assume that you are
executing the `wallet` command in the `"$SUI_ROOT"/sui_instance` directory as well.
Adjust your paths accordingly.

## Gather accounts and gas objects

After completing the [Setup section](#setup) you should have a Sui instance running in a terminal window. Now switch to a new terminal window and keep the first terminal running.
Make sure that you run the `wallet` command in the directory
where wallet configuration is located or by passing wallet's
configuration file as a parameter, as described in the `wallet`
[command description](../build/wallet.md#using-the-wallet).
This will be the same directory where you ran `sui genesis`,
so return to $SUI_ROOT/sui_instance.

There take a look at the account addresses we own in our wallet:
Let us take a look at the account addresses we own in our wallet:
```
$ wallet --no-shell addresses
Showing 5 results.
Expand Down Expand Up @@ -93,9 +76,19 @@ export O_GAS=2110ADFB7BAF889A05EA6F5889AF7724299F9BED
```

## Publish the TicTacToe game on Sui
We implemented a TicTacToe game in [TicTacToe.move](https://github.com/MystenLabs/sui/tree/main/sui_programmability/examples/games/sources/TicTacToe.move). To publish the game, we run the publish command and specify the path to the game package. As described in the earlier [setup section](#setup), we assume that Sui repository was cloned locally - *let us further assume that it was cloned into `"$SUI_ROOT"/sui` directory* **Adjust the `--path` to match your own environment if you used different paths**.
We implemented a TicTacToe game in [TicTacToe.move](https://github.com/MystenLabs/sui/tree/main/sui_programmability/examples/games/sources/TicTacToe.move).

In order to obtain source code for the game, let us clone the Sui
repository to the current directory:

```shell
git clone https://github.com/MystenLabs/sui.git
```

To publish the game, we run the publish command and specify the path to the source code of the game package:

```
$ wallet --no-shell publish --path "$SUI_ROOT"/sui/sui_programmability/examples/games --gas $ADMIN_GAS --gas-budget 30000
$ wallet --no-shell publish --path ./sui/sui_programmability/examples/games --gas $ADMIN_GAS --gas-budget 30000
----- Certificate ----
Signed Authorities : ...
Transaction Kind : Publish
Expand Down
1 change: 1 addition & 0 deletions sui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ tracing-subscriber = { version = "0.3.9", features = ["time", "registry", "env-f
tracing-bunyan-formatter = "0.3"
serde-value = "0.7.0"
log = "0.4.14"
dirs = "4.0.0"

bcs = "0.1.3"
sui_core = { path = "../sui_core" }
Expand Down
103 changes: 78 additions & 25 deletions sui/src/sui_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
// SPDX-License-Identifier: Apache-2.0

use std::collections::BTreeMap;
use std::fs;
use std::path::PathBuf;
use std::sync::Arc;

use anyhow::anyhow;
use anyhow::{anyhow, bail};
use futures::future::join_all;
use move_binary_format::CompiledModule;
use move_package::BuildConfig;
Expand All @@ -29,53 +30,105 @@ use crate::config::{
use crate::gateway::{EmbeddedGatewayConfig, GatewayType};
use crate::keystore::{Keystore, KeystoreType, SuiKeystore};

const SUI_DIR: &str = ".sui";
const SUI_CONFIG_DIR: &str = "sui_config";
pub const SUI_NETWORK_CONFIG: &str = "network.conf";
pub const SUI_WALLET_CONFIG: &str = "wallet.conf";

#[derive(StructOpt)]
#[structopt(rename_all = "kebab-case")]
pub enum SuiCommand {
/// Start sui network.
#[structopt(name = "start")]
Start {
#[structopt(long, default_value = "./network.conf")]
config: PathBuf,
#[structopt(long)]
config: Option<PathBuf>,
},
#[structopt(name = "genesis")]
Genesis {
#[structopt(long, default_value = ".")]
working_dir: PathBuf,
#[structopt(long)]
config: Option<PathBuf>,
working_dir: Option<PathBuf>,
#[structopt(short, long, help = "Forces overwriting existing configuration")]
force: bool,
},
}

pub fn sui_config_dir() -> Result<PathBuf, anyhow::Error> {
match dirs::home_dir() {
Some(v) => Ok(v.join(SUI_DIR).join(SUI_CONFIG_DIR)),
None => bail!("Cannot obtain home directory path"),
}
}

impl SuiCommand {
pub async fn execute(&self) -> Result<(), anyhow::Error> {
match self {
SuiCommand::Start { config } => {
let config: NetworkConfig = PersistedConfig::read(config)?;
let config_path = config
.clone()
.unwrap_or(sui_config_dir()?.join(SUI_NETWORK_CONFIG));
let config: NetworkConfig = PersistedConfig::read(&config_path).map_err(|err| {
err.context(format!(
"Cannot open Sui network config file at {:?}",
config_path
))
})?;
SuiNetwork::start(&config)
.await?
.wait_for_completion()
.await
}
SuiCommand::Genesis {
working_dir,
config: path,
} => {
let network_path = working_dir.join("network.conf");
let wallet_path = working_dir.join("wallet.conf");
let keystore_path = working_dir.join("wallet.key");
let db_folder_path = working_dir.join("client_db");

if let Ok(config) = PersistedConfig::<NetworkConfig>::read(&network_path) {
if !config.authorities.is_empty() {
return Err(anyhow!("Cannot run genesis on a existing network, please delete network config file and try again."));
SuiCommand::Genesis { working_dir, force } => {
let sui_config_dir = &match working_dir {
// if a directory is specified, it must exist (it
// will not be created)
Some(v) => v.clone(),
// create default Sui config dir if not specified
// on the command line and if it does not exist
// yet
None => {
let config_path = sui_config_dir()?;
fs::create_dir_all(&config_path)?;
config_path
}
}
let genesis_conf = if let Some(path) = path {
PersistedConfig::read(path)?
} else {
GenesisConfig::default_genesis(working_dir)?
};

// if Sui config dir is not empty then either clean it
// up (if --force/-f option was specified or report an
// error
if sui_config_dir
.read_dir()
.map_err(|err| {
anyhow!(err)
.context(format!("Cannot open Sui config dir {:?}", sui_config_dir))
})?
.next()
.is_some()
{
if *force {
fs::remove_dir_all(sui_config_dir).map_err(|err| {
anyhow!(err).context(format!(
"Cannot remove Sui config dir {:?}",
sui_config_dir
))
})?;
fs::create_dir(sui_config_dir).map_err(|err| {
anyhow!(err).context(format!(
"Cannot create Sui config dir {:?}",
sui_config_dir
))
})?;
} else {
bail!("Cannot run genesis with non-empty Sui config directory {}, please use --force/-f option to remove existing configuration", sui_config_dir.to_str().unwrap());
}
}

let network_path = sui_config_dir.join(SUI_NETWORK_CONFIG);
let wallet_path = sui_config_dir.join(SUI_WALLET_CONFIG);
let keystore_path = sui_config_dir.join("wallet.key");
let db_folder_path = sui_config_dir.join("client_db");

let genesis_conf = GenesisConfig::default_genesis(sui_config_dir)?;
let (network_config, accounts, keystore) = genesis(genesis_conf).await?;
info!("Network genesis completed.");
let network_config = network_config.persisted(&network_path);
Expand Down Expand Up @@ -245,7 +298,7 @@ pub async fn genesis(
let package_id = generate_package_id(&mut modules, &mut genesis_ctx)?;

info!("Loaded package [{}] from {:?}.", package_id, path);
// Writing package id to network.conf for user to retrieve later.
// Writing package id to network config for user to retrieve later.
network_config.loaded_move_packages.push((path, package_id));
preload_modules.push(modules)
}
Expand Down
Loading

0 comments on commit 5b112c5

Please sign in to comment.