genesis: Add support for multiple bootstrap validators (#8656)
automerge
This commit is contained in:
parent
448b957a13
commit
44fde2d964
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
use clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg, ArgMatches};
|
use clap::{crate_description, crate_name, value_t, value_t_or_exit, App, Arg, ArgMatches};
|
||||||
use solana_clap_utils::{
|
use solana_clap_utils::{
|
||||||
input_parsers::{pubkey_of, unix_timestamp_from_rfc3339_datetime},
|
input_parsers::{pubkey_of, pubkeys_of, unix_timestamp_from_rfc3339_datetime},
|
||||||
input_validators::{is_rfc3339_datetime, is_valid_percentage},
|
input_validators::{is_pubkey_or_keypair, is_rfc3339_datetime, is_valid_percentage},
|
||||||
};
|
};
|
||||||
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
||||||
use solana_ledger::{blockstore::create_new_ledger, poh::compute_hashes_per_tick};
|
use solana_ledger::{blockstore::create_new_ledger, poh::compute_hashes_per_tick};
|
||||||
|
@ -21,16 +21,9 @@ use solana_sdk::{
|
||||||
system_program, timing,
|
system_program, timing,
|
||||||
};
|
};
|
||||||
use solana_stake_program::stake_state::{self, StakeState};
|
use solana_stake_program::stake_state::{self, StakeState};
|
||||||
use solana_storage_program::storage_contract;
|
|
||||||
use solana_vote_program::vote_state::{self, VoteState};
|
use solana_vote_program::vote_state::{self, VoteState};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap},
|
collections::HashMap, error, fs::File, io, path::PathBuf, process, str::FromStr, time::Duration,
|
||||||
error,
|
|
||||||
fs::File,
|
|
||||||
io,
|
|
||||||
path::PathBuf,
|
|
||||||
str::FromStr,
|
|
||||||
time::Duration,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub enum AccountFileFormat {
|
pub enum AccountFileFormat {
|
||||||
|
@ -38,16 +31,6 @@ pub enum AccountFileFormat {
|
||||||
Keypair,
|
Keypair,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn required_pubkey(matches: &ArgMatches<'_>, name: &str) -> Result<Pubkey, Box<dyn error::Error>> {
|
|
||||||
pubkey_of(matches, name).ok_or_else(|| {
|
|
||||||
format!(
|
|
||||||
"Invalid pubkey or file: {}",
|
|
||||||
matches.value_of(name).unwrap()
|
|
||||||
)
|
|
||||||
.into()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pubkey_from_str(key_str: &str) -> Result<Pubkey, Box<dyn error::Error>> {
|
fn pubkey_from_str(key_str: &str) -> Result<Pubkey, Box<dyn error::Error>> {
|
||||||
Pubkey::from_str(key_str).or_else(|_| {
|
Pubkey::from_str(key_str).or_else(|_| {
|
||||||
let bytes: Vec<u8> = serde_json::from_str(key_str)?;
|
let bytes: Vec<u8> = serde_json::from_str(key_str)?;
|
||||||
|
@ -151,13 +134,16 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.help("Time when the bootstrap validator will start the cluster [default: current system time]"),
|
.help("Time when the bootstrap validator will start the cluster [default: current system time]"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("bootstrap_validator_pubkey_file")
|
Arg::with_name("bootstrap_validator")
|
||||||
.short("b")
|
.short("b")
|
||||||
.long("bootstrap-validator-pubkey")
|
.long("bootstrap-validator")
|
||||||
.value_name("BOOTSTRAP VALIDATOR PUBKEY")
|
.value_name("IDENTITY_PUBKEY VOTE_PUBKEY STAKE_PUBKEY")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.validator(is_pubkey_or_keypair)
|
||||||
|
.number_of_values(3)
|
||||||
|
.multiple(true)
|
||||||
.required(true)
|
.required(true)
|
||||||
.help("Path to file containing the bootstrap validator's pubkey"),
|
.help("The bootstrap validator's identity, vote and stake pubkeys"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("ledger_path")
|
Arg::with_name("ledger_path")
|
||||||
|
@ -174,58 +160,36 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.long("faucet-lamports")
|
.long("faucet-lamports")
|
||||||
.value_name("LAMPORTS")
|
.value_name("LAMPORTS")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.requires("faucet_pubkey_file")
|
.requires("faucet_pubkey")
|
||||||
.help("Number of lamports to assign to the faucet"),
|
.help("Number of lamports to assign to the faucet"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("faucet_pubkey_file")
|
Arg::with_name("faucet_pubkey")
|
||||||
.short("m")
|
.short("m")
|
||||||
.long("faucet-pubkey")
|
.long("faucet-pubkey")
|
||||||
.value_name("PUBKEY")
|
.value_name("PUBKEY")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.validator(is_pubkey_or_keypair)
|
||||||
.requires("faucet_lamports")
|
.requires("faucet_lamports")
|
||||||
.help("Path to file containing the faucet's pubkey"),
|
.help("Path to file containing the faucet's pubkey"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("bootstrap_vote_pubkey_file")
|
Arg::with_name("bootstrap_stake_authorized_pubkey")
|
||||||
.long("bootstrap-vote-pubkey")
|
|
||||||
.value_name("BOOTSTRAP VOTE PUBKEY")
|
|
||||||
.takes_value(true)
|
|
||||||
.required(true)
|
|
||||||
.help("Path to file containing the bootstrap validator's voting pubkey"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("bootstrap_stake_pubkey_file")
|
|
||||||
.long("bootstrap-stake-pubkey")
|
|
||||||
.value_name("BOOTSTRAP STAKE PUBKEY")
|
|
||||||
.takes_value(true)
|
|
||||||
.required(true)
|
|
||||||
.help("Path to file containing the bootstrap validator's staking pubkey"),
|
|
||||||
)
|
|
||||||
.arg(
|
|
||||||
Arg::with_name("bootstrap_stake_authorized_pubkey_file")
|
|
||||||
.long("bootstrap-stake-authorized-pubkey")
|
.long("bootstrap-stake-authorized-pubkey")
|
||||||
.value_name("BOOTSTRAP STAKE AUTHORIZED PUBKEY")
|
.value_name("BOOTSTRAP STAKE AUTHORIZED PUBKEY")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
|
.validator(is_pubkey_or_keypair)
|
||||||
.help(
|
.help(
|
||||||
"Path to file containing the pubkey authorized to manage the bootstrap \
|
"Path to file containing the pubkey authorized to manage the bootstrap \
|
||||||
validator's stake [default: --bootstrap-validator-pubkey]",
|
validator's stake [default: --bootstrap-validator-pubkey]",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.arg(
|
|
||||||
Arg::with_name("bootstrap_storage_pubkey_file")
|
|
||||||
.long("bootstrap-storage-pubkey")
|
|
||||||
.value_name("BOOTSTRAP STORAGE PUBKEY")
|
|
||||||
.takes_value(true)
|
|
||||||
.help("Path to file containing the bootstrap validator's storage pubkey"),
|
|
||||||
)
|
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("bootstrap_validator_lamports")
|
Arg::with_name("bootstrap_validator_lamports")
|
||||||
.long("bootstrap-validator-lamports")
|
.long("bootstrap-validator-lamports")
|
||||||
.value_name("LAMPORTS")
|
.value_name("LAMPORTS")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.default_value(default_bootstrap_validator_lamports)
|
.default_value(default_bootstrap_validator_lamports)
|
||||||
.required(true)
|
|
||||||
.help("Number of lamports to assign to the bootstrap validator"),
|
.help("Number of lamports to assign to the bootstrap validator"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -234,7 +198,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.value_name("LAMPORTS")
|
.value_name("LAMPORTS")
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.default_value(default_bootstrap_validator_stake_lamports)
|
.default_value(default_bootstrap_validator_stake_lamports)
|
||||||
.required(true)
|
|
||||||
.help("Number of lamports to assign to the bootstrap validator's stake account"),
|
.help("Number of lamports to assign to the bootstrap validator's stake account"),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
|
@ -391,6 +354,20 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let bootstrap_validator_pubkeys = pubkeys_of(&matches, "bootstrap_validator").unwrap();
|
||||||
|
assert_eq!(bootstrap_validator_pubkeys.len() % 3, 0);
|
||||||
|
|
||||||
|
// Ensure there are no duplicated pubkeys in the --bootstrap-validator list
|
||||||
|
{
|
||||||
|
let mut v = bootstrap_validator_pubkeys.clone();
|
||||||
|
v.sort();
|
||||||
|
v.dedup();
|
||||||
|
if v.len() != bootstrap_validator_pubkeys.len() {
|
||||||
|
eprintln!("Error: --bootstrap-validator pubkeys cannot be duplicated");
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let bootstrap_validator_lamports =
|
let bootstrap_validator_lamports =
|
||||||
value_t_or_exit!(matches, "bootstrap_validator_lamports", u64);
|
value_t_or_exit!(matches, "bootstrap_validator_lamports", u64);
|
||||||
|
|
||||||
|
@ -400,52 +377,9 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
StakeState::get_rent_exempt_reserve(&rent),
|
StakeState::get_rent_exempt_reserve(&rent),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let bootstrap_validator_pubkey = required_pubkey(&matches, "bootstrap_validator_pubkey_file")?;
|
|
||||||
let bootstrap_vote_pubkey = required_pubkey(&matches, "bootstrap_vote_pubkey_file")?;
|
|
||||||
let bootstrap_stake_pubkey = required_pubkey(&matches, "bootstrap_stake_pubkey_file")?;
|
|
||||||
let bootstrap_stake_authorized_pubkey =
|
let bootstrap_stake_authorized_pubkey =
|
||||||
pubkey_of(&matches, "bootstrap_stake_authorized_pubkey_file");
|
pubkey_of(&matches, "bootstrap_stake_authorized_pubkey");
|
||||||
let bootstrap_storage_pubkey = pubkey_of(&matches, "bootstrap_storage_pubkey_file");
|
let faucet_pubkey = pubkey_of(&matches, "faucet_pubkey");
|
||||||
let faucet_pubkey = pubkey_of(&matches, "faucet_pubkey_file");
|
|
||||||
|
|
||||||
let bootstrap_validator_vote_account = vote_state::create_account(
|
|
||||||
&bootstrap_vote_pubkey,
|
|
||||||
&bootstrap_validator_pubkey,
|
|
||||||
100,
|
|
||||||
VoteState::get_rent_exempt_reserve(&rent).max(1),
|
|
||||||
);
|
|
||||||
|
|
||||||
let bootstrap_validator_stake_account = stake_state::create_account(
|
|
||||||
bootstrap_stake_authorized_pubkey
|
|
||||||
.as_ref()
|
|
||||||
.unwrap_or(&bootstrap_validator_pubkey),
|
|
||||||
&bootstrap_vote_pubkey,
|
|
||||||
&bootstrap_validator_vote_account,
|
|
||||||
&rent,
|
|
||||||
bootstrap_validator_stake_lamports,
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut accounts: BTreeMap<Pubkey, Account> = [
|
|
||||||
// node needs an account to issue votes from
|
|
||||||
(
|
|
||||||
bootstrap_validator_pubkey,
|
|
||||||
Account::new(bootstrap_validator_lamports, 0, &system_program::id()),
|
|
||||||
),
|
|
||||||
// where votes go to
|
|
||||||
(bootstrap_vote_pubkey, bootstrap_validator_vote_account),
|
|
||||||
// bootstrap validator stake
|
|
||||||
(bootstrap_stake_pubkey, bootstrap_validator_stake_account),
|
|
||||||
]
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
if let Some(bootstrap_storage_pubkey) = bootstrap_storage_pubkey {
|
|
||||||
accounts.insert(
|
|
||||||
bootstrap_storage_pubkey,
|
|
||||||
storage_contract::create_validator_storage_account(bootstrap_validator_pubkey, 1),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64);
|
let ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64);
|
||||||
|
|
||||||
|
@ -508,7 +442,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
let inflation = solana_genesis_programs::get_inflation(operating_mode, 0).unwrap();
|
let inflation = solana_genesis_programs::get_inflation(operating_mode, 0).unwrap();
|
||||||
|
|
||||||
let mut genesis_config = GenesisConfig {
|
let mut genesis_config = GenesisConfig {
|
||||||
accounts,
|
|
||||||
native_instruction_processors,
|
native_instruction_processors,
|
||||||
ticks_per_slot,
|
ticks_per_slot,
|
||||||
epoch_schedule,
|
epoch_schedule,
|
||||||
|
@ -520,6 +453,43 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
..GenesisConfig::default()
|
..GenesisConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut bootstrap_validator_pubkeys_iter = bootstrap_validator_pubkeys.iter();
|
||||||
|
loop {
|
||||||
|
let identity_pubkey = match bootstrap_validator_pubkeys_iter.next() {
|
||||||
|
None => break,
|
||||||
|
Some(identity_pubkey) => identity_pubkey,
|
||||||
|
};
|
||||||
|
let vote_pubkey = bootstrap_validator_pubkeys_iter.next().unwrap();
|
||||||
|
let stake_pubkey = bootstrap_validator_pubkeys_iter.next().unwrap();
|
||||||
|
|
||||||
|
genesis_config.add_account(
|
||||||
|
*identity_pubkey,
|
||||||
|
Account::new(bootstrap_validator_lamports, 0, &system_program::id()),
|
||||||
|
);
|
||||||
|
|
||||||
|
let vote_account = vote_state::create_account(
|
||||||
|
&vote_pubkey,
|
||||||
|
&identity_pubkey,
|
||||||
|
100,
|
||||||
|
VoteState::get_rent_exempt_reserve(&rent).max(1),
|
||||||
|
);
|
||||||
|
|
||||||
|
genesis_config.add_account(
|
||||||
|
*stake_pubkey,
|
||||||
|
stake_state::create_account(
|
||||||
|
bootstrap_stake_authorized_pubkey
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(&identity_pubkey),
|
||||||
|
&vote_pubkey,
|
||||||
|
&vote_account,
|
||||||
|
&rent,
|
||||||
|
bootstrap_validator_stake_lamports,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
genesis_config.add_account(*vote_pubkey, vote_account);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(creation_time) = unix_timestamp_from_rfc3339_datetime(&matches, "creation_time") {
|
if let Some(creation_time) = unix_timestamp_from_rfc3339_datetime(&matches, "creation_time") {
|
||||||
genesis_config.creation_time = creation_time;
|
genesis_config.creation_time = creation_time;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,6 @@ done
|
||||||
# These keypairs are created by ./setup.sh and included in the genesis config
|
# These keypairs are created by ./setup.sh and included in the genesis config
|
||||||
identity_keypair=$SOLANA_CONFIG_DIR/bootstrap-validator/identity-keypair.json
|
identity_keypair=$SOLANA_CONFIG_DIR/bootstrap-validator/identity-keypair.json
|
||||||
vote_keypair="$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-keypair.json
|
vote_keypair="$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-keypair.json
|
||||||
storage_keypair=$SOLANA_CONFIG_DIR/bootstrap-validator/storage-keypair.json
|
|
||||||
|
|
||||||
ledger_dir="$SOLANA_CONFIG_DIR"/bootstrap-validator
|
ledger_dir="$SOLANA_CONFIG_DIR"/bootstrap-validator
|
||||||
[[ -d "$ledger_dir" ]] || {
|
[[ -d "$ledger_dir" ]] || {
|
||||||
|
@ -82,7 +81,6 @@ args+=(
|
||||||
--rpc-port 8899
|
--rpc-port 8899
|
||||||
--snapshot-interval-slots 100
|
--snapshot-interval-slots 100
|
||||||
--identity-keypair "$identity_keypair"
|
--identity-keypair "$identity_keypair"
|
||||||
--storage-keypair "$storage_keypair"
|
|
||||||
--voting-keypair "$vote_keypair"
|
--voting-keypair "$vote_keypair"
|
||||||
--rpc-faucet-address 127.0.0.1:9900
|
--rpc-faucet-address 127.0.0.1:9900
|
||||||
)
|
)
|
||||||
|
@ -90,7 +88,6 @@ default_arg --gossip-port 8001
|
||||||
default_arg --log -
|
default_arg --log -
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pid=
|
pid=
|
||||||
kill_node() {
|
kill_node() {
|
||||||
# Note: do not echo anything from this function to ensure $pid is actually
|
# Note: do not echo anything from this function to ensure $pid is actually
|
||||||
|
|
|
@ -24,14 +24,14 @@ fi
|
||||||
|
|
||||||
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-keypair.json
|
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-keypair.json
|
||||||
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/stake-keypair.json
|
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/stake-keypair.json
|
||||||
$solana_keygen new --no-passphrase -so "$SOLANA_CONFIG_DIR"/bootstrap-validator/storage-keypair.json
|
|
||||||
|
|
||||||
args=("$@")
|
args=(
|
||||||
default_arg --enable-warmup-epochs
|
"$@"
|
||||||
default_arg --bootstrap-validator-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-validator/identity-keypair.json
|
--enable-warmup-epochs
|
||||||
default_arg --bootstrap-vote-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-keypair.json
|
--bootstrap-validator "$SOLANA_CONFIG_DIR"/bootstrap-validator/identity-keypair.json
|
||||||
default_arg --bootstrap-stake-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-validator/stake-keypair.json
|
"$SOLANA_CONFIG_DIR"/bootstrap-validator/vote-keypair.json
|
||||||
default_arg --bootstrap-storage-pubkey "$SOLANA_CONFIG_DIR"/bootstrap-validator/storage-keypair.json
|
"$SOLANA_CONFIG_DIR"/bootstrap-validator/stake-keypair.json
|
||||||
|
)
|
||||||
default_arg --ledger "$SOLANA_CONFIG_DIR"/bootstrap-validator
|
default_arg --ledger "$SOLANA_CONFIG_DIR"/bootstrap-validator
|
||||||
default_arg --faucet-pubkey "$SOLANA_CONFIG_DIR"/faucet-keypair.json
|
default_arg --faucet-pubkey "$SOLANA_CONFIG_DIR"/faucet-keypair.json
|
||||||
default_arg --faucet-lamports 500000000000000000
|
default_arg --faucet-lamports 500000000000000000
|
||||||
|
|
15
run.sh
15
run.sh
|
@ -70,12 +70,6 @@ if [[ -e $faucet_keypair ]]; then
|
||||||
else
|
else
|
||||||
solana-keygen new --no-passphrase -fso "$faucet_keypair"
|
solana-keygen new --no-passphrase -fso "$faucet_keypair"
|
||||||
fi
|
fi
|
||||||
leader_storage_account_keypair="$dataDir"/leader-storage-account-keypair.json
|
|
||||||
if [[ -e $leader_storage_account_keypair ]]; then
|
|
||||||
echo "Use existing leader storage account keypair"
|
|
||||||
else
|
|
||||||
solana-keygen new --no-passphrase -fso "$leader_storage_account_keypair"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -e "$ledgerDir"/genesis.bin ]]; then
|
if [[ -e "$ledgerDir"/genesis.bin ]]; then
|
||||||
echo "Use existing genesis"
|
echo "Use existing genesis"
|
||||||
|
@ -84,10 +78,10 @@ else
|
||||||
--hashes-per-tick sleep \
|
--hashes-per-tick sleep \
|
||||||
--faucet-pubkey "$dataDir"/faucet-keypair.json \
|
--faucet-pubkey "$dataDir"/faucet-keypair.json \
|
||||||
--faucet-lamports 500000000000000000 \
|
--faucet-lamports 500000000000000000 \
|
||||||
--bootstrap-validator-pubkey "$dataDir"/leader-keypair.json \
|
--bootstrap-validator \
|
||||||
--bootstrap-vote-pubkey "$dataDir"/leader-vote-account-keypair.json \
|
"$dataDir"/leader-keypair.json \
|
||||||
--bootstrap-stake-pubkey "$dataDir"/leader-stake-account-keypair.json \
|
"$dataDir"/leader-vote-account-keypair.json \
|
||||||
--bootstrap-storage-pubkey "$dataDir"/leader-storage-account-keypair.json \
|
"$dataDir"/leader-stake-account-keypair.json \
|
||||||
--ledger "$ledgerDir" \
|
--ledger "$ledgerDir" \
|
||||||
--operating-mode development
|
--operating-mode development
|
||||||
fi
|
fi
|
||||||
|
@ -104,7 +98,6 @@ faucet=$!
|
||||||
|
|
||||||
args=(
|
args=(
|
||||||
--identity-keypair "$dataDir"/leader-keypair.json
|
--identity-keypair "$dataDir"/leader-keypair.json
|
||||||
--storage-keypair "$dataDir"/leader-storage-account-keypair.json
|
|
||||||
--voting-keypair "$dataDir"/leader-vote-account-keypair.json
|
--voting-keypair "$dataDir"/leader-vote-account-keypair.json
|
||||||
--ledger "$ledgerDir"
|
--ledger "$ledgerDir"
|
||||||
--gossip-port 8001
|
--gossip-port 8001
|
||||||
|
|
Loading…
Reference in New Issue