Boot the Builder pattern from GenesisBlock (#6364)
This commit is contained in:
parent
41067de5e4
commit
ae41c88eb2
|
@ -3423,9 +3423,7 @@ name = "solana-genesis"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"bincode 1.2.0 (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)",
|
||||||
"rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3436,7 +3434,6 @@ dependencies = [
|
||||||
"solana-stake-api 0.20.0",
|
"solana-stake-api 0.20.0",
|
||||||
"solana-storage-api 0.20.0",
|
"solana-storage-api 0.20.0",
|
||||||
"solana-vote-api 0.20.0",
|
"solana-vote-api 0.20.0",
|
||||||
"sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use solana_drone::drone::request_airdrop_transaction;
|
||||||
use solana_exchange_api::exchange_instruction;
|
use solana_exchange_api::exchange_instruction;
|
||||||
use solana_exchange_api::exchange_state::*;
|
use solana_exchange_api::exchange_state::*;
|
||||||
use solana_exchange_api::id;
|
use solana_exchange_api::id;
|
||||||
use solana_genesis::PrimordialAccountDetails;
|
use solana_genesis::Base64Account;
|
||||||
use solana_metrics::datapoint_info;
|
use solana_metrics::datapoint_info;
|
||||||
use solana_sdk::client::Client;
|
use solana_sdk::client::Client;
|
||||||
use solana_sdk::client::SyncClient;
|
use solana_sdk::client::SyncClient;
|
||||||
|
@ -89,7 +89,7 @@ pub fn create_client_accounts_file(
|
||||||
keypairs.iter().for_each(|keypair| {
|
keypairs.iter().for_each(|keypair| {
|
||||||
accounts.insert(
|
accounts.insert(
|
||||||
serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap(),
|
serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
balance: fund_amount,
|
balance: fund_amount,
|
||||||
executable: false,
|
executable: false,
|
||||||
owner: system_program::id().to_string(),
|
owner: system_program::id().to_string(),
|
||||||
|
@ -140,8 +140,7 @@ where
|
||||||
let path = Path::new(&client_ids_and_stake_file);
|
let path = Path::new(&client_ids_and_stake_file);
|
||||||
let file = File::open(path).unwrap();
|
let file = File::open(path).unwrap();
|
||||||
|
|
||||||
let accounts: HashMap<String, PrimordialAccountDetails> =
|
let accounts: HashMap<String, Base64Account> = serde_yaml::from_reader(file).unwrap();
|
||||||
serde_yaml::from_reader(file).unwrap();
|
|
||||||
accounts
|
accounts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(keypair, _)| {
|
.map(|(keypair, _)| {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use log::*;
|
||||||
use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate_keypairs};
|
use solana_bench_tps::bench::{do_bench_tps, generate_and_fund_keypairs, generate_keypairs};
|
||||||
use solana_bench_tps::cli;
|
use solana_bench_tps::cli;
|
||||||
use solana_core::gossip_service::{discover_cluster, get_multi_client};
|
use solana_core::gossip_service::{discover_cluster, get_multi_client};
|
||||||
use solana_genesis::PrimordialAccountDetails;
|
use solana_genesis::Base64Account;
|
||||||
use solana_sdk::fee_calculator::FeeCalculator;
|
use solana_sdk::fee_calculator::FeeCalculator;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil};
|
use solana_sdk::signature::{Keypair, KeypairUtil};
|
||||||
use solana_sdk::system_program;
|
use solana_sdk::system_program;
|
||||||
|
@ -46,7 +46,7 @@ fn main() {
|
||||||
keypairs.iter().for_each(|keypair| {
|
keypairs.iter().for_each(|keypair| {
|
||||||
accounts.insert(
|
accounts.insert(
|
||||||
serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap(),
|
serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
balance: num_lamports_per_account,
|
balance: num_lamports_per_account,
|
||||||
executable: false,
|
executable: false,
|
||||||
owner: system_program::id().to_string(),
|
owner: system_program::id().to_string(),
|
||||||
|
@ -85,8 +85,7 @@ fn main() {
|
||||||
let file = File::open(path).unwrap();
|
let file = File::open(path).unwrap();
|
||||||
|
|
||||||
info!("Reading {}", client_ids_and_stake_file);
|
info!("Reading {}", client_ids_and_stake_file);
|
||||||
let accounts: HashMap<String, PrimordialAccountDetails> =
|
let accounts: HashMap<String, Base64Account> = serde_yaml::from_reader(file).unwrap();
|
||||||
serde_yaml::from_reader(file).unwrap();
|
|
||||||
let mut keypairs = vec![];
|
let mut keypairs = vec![];
|
||||||
let mut last_balance = 0;
|
let mut last_balance = 0;
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ homepage = "https://solana.com/"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.10.1"
|
base64 = "0.10.1"
|
||||||
bincode = "1.2.0"
|
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
serde = "1.0.101"
|
serde = "1.0.101"
|
||||||
serde_derive = "1.0.101"
|
serde_derive = "1.0.101"
|
||||||
|
@ -23,5 +22,3 @@ solana-stake-api = { path = "../programs/stake_api", version = "0.20.0" }
|
||||||
solana-storage-api = { path = "../programs/storage_api", version = "0.20.0" }
|
solana-storage-api = { path = "../programs/storage_api", version = "0.20.0" }
|
||||||
solana-vote-api = { path = "../programs/vote_api", version = "0.20.0" }
|
solana-vote-api = { path = "../programs/vote_api", version = "0.20.0" }
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
sys-info = "0.5.8"
|
|
||||||
rayon = "1.2.0"
|
|
|
@ -1,7 +1,8 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// An account where the data is encoded as a Base64 string.
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct PrimordialAccountDetails {
|
pub struct Base64Account {
|
||||||
pub balance: u64,
|
pub balance: u64,
|
||||||
pub owner: String,
|
pub owner: String,
|
||||||
pub data: String,
|
pub data: String,
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
//! A command-line executable for generating the chain's genesis block.
|
//! A command-line executable for generating the chain's genesis block.
|
||||||
|
|
||||||
use base64;
|
|
||||||
use clap::{crate_description, crate_name, crate_version, value_t_or_exit, App, Arg};
|
use clap::{crate_description, crate_name, crate_version, value_t_or_exit, App, Arg};
|
||||||
use solana_core::blocktree::create_new_ledger;
|
use solana_core::blocktree::create_new_ledger;
|
||||||
use solana_core::poh::compute_hashes_per_tick;
|
use solana_core::poh::compute_hashes_per_tick;
|
||||||
use solana_genesis::PrimordialAccountDetails;
|
use solana_genesis::Base64Account;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
clock,
|
clock,
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeCalculator,
|
||||||
genesis_block::Builder,
|
genesis_block::GenesisBlock,
|
||||||
poh_config::PohConfig,
|
poh_config::PohConfig,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent_calculator::RentCalculator,
|
rent_calculator::RentCalculator,
|
||||||
|
@ -29,18 +28,18 @@ pub enum AccountFileFormat {
|
||||||
Keypair,
|
Keypair,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append_primordial_accounts(
|
pub fn add_genesis_accounts(
|
||||||
file: &str,
|
file: &str,
|
||||||
file_format: AccountFileFormat,
|
file_format: AccountFileFormat,
|
||||||
mut builder: Builder,
|
genesis_block: &mut GenesisBlock,
|
||||||
) -> io::Result<(Builder)> {
|
) -> io::Result<()> {
|
||||||
let accounts_file = File::open(file.to_string())?;
|
let accounts_file = File::open(file.to_string())?;
|
||||||
|
|
||||||
let primordial_accounts: HashMap<String, PrimordialAccountDetails> =
|
let genesis_accounts: HashMap<String, Base64Account> =
|
||||||
serde_yaml::from_reader(accounts_file)
|
serde_yaml::from_reader(accounts_file)
|
||||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, format!("{:?}", err)))?;
|
.map_err(|err| io::Error::new(io::ErrorKind::Other, format!("{:?}", err)))?;
|
||||||
|
|
||||||
for (account, account_details) in primordial_accounts {
|
for (account, account_details) in genesis_accounts {
|
||||||
let pubkey = match file_format {
|
let pubkey = match file_format {
|
||||||
AccountFileFormat::Pubkey => Pubkey::from_str(account.as_str()).map_err(|err| {
|
AccountFileFormat::Pubkey => Pubkey::from_str(account.as_str()).map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
|
@ -72,10 +71,10 @@ pub fn append_primordial_accounts(
|
||||||
}
|
}
|
||||||
account.executable = account_details.executable;
|
account.executable = account_details.executable;
|
||||||
|
|
||||||
builder = builder.account(pubkey, account);
|
genesis_block.add_account(pubkey, account);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(builder)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
|
@ -317,50 +316,44 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
bootstrap_leader_stake_lamports,
|
bootstrap_leader_stake_lamports,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut builder = Builder::new()
|
let accounts = vec![
|
||||||
.accounts(&[
|
// the mint
|
||||||
// the mint
|
(
|
||||||
(
|
mint_keypair.pubkey(),
|
||||||
mint_keypair.pubkey(),
|
Account::new(lamports, 0, &system_program::id()),
|
||||||
Account::new(lamports, 0, &system_program::id()),
|
),
|
||||||
),
|
// node needs an account to issue votes from
|
||||||
// node needs an account to issue votes from
|
(
|
||||||
(
|
bootstrap_leader_keypair.pubkey(),
|
||||||
|
Account::new(bootstrap_leader_lamports, 0, &system_program::id()),
|
||||||
|
),
|
||||||
|
// where votes go to
|
||||||
|
(bootstrap_vote_keypair.pubkey(), vote_account),
|
||||||
|
// passive bootstrap leader stake
|
||||||
|
(bootstrap_stake_keypair.pubkey(), stake_account),
|
||||||
|
(
|
||||||
|
bootstrap_storage_keypair.pubkey(),
|
||||||
|
storage_contract::create_validator_storage_account(
|
||||||
bootstrap_leader_keypair.pubkey(),
|
bootstrap_leader_keypair.pubkey(),
|
||||||
Account::new(bootstrap_leader_lamports, 0, &system_program::id()),
|
1,
|
||||||
),
|
),
|
||||||
// where votes go to
|
),
|
||||||
(bootstrap_vote_keypair.pubkey(), vote_account),
|
];
|
||||||
// passive bootstrap leader stake
|
|
||||||
(bootstrap_stake_keypair.pubkey(), stake_account),
|
|
||||||
(
|
|
||||||
bootstrap_storage_keypair.pubkey(),
|
|
||||||
storage_contract::create_validator_storage_account(
|
|
||||||
bootstrap_leader_keypair.pubkey(),
|
|
||||||
1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
.native_instruction_processors(&solana_genesis_programs::get())
|
|
||||||
.ticks_per_slot(value_t_or_exit!(matches, "ticks_per_slot", u64));
|
|
||||||
|
|
||||||
|
let ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64);
|
||||||
let slots_per_epoch = value_t_or_exit!(matches, "slots_per_epoch", u64);
|
let slots_per_epoch = value_t_or_exit!(matches, "slots_per_epoch", u64);
|
||||||
let epoch_schedule = EpochSchedule::new(slots_per_epoch);
|
let epoch_schedule = EpochSchedule::new(slots_per_epoch);
|
||||||
|
|
||||||
builder = builder.epoch_schedule(epoch_schedule);
|
|
||||||
|
|
||||||
let fee_calculator = FeeCalculator::new(
|
let fee_calculator = FeeCalculator::new(
|
||||||
value_t_or_exit!(matches, "target_lamports_per_signature", u64),
|
value_t_or_exit!(matches, "target_lamports_per_signature", u64),
|
||||||
value_t_or_exit!(matches, "target_signatures_per_slot", usize),
|
value_t_or_exit!(matches, "target_signatures_per_slot", usize),
|
||||||
);
|
);
|
||||||
builder = builder.fee_calculator(fee_calculator);
|
|
||||||
|
|
||||||
let rent_calculator = RentCalculator {
|
let rent_calculator = RentCalculator {
|
||||||
lamports_per_byte_year: value_t_or_exit!(matches, "lamports_per_byte_year", u64),
|
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),
|
exemption_threshold: value_t_or_exit!(matches, "rent_exemption_threshold", f64),
|
||||||
burn_percent: value_t_or_exit!(matches, "rent_burn_percentage", u8),
|
burn_percent: value_t_or_exit!(matches, "rent_burn_percentage", u8),
|
||||||
};
|
};
|
||||||
builder = builder.rent_calculator(rent_calculator);
|
|
||||||
|
|
||||||
let mut poh_config = PohConfig::default();
|
let mut poh_config = PohConfig::default();
|
||||||
poh_config.target_tick_duration =
|
poh_config.target_tick_duration =
|
||||||
|
@ -380,28 +373,38 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
poh_config.hashes_per_tick = Some(value_t_or_exit!(matches, "hashes_per_tick", u64));
|
poh_config.hashes_per_tick = Some(value_t_or_exit!(matches, "hashes_per_tick", u64));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder = builder.poh_config(poh_config);
|
|
||||||
|
let mut genesis_block = GenesisBlock {
|
||||||
|
accounts,
|
||||||
|
native_instruction_processors: solana_genesis_programs::get(),
|
||||||
|
ticks_per_slot,
|
||||||
|
epoch_schedule,
|
||||||
|
fee_calculator,
|
||||||
|
rent_calculator,
|
||||||
|
poh_config,
|
||||||
|
..GenesisBlock::default()
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(file) = matches.value_of("primordial_accounts_file") {
|
if let Some(file) = matches.value_of("primordial_accounts_file") {
|
||||||
builder = append_primordial_accounts(file, AccountFileFormat::Pubkey, builder)?;
|
add_genesis_accounts(file, AccountFileFormat::Pubkey, &mut genesis_block)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(file) = matches.value_of("primordial_keypairs_file") {
|
if let Some(file) = matches.value_of("primordial_keypairs_file") {
|
||||||
builder = append_primordial_accounts(file, AccountFileFormat::Keypair, builder)?;
|
add_genesis_accounts(file, AccountFileFormat::Keypair, &mut genesis_block)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add genesis stuff from storage and stake
|
// add genesis stuff from storage and stake
|
||||||
builder = solana_storage_api::rewards_pools::genesis(builder);
|
solana_storage_api::rewards_pools::add_genesis_accounts(&mut genesis_block);
|
||||||
builder = solana_stake_api::genesis(builder);
|
solana_stake_api::add_genesis_accounts(&mut genesis_block);
|
||||||
|
|
||||||
create_new_ledger(&ledger_path, &builder.build())?;
|
create_new_ledger(&ledger_path, &genesis_block)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use solana_sdk::genesis_block::Builder;
|
use solana_sdk::genesis_block::GenesisBlock;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fs::remove_file;
|
use std::fs::remove_file;
|
||||||
|
@ -412,37 +415,37 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_append_primordial_accounts_to_genesis() {
|
fn test_append_primordial_accounts_to_genesis() {
|
||||||
// Test invalid file returns error
|
// Test invalid file returns error
|
||||||
assert!(append_primordial_accounts(
|
assert!(add_genesis_accounts(
|
||||||
"unknownfile",
|
"unknownfile",
|
||||||
AccountFileFormat::Pubkey,
|
AccountFileFormat::Pubkey,
|
||||||
Builder::new()
|
&mut GenesisBlock::default()
|
||||||
)
|
)
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
let mut builder = Builder::new();
|
let mut genesis_block = GenesisBlock::default();
|
||||||
|
|
||||||
let mut primordial_accounts = HashMap::new();
|
let mut genesis_accounts = HashMap::new();
|
||||||
primordial_accounts.insert(
|
genesis_accounts.insert(
|
||||||
Pubkey::new_rand().to_string(),
|
Pubkey::new_rand().to_string(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 2 as u64,
|
balance: 2 as u64,
|
||||||
executable: false,
|
executable: false,
|
||||||
data: String::from("aGVsbG8="),
|
data: String::from("aGVsbG8="),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
primordial_accounts.insert(
|
genesis_accounts.insert(
|
||||||
Pubkey::new_rand().to_string(),
|
Pubkey::new_rand().to_string(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 1 as u64,
|
balance: 1 as u64,
|
||||||
executable: true,
|
executable: true,
|
||||||
data: String::from("aGVsbG8gd29ybGQ="),
|
data: String::from("aGVsbG8gd29ybGQ="),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
primordial_accounts.insert(
|
genesis_accounts.insert(
|
||||||
Pubkey::new_rand().to_string(),
|
Pubkey::new_rand().to_string(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 3 as u64,
|
balance: 3 as u64,
|
||||||
executable: true,
|
executable: true,
|
||||||
|
@ -450,15 +453,15 @@ mod tests {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let serialized = serde_yaml::to_string(&primordial_accounts).unwrap();
|
let serialized = serde_yaml::to_string(&genesis_accounts).unwrap();
|
||||||
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
file.write_all(&serialized.into_bytes()).unwrap();
|
file.write_all(&serialized.into_bytes()).unwrap();
|
||||||
|
|
||||||
builder = append_primordial_accounts(
|
add_genesis_accounts(
|
||||||
"test_append_primordial_accounts_to_genesis.yml",
|
"test_append_primordial_accounts_to_genesis.yml",
|
||||||
AccountFileFormat::Pubkey,
|
AccountFileFormat::Pubkey,
|
||||||
builder,
|
&mut genesis_block,
|
||||||
)
|
)
|
||||||
.expect("test_append_primordial_accounts_to_genesis.yml");
|
.expect("test_append_primordial_accounts_to_genesis.yml");
|
||||||
// Test valid file returns ok
|
// Test valid file returns ok
|
||||||
|
@ -466,57 +469,56 @@ mod tests {
|
||||||
remove_file(path).unwrap();
|
remove_file(path).unwrap();
|
||||||
|
|
||||||
{
|
{
|
||||||
let genesis_block = builder.clone().build();
|
|
||||||
// Test all accounts were added
|
// Test all accounts were added
|
||||||
assert_eq!(genesis_block.accounts.len(), primordial_accounts.len());
|
assert_eq!(genesis_block.accounts.len(), genesis_accounts.len());
|
||||||
|
|
||||||
// Test account data matches
|
// Test account data matches
|
||||||
(0..primordial_accounts.len()).for_each(|i| {
|
(0..genesis_accounts.len()).for_each(|i| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts[&genesis_block.accounts[i].0.to_string()].owner,
|
genesis_accounts[&genesis_block.accounts[i].0.to_string()].owner,
|
||||||
genesis_block.accounts[i].1.owner.to_string()
|
genesis_block.accounts[i].1.owner.to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts[&genesis_block.accounts[i].0.to_string()].balance,
|
genesis_accounts[&genesis_block.accounts[i].0.to_string()].balance,
|
||||||
genesis_block.accounts[i].1.lamports
|
genesis_block.accounts[i].1.lamports
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts[&genesis_block.accounts[i].0.to_string()].executable,
|
genesis_accounts[&genesis_block.accounts[i].0.to_string()].executable,
|
||||||
genesis_block.accounts[i].1.executable
|
genesis_block.accounts[i].1.executable
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts[&genesis_block.accounts[i].0.to_string()].data,
|
genesis_accounts[&genesis_block.accounts[i].0.to_string()].data,
|
||||||
base64::encode(&genesis_block.accounts[i].1.data)
|
base64::encode(&genesis_block.accounts[i].1.data)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test more accounts can be appended
|
// Test more accounts can be appended
|
||||||
let mut primordial_accounts1 = HashMap::new();
|
let mut genesis_accounts1 = HashMap::new();
|
||||||
primordial_accounts1.insert(
|
genesis_accounts1.insert(
|
||||||
Pubkey::new_rand().to_string(),
|
Pubkey::new_rand().to_string(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 6 as u64,
|
balance: 6 as u64,
|
||||||
executable: true,
|
executable: true,
|
||||||
data: String::from("eW91IGFyZQ=="),
|
data: String::from("eW91IGFyZQ=="),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
primordial_accounts1.insert(
|
genesis_accounts1.insert(
|
||||||
Pubkey::new_rand().to_string(),
|
Pubkey::new_rand().to_string(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 5 as u64,
|
balance: 5 as u64,
|
||||||
executable: false,
|
executable: false,
|
||||||
data: String::from("bWV0YSBzdHJpbmc="),
|
data: String::from("bWV0YSBzdHJpbmc="),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
primordial_accounts1.insert(
|
genesis_accounts1.insert(
|
||||||
Pubkey::new_rand().to_string(),
|
Pubkey::new_rand().to_string(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 10 as u64,
|
balance: 10 as u64,
|
||||||
executable: false,
|
executable: false,
|
||||||
|
@ -524,101 +526,100 @@ mod tests {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let serialized = serde_yaml::to_string(&primordial_accounts1).unwrap();
|
let serialized = serde_yaml::to_string(&genesis_accounts1).unwrap();
|
||||||
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
file.write_all(&serialized.into_bytes()).unwrap();
|
file.write_all(&serialized.into_bytes()).unwrap();
|
||||||
|
|
||||||
builder = append_primordial_accounts(
|
add_genesis_accounts(
|
||||||
"test_append_primordial_accounts_to_genesis.yml",
|
"test_append_primordial_accounts_to_genesis.yml",
|
||||||
AccountFileFormat::Pubkey,
|
AccountFileFormat::Pubkey,
|
||||||
builder,
|
&mut genesis_block,
|
||||||
)
|
)
|
||||||
.expect("test_append_primordial_accounts_to_genesis.yml");
|
.expect("test_append_primordial_accounts_to_genesis.yml");
|
||||||
|
|
||||||
remove_file(path).unwrap();
|
remove_file(path).unwrap();
|
||||||
|
|
||||||
let genesis_block = builder.clone().build();
|
|
||||||
// Test total number of accounts is correct
|
// Test total number of accounts is correct
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
genesis_block.accounts.len(),
|
genesis_block.accounts.len(),
|
||||||
primordial_accounts.len() + primordial_accounts1.len()
|
genesis_accounts.len() + genesis_accounts1.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test old accounts are still there
|
// Test old accounts are still there
|
||||||
(0..primordial_accounts.len()).for_each(|i| {
|
(0..genesis_accounts.len()).for_each(|i| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts[&genesis_block.accounts[i].0.to_string()].balance,
|
genesis_accounts[&genesis_block.accounts[i].0.to_string()].balance,
|
||||||
genesis_block.accounts[i].1.lamports,
|
genesis_block.accounts[i].1.lamports,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test new account data matches
|
// Test new account data matches
|
||||||
(0..primordial_accounts1.len()).for_each(|i| {
|
(0..genesis_accounts1.len()).for_each(|i| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.owner,
|
.owner,
|
||||||
genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.1
|
.1
|
||||||
.owner
|
.owner
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.balance,
|
.balance,
|
||||||
genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.1
|
.1
|
||||||
.lamports,
|
.lamports,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.executable,
|
.executable,
|
||||||
genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.1
|
.1
|
||||||
.executable,
|
.executable,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.data,
|
.data,
|
||||||
base64::encode(&genesis_block.accounts[primordial_accounts.len() + i].1.data),
|
base64::encode(&genesis_block.accounts[genesis_accounts.len() + i].1.data),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test accounts from keypairs can be appended
|
// Test accounts from keypairs can be appended
|
||||||
let account_keypairs: Vec<_> = (0..3).map(|_| Keypair::new()).collect();
|
let account_keypairs: Vec<_> = (0..3).map(|_| Keypair::new()).collect();
|
||||||
let mut primordial_accounts2 = HashMap::new();
|
let mut genesis_accounts2 = HashMap::new();
|
||||||
primordial_accounts2.insert(
|
genesis_accounts2.insert(
|
||||||
serde_json::to_string(&account_keypairs[0].to_bytes().to_vec()).unwrap(),
|
serde_json::to_string(&account_keypairs[0].to_bytes().to_vec()).unwrap(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 20 as u64,
|
balance: 20 as u64,
|
||||||
executable: true,
|
executable: true,
|
||||||
data: String::from("Y2F0IGRvZw=="),
|
data: String::from("Y2F0IGRvZw=="),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
primordial_accounts2.insert(
|
genesis_accounts2.insert(
|
||||||
serde_json::to_string(&account_keypairs[1].to_bytes().to_vec()).unwrap(),
|
serde_json::to_string(&account_keypairs[1].to_bytes().to_vec()).unwrap(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 15 as u64,
|
balance: 15 as u64,
|
||||||
executable: false,
|
executable: false,
|
||||||
data: String::from("bW9ua2V5IGVsZXBoYW50"),
|
data: String::from("bW9ua2V5IGVsZXBoYW50"),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
primordial_accounts2.insert(
|
genesis_accounts2.insert(
|
||||||
serde_json::to_string(&account_keypairs[2].to_bytes().to_vec()).unwrap(),
|
serde_json::to_string(&account_keypairs[2].to_bytes().to_vec()).unwrap(),
|
||||||
PrimordialAccountDetails {
|
Base64Account {
|
||||||
owner: Pubkey::new_rand().to_string(),
|
owner: Pubkey::new_rand().to_string(),
|
||||||
balance: 30 as u64,
|
balance: 30 as u64,
|
||||||
executable: true,
|
executable: true,
|
||||||
|
@ -626,80 +627,79 @@ mod tests {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
let serialized = serde_yaml::to_string(&primordial_accounts2).unwrap();
|
let serialized = serde_yaml::to_string(&genesis_accounts2).unwrap();
|
||||||
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
file.write_all(&serialized.into_bytes()).unwrap();
|
file.write_all(&serialized.into_bytes()).unwrap();
|
||||||
|
|
||||||
builder = append_primordial_accounts(
|
add_genesis_accounts(
|
||||||
"test_append_primordial_accounts_to_genesis.yml",
|
"test_append_primordial_accounts_to_genesis.yml",
|
||||||
AccountFileFormat::Keypair,
|
AccountFileFormat::Keypair,
|
||||||
builder,
|
&mut genesis_block,
|
||||||
)
|
)
|
||||||
.expect("builder");
|
.expect("genesis");
|
||||||
|
|
||||||
builder = solana_storage_api::rewards_pools::genesis(builder);
|
solana_storage_api::rewards_pools::add_genesis_accounts(&mut genesis_block);
|
||||||
|
|
||||||
remove_file(path).unwrap();
|
remove_file(path).unwrap();
|
||||||
|
|
||||||
let genesis_block = builder.clone().build();
|
|
||||||
// Test total number of accounts is correct
|
// Test total number of accounts is correct
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
genesis_block.accounts.len(),
|
genesis_block.accounts.len(),
|
||||||
primordial_accounts.len() + primordial_accounts1.len() + primordial_accounts2.len()
|
genesis_accounts.len() + genesis_accounts1.len() + genesis_accounts2.len()
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test old accounts are still there
|
// Test old accounts are still there
|
||||||
(0..primordial_accounts.len()).for_each(|i| {
|
(0..genesis_accounts.len()).for_each(|i| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts[&genesis_block.accounts[i].0.to_string()].balance,
|
genesis_accounts[&genesis_block.accounts[i].0.to_string()].balance,
|
||||||
genesis_block.accounts[i].1.lamports,
|
genesis_block.accounts[i].1.lamports,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test new account data matches
|
// Test new account data matches
|
||||||
(0..primordial_accounts1.len()).for_each(|i| {
|
(0..genesis_accounts1.len()).for_each(|i| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.owner,
|
.owner,
|
||||||
genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.1
|
.1
|
||||||
.owner
|
.owner
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.balance,
|
.balance,
|
||||||
genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.1
|
.1
|
||||||
.lamports,
|
.lamports,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.executable,
|
.executable,
|
||||||
genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.1
|
.1
|
||||||
.executable,
|
.executable,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts1[&genesis_block.accounts[primordial_accounts.len() + i]
|
genesis_accounts1[&genesis_block.accounts[genesis_accounts.len() + i]
|
||||||
.0
|
.0
|
||||||
.to_string()]
|
.to_string()]
|
||||||
.data,
|
.data,
|
||||||
base64::encode(&genesis_block.accounts[primordial_accounts.len() + i].1.data),
|
base64::encode(&genesis_block.accounts[genesis_accounts.len() + i].1.data),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let offset = primordial_accounts.len() + primordial_accounts1.len();
|
let offset = genesis_accounts.len() + genesis_accounts1.len();
|
||||||
// Test account data for keypairs matches
|
// Test account data for keypairs matches
|
||||||
account_keypairs.iter().for_each(|keypair| {
|
account_keypairs.iter().for_each(|keypair| {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
@ -712,25 +712,25 @@ mod tests {
|
||||||
assert_ne!(i, 0);
|
assert_ne!(i, 0);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
||||||
.owner,
|
.owner,
|
||||||
genesis_block.accounts[i].1.owner.to_string(),
|
genesis_block.accounts[i].1.owner.to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
||||||
.balance,
|
.balance,
|
||||||
genesis_block.accounts[i].1.lamports,
|
genesis_block.accounts[i].1.lamports,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
||||||
.executable,
|
.executable,
|
||||||
genesis_block.accounts[i].1.executable,
|
genesis_block.accounts[i].1.executable,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
genesis_accounts2[&serde_json::to_string(&keypair.to_bytes().to_vec()).unwrap()]
|
||||||
.data,
|
.data,
|
||||||
base64::encode(&genesis_block.accounts[i].1.data),
|
base64::encode(&genesis_block.accounts[i].1.data),
|
||||||
);
|
);
|
||||||
|
@ -738,7 +738,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_primordial_account_struct_compatibility() {
|
fn test_genesis_account_struct_compatibility() {
|
||||||
let yaml_string_pubkey = "---
|
let yaml_string_pubkey = "---
|
||||||
98frSc8R8toHoS3tQ1xWSvHCvGEADRM9hAm5qmUKjSDX:
|
98frSc8R8toHoS3tQ1xWSvHCvGEADRM9hAm5qmUKjSDX:
|
||||||
balance: 4
|
balance: 4
|
||||||
|
@ -766,13 +766,15 @@ mod tests {
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
file.write_all(yaml_string_pubkey.as_bytes()).unwrap();
|
file.write_all(yaml_string_pubkey.as_bytes()).unwrap();
|
||||||
|
|
||||||
let builder = Builder::new();
|
let mut genesis_block = GenesisBlock::default();
|
||||||
let builder =
|
add_genesis_accounts(
|
||||||
append_primordial_accounts(path.to_str().unwrap(), AccountFileFormat::Pubkey, builder)
|
path.to_str().unwrap(),
|
||||||
.expect("builder");
|
AccountFileFormat::Pubkey,
|
||||||
|
&mut genesis_block,
|
||||||
|
)
|
||||||
|
.expect("genesis");
|
||||||
remove_file(path).unwrap();
|
remove_file(path).unwrap();
|
||||||
|
|
||||||
let genesis_block = builder.clone().build();
|
|
||||||
assert_eq!(genesis_block.accounts.len(), 4);
|
assert_eq!(genesis_block.accounts.len(), 4);
|
||||||
|
|
||||||
let yaml_string_keypair = "---
|
let yaml_string_keypair = "---
|
||||||
|
@ -797,13 +799,15 @@ mod tests {
|
||||||
let mut file = File::create(path).unwrap();
|
let mut file = File::create(path).unwrap();
|
||||||
file.write_all(yaml_string_keypair.as_bytes()).unwrap();
|
file.write_all(yaml_string_keypair.as_bytes()).unwrap();
|
||||||
|
|
||||||
let builder = Builder::new();
|
let mut genesis_block = GenesisBlock::default();
|
||||||
let builder =
|
add_genesis_accounts(
|
||||||
append_primordial_accounts(path.to_str().unwrap(), AccountFileFormat::Keypair, builder)
|
path.to_str().unwrap(),
|
||||||
.expect("builder");
|
AccountFileFormat::Keypair,
|
||||||
|
&mut genesis_block,
|
||||||
|
)
|
||||||
|
.expect("genesis");
|
||||||
remove_file(path).unwrap();
|
remove_file(path).unwrap();
|
||||||
|
|
||||||
let genesis_block = builder.clone().build();
|
|
||||||
assert_eq!(genesis_block.accounts.len(), 3);
|
assert_eq!(genesis_block.accounts.len(), 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl ConfigState for Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn genesis() -> (Pubkey, Account) {
|
pub fn create_genesis_account() -> (Pubkey, Account) {
|
||||||
(id(), create_config_account(vec![], &Config::default(), 100))
|
(id(), create_config_account(vec![], &Config::default(), 100))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ mod tests {
|
||||||
from_keyed_account(&KeyedAccount::new(&Pubkey::default(), false, &mut account)),
|
from_keyed_account(&KeyedAccount::new(&Pubkey::default(), false, &mut account)),
|
||||||
Err(InstructionError::InvalidArgument)
|
Err(InstructionError::InvalidArgument)
|
||||||
);
|
);
|
||||||
let (pubkey, mut account) = genesis();
|
let (pubkey, mut account) = create_genesis_account();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
from_keyed_account(&KeyedAccount::new(&pubkey, false, &mut account)),
|
from_keyed_account(&KeyedAccount::new(&pubkey, false, &mut account)),
|
||||||
Ok(Config::default())
|
Ok(Config::default())
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
use crate::config::create_genesis_account;
|
||||||
|
use crate::rewards_pools::create_rewards_accounts;
|
||||||
|
use solana_sdk::genesis_block::GenesisBlock;
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod rewards_pools;
|
pub mod rewards_pools;
|
||||||
pub mod stake_instruction;
|
pub mod stake_instruction;
|
||||||
|
@ -13,11 +17,11 @@ solana_sdk::solana_name_id!(
|
||||||
"Stake11111111111111111111111111111111111111"
|
"Stake11111111111111111111111111111111111111"
|
||||||
);
|
);
|
||||||
|
|
||||||
use solana_sdk::genesis_block::Builder;
|
pub fn add_genesis_accounts(genesis_block: &mut GenesisBlock) {
|
||||||
|
for (pubkey, account) in create_rewards_accounts() {
|
||||||
pub fn genesis(mut builder: Builder) -> Builder {
|
genesis_block.add_rewards_pool(pubkey, account);
|
||||||
for (pubkey, account) in crate::rewards_pools::genesis().iter() {
|
|
||||||
builder = builder.rewards_pool(*pubkey, account.clone());
|
|
||||||
}
|
}
|
||||||
builder.accounts(&[crate::config::genesis()])
|
|
||||||
|
let (pubkey, account) = create_genesis_account();
|
||||||
|
genesis_block.add_account(pubkey, account);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ pub fn random_id() -> Pubkey {
|
||||||
Pubkey::new(id.as_ref())
|
Pubkey::new(id.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn genesis() -> Vec<(Pubkey, Account)> {
|
pub fn create_rewards_accounts() -> Vec<(Pubkey, Account)> {
|
||||||
let mut accounts = Vec::with_capacity(NUM_REWARDS_POOLS);
|
let mut accounts = Vec::with_capacity(NUM_REWARDS_POOLS);
|
||||||
let mut pubkey = id();
|
let mut pubkey = id();
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let accounts = genesis();
|
let accounts = create_rewards_accounts();
|
||||||
|
|
||||||
for _i in 0..NUM_REWARDS_POOLS {
|
for _i in 0..NUM_REWARDS_POOLS {
|
||||||
let id = random_id();
|
let id = random_id();
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use crate::storage_contract::create_rewards_pool;
|
use crate::storage_contract::create_rewards_pool;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use solana_sdk::genesis_block::Builder;
|
use solana_sdk::genesis_block::GenesisBlock;
|
||||||
use solana_sdk::hash::{hash, Hash};
|
use solana_sdk::hash::{hash, Hash};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
|
||||||
|
@ -20,14 +20,13 @@ solana_sdk::solana_name_id!(ID, "StorageMiningPoo111111111111111111111111111");
|
||||||
// to cut down on collisions for redemptions, we make multiple accounts
|
// to cut down on collisions for redemptions, we make multiple accounts
|
||||||
pub const NUM_REWARDS_POOLS: usize = 32;
|
pub const NUM_REWARDS_POOLS: usize = 32;
|
||||||
|
|
||||||
pub fn genesis(mut builder: Builder) -> Builder {
|
pub fn add_genesis_accounts(genesis_block: &mut GenesisBlock) {
|
||||||
let mut pubkey = id();
|
let mut pubkey = id();
|
||||||
|
|
||||||
for _i in 0..NUM_REWARDS_POOLS {
|
for _i in 0..NUM_REWARDS_POOLS {
|
||||||
builder = builder.rewards_pool(pubkey, create_rewards_pool());
|
genesis_block.add_rewards_pool(pubkey, create_rewards_pool());
|
||||||
pubkey = Pubkey::new(hash(pubkey.as_ref()).as_ref());
|
pubkey = Pubkey::new(hash(pubkey.as_ref()).as_ref());
|
||||||
}
|
}
|
||||||
builder
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn random_id() -> Pubkey {
|
pub fn random_id() -> Pubkey {
|
||||||
|
@ -43,13 +42,11 @@ pub fn random_id() -> Pubkey {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use solana_sdk::genesis_block::Builder;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let builder = Builder::new();
|
let mut genesis_block = GenesisBlock::default();
|
||||||
|
add_genesis_accounts(&mut genesis_block);
|
||||||
let genesis_block = genesis(builder).build();
|
|
||||||
|
|
||||||
for _i in 0..NUM_REWARDS_POOLS {
|
for _i in 0..NUM_REWARDS_POOLS {
|
||||||
let id = random_id();
|
let id = random_id();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
fee_calculator::FeeCalculator,
|
fee_calculator::FeeCalculator,
|
||||||
genesis_block::{Builder, GenesisBlock},
|
genesis_block::GenesisBlock,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::{Keypair, KeypairUtil},
|
signature::{Keypair, KeypairUtil},
|
||||||
system_program::{self, solana_system_program},
|
system_program::{self, solana_system_program},
|
||||||
|
@ -47,38 +47,45 @@ pub fn create_genesis_block_with_leader(
|
||||||
bootstrap_leader_stake_lamports,
|
bootstrap_leader_stake_lamports,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut builder = Builder::new()
|
let accounts = vec![
|
||||||
.accounts(&[
|
// the mint
|
||||||
// the mint
|
(
|
||||||
(
|
mint_keypair.pubkey(),
|
||||||
mint_keypair.pubkey(),
|
Account::new(mint_lamports, 0, &system_program::id()),
|
||||||
Account::new(mint_lamports, 0, &system_program::id()),
|
),
|
||||||
),
|
// node needs an account to issue votes and storage proofs from, this will require
|
||||||
// node needs an account to issue votes and storage proofs from, this will require
|
// airdrops at some point to cover fees...
|
||||||
// airdrops at some point to cover fees...
|
(
|
||||||
(
|
*bootstrap_leader_pubkey,
|
||||||
*bootstrap_leader_pubkey,
|
Account::new(bootstrap_leader_lamports, 0, &system_program::id()),
|
||||||
Account::new(bootstrap_leader_lamports, 0, &system_program::id()),
|
),
|
||||||
),
|
// where votes go to
|
||||||
// where votes go to
|
(voting_keypair.pubkey(), vote_account),
|
||||||
(voting_keypair.pubkey(), vote_account),
|
// passive bootstrap leader stake, duplicates above temporarily
|
||||||
// passive bootstrap leader stake, duplicates above temporarily
|
(staking_keypair.pubkey(), stake_account),
|
||||||
(staking_keypair.pubkey(), stake_account),
|
];
|
||||||
])
|
|
||||||
// Bare minimum program set
|
|
||||||
.native_instruction_processors(&[
|
|
||||||
solana_system_program(),
|
|
||||||
solana_bpf_loader_program!(),
|
|
||||||
solana_vote_program!(),
|
|
||||||
solana_stake_program!(),
|
|
||||||
])
|
|
||||||
.fee_calculator(FeeCalculator::new(0, 0)); // most tests don't want fees
|
|
||||||
|
|
||||||
builder = solana_stake_api::genesis(builder);
|
// Bare minimum program set
|
||||||
builder = solana_storage_api::rewards_pools::genesis(builder);
|
let native_instruction_processors = vec![
|
||||||
|
solana_system_program(),
|
||||||
|
solana_bpf_loader_program!(),
|
||||||
|
solana_vote_program!(),
|
||||||
|
solana_stake_program!(),
|
||||||
|
];
|
||||||
|
let fee_calculator = FeeCalculator::new(0, 0); // most tests don't want fees
|
||||||
|
|
||||||
|
let mut genesis_block = GenesisBlock {
|
||||||
|
accounts,
|
||||||
|
native_instruction_processors,
|
||||||
|
fee_calculator,
|
||||||
|
..GenesisBlock::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
solana_stake_api::add_genesis_accounts(&mut genesis_block);
|
||||||
|
solana_storage_api::rewards_pools::add_genesis_accounts(&mut genesis_block);
|
||||||
|
|
||||||
GenesisBlockInfo {
|
GenesisBlockInfo {
|
||||||
genesis_block: builder.build(),
|
genesis_block,
|
||||||
mint_keypair,
|
mint_keypair,
|
||||||
voting_keypair,
|
voting_keypair,
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,79 +67,6 @@ impl Default for GenesisBlock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
|
||||||
pub struct Builder {
|
|
||||||
genesis_block: GenesisBlock,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Builder {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Builder::default()
|
|
||||||
}
|
|
||||||
// consuming builder because I don't want to clone all the accounts
|
|
||||||
pub fn build(self) -> GenesisBlock {
|
|
||||||
self.genesis_block
|
|
||||||
}
|
|
||||||
|
|
||||||
fn append<T: Clone>(items: &[T], mut dest: Vec<T>) -> Vec<T> {
|
|
||||||
items.iter().cloned().for_each(|item| dest.push(item));
|
|
||||||
dest
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn account(self, pubkey: Pubkey, account: Account) -> Self {
|
|
||||||
self.accounts(&[(pubkey, account)])
|
|
||||||
}
|
|
||||||
pub fn accounts(mut self, accounts: &[(Pubkey, Account)]) -> Self {
|
|
||||||
self.genesis_block.accounts = Self::append(accounts, self.genesis_block.accounts);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn native_instruction_processor(self, name: &str, pubkey: Pubkey) -> Self {
|
|
||||||
self.native_instruction_processors(&[(name.to_string(), pubkey)])
|
|
||||||
}
|
|
||||||
pub fn native_instruction_processors(
|
|
||||||
mut self,
|
|
||||||
native_instruction_processors: &[(String, Pubkey)],
|
|
||||||
) -> Self {
|
|
||||||
self.genesis_block.native_instruction_processors = Self::append(
|
|
||||||
native_instruction_processors,
|
|
||||||
self.genesis_block.native_instruction_processors,
|
|
||||||
);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn rewards_pool(self, pubkey: Pubkey, account: Account) -> Self {
|
|
||||||
self.rewards_pools(&[(pubkey, account)])
|
|
||||||
}
|
|
||||||
pub fn rewards_pools(mut self, rewards_pools: &[(Pubkey, Account)]) -> Self {
|
|
||||||
self.genesis_block.rewards_pools =
|
|
||||||
Self::append(rewards_pools, self.genesis_block.rewards_pools);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn epoch_schedule(mut self, epoch_schedule: EpochSchedule) -> Self {
|
|
||||||
self.genesis_block.epoch_schedule = epoch_schedule;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn ticks_per_slot(mut self, ticks_per_slot: u64) -> Self {
|
|
||||||
self.genesis_block.ticks_per_slot = ticks_per_slot;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn poh_config(mut self, poh_config: PohConfig) -> Self {
|
|
||||||
self.genesis_block.poh_config = poh_config;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn fee_calculator(mut self, fee_calculator: FeeCalculator) -> Self {
|
|
||||||
self.genesis_block.fee_calculator = fee_calculator;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn inflation(mut self, inflation: Inflation) -> Self {
|
|
||||||
self.genesis_block.inflation = inflation;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
pub fn rent_calculator(mut self, rent_calculator: RentCalculator) -> Self {
|
|
||||||
self.genesis_block.rent_calculator = rent_calculator;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GenesisBlock {
|
impl GenesisBlock {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
accounts: &[(Pubkey, Account)],
|
accounts: &[(Pubkey, Account)],
|
||||||
|
@ -179,6 +106,18 @@ impl GenesisBlock {
|
||||||
let mut file = File::create(&ledger_path.join("genesis.bin"))?;
|
let mut file = File::create(&ledger_path.join("genesis.bin"))?;
|
||||||
file.write_all(&serialized)
|
file.write_all(&serialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_account(&mut self, pubkey: Pubkey, account: Account) {
|
||||||
|
self.accounts.push((pubkey, account));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_native_instruction_processor(&mut self, name: String, program_id: Pubkey) {
|
||||||
|
self.native_instruction_processors.push((name, program_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_rewards_pool(&mut self, pubkey: Pubkey, account: Account) {
|
||||||
|
self.rewards_pools.push((pubkey, account));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -210,14 +149,13 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_genesis_block() {
|
fn test_genesis_block() {
|
||||||
let mint_keypair = Keypair::new();
|
let mint_keypair = Keypair::new();
|
||||||
let block = Builder::new()
|
let mut block = GenesisBlock::default();
|
||||||
.account(
|
block.add_account(
|
||||||
mint_keypair.pubkey(),
|
mint_keypair.pubkey(),
|
||||||
Account::new(10_000, 0, &Pubkey::default()),
|
Account::new(10_000, 0, &Pubkey::default()),
|
||||||
)
|
);
|
||||||
.accounts(&[(Pubkey::new_rand(), Account::new(1, 0, &Pubkey::default()))])
|
block.add_account(Pubkey::new_rand(), Account::new(1, 0, &Pubkey::default()));
|
||||||
.native_instruction_processor("hi", Pubkey::new_rand())
|
block.add_native_instruction_processor("hi".to_string(), Pubkey::new_rand());
|
||||||
.build();
|
|
||||||
|
|
||||||
assert_eq!(block.accounts.len(), 2);
|
assert_eq!(block.accounts.len(), 2);
|
||||||
assert!(block.accounts.iter().any(
|
assert!(block.accounts.iter().any(
|
||||||
|
|
Loading…
Reference in New Issue