diff --git a/Cargo.lock b/Cargo.lock index b8b734e8c2..ea2746d60f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3441,7 +3441,6 @@ version = "0.21.0" dependencies = [ "base64 0.11.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)", "serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ci/run-sanity.sh b/ci/run-sanity.sh index f83b8d6419..2d78237851 100755 --- a/ci/run-sanity.sh +++ b/ci/run-sanity.sh @@ -8,7 +8,7 @@ rm -f config/run/init-completed timeout 15 ./run.sh & pid=$! -attempts=20 +attempts=10 while [[ ! -f config/run/init-completed ]]; do sleep 1 if ((--attempts == 0)); then diff --git a/cli/src/cli.rs b/cli/src/cli.rs index df8922900a..273d2bf7e6 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -1871,10 +1871,7 @@ mod tests { stake_account: bob_keypair.into(), staker: None, withdrawer: None, - lockup: Lockup { - epoch: 0, - custodian, - }, + lockup: Lockup { slot: 0, custodian }, lamports: 1234, }; let signature = process_command(&config); diff --git a/cli/src/stake.rs b/cli/src/stake.rs index 1a6ef896ad..2d090e0e73 100644 --- a/cli/src/stake.rs +++ b/cli/src/stake.rs @@ -271,7 +271,7 @@ impl StakeSubCommands for App<'_, '_> { pub fn parse_stake_create_account(matches: &ArgMatches<'_>) -> Result { let stake_account = keypair_of(matches, "stake_account").unwrap(); - let epoch = value_of(&matches, "lockup").unwrap_or(0); + let slot = value_of(&matches, "lockup").unwrap_or(0); let custodian = pubkey_of(matches, "custodian").unwrap_or_default(); let staker = pubkey_of(matches, "authorized_staker"); let withdrawer = pubkey_of(matches, "authorized_withdrawer"); @@ -282,7 +282,7 @@ pub fn parse_stake_create_account(matches: &ArgMatches<'_>) -> Result Self { - Self { - base_pubkey: *base_pubkey, - base_name: base_name.to_string(), - nth: 0, - } - } - pub fn nth(&self, nth: usize) -> Pubkey { - Pubkey::new( - hashv(&[ - self.base_pubkey.as_ref(), - format!("{}:{}", self.base_name, nth).as_bytes(), - ]) - .as_ref(), - ) - } - pub fn next(&mut self) -> Pubkey { - let nth = self.nth; - self.nth += 1; - self.nth(nth) - } -} diff --git a/genesis/src/genesis_accounts.rs b/genesis/src/genesis_accounts.rs index 2e21055ec8..f2ca925c89 100644 --- a/genesis/src/genesis_accounts.rs +++ b/genesis/src/genesis_accounts.rs @@ -1,636 +1,7 @@ -use crate::{ - stakes::{create_and_add_stakes, StakerInfo}, - unlocks::UnlockInfo, -}; -use solana_sdk::{genesis_config::GenesisConfig, native_token::sol_to_lamports}; +use solana_sdk::{account::Account, pubkey::Pubkey}; -// 30 "month" schedule is 1/5th at 6 months -// 1/24 at each 1/12 of a year thereafter -const BATCH_ONE_UNLOCK_INFO: UnlockInfo = UnlockInfo { - cliff_fraction: 0.2, - cliff_years: 0.5, - unlocks: 24, - unlock_years: 1.0 / 12.0, -}; - -// 1st batch -const BATCH_ONE_STAKER_INFOS: &[StakerInfo] = &[ - StakerInfo { - name: "diligent bridge", - staker: "ab22196afde08a090a3721eb20e3e1ea84d36e14d1a3f0815b236b300d9d33ef", - withdrawer: "a2a7ae9098f862f4b3ba7d102d174de5e84a560444c39c035f3eeecce442eadc", - sol: 6_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "four wish", - staker: "6a56514c29f6b1de4d46164621d6bd25b337a711f569f9283c1143c7e8fb546e", - withdrawer: "b420af728f58d9f269d6e07fbbaecf6ed6535e5348538e3f39f2710351f2b940", - sol: 10_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "simple friends", - staker: "ddf2e4c81eafae2d68ac99171b066c87bddb168d6b7c07333cd951f36640163d", - withdrawer: "312fa06ccf1b671b26404a34136161ed2aba9e66f248441b4fddb5c592fde560", - sol: 1_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "noxious leather", - staker: "0cbf98cd35ceff84ca72b752c32cc3eeee4f765ca1bef1140927ebf5c6e74339", - withdrawer: "467e06fa25a9e06824eedc926ce431947ed99c728bed36be54561354c1330959", - sol: 6_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "worthless direction", - staker: "ef1562bf9edfd0f5e62530cce4244e8de544a3a30075a2cd5c9074edfbcbe78a", - withdrawer: "2ab26abb9d8131a30a4a63446125cf961ece4b926c31cce0eb84da4eac3f836e", - sol: 12_500_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "historical company", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 322_850.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "callous money", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 5_927_155.25, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "outstanding jump", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 625_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "feeble toes", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 750_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "disillusioned deer", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "unwritten songs", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "overt dime", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 500_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "slow committee", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 625_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "curvy twig", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 625_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "gamy scissors", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "mushy key", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "marked silver", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "free sock", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 625_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "tremendous meeting", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "panoramic cloth", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 625_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "normal kick", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 2_500_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "unbecoming observation", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "cut beginner", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "alcoholic button", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 625_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "old-fashioned clover", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 750_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "expensive underwear", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 2_500_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "like dust", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 5_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "rapid straw", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 5_850_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "windy trousers", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 2_579_350.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "dramatic veil", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 3_611_110.50, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "incandescent skin", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 3_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "spiky love", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 3_250_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, -]; - -// 30 "month" schedule is 1/5th at 6 months -// 1/24 at each 1/12 of a year thereafter -const BATCH_TWO_UNLOCK_INFO: UnlockInfo = UnlockInfo { - cliff_fraction: 0.2, - cliff_years: 0.5, - unlocks: 24, - unlock_years: 1.0 / 12.0, -}; -const BATCH_TWO_STAKER_INFOS: &[StakerInfo] = &[ - // 2nd batch - StakerInfo { - name: "macabre note", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "alcoholic letter", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "heady trucks", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "ten support", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "foregoing middle", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 800_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "ludicrous destruction", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "numberless wheel", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "short powder", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "cut name", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "six fly", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "mindless pickle", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 100_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "marked rabbit", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 38_741.36, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "jagged doctor", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 711_258.64, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "truthful pollution", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_587_300.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "unkempt activity", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 2_222_220.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "ritzy view", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 40_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "remarkable plant", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 300_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "busy value", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 100_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "imperfect slave", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 222_065.84, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "uneven drawer", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 400_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "far behavior", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 4_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "abaft memory", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 400_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "poor glove", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 2_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "strange iron", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 2_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "nonstop rail", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_000_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "milky bait", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 400_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "wandering start", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_200_000.0, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, -]; -// 30 "month" schedule is 1/5th at 6 months -// 1/24 at each 1/12 of a year thereafter -pub const BATCH_THREE_UNLOCK_INFO: UnlockInfo = UnlockInfo { - cliff_fraction: 0.2, - cliff_years: 0.5, - unlocks: 24, - unlock_years: 1.0 / 12.0, -}; -pub const BATCH_THREE_STAKER_INFOS: &[StakerInfo] = &[ - // 3rd batch - StakerInfo { - name: "dusty dress", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_212_121.21, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "godly bed", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 151_515.15, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "innocent property", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 227_272.73, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "responsible bikes", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 3_030_303.03, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "learned market", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 3_030_303.03, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "jumpy school", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 303_030.30, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "sticky houses", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_515_151.52, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "bustling basketball", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 1_515_152.52, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "ordinary dad", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 606_060.61, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "absurd bat", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 90_909.09, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "cloudy ocean", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 67_945.45, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "black-and-white fold", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 757_575.76, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "stale part", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 45_454.55, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "available health", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 2_797_575.76, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "afraid visitor", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 481_818.18, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "arrogant front", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 151_515.15, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "juvenile zinc", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 151_515.15, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "disturbed box", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 303_030.30, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "disagreeable skate", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 454_545.45, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "miscreant sidewalk", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 75_757.58, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - StakerInfo { - name: "shy play", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: 303_030.30, - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, -]; - -fn add_stakes( - genesis_config: &mut GenesisConfig, - staker_infos: &[StakerInfo], - unlock_info: &UnlockInfo, - granularity: u64, -) -> u64 { - staker_infos - .iter() - .map(|staker_info| { - create_and_add_stakes(genesis_config, staker_info, unlock_info, granularity) - }) - .sum::() -} - -pub(crate) fn add_genesis_accounts(genesis_config: &mut GenesisConfig) -> u64 { - add_stakes( - genesis_config, - &BATCH_ONE_STAKER_INFOS, - &BATCH_ONE_UNLOCK_INFO, - sol_to_lamports(1_000_000.0), - ) + add_stakes( - genesis_config, - &BATCH_TWO_STAKER_INFOS, - &BATCH_TWO_UNLOCK_INFO, - sol_to_lamports(1_000_000.0), - ) + add_stakes( - genesis_config, - &BATCH_THREE_STAKER_INFOS, - &BATCH_THREE_UNLOCK_INFO, - sol_to_lamports(1_000_000.0), - ) +pub(crate) fn create_genesis_accounts() -> Vec<(Pubkey, Account)> { + vec![] } #[cfg(test)] @@ -638,27 +9,7 @@ mod tests { use super::*; #[test] - fn test_add_genesis_accounts() { - let mut genesis_config = GenesisConfig::default(); - - let issued_lamports = add_genesis_accounts(&mut genesis_config); - - let lamports = genesis_config - .accounts - .iter() - .map(|(_, account)| account.lamports) - .sum::(); - - assert_eq!(issued_lamports, lamports); - - genesis_config - .accounts - .sort_by(|(ka, _), (kb, _)| ka.cmp(kb)); - - let len = genesis_config.accounts.len(); - genesis_config - .accounts - .dedup_by(|(ka, _), (kb, _)| ka == kb); - assert_eq!(genesis_config.accounts.len(), len); + fn test_create_genesis_accounts() { + assert_eq!(create_genesis_accounts(), vec![]); } } diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 1961f069cf..eb00b0f219 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -1,22 +1,19 @@ //! A command-line executable for generating the chain's genesis config. -mod address_generator; mod genesis_accounts; -mod stakes; -mod unlocks; -use crate::genesis_accounts::add_genesis_accounts; +use crate::genesis_accounts::create_genesis_accounts; 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_genesis::Base64Account; -use solana_ledger::{blocktree::create_new_ledger, poh::compute_hashes_per_tick}; +use solana_ledger::blocktree::create_new_ledger; +use solana_ledger::poh::compute_hashes_per_tick; use solana_sdk::{ account::Account, clock, epoch_schedule::EpochSchedule, fee_calculator::FeeCalculator, genesis_config::{GenesisConfig, OperatingMode}, - native_token::lamports_to_sol, native_token::sol_to_lamports, poh_config::PohConfig, pubkey::Pubkey, @@ -53,8 +50,7 @@ fn pubkey_from_str(key_str: &str) -> Result> { }) } -pub fn load_genesis_accounts(file: &str, genesis_config: &mut GenesisConfig) -> io::Result { - let mut lamports = 0; +pub fn add_genesis_accounts(file: &str, genesis_config: &mut GenesisConfig) -> io::Result<()> { let accounts_file = File::open(file.to_string())?; let genesis_accounts: HashMap = @@ -86,11 +82,11 @@ pub fn load_genesis_accounts(file: &str, genesis_config: &mut GenesisConfig) -> })?; } account.executable = account_details.executable; - lamports += account.lamports; + genesis_config.add_account(pubkey, account); } - Ok(lamports) + Ok(()) } #[allow(clippy::cognitive_complexity)] @@ -326,15 +322,15 @@ fn main() -> Result<(), Box> { let bootstrap_storage_pubkey = pubkey_of(&matches, "bootstrap_storage_pubkey_file"); let faucet_pubkey = pubkey_of(&matches, "faucet_pubkey_file"); + let bootstrap_leader_vote_account = + vote_state::create_account(&bootstrap_vote_pubkey, &bootstrap_leader_pubkey, 0, 1); + let rent = Rent { lamports_per_byte_year: value_t_or_exit!(matches, "lamports_per_byte_year", u64), exemption_threshold: value_t_or_exit!(matches, "rent_exemption_threshold", f64), burn_percent: value_t_or_exit!(matches, "rent_burn_percentage", u8), }; - let bootstrap_leader_vote_account = - vote_state::create_account(&bootstrap_vote_pubkey, &bootstrap_leader_pubkey, 0, 1); - let bootstrap_leader_stake_account = stake_state::create_account( &bootstrap_leader_pubkey, &bootstrap_vote_pubkey, @@ -362,6 +358,14 @@ fn main() -> Result<(), Box> { )); } + if let Some(faucet_pubkey) = faucet_pubkey { + accounts.push(( + faucet_pubkey, + Account::new(faucet_lamports.unwrap(), 0, &system_program::id()), + )); + } + accounts.append(&mut create_genesis_accounts()); + let ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64); let fee_calculator = FeeCalculator::new( @@ -384,6 +388,7 @@ fn main() -> Result<(), Box> { OperatingMode::Development => { let hashes_per_tick = compute_hashes_per_tick(poh_config.target_tick_duration, 1_000_000); + println!("Hashes per tick: {}", hashes_per_tick); poh_config.hashes_per_tick = Some(hashes_per_tick); } OperatingMode::SoftLaunch => { @@ -408,11 +413,14 @@ fn main() -> Result<(), Box> { } }; let epoch_schedule = EpochSchedule::new(slots_per_epoch); + println!( + "Genesis mode: {:?} hashes per tick: {:?} slots_per_epoch: {}", + operating_mode, poh_config.hashes_per_tick, slots_per_epoch + ); let native_instruction_processors = solana_genesis_programs::get_programs(operating_mode, 0).unwrap(); let inflation = solana_genesis_programs::get_inflation(operating_mode, 0).unwrap(); - let mut genesis_config = GenesisConfig { accounts, native_instruction_processors, @@ -426,46 +434,17 @@ fn main() -> Result<(), Box> { ..GenesisConfig::default() }; - if let Some(faucet_pubkey) = faucet_pubkey { - genesis_config.add_account( - faucet_pubkey, - Account::new(faucet_lamports.unwrap(), 0, &system_program::id()), - ); + if let Some(files) = matches.values_of("primordial_accounts_file") { + for file in files { + add_genesis_accounts(file, &mut genesis_config)?; + } } // add genesis stuff from storage and stake solana_storage_program::rewards_pools::add_genesis_accounts(&mut genesis_config); solana_stake_program::add_genesis_accounts(&mut genesis_config); - if let Some(files) = matches.values_of("primordial_accounts_file") { - for file in files { - load_genesis_accounts(file, &mut genesis_config)?; - } - } - - add_genesis_accounts(&mut genesis_config); - create_new_ledger(&ledger_path, &genesis_config)?; - - println!( - "Genesis mode: {:?} hashes per tick: {:?} slots_per_epoch: {} capitalization: {}SOL in {} accounts", - operating_mode, - genesis_config.poh_config.hashes_per_tick, - slots_per_epoch, - lamports_to_sol( - genesis_config - .accounts - .iter() - .map(|(pubkey, account)| { - if account.lamports == 0 { - panic!("{:?}", (pubkey, account)); - } - account.lamports - }) - .sum::()), - genesis_config.accounts.len() - ); - Ok(()) } @@ -483,7 +462,7 @@ mod tests { #[test] fn test_append_primordial_accounts_to_genesis() { // Test invalid file returns error - assert!(load_genesis_accounts("unknownfile", &mut GenesisConfig::default()).is_err()); + assert!(add_genesis_accounts("unknownfile", &mut GenesisConfig::default()).is_err()); let mut genesis_config = GenesisConfig::default(); @@ -521,7 +500,7 @@ mod tests { let mut file = File::create(path).unwrap(); file.write_all(&serialized.into_bytes()).unwrap(); - load_genesis_accounts( + add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", &mut genesis_config, ) @@ -593,7 +572,7 @@ mod tests { let mut file = File::create(path).unwrap(); file.write_all(&serialized.into_bytes()).unwrap(); - load_genesis_accounts( + add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", &mut genesis_config, ) @@ -693,7 +672,7 @@ mod tests { let mut file = File::create(path).unwrap(); file.write_all(&serialized.into_bytes()).unwrap(); - load_genesis_accounts( + add_genesis_accounts( "test_append_primordial_accounts_to_genesis.yml", &mut genesis_config, ) @@ -827,7 +806,7 @@ mod tests { file.write_all(yaml_string_pubkey.as_bytes()).unwrap(); let mut genesis_config = GenesisConfig::default(); - load_genesis_accounts(path.to_str().unwrap(), &mut genesis_config).expect("genesis"); + add_genesis_accounts(path.to_str().unwrap(), &mut genesis_config).expect("genesis"); remove_file(path).unwrap(); assert_eq!(genesis_config.accounts.len(), 4); @@ -855,7 +834,7 @@ mod tests { file.write_all(yaml_string_keypair.as_bytes()).unwrap(); let mut genesis_config = GenesisConfig::default(); - load_genesis_accounts(path.to_str().unwrap(), &mut genesis_config).expect("genesis"); + add_genesis_accounts(path.to_str().unwrap(), &mut genesis_config).expect("genesis"); remove_file(path).unwrap(); assert_eq!(genesis_config.accounts.len(), 3); diff --git a/genesis/src/stakes.rs b/genesis/src/stakes.rs deleted file mode 100644 index 73841ccc82..0000000000 --- a/genesis/src/stakes.rs +++ /dev/null @@ -1,265 +0,0 @@ -//! stakes generator -use crate::{ - address_generator::AddressGenerator, - unlocks::{UnlockInfo, Unlocks}, -}; -use solana_sdk::{ - account::Account, clock::Slot, genesis_config::GenesisConfig, native_token::sol_to_lamports, - pubkey::Pubkey, system_program, timing::years_as_slots, -}; -use solana_stake_program::stake_state::{ - create_lockup_stake_account, get_stake_rent_exempt_reserve, Authorized, Lockup, -}; - -#[derive(Debug)] -pub struct StakerInfo { - pub name: &'static str, - pub staker: &'static str, - pub withdrawer: &'static str, - pub sol: f64, - pub custodian: &'static str, -} - -// lamports required to run staking operations for one year -// the staker account needs to be rent exempt *and* carry enough -// lamports to cover TX fees (delegation) for one year, -// and we support one delegation per epoch -fn calculate_staker_lamports(genesis_config: &GenesisConfig) -> u64 { - genesis_config.rent.minimum_balance(0).max(1) - + genesis_config.fee_calculator.max_lamports_per_signature - * genesis_config.epoch_schedule.get_epoch(years_as_slots( - 1.0, - &genesis_config.poh_config.target_tick_duration, - genesis_config.ticks_per_slot, - ) as Slot) -} - -/// create stake accounts for lamports with at most stake_granularity in each -/// account -pub fn create_and_add_stakes( - genesis_config: &mut GenesisConfig, - // information about this staker for this group of stakes - staker_info: &StakerInfo, - // description of how the stakes' lockups will expire - unlock_info: &UnlockInfo, - // the largest each stake account should be, in lamports - granularity: u64, -) -> u64 { - let authorized = Authorized { - staker: Pubkey::new(&hex::decode(staker_info.staker).expect("hex")), - withdrawer: Pubkey::new(&hex::decode(staker_info.withdrawer).expect("hex")), - }; - let custodian = Pubkey::new(&hex::decode(staker_info.custodian).expect("hex")); - - let total_lamports = sol_to_lamports(staker_info.sol); - - let staker_lamports = calculate_staker_lamports(genesis_config); - let staker_account = ( - authorized.staker, - Account::new(staker_lamports, 0, &system_program::id()), - ); - - let stakes_lamports = if !genesis_config.accounts.contains(&staker_account) { - genesis_config.accounts.push(staker_account); - - total_lamports - staker_lamports - } else { - total_lamports - }; - - // the staker account needs to be rent exempt *and* carry enough - // lamports to cover TX fees (delegation) for one year - // as we support one re-delegation per epoch - let unlocks = Unlocks::new( - unlock_info.cliff_fraction, - unlock_info.cliff_years, - unlock_info.unlocks, - unlock_info.unlock_years, - &genesis_config.epoch_schedule, - &genesis_config.poh_config.target_tick_duration, - genesis_config.ticks_per_slot, - ); - - let mut address_generator = AddressGenerator::new(&authorized.staker, staker_info.name); - - let stake_rent_exempt_reserve = get_stake_rent_exempt_reserve(&genesis_config.rent); - - for unlock in unlocks { - let lamports = unlock.amount(stakes_lamports); - - let (granularity, remainder) = if granularity < lamports { - (granularity, lamports % granularity) - } else { - (lamports, 0) - }; - - let lockup = Lockup { - epoch: unlock.epoch, - custodian, - }; - for _ in 0..(lamports / granularity).saturating_sub(1) { - genesis_config.add_account( - address_generator.next(), - create_lockup_stake_account( - &authorized, - &lockup, - &genesis_config.rent, - granularity, - ), - ); - } - if remainder <= stake_rent_exempt_reserve { - genesis_config.add_account( - address_generator.next(), - create_lockup_stake_account( - &authorized, - &lockup, - &genesis_config.rent, - granularity + remainder, - ), - ); - } else { - genesis_config.add_account( - address_generator.next(), - create_lockup_stake_account( - &authorized, - &lockup, - &genesis_config.rent, - granularity, - ), - ); - genesis_config.add_account( - address_generator.next(), - create_lockup_stake_account(&authorized, &lockup, &genesis_config.rent, remainder), - ); - } - } - total_lamports -} - -#[cfg(test)] -mod tests { - use super::*; - use solana_sdk::{native_token::lamports_to_sol, rent::Rent}; - - fn create_and_check_stakes( - genesis_config: &mut GenesisConfig, - staker_info: &StakerInfo, - unlock_info: &UnlockInfo, - total_lamports: u64, - granularity: u64, - len: usize, - ) { - assert!( - total_lamports - == create_and_add_stakes(genesis_config, staker_info, unlock_info, granularity) - ); - - assert_eq!(genesis_config.accounts.len(), len); - assert_eq!( - genesis_config - .accounts - .iter() - .map(|(_pubkey, account)| account.lamports) - .sum::(), - total_lamports, - ); - assert!(genesis_config - .accounts - .iter() - .all(|(_pubkey, account)| account.lamports <= granularity - || account.lamports - granularity - < get_stake_rent_exempt_reserve(&genesis_config.rent))); - } - - #[test] - fn test_create_stakes() { - // 2 unlocks - - let rent = Rent { - lamports_per_byte_year: 1, - exemption_threshold: 1.0, - ..Rent::default() - }; - - let reserve = get_stake_rent_exempt_reserve(&rent); - - // verify that a small remainder ends up in the last stake - let granularity = reserve; - let total_lamports = reserve + reserve * 2 + 1; - create_and_check_stakes( - &mut GenesisConfig { - rent, - ..GenesisConfig::default() - }, - &StakerInfo { - name: "fun", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: lamports_to_sol(total_lamports), - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - &UnlockInfo { - cliff_fraction: 0.5, - cliff_years: 0.5, - unlocks: 1, - unlock_years: 0.5, - }, - total_lamports, - granularity, - 2 + 1, - ); - - // huge granularity doesn't blow up - let granularity = std::u64::MAX; - let total_lamports = reserve + reserve * 2 + 1; - create_and_check_stakes( - &mut GenesisConfig { - rent, - ..GenesisConfig::default() - }, - &StakerInfo { - name: "fun", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: lamports_to_sol(total_lamports), - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - &UnlockInfo { - cliff_fraction: 0.5, - cliff_years: 0.5, - unlocks: 1, - unlock_years: 0.5, - }, - total_lamports, - granularity, - 2 + 1, - ); - - // exactly reserve as a remainder - let granularity = reserve * 3; - let total_lamports = reserve + (granularity + reserve) * 2; - create_and_check_stakes( - &mut GenesisConfig { - rent, - ..GenesisConfig::default() - }, - &StakerInfo { - name: "fun", - staker: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - withdrawer: "cafebabedeadbeef000000000000000000000000000000000000000000000000", - sol: lamports_to_sol(total_lamports), - custodian: "0000000000000000000000000000000000000000000000000000000000000000", - }, - &UnlockInfo { - cliff_fraction: 0.5, - cliff_years: 0.5, - unlocks: 1, - unlock_years: 0.5, - }, - total_lamports, - granularity, - 4 + 1, - ); - } -} diff --git a/genesis/src/unlocks.rs b/genesis/src/unlocks.rs deleted file mode 100644 index 026a8e4e9b..0000000000 --- a/genesis/src/unlocks.rs +++ /dev/null @@ -1,210 +0,0 @@ -//! lockups generator -use solana_sdk::{clock::Epoch, epoch_schedule::EpochSchedule, timing::years_as_slots}; -use std::time::Duration; - -#[derive(Debug)] -pub struct UnlockInfo { - pub cliff_fraction: f64, - pub cliff_years: f64, - pub unlocks: usize, - pub unlock_years: f64, -} - -#[derive(Debug, Default, Clone)] -pub struct Unlocks { - /// where in iteration over unlocks, loop var - i: usize, - /// number of unlocks after the first cliff - unlocks: usize, - /// fraction unlocked as of last event - prev_fraction: f64, - - /// first cliff - /// fraction of unlocked at first cliff - cliff_fraction: f64, - /// time of cliff, in epochs, 0-based - cliff_epoch: Epoch, - - /// post cliff - /// fraction unlocked at each post-cliff unlock - unlock_fraction: f64, - /// time between each post-cliff unlock, in Epochs - unlock_epochs: Epoch, -} - -impl Unlocks { - pub fn new( - cliff_fraction: f64, // first cliff fraction - cliff_year: f64, // first cliff time, starting from genesis, in years - unlocks: usize, // number of follow-on unlocks - unlock_years: f64, // years between each following unlock - epoch_schedule: &EpochSchedule, - tick_duration: &Duration, - ticks_per_slot: u64, - ) -> Self { - // convert cliff year to a slot height, as the cliff_year is considered from genesis - let cliff_slot = years_as_slots(cliff_year, tick_duration, ticks_per_slot) as u64; - - // get the first cliff epoch from that slot height - let cliff_epoch = epoch_schedule.get_epoch(cliff_slot); - - // assumes that the first cliff is after any epoch warmup and that follow-on - // epochs are uniform in length - let first_unlock_slot = - years_as_slots(cliff_year + unlock_years, tick_duration, ticks_per_slot) as u64; - let unlock_epochs = epoch_schedule.get_epoch(first_unlock_slot) - cliff_epoch; - - Self::from_epochs(cliff_fraction, cliff_epoch, unlocks, unlock_epochs) - } - - pub fn from_epochs( - cliff_fraction: f64, // first cliff fraction - cliff_epoch: Epoch, // first cliff epoch - unlocks: usize, // number of follow-on unlocks - unlock_epochs: Epoch, // epochs between each following unlock - ) -> Self { - let unlock_fraction = if unlocks != 0 { - (1.0 - cliff_fraction) / unlocks as f64 - } else { - 0.0 - }; - - Self { - prev_fraction: 0.0, - i: 0, - unlocks, - cliff_fraction, - cliff_epoch, - unlock_fraction, - unlock_epochs, - } - } -} - -impl Iterator for Unlocks { - type Item = Unlock; - - fn next(&mut self) -> Option { - let i = self.i; - if i == 0 { - self.i += 1; - self.prev_fraction = self.cliff_fraction; - - Some(Unlock { - prev_fraction: 0.0, - fraction: self.cliff_fraction, - epoch: self.cliff_epoch, - }) - } else if i <= self.unlocks { - self.i += 1; - - let prev_fraction = self.prev_fraction; - // move forward, tortured-looking math comes from wanting to reach 1.0 by the last - // unlock - self.prev_fraction = 1.0 - (self.unlocks - i) as f64 * self.unlock_fraction; - - Some(Unlock { - prev_fraction, - fraction: self.prev_fraction, - epoch: self.cliff_epoch + i as u64 * self.unlock_epochs, - }) - } else { - None - } - } -} - -/// describes an unlock event -#[derive(Debug, Default)] -pub struct Unlock { - /// the epoch height at which this unlock occurs - pub epoch: Epoch, - /// the fraction that was unlocked last iteration - pub prev_fraction: f64, - /// the fraction unlocked this iteration - pub fraction: f64, -} - -impl Unlock { - /// the number of lamports unlocked at this event - #[allow(clippy::float_cmp)] - pub fn amount(&self, total: u64) -> u64 { - if self.fraction == 1.0 { - total - (self.prev_fraction * total as f64) as u64 - } else { - (self.fraction * total as f64) as u64 - (self.prev_fraction * total as f64) as u64 - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_make_lockups() { - // this number just a random val - let total_lamports: u64 = 1725987234408923; - - // expected config - const EPOCHS_PER_MONTH: Epoch = 2; - - assert_eq!( - Unlocks::from_epochs(0.20, 6 * EPOCHS_PER_MONTH, 24, EPOCHS_PER_MONTH) - .map(|unlock| unlock.amount(total_lamports)) - .sum::(), - total_lamports - ); - - // one tick/sec - let tick_duration = Duration::new(1, 0); - // one tick per slot - let ticks_per_slot = 1; - // two-week epochs at one second per slot - let epoch_schedule = EpochSchedule::custom(14 * 24 * 60 * 60, 0, false); - assert_eq!( - // 30 "month" schedule is 1/5th at 6 months - // 1/24 at each 1/12 of a year thereafter - Unlocks::new( - 0.20, - 0.5, - 24, - 1.0 / 12.0, - &epoch_schedule, - &tick_duration, - ticks_per_slot, - ) - .map(|unlock| { - if unlock.prev_fraction == 0.0 { - assert_eq!(unlock.epoch, 13); // 26 weeks is 1/2 year, first cliff - } else if unlock.prev_fraction == 0.2 { - assert_eq!(unlock.epoch, 15); // subsequent unlocks are separated by 2 weeks - } - unlock.amount(total_lamports) - }) - .sum::(), - total_lamports - ); - assert_eq!( - Unlocks::new( - 0.20, - 1.5, // start 1.5 years after genesis - 24, - 1.0 / 12.0, - &epoch_schedule, - &tick_duration, - ticks_per_slot, - ) - .map(|unlock| { - if unlock.prev_fraction == 0.0 { - assert_eq!(unlock.epoch, 26 + 13); // 26 weeks is 1/2 year, first cliff is 1.5 years - } else if unlock.prev_fraction == 0.2 { - assert_eq!(unlock.epoch, 26 + 15); // subsequent unlocks are separated by 2 weeks - } - unlock.amount(total_lamports) - }) - .sum::(), - total_lamports - ); - } -} diff --git a/programs/stake/src/config.rs b/programs/stake/src/config.rs index 05a3bb84ab..91bacd2f3d 100644 --- a/programs/stake/src/config.rs +++ b/programs/stake/src/config.rs @@ -5,8 +5,8 @@ use serde_derive::{Deserialize, Serialize}; use solana_config_program::{create_config_account, get_config_data, ConfigState}; use solana_sdk::{ account::{Account, KeyedAccount}, - genesis_config::GenesisConfig, instruction::InstructionError, + pubkey::Pubkey, }; // stake config ID @@ -52,15 +52,8 @@ impl ConfigState for Config { } } -pub fn add_genesis_account(genesis_config: &mut GenesisConfig) -> u64 { - let mut account = create_config_account(vec![], &Config::default(), 0); - let lamports = genesis_config.rent.minimum_balance(account.data.len()); - - account.lamports = lamports.max(1); - - genesis_config.add_account(id(), account); - - lamports +pub fn create_genesis_account() -> (Pubkey, Account) { + (id(), create_config_account(vec![], &Config::default(), 100)) } pub fn create_account(lamports: u64, config: &Config) -> Account { @@ -77,15 +70,19 @@ pub fn from_keyed_account(account: &KeyedAccount) -> Result u64 { - for (pubkey, account) in rewards_pools::create_genesis_accounts() { +pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig) { + for (pubkey, account) in create_rewards_accounts() { genesis_config.add_rewards_pool(pubkey, account); } - config::add_genesis_account(genesis_config) + let (pubkey, account) = create_genesis_account(); + genesis_config.add_account(pubkey, account); } diff --git a/programs/stake/src/rewards_pools.rs b/programs/stake/src/rewards_pools.rs index e00769704b..6af146ec6b 100644 --- a/programs/stake/src/rewards_pools.rs +++ b/programs/stake/src/rewards_pools.rs @@ -26,7 +26,7 @@ pub fn random_id() -> Pubkey { Pubkey::new(id.as_ref()) } -pub fn create_genesis_accounts() -> Vec<(Pubkey, Account)> { +pub fn create_rewards_accounts() -> Vec<(Pubkey, Account)> { let mut accounts = Vec::with_capacity(NUM_REWARDS_POOLS); let mut pubkey = id(); @@ -46,7 +46,7 @@ mod tests { #[test] fn test() { - let accounts = create_genesis_accounts(); + let accounts = create_rewards_accounts(); for _i in 0..NUM_REWARDS_POOLS { let id = random_id(); diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 3587e9acd1..425b62f70b 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -365,7 +365,7 @@ mod tests { } else if sysvar::stake_history::check_id(&meta.pubkey) { sysvar::stake_history::create_account(1, &StakeHistory::default()) } else if config::check_id(&meta.pubkey) { - config::create_account(0, &config::Config::default()) + config::create_account(1, &config::Config::default()) } else if sysvar::rent::check_id(&meta.pubkey) { sysvar::rent::create_account(1, &Rent::default()) } else { @@ -588,7 +588,7 @@ mod tests { KeyedAccount::new( &config::id(), false, - &mut config::create_account(0, &config::Config::default()) + &mut config::create_account(1, &config::Config::default()) ), ], &serialize(&StakeInstruction::DelegateStake).unwrap(), diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index 5f80599ad0..a964b2494c 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -72,9 +72,9 @@ pub enum StakeAuthorize { #[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] pub struct Lockup { - /// epoch at which this stake will allow withdrawal, unless + /// slot height at which this stake will allow withdrawal, unless /// to the custodian - pub epoch: Epoch, + pub slot: Slot, /// custodian account, the only account to which this stake will honor a /// withdrawal before lockup expires. After lockup expires, custodian /// is irrelevant @@ -94,6 +94,16 @@ pub struct Meta { pub lockup: Lockup, } +impl Meta { + pub fn auto(authorized: &Pubkey) -> Self { + Self { + authorized: Authorized::auto(authorized), + rent_exempt_reserve: Rent::default().minimum_balance(std::mem::size_of::()), + ..Meta::default() + } + } +} + #[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)] pub struct Stake { /// most recently delegated vote account pubkey @@ -705,7 +715,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> { // verify that lockup has expired or that the withdrawal is going back // to the custodian - if lockup.epoch > clock.epoch && lockup.custodian != *to.unsigned_key() { + if lockup.slot > clock.slot && lockup.custodian != *to.unsigned_key() { return Err(StakeError::LockupInForce.into()); } @@ -754,34 +764,7 @@ where } } -pub fn get_stake_rent_exempt_reserve(rent: &Rent) -> u64 { - rent.minimum_balance(std::mem::size_of::()) -} - -// genesis investor accounts -pub fn create_lockup_stake_account( - authorized: &Authorized, - lockup: &Lockup, - rent: &Rent, - lamports: u64, -) -> Account { - let mut stake_account = Account::new(lamports, std::mem::size_of::(), &id()); - - let rent_exempt_reserve = rent.minimum_balance(stake_account.data.len()); - assert!(lamports >= rent_exempt_reserve); - - stake_account - .set_state(&StakeState::Initialized(Meta { - authorized: *authorized, - lockup: *lockup, - rent_exempt_reserve, - })) - .expect("set_state"); - - stake_account -} - -// utility function, used by Bank, tests, genesis for bootstrap +// utility function, used by Bank, tests, genesis pub fn create_account( authorized: &Pubkey, voter_pubkey: &Pubkey, @@ -792,18 +775,19 @@ pub fn create_account( let mut stake_account = Account::new(lamports, std::mem::size_of::(), &id()); let vote_state = VoteState::from(vote_account).expect("vote_state"); - - let rent_exempt_reserve = rent.minimum_balance(stake_account.data.len()); - + let rent_exempt_reserve = rent.minimum_balance(std::mem::size_of::()); stake_account .set_state(&StakeState::Stake( Meta { - authorized: Authorized::auto(authorized), rent_exempt_reserve, - ..Meta::default() + authorized: Authorized { + staker: *authorized, + withdrawer: *authorized, + }, + lockup: Lockup::default(), }, Stake::new( - lamports - rent_exempt_reserve, // underflow is an error, is basically: assert!(lamports > rent_exempt_reserve); + lamports - rent_exempt_reserve, // underflow is an error, assert!(lamports> rent_exempt_reserve); voter_pubkey, &vote_state, std::u64::MAX, @@ -822,15 +806,6 @@ mod tests { use solana_sdk::{account::Account, pubkey::Pubkey, system_program}; use solana_vote_program::vote_state; - impl Meta { - pub fn auto(authorized: &Pubkey) -> Self { - Self { - authorized: Authorized::auto(authorized), - ..Meta::default() - } - } - } - #[test] fn test_stake_state_stake_from_fail() { let mut stake_account = Account::new(0, std::mem::size_of::(), &id()); @@ -1349,10 +1324,7 @@ mod tests { assert_eq!( stake_keyed_account.initialize( &Authorized::auto(&stake_pubkey), - &Lockup { - epoch: 1, - custodian - }, + &Lockup { slot: 1, custodian }, &Rent::default(), ), Ok(()) @@ -1361,14 +1333,8 @@ mod tests { assert_eq!( StakeState::from(&stake_keyed_account.account).unwrap(), StakeState::Initialized(Meta { - lockup: Lockup { - epoch: 1, - custodian - }, - ..Meta { - authorized: Authorized::auto(&stake_pubkey), - ..Meta::default() - } + lockup: Lockup { slot: 1, custodian }, + ..Meta::auto(&stake_pubkey) }) ); @@ -1501,10 +1467,7 @@ mod tests { stake_keyed_account .initialize( &Authorized::auto(&stake_pubkey), - &Lockup { - epoch: 0, - custodian, - }, + &Lockup { slot: 0, custodian }, &Rent::default(), ) .unwrap(); @@ -1703,10 +1666,7 @@ mod tests { let mut stake_account = Account::new_data_with_space( total_lamports, &StakeState::Initialized(Meta { - lockup: Lockup { - epoch: 1, - custodian, - }, + lockup: Lockup { slot: 1, custodian }, ..Meta::auto(&stake_pubkey) }), std::mem::size_of::(), @@ -1755,7 +1715,7 @@ mod tests { // lockup has expired let mut to_keyed_account = KeyedAccount::new(&to, false, &mut to_account); - clock.epoch += 1; + clock.slot += 1; assert_eq!( stake_keyed_account.withdraw( total_lamports, diff --git a/programs/storage/src/rewards_pools.rs b/programs/storage/src/rewards_pools.rs index ca7a938036..dc85883662 100644 --- a/programs/storage/src/rewards_pools.rs +++ b/programs/storage/src/rewards_pools.rs @@ -15,14 +15,13 @@ solana_sdk::declare_id!("StorageMiningPoo111111111111111111111111111"); // to cut down on collisions for redemptions, we make multiple accounts pub const NUM_REWARDS_POOLS: usize = 32; -pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig) -> u64 { +pub fn add_genesis_accounts(genesis_config: &mut GenesisConfig) { let mut pubkey = id(); for _i in 0..NUM_REWARDS_POOLS { genesis_config.add_rewards_pool(pubkey, create_rewards_pool()); pubkey = Pubkey::new(hash(pubkey.as_ref()).as_ref()); } - 0 // didn't consume any lamports } pub fn random_id() -> Pubkey { diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index b4b595106c..e21d96d469 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -41,7 +41,7 @@ use solana_sdk::{ slot_hashes::SlotHashes, system_transaction, sysvar::{self, Sysvar}, - timing::years_as_slots, + timing::duration_as_ns, transaction::{Result, Transaction, TransactionError}, }; use std::{ @@ -699,11 +699,12 @@ impl Bank { self.ticks_per_slot = genesis_config.ticks_per_slot; self.slots_per_segment = genesis_config.slots_per_segment; self.max_tick_height = (self.slot + 1) * self.ticks_per_slot; - self.slots_per_year = years_as_slots( - 1.0, - &genesis_config.poh_config.target_tick_duration, - self.ticks_per_slot, - ); + // ticks/year = seconds/year ... + self.slots_per_year = SECONDS_PER_YEAR + // * (ns/s)/(ns/tick) / ticks/slot = 1/s/1/tick = ticks/s + *(1_000_000_000.0 / duration_as_ns(&genesis_config.poh_config.target_tick_duration) as f64) + // / ticks/slot + / self.ticks_per_slot as f64; self.epoch_schedule = genesis_config.epoch_schedule; @@ -1689,6 +1690,7 @@ mod tests { signature::{Keypair, KeypairUtil}, system_instruction, sysvar::{fees::Fees, rewards::Rewards}, + timing::years_as_slots, }; use solana_stake_program::stake_state::Stake; use solana_vote_program::{ diff --git a/sdk/src/epoch_schedule.rs b/sdk/src/epoch_schedule.rs index 514ef19a5f..4c44370f81 100644 --- a/sdk/src/epoch_schedule.rs +++ b/sdk/src/epoch_schedule.rs @@ -45,7 +45,7 @@ impl EpochSchedule { pub fn new(slots_per_epoch: u64) -> Self { Self::custom(slots_per_epoch, slots_per_epoch, true) } - pub fn custom(slots_per_epoch: u64, leader_schedule_slot_offset: u64, warmup: bool) -> Self { + pub fn custom(slots_per_epoch: Epoch, leader_schedule_slot_offset: u64, warmup: bool) -> Self { assert!(slots_per_epoch >= MINIMUM_SLOTS_PER_EPOCH as u64); let (first_normal_epoch, first_normal_slot) = if warmup { let next_power_of_two = slots_per_epoch.next_power_of_two();