Submit a vote timestamp every vote (#10630)

* Submit a timestamp for every vote

* Submit at most one vote timestamp per second

* Submit a timestamp for every new vote

Co-authored-by: Tyera Eulberg <tyera@solana.com>
This commit is contained in:
Michael Vines 2020-08-21 10:10:51 -07:00 committed by GitHub
parent 41868f8adb
commit 247f27af37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 40 deletions

View File

@ -13,9 +13,7 @@ use solana_sdk::{
};
use solana_vote_program::{
vote_instruction,
vote_state::{
BlockTimestamp, Lockout, Vote, VoteState, MAX_LOCKOUT_HISTORY, TIMESTAMP_SLOT_INTERVAL,
},
vote_state::{BlockTimestamp, Lockout, Vote, VoteState, MAX_LOCKOUT_HISTORY},
};
use std::{
collections::{BTreeMap, HashMap, HashSet},
@ -345,6 +343,20 @@ impl Tower {
last_vote
}
fn maybe_timestamp(&mut self, current_slot: Slot) -> Option<UnixTimestamp> {
if current_slot > self.last_timestamp.slot {
let timestamp = Utc::now().timestamp();
if timestamp >= self.last_timestamp.timestamp {
self.last_timestamp = BlockTimestamp {
slot: current_slot,
timestamp,
};
return Some(timestamp);
}
}
None
}
pub fn root(&self) -> Option<Slot> {
self.lockouts.root_slot
}
@ -650,21 +662,6 @@ impl Tower {
);
}
}
fn maybe_timestamp(&mut self, current_slot: Slot) -> Option<UnixTimestamp> {
if self.last_timestamp.slot == 0
|| self.last_timestamp.slot < (current_slot - (current_slot % TIMESTAMP_SLOT_INTERVAL))
{
let timestamp = Utc::now().timestamp();
self.last_timestamp = BlockTimestamp {
slot: current_slot,
timestamp,
};
Some(timestamp)
} else {
None
}
}
}
#[cfg(test)]
@ -691,12 +688,7 @@ pub mod test {
vote_state::{Vote, VoteStateVersions, MAX_LOCKOUT_HISTORY},
vote_transaction,
};
use std::{
collections::HashMap,
rc::Rc,
sync::RwLock,
{thread::sleep, time::Duration},
};
use std::{collections::HashMap, rc::Rc, sync::RwLock};
use trees::{tr, Tree, TreeWalk};
pub(crate) struct VoteSimulator {
@ -1829,17 +1821,15 @@ pub mod test {
#[test]
fn test_maybe_timestamp() {
let mut tower = Tower::default();
assert!(tower.maybe_timestamp(TIMESTAMP_SLOT_INTERVAL).is_some());
let BlockTimestamp { slot, timestamp } = tower.last_timestamp;
assert!(tower.maybe_timestamp(0).is_none());
assert!(tower.maybe_timestamp(1).is_some());
assert!(tower.maybe_timestamp(0).is_none()); // Refuse to timestamp an older slot
assert!(tower.maybe_timestamp(1).is_none()); // Refuse to timestamp the same slot twice
assert_eq!(tower.maybe_timestamp(1), None);
assert_eq!(tower.maybe_timestamp(slot), None);
assert_eq!(tower.maybe_timestamp(slot + 1), None);
tower.last_timestamp.timestamp -= 1; // Move last_timestamp into the past
assert!(tower.maybe_timestamp(2).is_some()); // slot 2 gets a timestamp
sleep(Duration::from_secs(1));
assert!(tower
.maybe_timestamp(slot + TIMESTAMP_SLOT_INTERVAL + 1)
.is_some());
assert!(tower.last_timestamp.timestamp > timestamp);
tower.last_timestamp.timestamp += 1_000_000; // Move last_timestamp well into the future
assert!(tower.maybe_timestamp(3).is_none()); // slot 3 gets no timestamp
}
}

View File

@ -46,7 +46,7 @@ impl From<RpcCustomError> for Error {
},
RpcCustomError::BlockNotAvailable { slot } => Self {
code: ErrorCode::ServerError(JSON_RPC_SERVER_ERROR_4),
message: format!("Block not available for slot {}", slot,),
message: format!("Block not available for slot {}", slot),
data: None,
},
}

View File

@ -41,7 +41,7 @@ use solana_transaction_status::{
EncodedTransaction, Rewards, TransactionStatusMeta, TransactionWithStatusMeta,
UiTransactionEncoding, UiTransactionStatusMeta,
};
use solana_vote_program::{vote_instruction::VoteInstruction, vote_state::TIMESTAMP_SLOT_INTERVAL};
use solana_vote_program::vote_instruction::VoteInstruction;
use std::{
cell::RefCell,
cmp,
@ -78,6 +78,7 @@ thread_local!(static PAR_THREAD_POOL_ALL_CPUS: RefCell<ThreadPool> = RefCell::ne
pub const MAX_COMPLETED_SLOTS_IN_CHANNEL: usize = 100_000;
pub const MAX_TURBINE_PROPAGATION_IN_MS: u64 = 100;
pub const MAX_TURBINE_DELAY_IN_TICKS: u64 = MAX_TURBINE_PROPAGATION_IN_MS / MS_PER_TICK;
const TIMESTAMP_SLOT_INTERVAL: u64 = 4500;
const TIMESTAMP_SLOT_RANGE: usize = 16;
// An upper bound on maximum number of data shreds we can handle in a slot

View File

@ -32,10 +32,6 @@ pub const INITIAL_LOCKOUT: usize = 2;
// smaller numbers makes
pub const MAX_EPOCH_CREDITS_HISTORY: usize = 64;
// Frequency of timestamp Votes. In v0.22.0, this is approximately 30min with cluster clock
// defaults, intended to limit block time drift to < 1hr
pub const TIMESTAMP_SLOT_INTERVAL: u64 = 4500;
#[frozen_abi(digest = "69hYtmmcuqPbhpc64ZaNJDidaUcg66CW6wzPFiuYZ3To")]
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample)]
pub struct Vote {