Skip to content

Commit

Permalink
[fastx CLI] Add customisation to genesis (#461)
Browse files Browse the repository at this point in the history
* * genesis customisation with config files
* ability to preload move module

* fixup after rebase
  • Loading branch information
patrickkuo authored Feb 18, 2022
1 parent 4a2385f commit bfde55c
Show file tree
Hide file tree
Showing 9 changed files with 603 additions and 114 deletions.
55 changes: 53 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,60 @@ This will create `sui` and `wallet` binaries in `target/release` directory.
./sui genesis
```

The genesis command creates 4 authorities, 5 user accounts each with 5 gas objects.
The genesis command creates 4 authorities, 5 user accounts each with 5 gas objects.
The network configuration are stored in `network.conf` and can be used subsequently to start the network.
A `wallet.conf` will also be generated to be used by the `wallet` binary to manage the newly created accounts.
A `wallet.conf` will also be generated to be used by the `wallet` binary to manage the newly created accounts.

### 2.1 Genesis customization

The genesis process can be customised by providing a genesis config file.

```shell
./sui genesis --config genesis.conf
```
Example `genesis.conf`
```json
{
"authorities": [
{
"key_pair": "xWhgxF5fagohi2V9jzUToxnhJbTwbtV2qX4dbMGXR7lORTBuDBe+ppFDnnHz8L/BcYHWO76EuQzUYe5pnpLsFQ==",
"host": "127.0.0.1",
"port": 10000,
"db_path": "./authorities_db/4e45306e0c17bea691439e71f3f0bfc17181d63bbe84b90cd461ee699e92ec15",
"stake": 1
}
],
"accounts": [
{
"address": "bd654f352c895d9ec14c491d3f2b4e1f98fb07323383bebe9f95ab625bff2fa0",
"gas_objects": [
{
"object_id": "5c68ac7ba66ef69fdea0651a21b531a37bf342b7",
"gas_value": 1000
}
]
}
],
"move_packages": ["<Paths to custom move packages>"],
"sui_framework_lib_path": "<Paths to sui framework lib>",
"move_framework_lib_path": "<Paths to move framework lib>"
}
```
All attributes in genesis.conf are optional, default value will be use if the attributes are not provided.
For example, the config shown below will create a network of 4 authorities, and pre-populate 2 gas objects for 4 accounts.
```json
{
"authorities": [
{},{},{},{}
],
"accounts": [
{ "gas_objects":[{},{}] },
{ "gas_objects":[{},{}] },
{ "gas_objects":[{},{}] },
{ "gas_objects":[{},{}] }
]
}
```

### 3. Starting the network

Expand Down
2 changes: 2 additions & 0 deletions sui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ move-package = { git = "https://github.com/diem/move", rev = "7683d09732dd930c58
move-core-types = { git = "https://github.com/diem/move", rev = "7683d09732dd930c581583bf5fde97fb7ac02ff7", features = ["address20"] }
move-bytecode-verifier = { git = "https://github.com/diem/move", rev = "7683d09732dd930c581583bf5fde97fb7ac02ff7" }

once_cell = "1.9.0"

[dev-dependencies]
tracing-test = "0.2.1"

Expand Down
186 changes: 182 additions & 4 deletions sui/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,29 @@
// SPDX-License-Identifier: Apache-2.0

use sui_types::base_types::*;
use sui_types::crypto::KeyPair;
use sui_types::crypto::{get_key_pair, KeyPair};

use crate::utils::Config;
use crate::utils::optional_address_as_hex;
use crate::utils::optional_address_from_hex;
use crate::utils::{Config, PortAllocator, DEFAULT_STARTING_PORT};
use anyhow::anyhow;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::fmt::{Display, Formatter};
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use std::time::Duration;
use sui_framework::DEFAULT_FRAMEWORK_PATH;
use sui_network::transport;

const DEFAULT_WEIGHT: usize = 1;
const DEFAULT_GAS_AMOUNT: u64 = 100000;
pub const AUTHORITIES_DB_NAME: &str = "authorities_db";

static PORT_ALLOCATOR: Lazy<Mutex<PortAllocator>> =
Lazy::new(|| Mutex::new(PortAllocator::new(DEFAULT_STARTING_PORT)));

#[derive(Serialize, Deserialize)]
pub struct AccountInfo {
#[serde(serialize_with = "bytes_as_hex", deserialize_with = "bytes_from_hex")]
Expand All @@ -26,12 +40,64 @@ pub struct AuthorityInfo {
pub base_port: u16,
}

#[derive(Serialize, Deserialize)]
#[derive(Serialize)]
pub struct AuthorityPrivateInfo {
pub key_pair: KeyPair,
pub host: String,
pub port: u16,
pub db_path: PathBuf,
pub stake: usize,
}

// Custom deserializer with optional default fields
impl<'de> Deserialize<'de> for AuthorityPrivateInfo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::de::Deserializer<'de>,
{
let (_, new_key_pair) = get_key_pair();

let json = Value::deserialize(deserializer)?;
let key_pair = if let Some(val) = json.get("key_pair") {
KeyPair::deserialize(val).map_err(serde::de::Error::custom)?
} else {
new_key_pair
};
let host = if let Some(val) = json.get("host") {
String::deserialize(val).map_err(serde::de::Error::custom)?
} else {
"127.0.0.1".to_string()
};
let port = if let Some(val) = json.get("port") {
u16::deserialize(val).map_err(serde::de::Error::custom)?
} else {
PORT_ALLOCATOR
.lock()
.map_err(serde::de::Error::custom)?
.next_port()
.ok_or_else(|| serde::de::Error::custom("No available port."))?
};
let db_path = if let Some(val) = json.get("db_path") {
PathBuf::deserialize(val).map_err(serde::de::Error::custom)?
} else {
PathBuf::from(".")
.join(AUTHORITIES_DB_NAME)
.join(encode_bytes_hex(key_pair.public_key_bytes()))
};
let stake = if let Some(val) = json.get("stake") {
usize::deserialize(val).map_err(serde::de::Error::custom)?
} else {
DEFAULT_WEIGHT
};

Ok(AuthorityPrivateInfo {
key_pair,
host,
port,
db_path,
stake,
})
}
}

#[derive(Serialize, Deserialize)]
Expand Down Expand Up @@ -85,15 +151,17 @@ impl Display for WalletConfig {
pub struct NetworkConfig {
pub authorities: Vec<AuthorityPrivateInfo>,
pub buffer_size: usize,
pub loaded_move_packages: Vec<(PathBuf, ObjectID)>,
#[serde(skip)]
config_path: PathBuf,
}

impl Config for NetworkConfig {
fn create(path: &Path) -> Result<Self, anyhow::Error> {
Ok(Self {
authorities: Vec::new(),
authorities: vec![],
buffer_size: transport::DEFAULT_MAX_DATAGRAM_SIZE.to_string().parse()?,
loaded_move_packages: vec![],
config_path: path.to_path_buf(),
})
}
Expand All @@ -106,3 +174,113 @@ impl Config for NetworkConfig {
&self.config_path
}
}

#[derive(Serialize, Deserialize, Default)]
#[serde(default)]
pub struct GenesisConfig {
pub authorities: Vec<AuthorityPrivateInfo>,
pub accounts: Vec<AccountConfig>,
pub move_packages: Vec<PathBuf>,
#[serde(default = "default_sui_framework_lib")]
pub sui_framework_lib_path: PathBuf,
#[serde(default = "default_move_framework_lib")]
pub move_framework_lib_path: PathBuf,
#[serde(skip)]
config_path: PathBuf,
}

#[derive(Serialize, Deserialize, Default)]
#[serde(default)]
pub struct AccountConfig {
#[serde(
skip_serializing_if = "Option::is_none",
serialize_with = "optional_address_as_hex",
deserialize_with = "optional_address_from_hex"
)]
pub address: Option<SuiAddress>,
pub gas_objects: Vec<ObjectConfig>,
}

#[derive(Serialize, Deserialize)]
pub struct ObjectConfig {
#[serde(default = "ObjectID::random")]
pub object_id: ObjectID,
#[serde(default = "default_gas_value")]
pub gas_value: u64,
}

fn default_gas_value() -> u64 {
DEFAULT_GAS_AMOUNT
}

fn default_sui_framework_lib() -> PathBuf {
PathBuf::from(DEFAULT_FRAMEWORK_PATH)
}

fn default_move_framework_lib() -> PathBuf {
PathBuf::from(DEFAULT_FRAMEWORK_PATH)
.join("deps")
.join("move-stdlib")
}

const DEFAULT_NUMBER_OF_AUTHORITIES: usize = 4;
const DEFAULT_NUMBER_OF_ACCOUNT: usize = 5;
const DEFAULT_NUMBER_OF_OBJECT_PER_ACCOUNT: usize = 5;

impl GenesisConfig {
pub fn default_genesis(path: &Path) -> Result<Self, anyhow::Error> {
let working_dir = path.parent().ok_or(anyhow!("Cannot resolve file path."))?;
let mut authorities = Vec::new();
for _ in 0..DEFAULT_NUMBER_OF_AUTHORITIES {
// Get default authority config from deserialization logic.
let mut authority = AuthorityPrivateInfo::deserialize(Value::String(String::new()))?;
authority.db_path = working_dir
.join(AUTHORITIES_DB_NAME)
.join(encode_bytes_hex(&authority.key_pair.public_key_bytes()));
authorities.push(authority)
}
let mut accounts = Vec::new();
for _ in 0..DEFAULT_NUMBER_OF_ACCOUNT {
let mut objects = Vec::new();
for _ in 0..DEFAULT_NUMBER_OF_OBJECT_PER_ACCOUNT {
objects.push(ObjectConfig {
object_id: ObjectID::random(),
gas_value: DEFAULT_GAS_AMOUNT,
})
}
accounts.push(AccountConfig {
address: None,
gas_objects: objects,
})
}
Ok(Self {
authorities,
accounts,
move_packages: vec![],
sui_framework_lib_path: default_sui_framework_lib(),
move_framework_lib_path: default_move_framework_lib(),
config_path: path.to_path_buf(),
})
}
}

impl Config for GenesisConfig {
fn create(path: &Path) -> Result<Self, anyhow::Error> {
Ok(Self {
authorities: vec![],
accounts: vec![],
config_path: path.to_path_buf(),
move_packages: vec![],
sui_framework_lib_path: default_sui_framework_lib(),
move_framework_lib_path: default_move_framework_lib(),
})
}

fn set_config_path(&mut self, path: &Path) {
self.config_path = path.to_path_buf()
}

fn config_path(&self) -> &Path {
&self.config_path
}
}
Loading

1 comment on commit bfde55c

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bench results

�[0m�[0m�[1m�[32m Finished�[0m release [optimized + debuginfo] target(s) in 1.15s
�[0m�[0m�[1m�[32m Running�[0m target/release/bench
�[2m2022-02-18T23:24:54.737854Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Starting benchmark: OrdersAndCerts
�[2m2022-02-18T23:24:54.737878Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Preparing accounts.
�[2m2022-02-18T23:24:54.738461Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Open database on path: "/tmp/DB_21C20BC287E51389E6AEB2889FE2DF6CBF52F5AC"
�[2m2022-02-18T23:24:59.631690Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Preparing transactions.
�[2m2022-02-18T23:25:08.879575Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m Listening to TCP traffic on 127.0.0.1:9555
�[2m2022-02-18T23:25:09.881097Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Number of TCP connections: 2
�[2m2022-02-18T23:25:09.881127Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Set max_in_flight to 500
�[2m2022-02-18T23:25:09.881130Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Sending requests.
�[2m2022-02-18T23:25:09.886115Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m Sending TCP requests to 127.0.0.1:9555
�[2m2022-02-18T23:25:09.889971Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m Sending TCP requests to 127.0.0.1:9555
�[2m2022-02-18T23:25:10.793130Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 5000 packets
�[2m2022-02-18T23:25:11.582877Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 35000
�[2m2022-02-18T23:25:11.619750Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 35000
�[2m2022-02-18T23:25:11.694962Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 10000 packets
�[2m2022-02-18T23:25:12.597087Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 15000 packets
�[2m2022-02-18T23:25:13.428072Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 30000
�[2m2022-02-18T23:25:13.435272Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 30000
�[2m2022-02-18T23:25:13.504180Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 20000 packets
�[2m2022-02-18T23:25:14.403692Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 25000 packets
�[2m2022-02-18T23:25:15.176164Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 25000
�[2m2022-02-18T23:25:15.272650Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 25000
�[2m2022-02-18T23:25:15.302476Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 30000 packets
�[2m2022-02-18T23:25:16.201323Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 35000 packets
�[2m2022-02-18T23:25:17.014230Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 20000
�[2m2022-02-18T23:25:17.032513Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 20000
�[2m2022-02-18T23:25:17.109212Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 40000 packets
�[2m2022-02-18T23:25:18.013051Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 45000 packets
�[2m2022-02-18T23:25:18.840380Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 15000
�[2m2022-02-18T23:25:18.868775Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 15000
�[2m2022-02-18T23:25:18.917620Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 50000 packets
�[2m2022-02-18T23:25:19.824117Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 55000 packets
�[2m2022-02-18T23:25:20.651714Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 10000
�[2m2022-02-18T23:25:20.657483Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 10000
�[2m2022-02-18T23:25:20.748244Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 60000 packets
�[2m2022-02-18T23:25:21.656022Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 65000 packets
�[2m2022-02-18T23:25:22.475500Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 5000
�[2m2022-02-18T23:25:22.501573Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m In flight 500 Remaining 5000
�[2m2022-02-18T23:25:22.562989Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 70000 packets
�[2m2022-02-18T23:25:23.466708Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 75000 packets
�[2m2022-02-18T23:25:24.391291Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m Done sending TCP requests to 127.0.0.1:9555
�[2m2022-02-18T23:25:24.395065Z�[0m �[32m INFO�[0m �[2msui_core::authority_server�[0m�[2m:�[0m 127.0.0.1:9555 has processed 80000 packets
�[2m2022-02-18T23:25:24.442174Z�[0m �[32m INFO�[0m �[2msui_network::network�[0m�[2m:�[0m Done sending TCP requests to 127.0.0.1:9555
�[2m2022-02-18T23:25:24.442421Z�[0m �[32m INFO�[0m �[2mbench�[0m�[2m:�[0m Received 80000 responses.
�[2m2022-02-18T23:25:24.641669Z�[0m �[33m WARN�[0m �[2mbench�[0m�[2m:�[0m Completed benchmark for OrdersAndCerts
Total time: 14561280us, items: 40000, tx/sec: 2747.0112517580874

Please sign in to comment.