Add time since genesis to sysvar::clock (#7289)
* genesis timestamp * remove clock::create_account() * .. * add configure-able creation time * dividing by 1T, should be dividing by 1B
This commit is contained in:
parent
1b2a9270e8
commit
777ae3c215
|
@ -3469,6 +3469,7 @@ name = "solana-genesis"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -11,6 +11,7 @@ homepage = "https://solana.com/"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.11.0"
|
base64 = "0.11.0"
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
|
chrono = "0.4"
|
||||||
hex = "0.4.0"
|
hex = "0.4.0"
|
||||||
serde = "1.0.103"
|
serde = "1.0.103"
|
||||||
serde_derive = "1.0.103"
|
serde_derive = "1.0.103"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//! A command-line executable for generating the chain's genesis config.
|
//! A command-line executable for generating the chain's genesis config.
|
||||||
|
|
||||||
|
use chrono::DateTime;
|
||||||
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::input_parsers::pubkey_of;
|
use solana_clap_utils::{input_parsers::pubkey_of, input_validators::is_valid_percentage};
|
||||||
use solana_clap_utils::input_validators::is_valid_percentage;
|
|
||||||
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
use solana_genesis::{genesis_accounts::add_genesis_accounts, Base64Account};
|
||||||
use solana_ledger::{blocktree::create_new_ledger, poh::compute_hashes_per_tick};
|
use solana_ledger::{blocktree::create_new_ledger, poh::compute_hashes_per_tick};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
@ -134,6 +134,13 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
let matches = App::new(crate_name!())
|
let matches = App::new(crate_name!())
|
||||||
.about(crate_description!())
|
.about(crate_description!())
|
||||||
.version(solana_clap_utils::version!())
|
.version(solana_clap_utils::version!())
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("creation_time")
|
||||||
|
.long("creation-time")
|
||||||
|
.value_name("RFC3339 DATE TIME")
|
||||||
|
.takes_value(true)
|
||||||
|
.help("Time when the bootrap leader will start, defaults to current system time"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("bootstrap_leader_pubkey_file")
|
Arg::with_name("bootstrap_leader_pubkey_file")
|
||||||
.short("b")
|
.short("b")
|
||||||
|
@ -477,6 +484,10 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
..GenesisConfig::default()
|
..GenesisConfig::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(creation_time) = matches.value_of("creation_time") {
|
||||||
|
genesis_config.creation_time = DateTime::parse_from_rfc3339(creation_time)?.timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(faucet_pubkey) = faucet_pubkey {
|
if let Some(faucet_pubkey) = faucet_pubkey {
|
||||||
genesis_config.add_account(
|
genesis_config.add_account(
|
||||||
faucet_pubkey,
|
faucet_pubkey,
|
||||||
|
|
|
@ -380,7 +380,7 @@ mod tests {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|meta| {
|
.map(|meta| {
|
||||||
if sysvar::clock::check_id(&meta.pubkey) {
|
if sysvar::clock::check_id(&meta.pubkey) {
|
||||||
sysvar::clock::create_account(1, 0, 0, 0, 0)
|
sysvar::clock::Clock::default().create_account(1)
|
||||||
} else if sysvar::rewards::check_id(&meta.pubkey) {
|
} else if sysvar::rewards::check_id(&meta.pubkey) {
|
||||||
sysvar::rewards::create_account(1, 0.0, 0.0)
|
sysvar::rewards::create_account(1, 0.0, 0.0)
|
||||||
} else if sysvar::stake_history::check_id(&meta.pubkey) {
|
} else if sysvar::stake_history::check_id(&meta.pubkey) {
|
||||||
|
@ -604,7 +604,7 @@ mod tests {
|
||||||
KeyedAccount::new(
|
KeyedAccount::new(
|
||||||
&sysvar::clock::id(),
|
&sysvar::clock::id(),
|
||||||
false,
|
false,
|
||||||
&mut sysvar::clock::create_account(1, 0, 0, 0, 0)
|
&mut sysvar::clock::Clock::default().create_account(1)
|
||||||
),
|
),
|
||||||
KeyedAccount::new(
|
KeyedAccount::new(
|
||||||
&config::id(),
|
&config::id(),
|
||||||
|
|
|
@ -159,7 +159,7 @@ mod tests {
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
);
|
);
|
||||||
// the proof is for segment 0, need to move the slot into segment 2
|
// the proof is for segment 0, need to move the slot into segment 2
|
||||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
let mut clock_account = Clock::default().create_account(1);
|
||||||
Clock::to_account(
|
Clock::to_account(
|
||||||
&Clock {
|
&Clock {
|
||||||
slot: DEFAULT_SLOTS_PER_SEGMENT * 2,
|
slot: DEFAULT_SLOTS_PER_SEGMENT * 2,
|
||||||
|
@ -186,7 +186,7 @@ mod tests {
|
||||||
let clock_id = clock::id();
|
let clock_id = clock::id();
|
||||||
let mut keyed_accounts = Vec::new();
|
let mut keyed_accounts = Vec::new();
|
||||||
let mut user_account = Account::default();
|
let mut user_account = Account::default();
|
||||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
let mut clock_account = Clock::default().create_account(1);
|
||||||
keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account));
|
keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account));
|
||||||
keyed_accounts.push(KeyedAccount::new(&clock_id, false, &mut clock_account));
|
keyed_accounts.push(KeyedAccount::new(&clock_id, false, &mut clock_account));
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ mod tests {
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
);
|
);
|
||||||
// move tick height into segment 1
|
// move tick height into segment 1
|
||||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
let mut clock_account = Clock::default().create_account(1);
|
||||||
Clock::to_account(
|
Clock::to_account(
|
||||||
&Clock {
|
&Clock {
|
||||||
slot: 16,
|
slot: 16,
|
||||||
|
@ -270,7 +270,7 @@ mod tests {
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
);
|
);
|
||||||
// move slot into segment 1
|
// move slot into segment 1
|
||||||
let mut clock_account = clock::create_account(1, 0, 0, 0, 0);
|
let mut clock_account = Clock::default().create_account(1);
|
||||||
Clock::to_account(
|
Clock::to_account(
|
||||||
&Clock {
|
&Clock {
|
||||||
slot: DEFAULT_SLOTS_PER_SEGMENT,
|
slot: DEFAULT_SLOTS_PER_SEGMENT,
|
||||||
|
|
|
@ -206,7 +206,7 @@ mod tests {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|meta| {
|
.map(|meta| {
|
||||||
if sysvar::clock::check_id(&meta.pubkey) {
|
if sysvar::clock::check_id(&meta.pubkey) {
|
||||||
sysvar::clock::create_account(1, 0, 0, 0, 0)
|
sysvar::clock::Clock::default().create_account(1)
|
||||||
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
|
} else if sysvar::slot_hashes::check_id(&meta.pubkey) {
|
||||||
sysvar::slot_hashes::create_account(1, &[])
|
sysvar::slot_hashes::create_account(1, &[])
|
||||||
} else if sysvar::rent::check_id(&meta.pubkey) {
|
} else if sysvar::rent::check_id(&meta.pubkey) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ use solana_metrics::{
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
clock::{get_segment_from_slot, Epoch, Slot, MAX_RECENT_BLOCKHASHES},
|
clock::{get_segment_from_slot, Epoch, Slot, UnixTimestamp, MAX_RECENT_BLOCKHASHES},
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeCalculator,
|
||||||
genesis_config::GenesisConfig,
|
genesis_config::GenesisConfig,
|
||||||
|
@ -190,6 +190,7 @@ pub struct Bank {
|
||||||
/// Hash of this Bank's parent's state
|
/// Hash of this Bank's parent's state
|
||||||
parent_hash: Hash,
|
parent_hash: Hash,
|
||||||
|
|
||||||
|
/// parent's slot
|
||||||
parent_slot: Slot,
|
parent_slot: Slot,
|
||||||
|
|
||||||
/// The number of transactions processed without error
|
/// The number of transactions processed without error
|
||||||
|
@ -221,6 +222,12 @@ pub struct Bank {
|
||||||
/// The number of ticks in each slot.
|
/// The number of ticks in each slot.
|
||||||
ticks_per_slot: u64,
|
ticks_per_slot: u64,
|
||||||
|
|
||||||
|
/// length of a slot in ns
|
||||||
|
ns_per_slot: u128,
|
||||||
|
|
||||||
|
/// genesis time, used for computed clock
|
||||||
|
genesis_creation_time: UnixTimestamp,
|
||||||
|
|
||||||
/// The number of slots per year, used for inflation
|
/// The number of slots per year, used for inflation
|
||||||
slots_per_year: f64,
|
slots_per_year: f64,
|
||||||
|
|
||||||
|
@ -352,6 +359,8 @@ impl Bank {
|
||||||
// TODO: clean this up, soo much special-case copying...
|
// TODO: clean this up, soo much special-case copying...
|
||||||
hashes_per_tick: parent.hashes_per_tick,
|
hashes_per_tick: parent.hashes_per_tick,
|
||||||
ticks_per_slot: parent.ticks_per_slot,
|
ticks_per_slot: parent.ticks_per_slot,
|
||||||
|
ns_per_slot: parent.ns_per_slot,
|
||||||
|
genesis_creation_time: parent.genesis_creation_time,
|
||||||
slots_per_segment: parent.slots_per_segment,
|
slots_per_segment: parent.slots_per_segment,
|
||||||
slots_per_year: parent.slots_per_year,
|
slots_per_year: parent.slots_per_year,
|
||||||
epoch_schedule,
|
epoch_schedule,
|
||||||
|
@ -474,16 +483,22 @@ impl Bank {
|
||||||
ancestors
|
ancestors
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// computed unix_timestamp at this slot height
|
||||||
|
pub fn unix_timestamp(&self) -> i64 {
|
||||||
|
self.genesis_creation_time + ((self.slot as u128 * self.ns_per_slot) / 1_000_000_000) as i64
|
||||||
|
}
|
||||||
|
|
||||||
fn update_clock(&self) {
|
fn update_clock(&self) {
|
||||||
self.store_account(
|
self.store_account(
|
||||||
&sysvar::clock::id(),
|
&sysvar::clock::id(),
|
||||||
&sysvar::clock::create_account(
|
&sysvar::clock::Clock {
|
||||||
1,
|
slot: self.slot,
|
||||||
self.slot,
|
segment: get_segment_from_slot(self.slot, self.slots_per_segment),
|
||||||
get_segment_from_slot(self.slot, self.slots_per_segment),
|
epoch: self.epoch_schedule.get_epoch(self.slot),
|
||||||
self.epoch_schedule.get_epoch(self.slot),
|
leader_schedule_epoch: self.epoch_schedule.get_leader_schedule_epoch(self.slot),
|
||||||
self.epoch_schedule.get_leader_schedule_epoch(self.slot),
|
unix_timestamp: self.unix_timestamp(),
|
||||||
),
|
}
|
||||||
|
.create_account(1),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,6 +729,9 @@ impl Bank {
|
||||||
|
|
||||||
self.hashes_per_tick = genesis_config.poh_config.hashes_per_tick;
|
self.hashes_per_tick = genesis_config.poh_config.hashes_per_tick;
|
||||||
self.ticks_per_slot = genesis_config.ticks_per_slot;
|
self.ticks_per_slot = genesis_config.ticks_per_slot;
|
||||||
|
self.ns_per_slot = genesis_config.poh_config.target_tick_duration.as_nanos()
|
||||||
|
* genesis_config.ticks_per_slot as u128;
|
||||||
|
self.genesis_creation_time = genesis_config.creation_time;
|
||||||
self.slots_per_segment = genesis_config.slots_per_segment;
|
self.slots_per_segment = genesis_config.slots_per_segment;
|
||||||
self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
|
self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
|
||||||
self.slots_per_year = years_as_slots(
|
self.slots_per_year = years_as_slots(
|
||||||
|
@ -1801,6 +1819,7 @@ mod tests {
|
||||||
signature::{Keypair, KeypairUtil},
|
signature::{Keypair, KeypairUtil},
|
||||||
system_instruction, system_program,
|
system_instruction, system_program,
|
||||||
sysvar::{fees::Fees, rewards::Rewards},
|
sysvar::{fees::Fees, rewards::Rewards},
|
||||||
|
timing::duration_as_s,
|
||||||
};
|
};
|
||||||
use solana_stake_program::{
|
use solana_stake_program::{
|
||||||
stake_instruction,
|
stake_instruction,
|
||||||
|
@ -1813,6 +1832,23 @@ mod tests {
|
||||||
use std::{io::Cursor, result, time::Duration};
|
use std::{io::Cursor, result, time::Duration};
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bank_unix_timestamp() {
|
||||||
|
let (genesis_config, _mint_keypair) = create_genesis_config(1);
|
||||||
|
let mut bank = Arc::new(Bank::new(&genesis_config));
|
||||||
|
|
||||||
|
assert_eq!(genesis_config.creation_time, bank.unix_timestamp());
|
||||||
|
let slots_per_sec = 1.0
|
||||||
|
/ (duration_as_s(&genesis_config.poh_config.target_tick_duration)
|
||||||
|
* genesis_config.ticks_per_slot as f32);
|
||||||
|
|
||||||
|
for _i in 0..slots_per_sec as usize + 1 {
|
||||||
|
bank = Arc::new(new_from_parent(&bank));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(bank.unix_timestamp() - genesis_config.creation_time >= 1);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bank_new() {
|
fn test_bank_new() {
|
||||||
let dummy_leader_pubkey = Pubkey::new_rand();
|
let dummy_leader_pubkey = Pubkey::new_rand();
|
||||||
|
|
|
@ -108,6 +108,9 @@ pub struct Clock {
|
||||||
/// the future Epoch for which the leader schedule has
|
/// the future Epoch for which the leader schedule has
|
||||||
/// most recently been calculated
|
/// most recently been calculated
|
||||||
pub leader_schedule_epoch: Epoch,
|
pub leader_schedule_epoch: Epoch,
|
||||||
|
/// computed from genesis creation time and network time
|
||||||
|
/// in slots, drifts!
|
||||||
|
pub unix_timestamp: UnixTimestamp,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
account::Account,
|
account::Account,
|
||||||
clock::{DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT},
|
clock::{UnixTimestamp, DEFAULT_SLOTS_PER_SEGMENT, DEFAULT_TICKS_PER_SLOT},
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeCalculator,
|
||||||
hash::{hash, Hash},
|
hash::{hash, Hash},
|
||||||
|
@ -21,6 +21,7 @@ use std::{
|
||||||
fs::{File, OpenOptions},
|
fs::{File, OpenOptions},
|
||||||
io::Write,
|
io::Write,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||||
|
@ -31,16 +32,27 @@ pub enum OperatingMode {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct GenesisConfig {
|
pub struct GenesisConfig {
|
||||||
|
/// when the network (bootstrap leader) was started relative to the UNIX Epoch
|
||||||
|
pub creation_time: UnixTimestamp,
|
||||||
|
/// initial accounts
|
||||||
pub accounts: BTreeMap<Pubkey, Account>,
|
pub accounts: BTreeMap<Pubkey, Account>,
|
||||||
|
/// built-in programs
|
||||||
pub native_instruction_processors: Vec<(String, Pubkey)>,
|
pub native_instruction_processors: Vec<(String, Pubkey)>,
|
||||||
|
/// accounts for network rewards, these do not count towards capitalization
|
||||||
pub rewards_pools: BTreeMap<Pubkey, Account>,
|
pub rewards_pools: BTreeMap<Pubkey, Account>,
|
||||||
pub ticks_per_slot: u64,
|
pub ticks_per_slot: u64,
|
||||||
pub slots_per_segment: u64,
|
pub slots_per_segment: u64,
|
||||||
|
/// network speed configuration
|
||||||
pub poh_config: PohConfig,
|
pub poh_config: PohConfig,
|
||||||
|
/// transaction fee config
|
||||||
pub fee_calculator: FeeCalculator,
|
pub fee_calculator: FeeCalculator,
|
||||||
|
/// rent config
|
||||||
pub rent: Rent,
|
pub rent: Rent,
|
||||||
|
/// inflation config
|
||||||
pub inflation: Inflation,
|
pub inflation: Inflation,
|
||||||
|
/// how slots map to epochs
|
||||||
pub epoch_schedule: EpochSchedule,
|
pub epoch_schedule: EpochSchedule,
|
||||||
|
/// network runlevel
|
||||||
pub operating_mode: OperatingMode,
|
pub operating_mode: OperatingMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +74,10 @@ pub fn create_genesis_config(lamports: u64) -> (GenesisConfig, Keypair) {
|
||||||
impl Default for GenesisConfig {
|
impl Default for GenesisConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
creation_time: SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_secs() as UnixTimestamp,
|
||||||
accounts: BTreeMap::default(),
|
accounts: BTreeMap::default(),
|
||||||
native_instruction_processors: Vec::default(),
|
native_instruction_processors: Vec::default(),
|
||||||
rewards_pools: BTreeMap::default(),
|
rewards_pools: BTreeMap::default(),
|
||||||
|
|
|
@ -2,40 +2,8 @@
|
||||||
//!
|
//!
|
||||||
pub use crate::clock::Clock;
|
pub use crate::clock::Clock;
|
||||||
|
|
||||||
use crate::{
|
use crate::sysvar::Sysvar;
|
||||||
account::Account,
|
|
||||||
clock::{Epoch, Segment, Slot},
|
|
||||||
sysvar::Sysvar,
|
|
||||||
};
|
|
||||||
|
|
||||||
crate::declare_sysvar_id!("SysvarC1ock11111111111111111111111111111111", Clock);
|
crate::declare_sysvar_id!("SysvarC1ock11111111111111111111111111111111", Clock);
|
||||||
|
|
||||||
impl Sysvar for Clock {}
|
impl Sysvar for Clock {}
|
||||||
|
|
||||||
pub fn create_account(
|
|
||||||
lamports: u64,
|
|
||||||
slot: Slot,
|
|
||||||
segment: Segment,
|
|
||||||
epoch: Epoch,
|
|
||||||
leader_schedule_epoch: Epoch,
|
|
||||||
) -> Account {
|
|
||||||
Clock {
|
|
||||||
slot,
|
|
||||||
segment,
|
|
||||||
epoch,
|
|
||||||
leader_schedule_epoch,
|
|
||||||
}
|
|
||||||
.create_account(lamports)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_new() {
|
|
||||||
let account = create_account(1, 0, 0, 0, 0);
|
|
||||||
let clock = Clock::from_account(&account).unwrap();
|
|
||||||
assert_eq!(clock, Clock::default());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue