2019-01-24 12:04:04 -08:00
|
|
|
//! The `genesis_block` module is a library for generating the chain's genesis block.
|
|
|
|
|
2019-02-18 22:26:22 -08:00
|
|
|
use crate::hash::{hash, Hash};
|
|
|
|
use crate::pubkey::Pubkey;
|
|
|
|
use crate::signature::{Keypair, KeypairUtil};
|
2019-02-21 16:01:10 -08:00
|
|
|
use crate::timing::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT};
|
2019-01-24 12:04:04 -08:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::Write;
|
|
|
|
use std::path::Path;
|
|
|
|
|
2019-03-05 16:28:14 -08:00
|
|
|
// The default (and minimal) amount of lamports given to the bootstrap leader:
|
2019-03-11 13:29:44 -07:00
|
|
|
// * 1 lamports for the bootstrap leader ID account
|
2019-03-05 16:28:14 -08:00
|
|
|
// * 1 lamport for the bootstrap leader vote account
|
2019-03-11 13:29:44 -07:00
|
|
|
pub const BOOTSTRAP_LEADER_LAMPORTS: u64 = 2;
|
2019-02-05 08:03:52 -08:00
|
|
|
|
2019-01-24 12:04:04 -08:00
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
|
|
pub struct GenesisBlock {
|
|
|
|
pub bootstrap_leader_id: Pubkey,
|
2019-03-05 16:28:14 -08:00
|
|
|
pub bootstrap_leader_lamports: u64,
|
2019-02-05 08:03:52 -08:00
|
|
|
pub bootstrap_leader_vote_account_id: Pubkey,
|
2019-01-24 12:04:04 -08:00
|
|
|
pub mint_id: Pubkey,
|
2019-03-05 16:28:14 -08:00
|
|
|
pub lamports: u64,
|
2019-02-21 16:01:10 -08:00
|
|
|
pub ticks_per_slot: u64,
|
|
|
|
pub slots_per_epoch: u64,
|
2019-02-25 08:38:30 -08:00
|
|
|
pub stakers_slot_offset: u64,
|
2019-03-06 16:32:23 -08:00
|
|
|
pub epoch_warmup: bool,
|
2019-01-24 12:04:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl GenesisBlock {
|
|
|
|
#[allow(clippy::new_ret_no_self)]
|
2019-03-05 16:28:14 -08:00
|
|
|
pub fn new(lamports: u64) -> (Self, Keypair) {
|
|
|
|
let lamports = lamports
|
|
|
|
.checked_add(BOOTSTRAP_LEADER_LAMPORTS)
|
|
|
|
.unwrap_or(lamports);
|
2019-03-09 19:28:43 -08:00
|
|
|
Self::new_with_leader(
|
|
|
|
lamports,
|
|
|
|
&Keypair::new().pubkey(),
|
|
|
|
BOOTSTRAP_LEADER_LAMPORTS,
|
|
|
|
)
|
2019-01-24 12:04:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_with_leader(
|
2019-03-05 16:28:14 -08:00
|
|
|
lamports: u64,
|
2019-03-09 19:28:43 -08:00
|
|
|
bootstrap_leader_id: &Pubkey,
|
2019-03-05 16:28:14 -08:00
|
|
|
bootstrap_leader_lamports: u64,
|
2019-01-24 12:04:04 -08:00
|
|
|
) -> (Self, Keypair) {
|
|
|
|
let mint_keypair = Keypair::new();
|
2019-02-05 08:03:52 -08:00
|
|
|
let bootstrap_leader_vote_account_keypair = Keypair::new();
|
2019-01-24 12:04:04 -08:00
|
|
|
(
|
|
|
|
Self {
|
2019-03-09 19:28:43 -08:00
|
|
|
bootstrap_leader_id: *bootstrap_leader_id,
|
2019-03-05 16:28:14 -08:00
|
|
|
bootstrap_leader_lamports,
|
2019-02-05 08:03:52 -08:00
|
|
|
bootstrap_leader_vote_account_id: bootstrap_leader_vote_account_keypair.pubkey(),
|
2019-01-24 12:04:04 -08:00
|
|
|
mint_id: mint_keypair.pubkey(),
|
2019-03-05 16:28:14 -08:00
|
|
|
lamports,
|
2019-02-21 16:01:10 -08:00
|
|
|
ticks_per_slot: DEFAULT_TICKS_PER_SLOT,
|
|
|
|
slots_per_epoch: DEFAULT_SLOTS_PER_EPOCH,
|
2019-02-25 08:38:30 -08:00
|
|
|
stakers_slot_offset: DEFAULT_SLOTS_PER_EPOCH,
|
2019-03-06 16:32:23 -08:00
|
|
|
epoch_warmup: true,
|
2019-01-24 12:04:04 -08:00
|
|
|
},
|
|
|
|
mint_keypair,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-03-01 09:49:37 -08:00
|
|
|
pub fn hash(&self) -> Hash {
|
2019-01-24 12:04:04 -08:00
|
|
|
let serialized = serde_json::to_string(self).unwrap();
|
|
|
|
hash(&serialized.into_bytes())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn load(ledger_path: &str) -> Result<Self, std::io::Error> {
|
|
|
|
let file = File::open(&Path::new(ledger_path).join("genesis.json"))?;
|
|
|
|
let genesis_block = serde_json::from_reader(file)?;
|
|
|
|
Ok(genesis_block)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn write(&self, ledger_path: &str) -> Result<(), std::io::Error> {
|
|
|
|
let serialized = serde_json::to_string(self)?;
|
|
|
|
let mut file = File::create(&Path::new(ledger_path).join("genesis.json"))?;
|
|
|
|
file.write_all(&serialized.into_bytes())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_genesis_block_new() {
|
|
|
|
let (genesis_block, mint) = GenesisBlock::new(10_000);
|
2019-03-05 16:28:14 -08:00
|
|
|
assert_eq!(genesis_block.lamports, 10_000 + BOOTSTRAP_LEADER_LAMPORTS);
|
2019-01-24 12:04:04 -08:00
|
|
|
assert_eq!(genesis_block.mint_id, mint.pubkey());
|
2019-02-05 08:03:52 -08:00
|
|
|
assert!(genesis_block.bootstrap_leader_id != Pubkey::default());
|
|
|
|
assert!(genesis_block.bootstrap_leader_vote_account_id != Pubkey::default());
|
|
|
|
assert_eq!(
|
2019-03-05 16:28:14 -08:00
|
|
|
genesis_block.bootstrap_leader_lamports,
|
|
|
|
BOOTSTRAP_LEADER_LAMPORTS
|
2019-02-05 08:03:52 -08:00
|
|
|
);
|
2019-01-24 12:04:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_genesis_block_new_with_leader() {
|
|
|
|
let leader_keypair = Keypair::new();
|
|
|
|
let (genesis_block, mint) =
|
2019-03-09 19:28:43 -08:00
|
|
|
GenesisBlock::new_with_leader(20_000, &leader_keypair.pubkey(), 123);
|
2019-01-24 12:04:04 -08:00
|
|
|
|
2019-03-05 16:28:14 -08:00
|
|
|
assert_eq!(genesis_block.lamports, 20_000);
|
2019-01-24 12:04:04 -08:00
|
|
|
assert_eq!(genesis_block.mint_id, mint.pubkey());
|
|
|
|
assert_eq!(genesis_block.bootstrap_leader_id, leader_keypair.pubkey());
|
2019-03-05 16:28:14 -08:00
|
|
|
assert_eq!(genesis_block.bootstrap_leader_lamports, 123);
|
2019-01-24 12:04:04 -08:00
|
|
|
}
|
|
|
|
}
|