Skip to content

Commit

Permalink
[aptos-cli] Output Validator and VFN identity files for genesis (apto…
Browse files Browse the repository at this point in the history
  • Loading branch information
gregnazario authored May 12, 2022
1 parent 73ad2b2 commit a69cbef
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 34 deletions.
11 changes: 9 additions & 2 deletions config/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,19 @@ impl WaypointConfig {
}
}

/// A single struct for reading / writing to a file for identity across config
#[derive(Deserialize, Serialize)]
pub struct IdentityBlob {
pub account_address: AccountAddress,
pub account_key: Ed25519PrivateKey,
/// Optional account address. Used for validators and validator full nodes
#[serde(skip_serializing_if = "Option::is_none")]
pub account_address: Option<AccountAddress>,
/// Optional account key. Only used for validators
#[serde(skip_serializing_if = "Option::is_none")]
pub account_key: Option<Ed25519PrivateKey>,
/// Optional consensus key. Only used for validators
#[serde(skip_serializing_if = "Option::is_none")]
pub consensus_key: Option<Ed25519PrivateKey>,
/// Network private key. Peer id is derived from this if account address is not present
pub network_key: x25519::PrivateKey,
}

Expand Down
15 changes: 12 additions & 3 deletions config/src/config/network_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use crate::{
use aptos_crypto::{x25519, Uniform};
use aptos_secure_storage::{CryptoStorage, KVStorage, Storage};
use aptos_types::{
network_address::NetworkAddress, transaction::authenticator::AuthenticationKey, PeerId,
account_address::from_identity_public_key, network_address::NetworkAddress,
transaction::authenticator::AuthenticationKey, PeerId,
};
use rand::{
rngs::{OsRng, StdRng},
Expand Down Expand Up @@ -138,7 +139,7 @@ impl NetworkConfig {
impl NetworkConfig {
pub fn identity_key(&self) -> x25519::PrivateKey {
let key = match &self.identity {
Identity::FromConfig(config) => Some(config.key.clone().key),
Identity::FromConfig(config) => Some(config.key.private_key()),
Identity::FromStorage(config) => {
let storage: Storage = (&config.backend).into();
let key = storage
Expand Down Expand Up @@ -218,7 +219,15 @@ impl NetworkConfig {
}
Identity::FromFile(config) => {
let identity_blob: IdentityBlob = IdentityBlob::from_file(&config.path).unwrap();
Some(identity_blob.account_address)

// If account is not specified, generate peer id from public key
if let Some(address) = identity_blob.account_address {
Some(address)
} else {
Some(from_identity_public_key(
identity_blob.network_key.public_key(),
))
}
}
Identity::None => None,
}
Expand Down
4 changes: 2 additions & 2 deletions config/src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
pub struct ConfigKey<T: PrivateKey + Serialize> {
#[serde(bound(deserialize = "T: Deserialize<'de>"))]
pub(crate) key: T,
key: T,
}

impl<T: DeserializeOwned + PrivateKey + Serialize> ConfigKey<T> {
pub(crate) fn new(key: T) -> Self {
pub fn new(key: T) -> Self {
Self { key }
}

Expand Down
8 changes: 6 additions & 2 deletions consensus/safety-rules/src/safety_rules_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,15 @@ pub fn storage(config: &SafetyRulesConfig) -> PersistentSafetyStorage {
backend.try_into().expect("Unable to initialize storage");
PersistentSafetyStorage::initialize(
internal_storage,
identity_blob.account_address,
identity_blob
.account_address
.expect("AccountAddress needed for safety rules"),
identity_blob
.consensus_key
.expect("Consensus key needed for safety rules"),
identity_blob.account_key,
identity_blob
.account_key
.expect("Account key needed for safety rules"),
waypoint,
config.enable_cached_safety_data,
)
Expand Down
2 changes: 1 addition & 1 deletion crates/aptos/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ toml = "0.5.9"
uuid = { version = "1.0.0", features = ["v4", "serde"] }

aptos-config = { path = "../../config" }
aptos-crypto = { path = "../aptos-crypto" }
aptos-crypto = { path = "../aptos-crypto", features = [] }
aptos-github-client = { path = "../../secure/storage/github" }
aptos-logger = { path = "../aptos-logger" }
aptos-management = { path = "../../config/management" }
Expand Down
10 changes: 6 additions & 4 deletions crates/aptos/src/genesis/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,12 @@ pub struct ValidatorConfiguration {
pub consensus_key: Ed25519PublicKey,
/// Key used for signing transactions with the account
pub account_key: Ed25519PublicKey,
/// Public key used for network identity (same as account address)
pub network_key: x25519::PublicKey,
/// Public key used for validator network identity (same as account address)
pub validator_network_key: x25519::PublicKey,
/// Host for validator which can be an IP or a DNS name
pub validator_host: HostAndPort,
/// Public key used for full node network identity (same as account address)
pub full_node_network_key: x25519::PublicKey,
/// Host for full node which can be an IP or a DNS name and is optional
pub full_node_host: Option<HostAndPort>,
/// Stake amount for consensus
Expand All @@ -76,11 +78,11 @@ impl TryFrom<ValidatorConfiguration> for Validator {
let auth_key = AuthenticationKey::ed25519(&config.account_key);
let validator_addresses = vec![config
.validator_host
.as_network_address(config.network_key)
.as_network_address(config.validator_network_key)
.unwrap()];
let full_node_addresses = if let Some(full_node_host) = config.full_node_host {
vec![full_node_host
.as_network_address(config.network_key)
.as_network_address(config.full_node_network_key)
.unwrap()]
} else {
vec![]
Expand Down
76 changes: 56 additions & 20 deletions crates/aptos/src/genesis/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

use crate::{
common::{
types::{CliError, CliTypedResult},
utils::{read_from_file, write_to_file},
types::{CliError, CliTypedResult, PromptOptions},
utils::{check_if_file_exists, read_from_file, write_to_file},
},
genesis::{
config::{HostAndPort, ValidatorConfiguration},
Expand All @@ -13,6 +13,7 @@ use crate::{
op::key,
CliCommand,
};
use aptos_config::{config::IdentityBlob, keys::ConfigKey};
use aptos_crypto::{ed25519::Ed25519PrivateKey, x25519, PrivateKey};
use aptos_types::transaction::authenticator::AuthenticationKey;
use async_trait::async_trait;
Expand All @@ -22,59 +23,92 @@ use serde::{Deserialize, Serialize};
use std::path::PathBuf;

const PRIVATE_KEYS_FILE: &str = "private-keys.yaml";
const VALIDATOR_FILE: &str = "validator-identity.yaml";
const VFN_FILE: &str = "validator-full-node-identity.yaml";

/// Generate account key, consensus key, and network key for a validator
#[derive(Parser)]
pub struct GenerateKeys {
#[clap(flatten)]
prompt_options: PromptOptions,
/// Output path for the three keys
#[clap(long, parse(from_os_str), default_value = ".")]
output_dir: PathBuf,
}

#[async_trait]
impl CliCommand<PathBuf> for GenerateKeys {
impl CliCommand<Vec<PathBuf>> for GenerateKeys {
fn command_name(&self) -> &'static str {
"GenerateKeys"
}

async fn execute(self) -> CliTypedResult<PathBuf> {
let account_key = key::GenerateKey::generate_ed25519_in_memory();
let consensus_key = key::GenerateKey::generate_ed25519_in_memory();
// Start network key based off of the account key, we can update it later
let network_key =
x25519::PrivateKey::from_ed25519_private_bytes(&account_key.to_bytes()).unwrap();
async fn execute(self) -> CliTypedResult<Vec<PathBuf>> {
let keys_file = self.output_dir.join(PRIVATE_KEYS_FILE);
let validator_file = self.output_dir.join(VALIDATOR_FILE);
let vfn_file = self.output_dir.join(VFN_FILE);
check_if_file_exists(keys_file.as_path(), self.prompt_options)?;
check_if_file_exists(validator_file.as_path(), self.prompt_options)?;
check_if_file_exists(vfn_file.as_path(), self.prompt_options)?;

let account_key = ConfigKey::new(key::GenerateKey::generate_ed25519_in_memory());
let consensus_key = ConfigKey::new(key::GenerateKey::generate_ed25519_in_memory());
let validator_network_key = ConfigKey::new(key::GenerateKey::generate_x25519_in_memory()?);
let full_node_network_key = ConfigKey::new(key::GenerateKey::generate_x25519_in_memory()?);

let account_address =
AuthenticationKey::ed25519(&account_key.public_key()).derived_address();

let config = KeysAndAccount {
// Build these for use later as node identity
let validator_blob = IdentityBlob {
account_address: Some(account_address),
account_key: Some(account_key.private_key()),
consensus_key: Some(consensus_key.private_key()),
network_key: validator_network_key.private_key(),
};
let vfn_blob = IdentityBlob {
account_address: Some(account_address),
account_key: None,
consensus_key: None,
network_key: full_node_network_key.private_key(),
};

let config = PrivateIdentity {
account_address,
account_key,
consensus_key,
network_key,
account_key: account_key.private_key(),
consensus_key: consensus_key.private_key(),
full_node_network_key: full_node_network_key.private_key(),
validator_network_key: validator_network_key.private_key(),
};

// Create the directory if it doesn't exist
if !self.output_dir.exists() || !self.output_dir.is_dir() {
std::fs::create_dir(&self.output_dir)
.map_err(|e| CliError::IO(self.output_dir.to_str().unwrap().to_string(), e))?
};

write_to_file(
keys_file.as_path(),
"private_keys.yaml",
PRIVATE_KEYS_FILE,
to_yaml(&config)?.as_bytes(),
)?;
Ok(keys_file)
write_to_file(
validator_file.as_path(),
VALIDATOR_FILE,
to_yaml(&validator_blob)?.as_bytes(),
)?;
write_to_file(vfn_file.as_path(), VFN_FILE, to_yaml(&vfn_blob)?.as_bytes())?;
Ok(vec![keys_file, validator_file, vfn_file])
}
}

/// Type for serializing private keys file
#[derive(Deserialize, Serialize)]
pub struct KeysAndAccount {
pub struct PrivateIdentity {
account_address: AccountAddress,
account_key: Ed25519PrivateKey,
consensus_key: Ed25519PrivateKey,
network_key: x25519::PrivateKey,
full_node_network_key: x25519::PrivateKey,
validator_network_key: x25519::PrivateKey,
}

/// Set ValidatorConfiguration for a single validator in the git repository
Expand Down Expand Up @@ -108,19 +142,21 @@ impl CliCommand<()> for SetValidatorConfiguration {
async fn execute(self) -> CliTypedResult<()> {
let private_keys_path = self.keys_dir.join(PRIVATE_KEYS_FILE);
let bytes = read_from_file(private_keys_path.as_path())?;
let key_files: KeysAndAccount =
let key_files: PrivateIdentity =
from_yaml(&String::from_utf8(bytes).map_err(CliError::from)?)?;
let account_address = key_files.account_address;
let account_key = key_files.account_key.public_key();
let consensus_key = key_files.consensus_key.public_key();
let network_key = key_files.network_key.public_key();
let validator_network_key = key_files.validator_network_key.public_key();
let full_node_network_key = key_files.full_node_network_key.public_key();

let credentials = ValidatorConfiguration {
account_address,
consensus_key,
account_key,
network_key,
validator_network_key,
validator_host: self.validator_host,
full_node_network_key,
full_node_host: self.full_node_host,
stake_amount: self.stake_amount,
};
Expand Down

0 comments on commit a69cbef

Please sign in to comment.