Skip to content

Commit

Permalink
genesis: enable generating validator keys
Browse files Browse the repository at this point in the history
  • Loading branch information
bmwill committed Jul 21, 2022
1 parent a652fa3 commit 7516b53
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 23 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/sui-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ serde_with = "1.14.0"
signature = "1.5.0"
static_assertions = "1.1.0"
opentelemetry = { version = "0.17.0", features = ["rt-tokio"] }
base64ct = { version = "1.5.1", features = ["alloc"] }
base64ct = { version = "1.5.1", features = ["std", "alloc"] }
zeroize = "1.5.4"
hkdf = "0.12.3"
digest = "0.10.3"
Expand Down
4 changes: 2 additions & 2 deletions crates/sui-types/src/base_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ pub fn get_new_address() -> SuiAddress {
crate::crypto::get_key_pair().0
}

pub fn bytes_as_hex<B, S>(bytes: &B, serializer: S) -> Result<S::Ok, S::Error>
pub fn bytes_as_hex<B, S>(bytes: B, serializer: S) -> Result<S::Ok, S::Error>
where
B: AsRef<[u8]>,
S: serde::ser::Serializer,
Expand All @@ -503,7 +503,7 @@ where
Ok(value)
}

pub fn encode_bytes_hex<B: AsRef<[u8]>>(bytes: &B) -> String {
pub fn encode_bytes_hex<B: AsRef<[u8]>>(bytes: B) -> String {
hex::encode(bytes.as_ref())
}

Expand Down
2 changes: 2 additions & 0 deletions crates/sui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ serde = { version = "1.0.139", features = ["derive"] }
serde_json = "1.0.80"
signature = "1.5.0"
camino = "1.0.9"
ed25519-dalek = "1"
base64ct = "1"
tokio = { version = "1.20.0", features = ["full"] }
async-trait = "0.1.53"
serde_with = { version = "1.14.0", features = ["hex"] }
Expand Down
8 changes: 5 additions & 3 deletions crates/sui/genesis.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ Each validator participating in the ceremony will need the following:
- Narwhal_worker_to_worker network address // WAN
- Narwhal_consensus_address network address // LAN

Note: Network addresses should be Multiaddrs in the form of `/dns/{dns name}/tcp/{port}/http` and
Note:
- Network addresses should be Multiaddrs in the form of `/dns/{dns name}/tcp/{port}/http` and
only the addresses marked WAN need to be publicly accessible by the wider internet.
- An Ed25519 key can be created using `sui keytool generate`

## Ceremony

Expand Down Expand Up @@ -43,7 +45,7 @@ Once the shared workspace has been initialized, each validator can contribute th
$ git clone <url to genesis repo> && cd genesis
$ sui genesis-ceremony add-validator \
--name <human-readable validator name> \
--public-key <hex encoded ed25519 public key> \
--key-file <path to key file> \
--network-address <multiaddr> \
--narwhal-primary-to-primary <multiaddr> \
--narwhal-worker-to-primary <multiaddr> \
Expand Down Expand Up @@ -87,7 +89,7 @@ Once genesis is built each validator will need to verify and sign genesis:

```
$ git genesis-ceremony verify-and-sign \
--keypair <hex encoded ed25519 keypair>
--key-file <path to key file>
$ git add .
$ git commit -m "sign genesis"
$ git push
Expand Down
38 changes: 28 additions & 10 deletions crates/sui/src/genesis_ceremony.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ use sui_config::{
};
use sui_types::{
base_types::{encode_bytes_hex, ObjectID, SuiAddress},
crypto::KeyPair,
crypto::{KeypairTraits, PublicKeyBytes, Signature, ToFromBytes},
object::Object,
};

use crate::keytool::read_keypair_from_file;

const GENESIS_BUILDER_SIGNATURE_DIR: &str = "signatures";

#[derive(Parser)]
Expand All @@ -40,26 +41,38 @@ pub enum CeremonyCommand {
Init,

AddValidator {
#[clap(long)]
name: String,
public_key: PublicKeyBytes,
#[clap(long)]
key_file: PathBuf,
#[clap(long)]
network_address: Multiaddr,
#[clap(long)]
narwhal_primary_to_primary: Multiaddr,
#[clap(long)]
narwhal_worker_to_primary: Multiaddr,
#[clap(long)]
narwhal_primary_to_worker: Multiaddr,
#[clap(long)]
narwhal_worker_to_worker: Multiaddr,
#[clap(long)]
narwhal_consensus_address: Multiaddr,
},

AddGasObject {
#[clap(long)]
address: SuiAddress,
#[clap(long)]
object_id: Option<ObjectID>,
#[clap(long)]
value: u64,
},

Build,

VerifyAndSign {
keypair: KeyPair,
#[clap(long)]
key_file: PathBuf,
},

Finalize,
Expand All @@ -81,7 +94,7 @@ pub fn run(cmd: Ceremony) -> Result<()> {

CeremonyCommand::AddValidator {
name,
public_key,
key_file,
network_address,
narwhal_primary_to_primary,
narwhal_worker_to_primary,
Expand All @@ -90,9 +103,10 @@ pub fn run(cmd: Ceremony) -> Result<()> {
narwhal_consensus_address,
} => {
let mut builder = Builder::load(&dir)?;
let keypair = read_keypair_from_file(key_file)?;
builder = builder.add_validator(sui_config::ValidatorInfo {
name,
public_key,
public_key: keypair.public().into(),
stake: 1,
delegation: 0,
network_address,
Expand Down Expand Up @@ -127,7 +141,8 @@ pub fn run(cmd: Ceremony) -> Result<()> {
genesis.save(dir.join(SUI_GENESIS_FILENAME))?;
}

CeremonyCommand::VerifyAndSign { keypair } => {
CeremonyCommand::VerifyAndSign { key_file } => {
let keypair = read_keypair_from_file(key_file)?;
let loaded_genesis = Genesis::load(dir.join(SUI_GENESIS_FILENAME))?;
let loaded_genesis_bytes = loaded_genesis.to_bytes();

Expand Down Expand Up @@ -210,6 +225,7 @@ pub fn run(cmd: Ceremony) -> Result<()> {
#[cfg(test)]
mod test {
use super::*;
use crate::keytool::write_keypair_to_file;
use anyhow::Result;
use sui_config::{utils, ValidatorInfo};
use sui_types::crypto::get_key_pair_from_rng;
Expand All @@ -233,7 +249,9 @@ mod test {
narwhal_worker_to_worker: utils::new_network_address(),
narwhal_consensus_address: utils::new_network_address(),
};
(keypair, info)
let key_file = dir.path().join(format!("{}.key", info.name));
write_keypair_to_file(&keypair, &key_file).unwrap();
(key_file, info)
})
.collect::<Vec<_>>();

Expand All @@ -245,12 +263,12 @@ mod test {
command.run()?;

// Add the validators
for (_key, validator) in &validators {
for (key_file, validator) in &validators {
let command = Ceremony {
path: Some(dir.path().into()),
command: CeremonyCommand::AddValidator {
name: validator.name().to_owned(),
public_key: validator.public_key(),
key_file: key_file.into(),
network_address: validator.network_address().to_owned(),
narwhal_primary_to_primary: validator.narwhal_primary_to_primary.clone(),
narwhal_worker_to_primary: validator.narwhal_worker_to_primary.clone(),
Expand All @@ -274,7 +292,7 @@ mod test {
let command = Ceremony {
path: Some(dir.path().into()),
command: CeremonyCommand::VerifyAndSign {
keypair: key.copy(),
key_file: key.into(),
},
};
command.run()?;
Expand Down
46 changes: 41 additions & 5 deletions crates/sui/src/keytool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
use anyhow::anyhow;
use clap::*;
use std::fs;
use std::path::Path;
use std::path::{Path, PathBuf};
use sui_sdk::crypto::{Keystore, SuiKeystore};
use sui_types::base_types::decode_bytes_hex;
use sui_types::base_types::{decode_bytes_hex, encode_bytes_hex};
use sui_types::crypto::KeypairTraits;
use sui_types::sui_serde::{Base64, Encoding};
use sui_types::{
Expand All @@ -21,8 +21,13 @@ use tracing::info;
pub enum KeyToolCommand {
/// Generate a new keypair
Generate,
Show {
file: PathBuf,
},
/// Extract components
Unpack { keypair: KeyPair },
Unpack {
keypair: KeyPair,
},
/// List all keys in the keystore
List,
/// Create signature using the sui keystore and provided data.
Expand All @@ -38,9 +43,19 @@ impl KeyToolCommand {
pub fn execute(self, keystore: SuiKeystore) -> Result<(), anyhow::Error> {
match self {
KeyToolCommand::Generate => {
let (address, keypair) = get_key_pair();
store_and_print_keypair(address, keypair)
let (_address, keypair) = get_key_pair();

let hex = encode_bytes_hex(keypair.public());
let file_name = format!("{hex}.key");
write_keypair_to_file(&keypair, &file_name)?;
println!("Ed25519 key generated and saved to '{file_name}'");
}

KeyToolCommand::Show { file } => {
let keypair = read_keypair_from_file(file)?;
println!("Public Key: {}", encode_bytes_hex(keypair.public()));
}

KeyToolCommand::Unpack { keypair } => {
store_and_print_keypair(keypair.public().into(), keypair)
}
Expand Down Expand Up @@ -91,3 +106,24 @@ fn store_and_print_keypair(address: SuiAddress, keypair: KeyPair) {
fs::write(path, out_str).unwrap();
println!("Address and keypair written to {}", path.to_str().unwrap());
}

pub fn write_keypair_to_file<P: AsRef<std::path::Path>>(
keypair: &KeyPair,
path: P,
) -> anyhow::Result<()> {
use base64ct::Encoding;

let keypair = keypair.copy();
let public = keypair.public().0;
let secret = keypair.private().0;
let dalek = ed25519_dalek::Keypair { public, secret };
let contents = base64ct::Base64::encode_string(&dalek.to_bytes());
std::fs::write(path, contents)?;

Ok(())
}

pub fn read_keypair_from_file<P: AsRef<std::path::Path>>(path: P) -> anyhow::Result<KeyPair> {
let contents = std::fs::read_to_string(path)?;
contents.parse()
}
4 changes: 2 additions & 2 deletions crates/workspace-hack/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ backoff = { version = "0.4", features = ["futures", "futures-core", "pin-project
backtrace = { version = "0.3", features = ["std"] }
base16ct = { version = "0.1", default-features = false, features = ["alloc"] }
base64 = { version = "0.13", features = ["alloc", "std"] }
base64ct = { version = "1", default-features = false, features = ["alloc"] }
base64ct = { version = "1", default-features = false, features = ["alloc", "std"] }
bcs = { version = "0.1", default-features = false }
beef = { version = "0.5", features = ["impl_serde", "serde"] }
better_any = { version = "0.1", default-features = false }
Expand Down Expand Up @@ -602,7 +602,7 @@ backoff = { version = "0.4", features = ["futures", "futures-core", "pin-project
backtrace = { version = "0.3", features = ["std"] }
base16ct = { version = "0.1", default-features = false, features = ["alloc"] }
base64 = { version = "0.13", features = ["alloc", "std"] }
base64ct = { version = "1", default-features = false, features = ["alloc"] }
base64ct = { version = "1", default-features = false, features = ["alloc", "std"] }
bcs = { version = "0.1", default-features = false }
beef = { version = "0.5", features = ["impl_serde", "serde"] }
better_any = { version = "0.1", default-features = false }
Expand Down

0 comments on commit 7516b53

Please sign in to comment.