1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
use crate::hash::{hash, Hash};
use crate::pubkey::Pubkey;
use crate::signature::{Keypair, KeypairUtil};
use crate::timing::{DEFAULT_SLOTS_PER_EPOCH, DEFAULT_TICKS_PER_SLOT};
use std::fs::File;
use std::io::Write;
use std::path::Path;
pub const BOOTSTRAP_LEADER_LAMPORTS: u64 = 2;
#[derive(Serialize, Deserialize, Debug)]
pub struct GenesisBlock {
pub bootstrap_leader_id: Pubkey,
pub bootstrap_leader_lamports: u64,
pub bootstrap_leader_vote_account_id: Pubkey,
pub mint_id: Pubkey,
pub lamports: u64,
pub ticks_per_slot: u64,
pub slots_per_epoch: u64,
pub stakers_slot_offset: u64,
pub epoch_warmup: bool,
pub native_instruction_processors: Vec<(String, Pubkey)>,
}
impl GenesisBlock {
#[allow(clippy::new_ret_no_self)]
pub fn new(lamports: u64) -> (Self, Keypair) {
let lamports = lamports
.checked_add(BOOTSTRAP_LEADER_LAMPORTS)
.unwrap_or(lamports);
Self::new_with_leader(lamports, &Pubkey::new_rand(), BOOTSTRAP_LEADER_LAMPORTS)
}
pub fn new_with_leader(
lamports: u64,
bootstrap_leader_id: &Pubkey,
bootstrap_leader_lamports: u64,
) -> (Self, Keypair) {
let mint_keypair = Keypair::new();
let bootstrap_leader_vote_account_keypair = Keypair::new();
(
Self {
bootstrap_leader_id: *bootstrap_leader_id,
bootstrap_leader_lamports,
bootstrap_leader_vote_account_id: bootstrap_leader_vote_account_keypair.pubkey(),
mint_id: mint_keypair.pubkey(),
lamports,
ticks_per_slot: DEFAULT_TICKS_PER_SLOT,
slots_per_epoch: DEFAULT_SLOTS_PER_EPOCH,
stakers_slot_offset: DEFAULT_SLOTS_PER_EPOCH,
epoch_warmup: true,
native_instruction_processors: vec![],
},
mint_keypair,
)
}
pub fn hash(&self) -> Hash {
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);
assert_eq!(genesis_block.lamports, 10_000 + BOOTSTRAP_LEADER_LAMPORTS);
assert_eq!(genesis_block.mint_id, mint.pubkey());
assert!(genesis_block.bootstrap_leader_id != Pubkey::default());
assert!(genesis_block.bootstrap_leader_vote_account_id != Pubkey::default());
assert_eq!(
genesis_block.bootstrap_leader_lamports,
BOOTSTRAP_LEADER_LAMPORTS
);
}
#[test]
fn test_genesis_block_new_with_leader() {
let leader_keypair = Keypair::new();
let (genesis_block, mint) =
GenesisBlock::new_with_leader(20_000, &leader_keypair.pubkey(), 123);
assert_eq!(genesis_block.lamports, 20_000);
assert_eq!(genesis_block.mint_id, mint.pubkey());
assert_eq!(genesis_block.bootstrap_leader_id, leader_keypair.pubkey());
assert_eq!(genesis_block.bootstrap_leader_lamports, 123);
}
}