Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
36398bc3f3 | |||
fa0e1ad356 | |||
f56c5dacca | |||
80e0da132a | |||
f89debdfa6 | |||
16f7e46fce | |||
3a039c8007 | |||
56d5324837 | |||
d3bf0fc707 | |||
f9d8a1d6c0 | |||
70559253ee | |||
9c61abe468 | |||
970954ac3b | |||
39d821ead8 |
@ -22,8 +22,9 @@ Methods
|
||||
---
|
||||
|
||||
* [confirmTransaction](#confirmtransaction)
|
||||
* [getBalance](#getbalance)
|
||||
* [getAccountInfo](#getaccountinfo)
|
||||
* [getBalance](#getbalance)
|
||||
* [getConfirmationTime](#getconfirmationTime)
|
||||
* [getLastId](#getlastid)
|
||||
* [getSignatureStatus](#getsignaturestatus)
|
||||
* [getTransactionCount](#gettransactioncount)
|
||||
@ -201,6 +202,25 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "m
|
||||
{"jsonrpc":"2.0","result":268,"id":1}
|
||||
```
|
||||
|
||||
---
|
||||
### getConfirmationTime
|
||||
Returns the current cluster confirmation time in milliseconds
|
||||
|
||||
##### Parameters:
|
||||
None
|
||||
|
||||
##### Results:
|
||||
* `integer` - confirmation time in milliseconds, as unsigned 64-bit integer
|
||||
|
||||
##### Example:
|
||||
```bash
|
||||
// Request
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getConfirmationTime"}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":500,"id":1}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### requestAirdrop
|
||||
|
@ -30,7 +30,7 @@ maybePackage="echo Package skipped"
|
||||
maybePublish="echo Publish skipped"
|
||||
|
||||
# Only package/publish if this is a tagged release
|
||||
if [[ -n $BUILDKITE_TAG && -n $TRIGGERED_BUILDKITE_TAG ]]; then
|
||||
if [[ -n $TRIGGERED_BUILDKITE_TAG ]]; then
|
||||
maybePackage="cargo package"
|
||||
|
||||
# Only publish if there's no human around
|
||||
|
@ -45,7 +45,7 @@ beta)
|
||||
CHANNEL_BRANCH=$BETA_CHANNEL
|
||||
;;
|
||||
stable)
|
||||
CHANNEL_BRANCH=$BETA_CHANNEL
|
||||
CHANNEL_BRANCH=$STABLE_CHANNEL
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid CHANNEL=$CHANNEL"
|
||||
|
@ -25,6 +25,7 @@ launchTestnet() {
|
||||
echo --- setup "$nodeCount" node test
|
||||
net/gce.sh create \
|
||||
-b \
|
||||
-d pd-ssd \
|
||||
-n "$nodeCount" -c "$CLIENT_COUNT" \
|
||||
-G "$LEADER_CPU_MACHINE_TYPE" \
|
||||
-p "$TESTNET_TAG" -z "$TESTNET_ZONE"
|
||||
@ -34,9 +35,9 @@ launchTestnet() {
|
||||
|
||||
echo --- start "$nodeCount" node test
|
||||
if [[ -n $USE_PREBUILT_CHANNEL_TARBALL ]]; then
|
||||
net/net.sh start -o noValidatorSanity -t "$CHANNEL"
|
||||
net/net.sh start -f "cuda" -o noValidatorSanity -t "$CHANNEL"
|
||||
else
|
||||
net/net.sh start -o noValidatorSanity -T solana*.tar.bz2
|
||||
net/net.sh start -f "cuda" -o noValidatorSanity -T solana*.tar.bz2
|
||||
fi
|
||||
|
||||
echo --- wait "$ITERATION_WAIT" seconds to complete test
|
||||
@ -56,24 +57,24 @@ launchTestnet() {
|
||||
WHERE time > now() - 300s GROUP BY time(1s)
|
||||
)'
|
||||
|
||||
declare q_mean_finality='
|
||||
SELECT round(mean("duration_ms")) as "mean_finality"
|
||||
FROM "testnet-automation"."autogen"."leader-finality"
|
||||
declare q_mean_confirmation='
|
||||
SELECT round(mean("duration_ms")) as "mean_confirmation"
|
||||
FROM "testnet-automation"."autogen"."leader-confirmation"
|
||||
WHERE time > now() - 300s'
|
||||
|
||||
declare q_max_finality='
|
||||
SELECT round(max("duration_ms")) as "max_finality"
|
||||
FROM "testnet-automation"."autogen"."leader-finality"
|
||||
declare q_max_confirmation='
|
||||
SELECT round(max("duration_ms")) as "max_confirmation"
|
||||
FROM "testnet-automation"."autogen"."leader-confirmation"
|
||||
WHERE time > now() - 300s'
|
||||
|
||||
declare q_99th_finality='
|
||||
SELECT round(percentile("duration_ms", 99)) as "99th_finality"
|
||||
FROM "testnet-automation"."autogen"."leader-finality"
|
||||
declare q_99th_confirmation='
|
||||
SELECT round(percentile("duration_ms", 99)) as "99th_confirmation"
|
||||
FROM "testnet-automation"."autogen"."leader-confirmation"
|
||||
WHERE time > now() - 300s'
|
||||
|
||||
curl -G "https://metrics.solana.com:8086/query?u=${INFLUX_USERNAME}&p=${INFLUX_PASSWORD}" \
|
||||
--data-urlencode "db=$INFLUX_DATABASE" \
|
||||
--data-urlencode "q=$q_mean_tps;$q_max_tps;$q_mean_finality;$q_max_finality;$q_99th_finality" |
|
||||
--data-urlencode "q=$q_mean_tps;$q_max_tps;$q_mean_confirmation;$q_max_confirmation;$q_99th_confirmation" |
|
||||
python ci/testnet-automation-json-parser.py >>TPS"$nodeCount".log
|
||||
|
||||
upload-ci-artifact TPS"$nodeCount".log
|
||||
|
@ -80,10 +80,11 @@ testnet-beta|testnet-beta-perf)
|
||||
testnet|testnet-perf)
|
||||
if [[ -n $BETA_CHANNEL_LATEST_TAG ]]; then
|
||||
CHANNEL_OR_TAG=$BETA_CHANNEL_LATEST_TAG
|
||||
CHANNEL_BRANCH=$BETA_CHANNEL
|
||||
else
|
||||
CHANNEL_OR_TAG=$STABLE_CHANNEL_LATEST_TAG
|
||||
CHANNEL_BRANCH=$STABLE_CHANNEL
|
||||
fi
|
||||
CHANNEL_BRANCH=$BETA_CHANNEL
|
||||
;;
|
||||
*)
|
||||
echo "Error: Invalid TESTNET=$TESTNET"
|
||||
|
@ -722,7 +722,7 @@
|
||||
],
|
||||
"orderByTime": "ASC",
|
||||
"policy": "default",
|
||||
"query": "SELECT mean(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-finality\" WHERE $timeFilter \n\n\n",
|
||||
"query": "SELECT mean(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-confirmation\" WHERE $timeFilter \n\n\n",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
@ -744,7 +744,7 @@
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Mean Finality",
|
||||
"title": "Mean Confirmation",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "70%",
|
||||
"valueMaps": [
|
||||
@ -833,7 +833,7 @@
|
||||
],
|
||||
"orderByTime": "ASC",
|
||||
"policy": "default",
|
||||
"query": "SELECT median(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-finality\" WHERE $timeFilter \n\n\n",
|
||||
"query": "SELECT median(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-confirmation\" WHERE $timeFilter \n\n\n",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
@ -855,7 +855,7 @@
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Median Finality",
|
||||
"title": "Median Confirmation",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "70%",
|
||||
"valueMaps": [
|
||||
@ -944,7 +944,7 @@
|
||||
],
|
||||
"orderByTime": "ASC",
|
||||
"policy": "default",
|
||||
"query": "SELECT min(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-finality\" WHERE $timeFilter \n\n\n",
|
||||
"query": "SELECT min(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-confirmation\" WHERE $timeFilter \n\n\n",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
@ -966,7 +966,7 @@
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Min Finality",
|
||||
"title": "Min Confirmation",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "70%",
|
||||
"valueMaps": [
|
||||
@ -1055,7 +1055,7 @@
|
||||
],
|
||||
"orderByTime": "ASC",
|
||||
"policy": "default",
|
||||
"query": "SELECT max(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-finality\" WHERE $timeFilter \n\n\n",
|
||||
"query": "SELECT max(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-confirmation\" WHERE $timeFilter \n\n\n",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
@ -1077,7 +1077,7 @@
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Max Finality",
|
||||
"title": "Max Confirmation",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "70%",
|
||||
"valueMaps": [
|
||||
@ -1166,7 +1166,7 @@
|
||||
],
|
||||
"orderByTime": "ASC",
|
||||
"policy": "default",
|
||||
"query": "SELECT percentile(\"duration_ms\", 99) FROM \"$testnet\".\"autogen\".\"leader-finality\" WHERE $timeFilter \n\n\n",
|
||||
"query": "SELECT percentile(\"duration_ms\", 99) FROM \"$testnet\".\"autogen\".\"leader-confirmation\" WHERE $timeFilter \n\n\n",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
@ -1188,7 +1188,7 @@
|
||||
}
|
||||
],
|
||||
"thresholds": "",
|
||||
"title": "Finality (99th percentile)",
|
||||
"title": "Confirmation (99th percentile)",
|
||||
"type": "singlestat",
|
||||
"valueFontSize": "70%",
|
||||
"valueMaps": [
|
||||
@ -1651,7 +1651,7 @@
|
||||
"measurement": "counter-cluster_info-vote-count",
|
||||
"orderByTime": "ASC",
|
||||
"policy": "autogen",
|
||||
"query": "SELECT mean(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-finality\" WHERE $timeFilter GROUP BY time(1s) FILL(0)\n",
|
||||
"query": "SELECT mean(\"duration_ms\") FROM \"$testnet\".\"autogen\".\"leader-confirmation\" WHERE $timeFilter GROUP BY time(1s) FILL(0)\n",
|
||||
"rawQuery": true,
|
||||
"refId": "A",
|
||||
"resultFormat": "time_series",
|
||||
@ -1675,7 +1675,7 @@
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Finality",
|
||||
"title": "Time since last Confirmation",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
|
@ -430,6 +430,10 @@ $(
|
||||
network-config.sh \
|
||||
remove-docker-interface.sh \
|
||||
|
||||
if "$enableGpu"; then
|
||||
cat enable-nvidia-persistence-mode.sh
|
||||
fi
|
||||
|
||||
)
|
||||
|
||||
cat > /etc/motd <<EOM
|
||||
|
2
net/scripts/enable-nvidia-persistence-mode.sh
Executable file
2
net/scripts/enable-nvidia-persistence-mode.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#!/usr/bin/env bash
|
||||
nvidia-smi -pm ENABLED || true
|
@ -14,7 +14,8 @@ fi
|
||||
|
||||
if [[ -z $CHANNEL ]]; then
|
||||
echo Unable to determine channel to publish into, exiting.
|
||||
exit 1
|
||||
echo "^^^ +++"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -rf usr/
|
||||
|
29
src/bank.rs
29
src/bank.rs
@ -94,8 +94,8 @@ pub struct Bank {
|
||||
/// FIFO queue of `last_id` items
|
||||
last_ids: RwLock<StatusDeque<Result<()>>>,
|
||||
|
||||
// The latest finality time for the network
|
||||
finality_time: AtomicUsize,
|
||||
// The latest confirmation time for the network
|
||||
confirmation_time: AtomicUsize,
|
||||
|
||||
// Mapping of account ids to Subscriber ids and sinks to notify on userdata update
|
||||
account_subscriptions: RwLock<HashMap<Pubkey, HashMap<Pubkey, Sink<Account>>>>,
|
||||
@ -115,7 +115,7 @@ impl Default for Bank {
|
||||
Bank {
|
||||
accounts: Accounts::default(),
|
||||
last_ids: RwLock::new(StatusDeque::default()),
|
||||
finality_time: AtomicUsize::new(std::usize::MAX),
|
||||
confirmation_time: AtomicUsize::new(std::usize::MAX),
|
||||
account_subscriptions: RwLock::new(HashMap::new()),
|
||||
signature_subscriptions: RwLock::new(HashMap::new()),
|
||||
leader_scheduler: Arc::new(RwLock::new(LeaderScheduler::default())),
|
||||
@ -316,14 +316,14 @@ impl Bank {
|
||||
}
|
||||
|
||||
/// Looks through a list of tick heights and stakes, and finds the latest
|
||||
/// tick that has achieved finality
|
||||
pub fn get_finality_timestamp(
|
||||
/// tick that has achieved confirmation
|
||||
pub fn get_confirmation_timestamp(
|
||||
&self,
|
||||
ticks_and_stakes: &mut [(u64, u64)],
|
||||
supermajority_stake: u64,
|
||||
) -> Option<u64> {
|
||||
let last_ids = self.last_ids.read().unwrap();
|
||||
last_ids.get_finality_timestamp(ticks_and_stakes, supermajority_stake)
|
||||
last_ids.get_confirmation_timestamp(ticks_and_stakes, supermajority_stake)
|
||||
}
|
||||
|
||||
/// Tell the bank which Entry IDs exist on the ledger. This function
|
||||
@ -871,12 +871,13 @@ impl Bank {
|
||||
self.accounts.hash_internal_state()
|
||||
}
|
||||
|
||||
pub fn finality(&self) -> usize {
|
||||
self.finality_time.load(Ordering::Relaxed)
|
||||
pub fn confirmation_time(&self) -> usize {
|
||||
self.confirmation_time.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub fn set_finality(&self, finality: usize) {
|
||||
self.finality_time.store(finality, Ordering::Relaxed);
|
||||
pub fn set_confirmation_time(&self, confirmation: usize) {
|
||||
self.confirmation_time
|
||||
.store(confirmation, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn send_account_notifications(
|
||||
@ -1403,11 +1404,11 @@ mod tests {
|
||||
assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
|
||||
}
|
||||
#[test]
|
||||
fn test_finality() {
|
||||
fn test_confirmation_time() {
|
||||
let def_bank = Bank::default();
|
||||
assert_eq!(def_bank.finality(), std::usize::MAX);
|
||||
def_bank.set_finality(90);
|
||||
assert_eq!(def_bank.finality(), 90);
|
||||
assert_eq!(def_bank.confirmation_time(), std::usize::MAX);
|
||||
def_bank.set_confirmation_time(90);
|
||||
assert_eq!(def_bank.confirmation_time(), 90);
|
||||
}
|
||||
#[test]
|
||||
fn test_interleaving_locks() {
|
||||
|
@ -3,7 +3,7 @@
|
||||
//! can do its processing in parallel with signature verification on the GPU.
|
||||
|
||||
use crate::bank::Bank;
|
||||
use crate::compute_leader_finality_service::ComputeLeaderFinalityService;
|
||||
use crate::compute_leader_confirmation_service::ComputeLeaderConfirmationService;
|
||||
use crate::counter::Counter;
|
||||
use crate::entry::Entry;
|
||||
use crate::packet::Packets;
|
||||
@ -40,7 +40,7 @@ pub struct BankingStage {
|
||||
/// Handle to the stage's thread.
|
||||
bank_thread_hdls: Vec<JoinHandle<Option<BankingStageReturnType>>>,
|
||||
poh_service: PohService,
|
||||
compute_finality_service: ComputeLeaderFinalityService,
|
||||
compute_confirmation_service: ComputeLeaderConfirmationService,
|
||||
}
|
||||
|
||||
impl BankingStage {
|
||||
@ -64,8 +64,8 @@ impl BankingStage {
|
||||
// Once an entry has been recorded, its last_id is registered with the bank.
|
||||
let poh_service = PohService::new(poh_recorder.clone(), config);
|
||||
|
||||
// Single thread to compute finality
|
||||
let compute_finality_service = ComputeLeaderFinalityService::new(
|
||||
// Single thread to compute confirmation
|
||||
let compute_confirmation_service = ComputeLeaderConfirmationService::new(
|
||||
bank.clone(),
|
||||
leader_id,
|
||||
poh_service.poh_exit.clone(),
|
||||
@ -120,7 +120,7 @@ impl BankingStage {
|
||||
Self {
|
||||
bank_thread_hdls,
|
||||
poh_service,
|
||||
compute_finality_service,
|
||||
compute_confirmation_service,
|
||||
},
|
||||
entry_receiver,
|
||||
)
|
||||
@ -239,7 +239,7 @@ impl Service for BankingStage {
|
||||
}
|
||||
}
|
||||
|
||||
self.compute_finality_service.join()?;
|
||||
self.compute_confirmation_service.join()?;
|
||||
|
||||
let poh_return_value = self.poh_service.join()?;
|
||||
match poh_return_value {
|
||||
|
79
src/compute_leader_finality_service.rs → src/compute_leader_confirmation_service.rs
Normal file → Executable file
79
src/compute_leader_finality_service.rs → src/compute_leader_confirmation_service.rs
Normal file → Executable file
@ -1,5 +1,5 @@
|
||||
//! The `compute_leader_finality_service` module implements the tools necessary
|
||||
//! to generate a thread which regularly calculates the last finality times
|
||||
//! The `compute_leader_confirmation_service` module implements the tools necessary
|
||||
//! to generate a thread which regularly calculates the last confirmation times
|
||||
//! observed by the leader
|
||||
|
||||
use crate::bank::Bank;
|
||||
@ -17,23 +17,23 @@ use std::thread::{self, Builder, JoinHandle};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum FinalityError {
|
||||
pub enum ConfirmationError {
|
||||
NoValidSupermajority,
|
||||
}
|
||||
|
||||
pub const COMPUTE_FINALITY_MS: u64 = 100;
|
||||
pub const COMPUTE_CONFIRMATION_MS: u64 = 100;
|
||||
|
||||
pub struct ComputeLeaderFinalityService {
|
||||
compute_finality_thread: JoinHandle<()>,
|
||||
pub struct ComputeLeaderConfirmationService {
|
||||
compute_confirmation_thread: JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl ComputeLeaderFinalityService {
|
||||
impl ComputeLeaderConfirmationService {
|
||||
fn get_last_supermajority_timestamp(
|
||||
bank: &Arc<Bank>,
|
||||
leader_id: Pubkey,
|
||||
now: u64,
|
||||
last_valid_validator_timestamp: u64,
|
||||
) -> result::Result<u64, FinalityError> {
|
||||
) -> result::Result<u64, ConfirmationError> {
|
||||
let mut total_stake = 0;
|
||||
|
||||
let mut ticks_and_stakes: Vec<(u64, u64)> = {
|
||||
@ -72,14 +72,14 @@ impl ComputeLeaderFinalityService {
|
||||
let super_majority_stake = (2 * total_stake) / 3;
|
||||
|
||||
if let Some(last_valid_validator_timestamp) =
|
||||
bank.get_finality_timestamp(&mut ticks_and_stakes, super_majority_stake)
|
||||
bank.get_confirmation_timestamp(&mut ticks_and_stakes, super_majority_stake)
|
||||
{
|
||||
return Ok(last_valid_validator_timestamp);
|
||||
}
|
||||
|
||||
if last_valid_validator_timestamp != 0 {
|
||||
submit(
|
||||
influxdb::Point::new(&"leader-finality")
|
||||
influxdb::Point::new(&"leader-confirmation")
|
||||
.add_field(
|
||||
"duration_ms",
|
||||
influxdb::Value::Integer((now - last_valid_validator_timestamp) as i64),
|
||||
@ -88,10 +88,10 @@ impl ComputeLeaderFinalityService {
|
||||
);
|
||||
}
|
||||
|
||||
Err(FinalityError::NoValidSupermajority)
|
||||
Err(ConfirmationError::NoValidSupermajority)
|
||||
}
|
||||
|
||||
pub fn compute_finality(
|
||||
pub fn compute_confirmation(
|
||||
bank: &Arc<Bank>,
|
||||
leader_id: Pubkey,
|
||||
last_valid_validator_timestamp: &mut u64,
|
||||
@ -103,53 +103,60 @@ impl ComputeLeaderFinalityService {
|
||||
now,
|
||||
*last_valid_validator_timestamp,
|
||||
) {
|
||||
let finality_ms = now - super_majority_timestamp;
|
||||
let confirmation_ms = now - super_majority_timestamp;
|
||||
|
||||
*last_valid_validator_timestamp = super_majority_timestamp;
|
||||
bank.set_finality((now - *last_valid_validator_timestamp) as usize);
|
||||
bank.set_confirmation_time((now - *last_valid_validator_timestamp) as usize);
|
||||
|
||||
submit(
|
||||
influxdb::Point::new(&"leader-finality")
|
||||
.add_field("duration_ms", influxdb::Value::Integer(finality_ms as i64))
|
||||
influxdb::Point::new(&"leader-confirmation")
|
||||
.add_field(
|
||||
"duration_ms",
|
||||
influxdb::Value::Integer(confirmation_ms as i64),
|
||||
)
|
||||
.to_owned(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new ComputeLeaderFinalityService for computing finality.
|
||||
/// Create a new ComputeLeaderConfirmationService for computing confirmation.
|
||||
pub fn new(bank: Arc<Bank>, leader_id: Pubkey, exit: Arc<AtomicBool>) -> Self {
|
||||
let compute_finality_thread = Builder::new()
|
||||
.name("solana-leader-finality-stage".to_string())
|
||||
let compute_confirmation_thread = Builder::new()
|
||||
.name("solana-leader-confirmation-stage".to_string())
|
||||
.spawn(move || {
|
||||
let mut last_valid_validator_timestamp = 0;
|
||||
loop {
|
||||
if exit.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
Self::compute_finality(&bank, leader_id, &mut last_valid_validator_timestamp);
|
||||
sleep(Duration::from_millis(COMPUTE_FINALITY_MS));
|
||||
Self::compute_confirmation(
|
||||
&bank,
|
||||
leader_id,
|
||||
&mut last_valid_validator_timestamp,
|
||||
);
|
||||
sleep(Duration::from_millis(COMPUTE_CONFIRMATION_MS));
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
(ComputeLeaderFinalityService {
|
||||
compute_finality_thread,
|
||||
(ComputeLeaderConfirmationService {
|
||||
compute_confirmation_thread,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Service for ComputeLeaderFinalityService {
|
||||
impl Service for ComputeLeaderConfirmationService {
|
||||
type JoinReturnType = ();
|
||||
|
||||
fn join(self) -> thread::Result<()> {
|
||||
self.compute_finality_thread.join()
|
||||
self.compute_confirmation_thread.join()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use crate::bank::Bank;
|
||||
use crate::compute_leader_finality_service::ComputeLeaderFinalityService;
|
||||
use crate::compute_leader_confirmation_service::ComputeLeaderConfirmationService;
|
||||
use crate::create_vote_account::*;
|
||||
|
||||
use crate::mint::Mint;
|
||||
@ -164,7 +171,7 @@ pub mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
fn test_compute_finality() {
|
||||
fn test_compute_confirmation() {
|
||||
solana_logger::setup();
|
||||
|
||||
let mint = Mint::new(1234);
|
||||
@ -206,14 +213,14 @@ pub mod tests {
|
||||
})
|
||||
.collect();
|
||||
|
||||
// There isn't 2/3 consensus, so the bank's finality value should be the default
|
||||
let mut last_finality_time = 0;
|
||||
ComputeLeaderFinalityService::compute_finality(
|
||||
// There isn't 2/3 consensus, so the bank's confirmation value should be the default
|
||||
let mut last_confirmation_time = 0;
|
||||
ComputeLeaderConfirmationService::compute_confirmation(
|
||||
&bank,
|
||||
dummy_leader_id,
|
||||
&mut last_finality_time,
|
||||
&mut last_confirmation_time,
|
||||
);
|
||||
assert_eq!(bank.finality(), std::usize::MAX);
|
||||
assert_eq!(bank.confirmation_time(), std::usize::MAX);
|
||||
|
||||
// Get another validator to vote, so we now have 2/3 consensus
|
||||
let vote_account = &vote_accounts[7];
|
||||
@ -221,12 +228,12 @@ pub mod tests {
|
||||
let vote_tx = Transaction::vote_new(&vote_account, vote, ids[6], 0);
|
||||
bank.process_transaction(&vote_tx).unwrap();
|
||||
|
||||
ComputeLeaderFinalityService::compute_finality(
|
||||
ComputeLeaderConfirmationService::compute_confirmation(
|
||||
&bank,
|
||||
dummy_leader_id,
|
||||
&mut last_finality_time,
|
||||
&mut last_confirmation_time,
|
||||
);
|
||||
assert!(bank.finality() != std::usize::MAX);
|
||||
assert!(last_finality_time > 0);
|
||||
assert!(bank.confirmation_time() != std::usize::MAX);
|
||||
assert!(last_confirmation_time > 0);
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ pub mod create_vote_account;
|
||||
#[macro_use]
|
||||
pub mod contact_info;
|
||||
pub mod cluster_info;
|
||||
pub mod compute_leader_finality_service;
|
||||
pub mod compute_leader_confirmation_service;
|
||||
pub mod db_ledger;
|
||||
pub mod db_window;
|
||||
pub mod entry;
|
||||
|
@ -25,7 +25,7 @@ use std::thread::{self, Builder, JoinHandle};
|
||||
use std::time::Duration;
|
||||
use std::time::Instant;
|
||||
|
||||
pub const BLOCK_TICK_COUNT: u64 = 8;
|
||||
pub const BLOCK_TICK_COUNT: u64 = 4;
|
||||
pub const MAX_ENTRY_RECV_PER_ITER: usize = 512;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
|
18
src/rpc.rs
18
src/rpc.rs
@ -135,8 +135,8 @@ build_rpc_trait! {
|
||||
#[rpc(meta, name = "getBalance")]
|
||||
fn get_balance(&self, Self::Metadata, String) -> Result<u64>;
|
||||
|
||||
#[rpc(meta, name = "getFinality")]
|
||||
fn get_finality(&self, Self::Metadata) -> Result<usize>;
|
||||
#[rpc(meta, name = "getConfirmationTime")]
|
||||
fn get_confirmation_time(&self, Self::Metadata) -> Result<usize>;
|
||||
|
||||
#[rpc(meta, name = "getLastId")]
|
||||
fn get_last_id(&self, Self::Metadata) -> Result<String>;
|
||||
@ -184,9 +184,9 @@ impl RpcSol for RpcSolImpl {
|
||||
let pubkey = verify_pubkey(id)?;
|
||||
meta.request_processor.get_balance(pubkey)
|
||||
}
|
||||
fn get_finality(&self, meta: Self::Metadata) -> Result<usize> {
|
||||
info!("get_finality rpc request received");
|
||||
meta.request_processor.get_finality()
|
||||
fn get_confirmation_time(&self, meta: Self::Metadata) -> Result<usize> {
|
||||
info!("get_confirmation_time rpc request received");
|
||||
meta.request_processor.get_confirmation_time()
|
||||
}
|
||||
fn get_last_id(&self, meta: Self::Metadata) -> Result<String> {
|
||||
info!("get_last_id rpc request received");
|
||||
@ -329,8 +329,8 @@ impl JsonRpcRequestProcessor {
|
||||
let val = self.bank.get_balance(&pubkey);
|
||||
Ok(val)
|
||||
}
|
||||
fn get_finality(&self) -> Result<usize> {
|
||||
Ok(self.bank.finality())
|
||||
fn get_confirmation_time(&self) -> Result<usize> {
|
||||
Ok(self.bank.confirmation_time())
|
||||
}
|
||||
fn get_last_id(&self) -> Result<String> {
|
||||
let id = self.bank.last_id();
|
||||
@ -612,11 +612,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_finality() {
|
||||
fn test_rpc_get_confirmation() {
|
||||
let bob_pubkey = Keypair::new().pubkey();
|
||||
let (io, meta, _last_id, _alice_keypair) = start_rpc_handler_with_tx(bob_pubkey);
|
||||
|
||||
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getFinality"}}"#);
|
||||
let req = format!(r#"{{"jsonrpc":"2.0","id":1,"method":"getConfirmationTime"}}"#);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let expected = format!(r#"{{"jsonrpc":"2.0","result":18446744073709551615,"id":1}}"#);
|
||||
let expected: Response =
|
||||
|
@ -44,7 +44,7 @@ pub enum RpcRequest {
|
||||
ConfirmTransaction,
|
||||
GetAccountInfo,
|
||||
GetBalance,
|
||||
GetFinality,
|
||||
GetConfirmationTime,
|
||||
GetLastId,
|
||||
GetSignatureStatus,
|
||||
GetTransactionCount,
|
||||
@ -89,7 +89,7 @@ impl RpcRequest {
|
||||
RpcRequest::ConfirmTransaction => "confirmTransaction",
|
||||
RpcRequest::GetAccountInfo => "getAccountInfo",
|
||||
RpcRequest::GetBalance => "getBalance",
|
||||
RpcRequest::GetFinality => "getFinality",
|
||||
RpcRequest::GetConfirmationTime => "getConfirmationTime",
|
||||
RpcRequest::GetLastId => "getLastId",
|
||||
RpcRequest::GetSignatureStatus => "getSignatureStatus",
|
||||
RpcRequest::GetTransactionCount => "getTransactionCount",
|
||||
@ -166,9 +166,9 @@ mod tests {
|
||||
);
|
||||
assert_eq!(request["method"], "getBalance");
|
||||
|
||||
let test_request = RpcRequest::GetFinality;
|
||||
let test_request = RpcRequest::GetConfirmationTime;
|
||||
let request = test_request.build_request_json(1, None);
|
||||
assert_eq!(request["method"], "getFinality");
|
||||
assert_eq!(request["method"], "getConfirmationTime");
|
||||
assert_eq!(request["params"], json!(null));
|
||||
|
||||
let test_request = RpcRequest::GetLastId;
|
||||
|
@ -44,7 +44,7 @@ struct StatusEntry<T> {
|
||||
/// when the id was registered, according to network time
|
||||
tick_height: u64,
|
||||
|
||||
/// timestamp when this id was registered, used for stats/finality
|
||||
/// timestamp when this id was registered, used for stats/confirmation
|
||||
timestamp: u64,
|
||||
|
||||
/// a map of signature status, used for duplicate detection
|
||||
@ -183,14 +183,14 @@ impl<T: Clone> StatusDeque<T> {
|
||||
}
|
||||
|
||||
/// Looks through a list of tick heights and stakes, and finds the latest
|
||||
/// tick that has achieved finality
|
||||
pub fn get_finality_timestamp(
|
||||
/// tick that has achieved confirmation
|
||||
pub fn get_confirmation_timestamp(
|
||||
&self,
|
||||
ticks_and_stakes: &mut [(u64, u64)],
|
||||
supermajority_stake: u64,
|
||||
) -> Option<u64> {
|
||||
// Sort by tick height
|
||||
ticks_and_stakes.sort_by(|a, b| a.0.cmp(&b.0));
|
||||
ticks_and_stakes.sort_by(|a, b| b.0.cmp(&a.0));
|
||||
let current_tick_height = self.tick_height;
|
||||
let mut total = 0;
|
||||
for (tick_height, stake) in ticks_and_stakes.iter() {
|
||||
|
@ -41,7 +41,7 @@ pub struct ThinClient {
|
||||
transaction_count: u64,
|
||||
balances: HashMap<Pubkey, Account>,
|
||||
signature_status: bool,
|
||||
finality: Option<usize>,
|
||||
confirmation: Option<usize>,
|
||||
|
||||
rpc_client: RpcClient,
|
||||
}
|
||||
@ -87,7 +87,7 @@ impl ThinClient {
|
||||
transaction_count: 0,
|
||||
balances: HashMap::new(),
|
||||
signature_status: false,
|
||||
finality: None,
|
||||
confirmation: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -187,23 +187,23 @@ impl ThinClient {
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "AccountNotFound"))
|
||||
}
|
||||
|
||||
/// Request the finality from the leader node
|
||||
pub fn get_finality(&mut self) -> usize {
|
||||
trace!("get_finality");
|
||||
/// Request the confirmation time from the leader node
|
||||
pub fn get_confirmation_time(&mut self) -> usize {
|
||||
trace!("get_confirmation_time");
|
||||
let mut done = false;
|
||||
while !done {
|
||||
debug!("get_finality send_to {}", &self.rpc_addr);
|
||||
let resp = RpcRequest::GetFinality.make_rpc_request(&self.rpc_client, 1, None);
|
||||
debug!("get_confirmation_time send_to {}", &self.rpc_addr);
|
||||
let resp = RpcRequest::GetConfirmationTime.make_rpc_request(&self.rpc_client, 1, None);
|
||||
|
||||
if let Ok(value) = resp {
|
||||
done = true;
|
||||
let finality = value.as_u64().unwrap() as usize;
|
||||
self.finality = Some(finality);
|
||||
let confirmation = value.as_u64().unwrap() as usize;
|
||||
self.confirmation = Some(confirmation);
|
||||
} else {
|
||||
debug!("thin_client get_finality error: {:?}", resp);
|
||||
debug!("thin_client get_confirmation_time error: {:?}", resp);
|
||||
}
|
||||
}
|
||||
self.finality.expect("some finality")
|
||||
self.confirmation.expect("some confirmation")
|
||||
}
|
||||
|
||||
/// Request the transaction count. If the response packet is dropped by the network,
|
||||
@ -477,8 +477,8 @@ mod tests {
|
||||
let mut client = ThinClient::new(leader_data.rpc, leader_data.tpu, transactions_socket);
|
||||
let transaction_count = client.transaction_count();
|
||||
assert_eq!(transaction_count, 0);
|
||||
let finality = client.get_finality();
|
||||
assert_eq!(finality, 18446744073709551615);
|
||||
let confirmation = client.get_confirmation_time();
|
||||
assert_eq!(confirmation, 18446744073709551615);
|
||||
let last_id = client.get_last_id();
|
||||
let signature = client
|
||||
.transfer(500, &alice.keypair(), bob_pubkey, &last_id)
|
||||
|
12
src/window_service.rs
Normal file → Executable file
12
src/window_service.rs
Normal file → Executable file
@ -89,12 +89,6 @@ fn recv_window(
|
||||
(p.index()?, p.meta.size)
|
||||
};
|
||||
|
||||
submit(
|
||||
influxdb::Point::new("window-service")
|
||||
.add_field("last-recv", influxdb::Value::Integer(pix as i64))
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
trace!("{} window pix: {} size: {}", id, pix, meta_size);
|
||||
|
||||
let _ = process_blob(
|
||||
@ -172,12 +166,6 @@ pub fn window_service(
|
||||
let received = meta.received;
|
||||
let consumed = meta.consumed;
|
||||
|
||||
submit(
|
||||
influxdb::Point::new("window-stage")
|
||||
.add_field("consumed", influxdb::Value::Integer(consumed as i64))
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
// Consumed should never be bigger than received
|
||||
assert!(consumed <= received);
|
||||
if received == consumed {
|
||||
|
@ -714,8 +714,8 @@ fn test_multi_node_dynamic_network() {
|
||||
let mut validators: Vec<_> = t2.into_iter().map(|t| t.join().unwrap()).collect();
|
||||
|
||||
let mut client = mk_client(&leader_data);
|
||||
let mut last_finality = client.get_finality();
|
||||
info!("Last finality {}", last_finality);
|
||||
let mut last_confirmation = client.get_confirmation_time();
|
||||
info!("Last confirmation {}", last_confirmation);
|
||||
let start = Instant::now();
|
||||
let mut consecutive_success = 0;
|
||||
let mut expected_balance = leader_balance;
|
||||
@ -738,28 +738,28 @@ fn test_multi_node_dynamic_network() {
|
||||
assert!(e.is_ok(), "err: {:?}", e);
|
||||
|
||||
let now = Instant::now();
|
||||
let mut finality = client.get_finality();
|
||||
let mut confirmation = client.get_confirmation_time();
|
||||
|
||||
// Need this to make sure the finality is updated
|
||||
// Need this to make sure the confirmation is updated
|
||||
// (i.e. the node is not returning stale value)
|
||||
while last_finality == finality {
|
||||
finality = client.get_finality();
|
||||
while last_confirmation == confirmation {
|
||||
confirmation = client.get_confirmation_time();
|
||||
}
|
||||
|
||||
while duration_as_ms(&now.elapsed()) < finality as u64 {
|
||||
while duration_as_ms(&now.elapsed()) < confirmation as u64 {
|
||||
sleep(Duration::from_millis(100));
|
||||
finality = client.get_finality()
|
||||
confirmation = client.get_confirmation_time()
|
||||
}
|
||||
|
||||
last_finality = finality;
|
||||
last_confirmation = confirmation;
|
||||
|
||||
let balance = retry_get_balance(&mut client, &bob_pubkey, Some(expected_balance));
|
||||
assert_eq!(balance, Some(expected_balance));
|
||||
consecutive_success += 1;
|
||||
|
||||
info!(
|
||||
"SUCCESS[{}] balance: {}, finality: {} ms",
|
||||
i, expected_balance, last_finality,
|
||||
"SUCCESS[{}] balance: {}, confirmation: {} ms",
|
||||
i, expected_balance, last_confirmation,
|
||||
);
|
||||
|
||||
if consecutive_success == 10 {
|
||||
|
Reference in New Issue
Block a user