solana-validator now verifies its genesis blockhash against the cluster entrypoint (#5589)
This commit is contained in:
parent
5034331131
commit
e2d6f01ad3
|
@ -3846,6 +3846,7 @@ dependencies = [
|
||||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"solana-client 0.18.0-pre2",
|
||||||
"solana-core 0.18.0-pre2",
|
"solana-core 0.18.0-pre2",
|
||||||
"solana-drone 0.18.0-pre2",
|
"solana-drone 0.18.0-pre2",
|
||||||
"solana-logger 0.18.0-pre2",
|
"solana-logger 0.18.0-pre2",
|
||||||
|
|
|
@ -26,6 +26,7 @@ Methods
|
||||||
* [getBalance](#getbalance)
|
* [getBalance](#getbalance)
|
||||||
* [getClusterNodes](#getclusternodes)
|
* [getClusterNodes](#getclusternodes)
|
||||||
* [getEpochInfo](#getepochinfo)
|
* [getEpochInfo](#getepochinfo)
|
||||||
|
* [getGenesisBlockhash](#getgenesisblockhash)
|
||||||
* [getLeaderSchedule](#getleaderschedule)
|
* [getLeaderSchedule](#getleaderschedule)
|
||||||
* [getProgramAccounts](#getprogramaccounts)
|
* [getProgramAccounts](#getprogramaccounts)
|
||||||
* [getRecentBlockhash](#getrecentblockhash)
|
* [getRecentBlockhash](#getrecentblockhash)
|
||||||
|
@ -197,6 +198,25 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
|
||||||
{"jsonrpc":"2.0","result":{"epoch":3,"slotIndex":126,"slotsInEpoch":256},"id":1}
|
{"jsonrpc":"2.0","result":{"epoch":3,"slotIndex":126,"slotsInEpoch":256},"id":1}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
### getGenesisBlockhash
|
||||||
|
Returns the genesis block hash
|
||||||
|
|
||||||
|
##### Parameters:
|
||||||
|
None
|
||||||
|
|
||||||
|
##### Results:
|
||||||
|
* `string` - a Hash as base-58 encoded string
|
||||||
|
|
||||||
|
##### Example:
|
||||||
|
```bash
|
||||||
|
// Request
|
||||||
|
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getGenesisBlockhash"}' http://localhost:8899
|
||||||
|
|
||||||
|
// Result
|
||||||
|
{"jsonrpc":"2.0","result":"GH7ome3EiwEr7tu9JuTh2dpYWBJK3z69Xm1ZE3MEE6JC","id":1}
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### getLeaderSchedule
|
### getLeaderSchedule
|
||||||
|
|
|
@ -369,7 +369,7 @@ impl RpcClient {
|
||||||
let blockhash = blockhash.parse().map_err(|err| {
|
let blockhash = blockhash.parse().map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("GetRecentBlockhash parse failure: {:?}", err),
|
format!("GetRecentBlockhash hash parse failure: {:?}", err),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok((blockhash, fee_calculator))
|
Ok((blockhash, fee_calculator))
|
||||||
|
@ -397,6 +397,33 @@ impl RpcClient {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_genesis_blockhash(&self) -> io::Result<Hash> {
|
||||||
|
let response = self
|
||||||
|
.client
|
||||||
|
.send(&RpcRequest::GetGenesisBlockhash, None, 0)
|
||||||
|
.map_err(|err| {
|
||||||
|
io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("GetGenesisBlockhash request failure: {:?}", err),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let blockhash = serde_json::from_value::<String>(response).map_err(|err| {
|
||||||
|
io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("GetGenesisBlockhash parse failure: {:?}", err),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let blockhash = blockhash.parse().map_err(|err| {
|
||||||
|
io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
format!("GetGenesisBlockhash hash parse failure: {:?}", err),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(blockhash)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn poll_balance_with_timeout(
|
pub fn poll_balance_with_timeout(
|
||||||
&self,
|
&self,
|
||||||
pubkey: &Pubkey,
|
pubkey: &Pubkey,
|
||||||
|
|
|
@ -9,6 +9,7 @@ pub enum RpcRequest {
|
||||||
GetAccountInfo,
|
GetAccountInfo,
|
||||||
GetBalance,
|
GetBalance,
|
||||||
GetClusterNodes,
|
GetClusterNodes,
|
||||||
|
GetGenesisBlockhash,
|
||||||
GetNumBlocksSinceSignatureConfirmation,
|
GetNumBlocksSinceSignatureConfirmation,
|
||||||
GetProgramAccounts,
|
GetProgramAccounts,
|
||||||
GetRecentBlockhash,
|
GetRecentBlockhash,
|
||||||
|
@ -38,6 +39,7 @@ impl RpcRequest {
|
||||||
RpcRequest::GetAccountInfo => "getAccountInfo",
|
RpcRequest::GetAccountInfo => "getAccountInfo",
|
||||||
RpcRequest::GetBalance => "getBalance",
|
RpcRequest::GetBalance => "getBalance",
|
||||||
RpcRequest::GetClusterNodes => "getClusterNodes",
|
RpcRequest::GetClusterNodes => "getClusterNodes",
|
||||||
|
RpcRequest::GetGenesisBlockhash => "getGenesisBlockhash",
|
||||||
RpcRequest::GetNumBlocksSinceSignatureConfirmation => {
|
RpcRequest::GetNumBlocksSinceSignatureConfirmation => {
|
||||||
"getNumBlocksSinceSignatureConfirmation"
|
"getNumBlocksSinceSignatureConfirmation"
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ use solana_drone::drone::request_airdrop_transaction;
|
||||||
use solana_runtime::bank::Bank;
|
use solana_runtime::bank::Bank;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
use solana_sdk::fee_calculator::FeeCalculator;
|
use solana_sdk::fee_calculator::FeeCalculator;
|
||||||
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::Signature;
|
use solana_sdk::signature::Signature;
|
||||||
use solana_sdk::transaction::{self, Transaction};
|
use solana_sdk::transaction::{self, Transaction};
|
||||||
|
@ -213,6 +214,7 @@ fn verify_signature(input: &str) -> Result<Signature> {
|
||||||
pub struct Meta {
|
pub struct Meta {
|
||||||
pub request_processor: Arc<RwLock<JsonRpcRequestProcessor>>,
|
pub request_processor: Arc<RwLock<JsonRpcRequestProcessor>>,
|
||||||
pub cluster_info: Arc<RwLock<ClusterInfo>>,
|
pub cluster_info: Arc<RwLock<ClusterInfo>>,
|
||||||
|
pub genesis_blockhash: Hash,
|
||||||
}
|
}
|
||||||
impl Metadata for Meta {}
|
impl Metadata for Meta {}
|
||||||
|
|
||||||
|
@ -298,6 +300,9 @@ pub trait RpcSol {
|
||||||
#[rpc(meta, name = "getEpochInfo")]
|
#[rpc(meta, name = "getEpochInfo")]
|
||||||
fn get_epoch_info(&self, _: Self::Metadata) -> Result<RpcEpochInfo>;
|
fn get_epoch_info(&self, _: Self::Metadata) -> Result<RpcEpochInfo>;
|
||||||
|
|
||||||
|
#[rpc(meta, name = "getGenesisBlockhash")]
|
||||||
|
fn get_genesis_blockhash(&self, _: Self::Metadata) -> Result<String>;
|
||||||
|
|
||||||
#[rpc(meta, name = "getLeaderSchedule")]
|
#[rpc(meta, name = "getLeaderSchedule")]
|
||||||
fn get_leader_schedule(&self, _: Self::Metadata) -> Result<Option<Vec<String>>>;
|
fn get_leader_schedule(&self, _: Self::Metadata) -> Result<Option<Vec<String>>>;
|
||||||
|
|
||||||
|
@ -448,6 +453,11 @@ impl RpcSol for RpcSolImpl {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_genesis_blockhash(&self, meta: Self::Metadata) -> Result<String> {
|
||||||
|
debug!("get_genesis_blockhash rpc request received");
|
||||||
|
Ok(meta.genesis_blockhash.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_leader_schedule(&self, meta: Self::Metadata) -> Result<Option<Vec<String>>> {
|
fn get_leader_schedule(&self, meta: Self::Metadata) -> Result<Option<Vec<String>>> {
|
||||||
let bank = meta.request_processor.read().unwrap().bank();
|
let bank = meta.request_processor.read().unwrap().bank();
|
||||||
Ok(
|
Ok(
|
||||||
|
@ -718,6 +728,7 @@ pub mod tests {
|
||||||
let meta = Meta {
|
let meta = Meta {
|
||||||
request_processor,
|
request_processor,
|
||||||
cluster_info,
|
cluster_info,
|
||||||
|
genesis_blockhash: Hash::default(),
|
||||||
};
|
};
|
||||||
(io, meta, bank, blockhash, alice, leader_pubkey)
|
(io, meta, bank, blockhash, alice, leader_pubkey)
|
||||||
}
|
}
|
||||||
|
@ -1060,6 +1071,7 @@ pub mod tests {
|
||||||
cluster_info: Arc::new(RwLock::new(ClusterInfo::new_with_invalid_keypair(
|
cluster_info: Arc::new(RwLock::new(ClusterInfo::new_with_invalid_keypair(
|
||||||
ContactInfo::default(),
|
ContactInfo::default(),
|
||||||
))),
|
))),
|
||||||
|
genesis_blockhash: Hash::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let req =
|
let req =
|
||||||
|
|
|
@ -12,6 +12,7 @@ use jsonrpc_http_server::{
|
||||||
hyper, AccessControlAllowOrigin, DomainsValidation, RequestMiddleware, RequestMiddlewareAction,
|
hyper, AccessControlAllowOrigin, DomainsValidation, RequestMiddleware, RequestMiddlewareAction,
|
||||||
ServerBuilder,
|
ServerBuilder,
|
||||||
};
|
};
|
||||||
|
use solana_sdk::hash::Hash;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
@ -91,6 +92,7 @@ impl JsonRpcService {
|
||||||
config: JsonRpcConfig,
|
config: JsonRpcConfig,
|
||||||
bank_forks: Arc<RwLock<BankForks>>,
|
bank_forks: Arc<RwLock<BankForks>>,
|
||||||
ledger_path: &Path,
|
ledger_path: &Path,
|
||||||
|
genesis_blockhash: Hash,
|
||||||
validator_exit: &Arc<RwLock<Option<ValidatorExit>>>,
|
validator_exit: &Arc<RwLock<Option<ValidatorExit>>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
info!("rpc bound to {:?}", rpc_addr);
|
info!("rpc bound to {:?}", rpc_addr);
|
||||||
|
@ -118,6 +120,7 @@ impl JsonRpcService {
|
||||||
ServerBuilder::with_meta_extractor(io, move |_req: &hyper::Request<hyper::Body>| Meta {
|
ServerBuilder::with_meta_extractor(io, move |_req: &hyper::Request<hyper::Body>| Meta {
|
||||||
request_processor: request_processor_.clone(),
|
request_processor: request_processor_.clone(),
|
||||||
cluster_info: cluster_info.clone(),
|
cluster_info: cluster_info.clone(),
|
||||||
|
genesis_blockhash
|
||||||
}).threads(4)
|
}).threads(4)
|
||||||
.cors(DomainsValidation::AllowOnly(vec![
|
.cors(DomainsValidation::AllowOnly(vec![
|
||||||
AccessControlAllowOrigin::Any,
|
AccessControlAllowOrigin::Any,
|
||||||
|
@ -201,6 +204,7 @@ mod tests {
|
||||||
JsonRpcConfig::default(),
|
JsonRpcConfig::default(),
|
||||||
bank_forks,
|
bank_forks,
|
||||||
&PathBuf::from("farf"),
|
&PathBuf::from("farf"),
|
||||||
|
Hash::default(),
|
||||||
&validator_exit,
|
&validator_exit,
|
||||||
);
|
);
|
||||||
let thread = rpc_service.thread_hdl.thread();
|
let thread = rpc_service.thread_hdl.thread();
|
||||||
|
|
|
@ -22,6 +22,7 @@ use crate::tpu::Tpu;
|
||||||
use crate::tvu::{Sockets, Tvu};
|
use crate::tvu::{Sockets, Tvu};
|
||||||
use solana_metrics::datapoint_info;
|
use solana_metrics::datapoint_info;
|
||||||
use solana_sdk::genesis_block::GenesisBlock;
|
use solana_sdk::genesis_block::GenesisBlock;
|
||||||
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::poh_config::PohConfig;
|
use solana_sdk::poh_config::PohConfig;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
|
@ -38,6 +39,7 @@ use std::thread::Result;
|
||||||
pub struct ValidatorConfig {
|
pub struct ValidatorConfig {
|
||||||
pub dev_sigverify_disabled: bool,
|
pub dev_sigverify_disabled: bool,
|
||||||
pub dev_halt_at_slot: Option<Slot>,
|
pub dev_halt_at_slot: Option<Slot>,
|
||||||
|
pub expected_genesis_blockhash: Option<Hash>,
|
||||||
pub voting_disabled: bool,
|
pub voting_disabled: bool,
|
||||||
pub blockstream_unix_socket: Option<PathBuf>,
|
pub blockstream_unix_socket: Option<PathBuf>,
|
||||||
pub storage_slots_per_turn: u64,
|
pub storage_slots_per_turn: u64,
|
||||||
|
@ -54,6 +56,7 @@ impl Default for ValidatorConfig {
|
||||||
Self {
|
Self {
|
||||||
dev_sigverify_disabled: false,
|
dev_sigverify_disabled: false,
|
||||||
dev_halt_at_slot: None,
|
dev_halt_at_slot: None,
|
||||||
|
expected_genesis_blockhash: None,
|
||||||
voting_disabled: false,
|
voting_disabled: false,
|
||||||
blockstream_unix_socket: None,
|
blockstream_unix_socket: None,
|
||||||
storage_slots_per_turn: DEFAULT_SLOTS_PER_TURN,
|
storage_slots_per_turn: DEFAULT_SLOTS_PER_TURN,
|
||||||
|
@ -136,6 +139,7 @@ impl Validator {
|
||||||
|
|
||||||
info!("creating bank...");
|
info!("creating bank...");
|
||||||
let (
|
let (
|
||||||
|
genesis_blockhash,
|
||||||
bank_forks,
|
bank_forks,
|
||||||
bank_forks_info,
|
bank_forks_info,
|
||||||
blocktree,
|
blocktree,
|
||||||
|
@ -144,6 +148,7 @@ impl Validator {
|
||||||
leader_schedule_cache,
|
leader_schedule_cache,
|
||||||
poh_config,
|
poh_config,
|
||||||
) = new_banks_from_blocktree(
|
) = new_banks_from_blocktree(
|
||||||
|
config.expected_genesis_blockhash,
|
||||||
ledger_path,
|
ledger_path,
|
||||||
config.account_paths.clone(),
|
config.account_paths.clone(),
|
||||||
config.snapshot_config.clone(),
|
config.snapshot_config.clone(),
|
||||||
|
@ -184,6 +189,7 @@ impl Validator {
|
||||||
config.rpc_config.clone(),
|
config.rpc_config.clone(),
|
||||||
bank_forks.clone(),
|
bank_forks.clone(),
|
||||||
ledger_path,
|
ledger_path,
|
||||||
|
genesis_blockhash,
|
||||||
&validator_exit,
|
&validator_exit,
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
@ -471,12 +477,14 @@ fn adjust_ulimit_nofile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_banks_from_blocktree(
|
pub fn new_banks_from_blocktree(
|
||||||
|
expected_genesis_blockhash: Option<Hash>,
|
||||||
blocktree_path: &Path,
|
blocktree_path: &Path,
|
||||||
account_paths: Option<String>,
|
account_paths: Option<String>,
|
||||||
snapshot_config: Option<SnapshotConfig>,
|
snapshot_config: Option<SnapshotConfig>,
|
||||||
verify_ledger: bool,
|
verify_ledger: bool,
|
||||||
dev_halt_at_slot: Option<Slot>,
|
dev_halt_at_slot: Option<Slot>,
|
||||||
) -> (
|
) -> (
|
||||||
|
Hash,
|
||||||
BankForks,
|
BankForks,
|
||||||
Vec<BankForksInfo>,
|
Vec<BankForksInfo>,
|
||||||
Blocktree,
|
Blocktree,
|
||||||
|
@ -486,6 +494,16 @@ pub fn new_banks_from_blocktree(
|
||||||
PohConfig,
|
PohConfig,
|
||||||
) {
|
) {
|
||||||
let genesis_block = GenesisBlock::load(blocktree_path).expect("Failed to load genesis block");
|
let genesis_block = GenesisBlock::load(blocktree_path).expect("Failed to load genesis block");
|
||||||
|
let genesis_blockhash = genesis_block.hash();
|
||||||
|
|
||||||
|
if let Some(expected_genesis_blockhash) = expected_genesis_blockhash {
|
||||||
|
if genesis_blockhash != expected_genesis_blockhash {
|
||||||
|
panic!(
|
||||||
|
"Genesis blockhash mismatch: expected {} but local genesis blockhash is {}",
|
||||||
|
expected_genesis_blockhash, genesis_blockhash,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
adjust_ulimit_nofile();
|
adjust_ulimit_nofile();
|
||||||
|
|
||||||
|
@ -502,6 +520,7 @@ pub fn new_banks_from_blocktree(
|
||||||
);
|
);
|
||||||
|
|
||||||
(
|
(
|
||||||
|
genesis_blockhash,
|
||||||
bank_forks,
|
bank_forks,
|
||||||
bank_forks_info,
|
bank_forks_info,
|
||||||
blocktree,
|
blocktree,
|
||||||
|
|
|
@ -91,6 +91,7 @@ fn test_replay() {
|
||||||
let tvu_addr = target1.info.tvu;
|
let tvu_addr = target1.info.tvu;
|
||||||
|
|
||||||
let (
|
let (
|
||||||
|
_genesis_blockhash,
|
||||||
bank_forks,
|
bank_forks,
|
||||||
_bank_forks_info,
|
_bank_forks_info,
|
||||||
blocktree,
|
blocktree,
|
||||||
|
@ -98,7 +99,7 @@ fn test_replay() {
|
||||||
completed_slots_receiver,
|
completed_slots_receiver,
|
||||||
leader_schedule_cache,
|
leader_schedule_cache,
|
||||||
_,
|
_,
|
||||||
) = validator::new_banks_from_blocktree(&blocktree_path, None, None, true, None);
|
) = validator::new_banks_from_blocktree(None, &blocktree_path, None, None, true, None);
|
||||||
let working_bank = bank_forks.working_bank();
|
let working_bank = bank_forks.working_bank();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
working_bank.get_balance(&mint_keypair.pubkey()),
|
working_bank.get_balance(&mint_keypair.pubkey()),
|
||||||
|
|
|
@ -272,14 +272,6 @@ setup_validator_accounts() {
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
rpc_url=$($solana_gossip get-rpc-url --entrypoint "$gossip_entrypoint")
|
rpc_url=$($solana_gossip get-rpc-url --entrypoint "$gossip_entrypoint")
|
||||||
if new_genesis_block; then
|
|
||||||
# If the genesis block has changed remove the now stale ledger and start all
|
|
||||||
# over again
|
|
||||||
(
|
|
||||||
set -x
|
|
||||||
rm -rf "$ledger_dir"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ -r "$identity_keypair_path" ]] || $solana_keygen new -o "$identity_keypair_path"
|
[[ -r "$identity_keypair_path" ]] || $solana_keygen new -o "$identity_keypair_path"
|
||||||
[[ -r "$voting_keypair_path" ]] || $solana_keygen new -o "$voting_keypair_path"
|
[[ -r "$voting_keypair_path" ]] || $solana_keygen new -o "$voting_keypair_path"
|
||||||
|
@ -312,7 +304,7 @@ EOF
|
||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
secs_to_next_genesis_poll=5
|
secs_to_next_genesis_poll=60
|
||||||
while true; do
|
while true; do
|
||||||
if [[ -z $pid ]] || ! kill -0 "$pid"; then
|
if [[ -z $pid ]] || ! kill -0 "$pid"; then
|
||||||
[[ -z $pid ]] || wait "$pid"
|
[[ -z $pid ]] || wait "$pid"
|
||||||
|
@ -326,9 +318,13 @@ EOF
|
||||||
echo "Polling for new genesis block..."
|
echo "Polling for new genesis block..."
|
||||||
if new_genesis_block; then
|
if new_genesis_block; then
|
||||||
echo "############## New genesis detected, restarting ##############"
|
echo "############## New genesis detected, restarting ##############"
|
||||||
|
(
|
||||||
|
set -x
|
||||||
|
rm -rf "$ledger_dir"
|
||||||
|
)
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
secs_to_next_genesis_poll=5
|
secs_to_next_genesis_poll=60
|
||||||
fi
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
|
@ -14,6 +14,7 @@ clap = "2.33.0"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
reqwest = "0.9.19"
|
reqwest = "0.9.19"
|
||||||
serde_json = "1.0.40"
|
serde_json = "1.0.40"
|
||||||
|
solana-client = { path = "../client", version = "0.18.0-pre2" }
|
||||||
solana-core = { path = "../core", version = "0.18.0-pre2" }
|
solana-core = { path = "../core", version = "0.18.0-pre2" }
|
||||||
solana-drone = { path = "../drone", version = "0.18.0-pre2" }
|
solana-drone = { path = "../drone", version = "0.18.0-pre2" }
|
||||||
solana-logger = { path = "../logger", version = "0.18.0-pre2" }
|
solana-logger = { path = "../logger", version = "0.18.0-pre2" }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use bzip2::bufread::BzDecoder;
|
use bzip2::bufread::BzDecoder;
|
||||||
use clap::{crate_description, crate_name, crate_version, value_t, App, Arg};
|
use clap::{crate_description, crate_name, crate_version, value_t, App, Arg};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use solana_client::rpc_client::RpcClient;
|
||||||
use solana_core::bank_forks::SnapshotConfig;
|
use solana_core::bank_forks::SnapshotConfig;
|
||||||
use solana_core::cluster_info::{Node, FULLNODE_PORT_RANGE};
|
use solana_core::cluster_info::{Node, FULLNODE_PORT_RANGE};
|
||||||
use solana_core::contact_info::ContactInfo;
|
use solana_core::contact_info::ContactInfo;
|
||||||
|
@ -11,6 +12,7 @@ use solana_core::service::Service;
|
||||||
use solana_core::socketaddr;
|
use solana_core::socketaddr;
|
||||||
use solana_core::validator::{Validator, ValidatorConfig};
|
use solana_core::validator::{Validator, ValidatorConfig};
|
||||||
use solana_netutil::parse_port_range;
|
use solana_netutil::parse_port_range;
|
||||||
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
|
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil};
|
||||||
use solana_sdk::timing::Slot;
|
use solana_sdk::timing::Slot;
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
|
@ -87,7 +89,7 @@ fn initialize_ledger_path(
|
||||||
gossip_addr: &SocketAddr,
|
gossip_addr: &SocketAddr,
|
||||||
ledger_path: &Path,
|
ledger_path: &Path,
|
||||||
no_snapshot_fetch: bool,
|
no_snapshot_fetch: bool,
|
||||||
) -> Result<(), String> {
|
) -> Result<Hash, String> {
|
||||||
let (nodes, _replicators) = discover(
|
let (nodes, _replicators) = discover(
|
||||||
&entrypoint.gossip,
|
&entrypoint.gossip,
|
||||||
Some(1),
|
Some(1),
|
||||||
|
@ -110,6 +112,10 @@ fn initialize_ledger_path(
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let genesis_blockhash = RpcClient::new_socket(rpc_addr)
|
||||||
|
.get_genesis_blockhash()
|
||||||
|
.map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
fs::create_dir_all(ledger_path).map_err(|err| err.to_string())?;
|
fs::create_dir_all(ledger_path).map_err(|err| err.to_string())?;
|
||||||
|
|
||||||
download_archive(&rpc_addr, "genesis.tar.bz2", ledger_path, true)?;
|
download_archive(&rpc_addr, "genesis.tar.bz2", ledger_path, true)?;
|
||||||
|
@ -119,7 +125,7 @@ fn initialize_ledger_path(
|
||||||
.unwrap_or_else(|err| eprintln!("Warning: Unable to fetch snapshot: {:?}", err));
|
.unwrap_or_else(|err| eprintln!("Warning: Unable to fetch snapshot: {:?}", err));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(genesis_blockhash)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -393,7 +399,7 @@ fn main() {
|
||||||
.map(PathBuf::from);
|
.map(PathBuf::from);
|
||||||
|
|
||||||
if let Some(ref entrypoint_addr) = cluster_entrypoint {
|
if let Some(ref entrypoint_addr) = cluster_entrypoint {
|
||||||
initialize_ledger_path(
|
let expected_genesis_blockhash = initialize_ledger_path(
|
||||||
entrypoint_addr,
|
entrypoint_addr,
|
||||||
&gossip_addr,
|
&gossip_addr,
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
|
@ -403,6 +409,7 @@ fn main() {
|
||||||
eprintln!("Failed to download ledger: {}", err);
|
eprintln!("Failed to download ledger: {}", err);
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
|
validator_config.expected_genesis_blockhash = Some(expected_genesis_blockhash);
|
||||||
} else {
|
} else {
|
||||||
// Without a cluster entrypoint, ledger_path must already be present
|
// Without a cluster entrypoint, ledger_path must already be present
|
||||||
if !ledger_path.is_dir() {
|
if !ledger_path.is_dir() {
|
||||||
|
|
Loading…
Reference in New Issue