Facility to add accounts with specific balance to genesis block (#4585)
* Facility to add accounts with specific balance to genesis block * address review comments
This commit is contained in:
parent
688f8a669a
commit
191483f4ee
|
@ -2458,9 +2458,13 @@ dependencies = [
|
|||
name = "solana-genesis"
|
||||
version = "0.16.0"
|
||||
dependencies = [
|
||||
"bincode 1.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"solana 0.16.0",
|
||||
"solana-budget-api 0.16.0",
|
||||
"solana-budget-program 0.16.0",
|
||||
|
|
|
@ -9,8 +9,12 @@ license = "Apache-2.0"
|
|||
homepage = "https://solana.com/"
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.1.4"
|
||||
clap = "2.33.0"
|
||||
serde = "1.0.92"
|
||||
serde_derive = "1.0.92"
|
||||
serde_json = "1.0.39"
|
||||
serde_yaml = "0.8.9"
|
||||
solana = { path = "../core", version = "0.16.0" }
|
||||
solana-budget-api = { path = "../programs/budget_api", version = "0.16.0" }
|
||||
solana-budget-program = { path = "../programs/budget_program", version = "0.16.0" }
|
||||
|
|
|
@ -13,12 +13,14 @@ extern crate solana_config_program;
|
|||
extern crate solana_exchange_program;
|
||||
|
||||
use clap::{crate_description, crate_name, crate_version, value_t_or_exit, App, Arg};
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use solana::blocktree::create_new_ledger;
|
||||
use solana_sdk::account::Account;
|
||||
use solana_sdk::fee_calculator::FeeCalculator;
|
||||
use solana_sdk::genesis_block::GenesisBlock;
|
||||
use solana_sdk::hash::{hash, Hash};
|
||||
use solana_sdk::poh_config::PohConfig;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use solana_sdk::signature::{read_keypair, KeypairUtil};
|
||||
use solana_sdk::system_program;
|
||||
use solana_sdk::timing;
|
||||
|
@ -26,10 +28,34 @@ use solana_stake_api::stake_state;
|
|||
use solana_storage_program::genesis_block_util::GenesisBlockUtil;
|
||||
use solana_vote_api::vote_state;
|
||||
use std::error;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub const BOOTSTRAP_LEADER_LAMPORTS: u64 = 42;
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug, PartialEq)]
|
||||
pub struct PrimordialAccount {
|
||||
pub pubkey: Pubkey,
|
||||
pub lamports: u64,
|
||||
}
|
||||
|
||||
pub fn append_primordial_accounts(file: &str, genesis_block: &mut GenesisBlock) -> io::Result<()> {
|
||||
let accounts_file = File::open(file.to_string())?;
|
||||
|
||||
let primordial_accounts: Vec<PrimordialAccount> = serde_yaml::from_reader(accounts_file)
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, format!("{:?}", err)))?;
|
||||
|
||||
primordial_accounts.iter().for_each(|primordial| {
|
||||
genesis_block.accounts.push((
|
||||
primordial.pubkey,
|
||||
Account::new(primordial.lamports, 0, &system_program::id()),
|
||||
))
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||
let default_bootstrap_leader_lamports = &BOOTSTRAP_LEADER_LAMPORTS.to_string();
|
||||
let default_lamports_per_signature =
|
||||
|
@ -167,6 +193,13 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||
.default_value(default_slots_per_epoch)
|
||||
.help("The number of slots in an epoch"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("primordial_accounts_file")
|
||||
.long("primordial-accounts-file")
|
||||
.value_name("FILENAME")
|
||||
.takes_value(true)
|
||||
.help("The location of pubkey for primordial accounts and balance"),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let bootstrap_leader_keypair_file = matches.value_of("bootstrap_leader_keypair_file").unwrap();
|
||||
|
@ -228,6 +261,11 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||
solana_exchange_program!(),
|
||||
],
|
||||
);
|
||||
|
||||
if let Some(file) = matches.value_of("primordial_accounts_file") {
|
||||
append_primordial_accounts(file, &mut genesis_block)?;
|
||||
}
|
||||
|
||||
genesis_block.add_storage_program(
|
||||
&bootstrap_leader_keypair.pubkey(),
|
||||
&bootstrap_storage_keypair.pubkey(),
|
||||
|
@ -272,7 +310,13 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use hashbrown::HashSet;
|
||||
use solana_sdk::genesis_block::GenesisBlock;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::fs::remove_file;
|
||||
use std::io::Write;
|
||||
use std::path::Path;
|
||||
|
||||
#[test]
|
||||
fn test_program_ids() {
|
||||
|
@ -342,4 +386,111 @@ mod tests {
|
|||
];
|
||||
assert!(ids.into_iter().all(move |id| unique.insert(id)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_append_primordial_accounts_to_genesis() {
|
||||
let mut genesis_block = GenesisBlock::new(&Pubkey::new_rand(), &[], &[]);
|
||||
|
||||
// Test invalid file returns error
|
||||
assert!(append_primordial_accounts("unknownfile", &mut genesis_block).is_err());
|
||||
|
||||
let primordial_accounts = [
|
||||
PrimordialAccount {
|
||||
pubkey: Pubkey::new_rand(),
|
||||
lamports: 2,
|
||||
},
|
||||
PrimordialAccount {
|
||||
pubkey: Pubkey::new_rand(),
|
||||
lamports: 1,
|
||||
},
|
||||
PrimordialAccount {
|
||||
pubkey: Pubkey::new_rand(),
|
||||
lamports: 3,
|
||||
},
|
||||
];
|
||||
|
||||
let serialized = serde_yaml::to_string(&primordial_accounts).unwrap();
|
||||
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
||||
let mut file = File::create(path).unwrap();
|
||||
file.write_all(&serialized.into_bytes()).unwrap();
|
||||
|
||||
// Test valid file returns ok
|
||||
assert!(append_primordial_accounts(
|
||||
"test_append_primordial_accounts_to_genesis.yml",
|
||||
&mut genesis_block
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
remove_file(path).unwrap();
|
||||
|
||||
// Test all accounts were added
|
||||
assert_eq!(genesis_block.accounts.len(), primordial_accounts.len());
|
||||
|
||||
// Test account data matches
|
||||
(0..primordial_accounts.len()).for_each(|i| {
|
||||
assert_eq!(genesis_block.accounts[i].0, primordial_accounts[i].pubkey);
|
||||
assert_eq!(
|
||||
genesis_block.accounts[i].1.lamports,
|
||||
primordial_accounts[i].lamports
|
||||
);
|
||||
});
|
||||
|
||||
// Test more accounts can be appended
|
||||
let primordial_accounts1 = [
|
||||
PrimordialAccount {
|
||||
pubkey: Pubkey::new_rand(),
|
||||
lamports: 6,
|
||||
},
|
||||
PrimordialAccount {
|
||||
pubkey: Pubkey::new_rand(),
|
||||
lamports: 5,
|
||||
},
|
||||
PrimordialAccount {
|
||||
pubkey: Pubkey::new_rand(),
|
||||
lamports: 10,
|
||||
},
|
||||
];
|
||||
|
||||
let serialized = serde_yaml::to_string(&primordial_accounts1).unwrap();
|
||||
let path = Path::new("test_append_primordial_accounts_to_genesis.yml");
|
||||
let mut file = File::create(path).unwrap();
|
||||
file.write_all(&serialized.into_bytes()).unwrap();
|
||||
|
||||
assert!(append_primordial_accounts(
|
||||
"test_append_primordial_accounts_to_genesis.yml",
|
||||
&mut genesis_block
|
||||
)
|
||||
.is_ok());
|
||||
|
||||
remove_file(path).unwrap();
|
||||
|
||||
// Test total number of accounts is correct
|
||||
assert_eq!(
|
||||
genesis_block.accounts.len(),
|
||||
primordial_accounts.len() + primordial_accounts1.len()
|
||||
);
|
||||
|
||||
// Test old accounts are still there
|
||||
(0..primordial_accounts.len()).for_each(|i| {
|
||||
assert_eq!(genesis_block.accounts[i].0, primordial_accounts[i].pubkey);
|
||||
assert_eq!(
|
||||
genesis_block.accounts[i].1.lamports,
|
||||
primordial_accounts[i].lamports
|
||||
);
|
||||
});
|
||||
|
||||
// Test new account data matches
|
||||
(0..primordial_accounts1.len()).for_each(|i| {
|
||||
assert_eq!(
|
||||
genesis_block.accounts[primordial_accounts.len() + i].0,
|
||||
primordial_accounts1[i].pubkey
|
||||
);
|
||||
assert_eq!(
|
||||
genesis_block.accounts[primordial_accounts.len() + i]
|
||||
.1
|
||||
.lamports,
|
||||
primordial_accounts1[i].lamports
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue