move genesis_block to builder pattern (#4736)
This commit is contained in:
parent
61483c18ca
commit
2e2b1881f5
|
@ -20,7 +20,7 @@ use clap::{crate_description, crate_name, crate_version, value_t_or_exit, App, A
|
||||||
use solana::blocktree::create_new_ledger;
|
use solana::blocktree::create_new_ledger;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
use solana_sdk::fee_calculator::FeeCalculator;
|
use solana_sdk::fee_calculator::FeeCalculator;
|
||||||
use solana_sdk::genesis_block::GenesisBlock;
|
use solana_sdk::genesis_block::Builder;
|
||||||
use solana_sdk::hash::{hash, Hash};
|
use solana_sdk::hash::{hash, Hash};
|
||||||
use solana_sdk::poh_config::PohConfig;
|
use solana_sdk::poh_config::PohConfig;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
@ -47,30 +47,26 @@ pub enum AccountFileFormat {
|
||||||
pub fn append_primordial_accounts(
|
pub fn append_primordial_accounts(
|
||||||
file: &str,
|
file: &str,
|
||||||
file_format: AccountFileFormat,
|
file_format: AccountFileFormat,
|
||||||
genesis_block: &mut GenesisBlock,
|
mut builder: Builder,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<(Builder)> {
|
||||||
let accounts_file = File::open(file.to_string())?;
|
let accounts_file = File::open(file.to_string())?;
|
||||||
|
|
||||||
let primordial_accounts: HashMap<String, u64> = serde_yaml::from_reader(accounts_file)
|
let primordial_accounts: HashMap<String, u64> = 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)))?;
|
||||||
|
|
||||||
primordial_accounts
|
for (account, balance) in primordial_accounts {
|
||||||
.into_iter()
|
let pubkey = match file_format {
|
||||||
.for_each(|(account, balance)| {
|
AccountFileFormat::Pubkey => Pubkey::from_str(account.as_str()).unwrap(),
|
||||||
let pubkey = match file_format {
|
AccountFileFormat::Keypair => {
|
||||||
AccountFileFormat::Pubkey => Pubkey::from_str(account.as_str()).unwrap(),
|
let bytes: Vec<u8> = serde_json::from_str(account.as_str()).unwrap();
|
||||||
AccountFileFormat::Keypair => {
|
Keypair::from_bytes(&bytes).unwrap().pubkey()
|
||||||
let bytes: Vec<u8> = serde_json::from_str(account.as_str()).unwrap();
|
}
|
||||||
Keypair::from_bytes(&bytes).unwrap().pubkey()
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
genesis_block
|
builder = builder.account(pubkey, Account::new(balance, 0, &system_program::id()));
|
||||||
.accounts
|
}
|
||||||
.push((pubkey, Account::new(balance, 0, &system_program::id())))
|
|
||||||
});
|
|
||||||
|
|
||||||
Ok(())
|
Ok(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn error::Error>> {
|
fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
|
@ -292,8 +288,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut genesis_block = GenesisBlock::new(
|
let mut builder = Builder::new()
|
||||||
&[
|
.accounts(&[
|
||||||
// the mint
|
// the mint
|
||||||
(
|
(
|
||||||
mint_keypair.pubkey(),
|
mint_keypair.pubkey(),
|
||||||
|
@ -326,8 +322,8 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
storage_mining_keypair.pubkey(),
|
storage_mining_keypair.pubkey(),
|
||||||
storage_contract::create_mining_pool_account(storage_pool_lamports),
|
storage_contract::create_mining_pool_account(storage_pool_lamports),
|
||||||
),
|
),
|
||||||
],
|
])
|
||||||
&[
|
.native_instruction_processors(&[
|
||||||
solana_bpf_loader_program!(),
|
solana_bpf_loader_program!(),
|
||||||
solana_vote_program!(),
|
solana_vote_program!(),
|
||||||
solana_stake_program!(),
|
solana_stake_program!(),
|
||||||
|
@ -336,27 +332,19 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
solana_config_program!(),
|
solana_config_program!(),
|
||||||
solana_exchange_program!(),
|
solana_exchange_program!(),
|
||||||
solana_storage_program!(),
|
solana_storage_program!(),
|
||||||
],
|
])
|
||||||
);
|
.ticks_per_slot(value_t_or_exit!(matches, "ticks_per_slot", u64))
|
||||||
|
.slots_per_epoch(value_t_or_exit!(matches, "slots_per_epoch", u64));
|
||||||
|
|
||||||
if let Some(file) = matches.value_of("primordial_accounts_file") {
|
let mut fee_calculator = FeeCalculator::default();
|
||||||
append_primordial_accounts(file, AccountFileFormat::Pubkey, &mut genesis_block)?;
|
fee_calculator.target_lamports_per_signature =
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(file) = matches.value_of("primordial_keypairs_file") {
|
|
||||||
append_primordial_accounts(file, AccountFileFormat::Keypair, &mut genesis_block)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
genesis_block.fee_calculator.target_lamports_per_signature =
|
|
||||||
value_t_or_exit!(matches, "target_lamports_per_signature", u64);
|
value_t_or_exit!(matches, "target_lamports_per_signature", u64);
|
||||||
genesis_block.fee_calculator.target_signatures_per_slot =
|
fee_calculator.target_signatures_per_slot =
|
||||||
value_t_or_exit!(matches, "target_signatures_per_slot", usize);
|
value_t_or_exit!(matches, "target_signatures_per_slot", usize);
|
||||||
genesis_block.fee_calculator = FeeCalculator::new_derived(&genesis_block.fee_calculator, 0);
|
builder = builder.fee_calculator(&FeeCalculator::new_derived(&fee_calculator, 0));
|
||||||
|
|
||||||
genesis_block.ticks_per_slot = value_t_or_exit!(matches, "ticks_per_slot", u64);
|
let mut poh_config = PohConfig::default();
|
||||||
genesis_block.slots_per_epoch = value_t_or_exit!(matches, "slots_per_epoch", u64);
|
poh_config.target_tick_duration =
|
||||||
genesis_block.stakers_slot_offset = genesis_block.slots_per_epoch;
|
|
||||||
genesis_block.poh_config.target_tick_duration =
|
|
||||||
Duration::from_millis(value_t_or_exit!(matches, "target_tick_duration", u64));
|
Duration::from_millis(value_t_or_exit!(matches, "target_tick_duration", u64));
|
||||||
|
|
||||||
match matches.value_of("hashes_per_tick").unwrap() {
|
match matches.value_of("hashes_per_tick").unwrap() {
|
||||||
|
@ -370,22 +358,29 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
let end = Instant::now();
|
let end = Instant::now();
|
||||||
let elapsed = end.duration_since(start).as_millis();
|
let elapsed = end.duration_since(start).as_millis();
|
||||||
|
|
||||||
let hashes_per_tick = (genesis_block.poh_config.target_tick_duration.as_millis()
|
let hashes_per_tick =
|
||||||
* 1_000_000
|
(poh_config.target_tick_duration.as_millis() * 1_000_000 / elapsed) as u64;
|
||||||
/ elapsed) as u64;
|
|
||||||
println!("Hashes per tick: {}", hashes_per_tick);
|
println!("Hashes per tick: {}", hashes_per_tick);
|
||||||
genesis_block.poh_config.hashes_per_tick = Some(hashes_per_tick);
|
poh_config.hashes_per_tick = Some(hashes_per_tick);
|
||||||
}
|
}
|
||||||
"sleep" => {
|
"sleep" => {
|
||||||
genesis_block.poh_config.hashes_per_tick = None;
|
poh_config.hashes_per_tick = None;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
genesis_block.poh_config.hashes_per_tick =
|
poh_config.hashes_per_tick = Some(value_t_or_exit!(matches, "hashes_per_tick", u64));
|
||||||
Some(value_t_or_exit!(matches, "hashes_per_tick", u64));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
builder = builder.poh_config(&poh_config);
|
||||||
|
|
||||||
create_new_ledger(ledger_path, &genesis_block)?;
|
if let Some(file) = matches.value_of("primordial_accounts_file") {
|
||||||
|
builder = append_primordial_accounts(file, AccountFileFormat::Pubkey, builder)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(file) = matches.value_of("primordial_keypairs_file") {
|
||||||
|
builder = append_primordial_accounts(file, AccountFileFormat::Keypair, builder)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_new_ledger(ledger_path, &builder.build())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +388,7 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use solana_sdk::genesis_block::GenesisBlock;
|
use solana_sdk::genesis_block::Builder;
|
||||||
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;
|
||||||
|
@ -420,16 +415,16 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_append_primordial_accounts_to_genesis() {
|
fn test_append_primordial_accounts_to_genesis() {
|
||||||
let mut genesis_block = GenesisBlock::new(&[], &[]);
|
|
||||||
|
|
||||||
// Test invalid file returns error
|
// Test invalid file returns error
|
||||||
assert!(append_primordial_accounts(
|
assert!(append_primordial_accounts(
|
||||||
"unknownfile",
|
"unknownfile",
|
||||||
AccountFileFormat::Pubkey,
|
AccountFileFormat::Pubkey,
|
||||||
&mut genesis_block
|
Builder::new()
|
||||||
)
|
)
|
||||||
.is_err());
|
.is_err());
|
||||||
|
|
||||||
|
let mut builder = Builder::new();
|
||||||
|
|
||||||
let mut primordial_accounts = HashMap::new();
|
let mut primordial_accounts = HashMap::new();
|
||||||
primordial_accounts.insert(Pubkey::new_rand().to_string(), 2 as u64);
|
primordial_accounts.insert(Pubkey::new_rand().to_string(), 2 as u64);
|
||||||
primordial_accounts.insert(Pubkey::new_rand().to_string(), 1 as u64);
|
primordial_accounts.insert(Pubkey::new_rand().to_string(), 1 as u64);
|
||||||
|
@ -440,26 +435,29 @@ mod tests {
|
||||||
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();
|
||||||
|
|
||||||
// Test valid file returns ok
|
builder = append_primordial_accounts(
|
||||||
assert!(append_primordial_accounts(
|
|
||||||
"test_append_primordial_accounts_to_genesis.yml",
|
"test_append_primordial_accounts_to_genesis.yml",
|
||||||
AccountFileFormat::Pubkey,
|
AccountFileFormat::Pubkey,
|
||||||
&mut genesis_block
|
builder,
|
||||||
)
|
)
|
||||||
.is_ok());
|
.expect("test_append_primordial_accounts_to_genesis.yml");
|
||||||
|
// Test valid file returns ok
|
||||||
|
|
||||||
remove_file(path).unwrap();
|
remove_file(path).unwrap();
|
||||||
|
|
||||||
// Test all accounts were added
|
{
|
||||||
assert_eq!(genesis_block.accounts.len(), primordial_accounts.len());
|
let genesis_block = builder.clone().build();
|
||||||
|
// Test all accounts were added
|
||||||
|
assert_eq!(genesis_block.accounts.len(), primordial_accounts.len());
|
||||||
|
|
||||||
// Test account data matches
|
// Test account data matches
|
||||||
(0..primordial_accounts.len()).for_each(|i| {
|
(0..primordial_accounts.len()).for_each(|i| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
primordial_accounts[&genesis_block.accounts[i].0.to_string()],
|
primordial_accounts[&genesis_block.accounts[i].0.to_string()],
|
||||||
genesis_block.accounts[i].1.lamports,
|
genesis_block.accounts[i].1.lamports,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Test more accounts can be appended
|
// Test more accounts can be appended
|
||||||
let mut primordial_accounts1 = HashMap::new();
|
let mut primordial_accounts1 = HashMap::new();
|
||||||
|
@ -472,15 +470,16 @@ mod tests {
|
||||||
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();
|
||||||
|
|
||||||
assert!(append_primordial_accounts(
|
builder = append_primordial_accounts(
|
||||||
"test_append_primordial_accounts_to_genesis.yml",
|
"test_append_primordial_accounts_to_genesis.yml",
|
||||||
AccountFileFormat::Pubkey,
|
AccountFileFormat::Pubkey,
|
||||||
&mut genesis_block
|
builder,
|
||||||
)
|
)
|
||||||
.is_ok());
|
.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(),
|
||||||
|
@ -528,15 +527,16 @@ mod tests {
|
||||||
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();
|
||||||
|
|
||||||
assert!(append_primordial_accounts(
|
builder = append_primordial_accounts(
|
||||||
"test_append_primordial_accounts_to_genesis.yml",
|
"test_append_primordial_accounts_to_genesis.yml",
|
||||||
AccountFileFormat::Keypair,
|
AccountFileFormat::Keypair,
|
||||||
&mut genesis_block
|
builder,
|
||||||
)
|
)
|
||||||
.is_ok());
|
.expect("builder");
|
||||||
|
|
||||||
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(),
|
||||||
|
|
|
@ -15,16 +15,17 @@ use std::fs::{File, OpenOptions};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct GenesisBlock {
|
pub struct GenesisBlock {
|
||||||
pub accounts: Vec<(Pubkey, Account)>,
|
pub accounts: Vec<(Pubkey, Account)>,
|
||||||
pub fee_calculator: FeeCalculator,
|
|
||||||
pub native_instruction_processors: Vec<(String, Pubkey)>,
|
pub native_instruction_processors: Vec<(String, Pubkey)>,
|
||||||
pub ticks_per_slot: u64,
|
pub rewards_pools: Vec<(Pubkey, Account)>,
|
||||||
pub slots_per_epoch: u64,
|
pub slots_per_epoch: u64,
|
||||||
pub stakers_slot_offset: u64,
|
pub stakers_slot_offset: u64,
|
||||||
pub epoch_warmup: bool,
|
pub epoch_warmup: bool,
|
||||||
|
pub ticks_per_slot: u64,
|
||||||
pub poh_config: PohConfig,
|
pub poh_config: PohConfig,
|
||||||
|
pub fee_calculator: FeeCalculator,
|
||||||
pub inflation: Inflation,
|
pub inflation: Inflation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,18 +48,102 @@ impl Default for GenesisBlock {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
accounts: Vec::new(),
|
accounts: Vec::new(),
|
||||||
epoch_warmup: true,
|
|
||||||
fee_calculator: FeeCalculator::default(),
|
|
||||||
native_instruction_processors: Vec::new(),
|
native_instruction_processors: Vec::new(),
|
||||||
|
rewards_pools: Vec::new(),
|
||||||
|
epoch_warmup: true,
|
||||||
slots_per_epoch: DEFAULT_SLOTS_PER_EPOCH,
|
slots_per_epoch: DEFAULT_SLOTS_PER_EPOCH,
|
||||||
stakers_slot_offset: DEFAULT_SLOTS_PER_EPOCH,
|
stakers_slot_offset: DEFAULT_SLOTS_PER_EPOCH,
|
||||||
ticks_per_slot: DEFAULT_TICKS_PER_SLOT,
|
ticks_per_slot: DEFAULT_TICKS_PER_SLOT,
|
||||||
poh_config: PohConfig::default(),
|
poh_config: PohConfig::default(),
|
||||||
inflation: Inflation::default(),
|
inflation: Inflation::default(),
|
||||||
|
fee_calculator: FeeCalculator::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Default, Clone)]
|
||||||
|
pub struct Builder {
|
||||||
|
genesis_block: GenesisBlock,
|
||||||
|
already_have_stakers_slot_offset: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
// also sets stakers_slot_offset, unless already set explicitly
|
||||||
|
pub fn slots_per_epoch(mut self, slots_per_epoch: u64) -> Self {
|
||||||
|
self.genesis_block.slots_per_epoch = slots_per_epoch;
|
||||||
|
if !self.already_have_stakers_slot_offset {
|
||||||
|
self.genesis_block.stakers_slot_offset = slots_per_epoch;
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn stakers_slot_offset(mut self, stakers_slot_offset: u64) -> Self {
|
||||||
|
self.genesis_block.stakers_slot_offset = stakers_slot_offset;
|
||||||
|
self.already_have_stakers_slot_offset = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn epoch_warmup(mut self, epoch_warmup: bool) -> Self {
|
||||||
|
self.genesis_block.epoch_warmup = epoch_warmup;
|
||||||
|
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.clone();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn fee_calculator(mut self, fee_calculator: &FeeCalculator) -> Self {
|
||||||
|
self.genesis_block.fee_calculator = fee_calculator.clone();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn inflation(mut self, inflation: &Inflation) -> Self {
|
||||||
|
self.genesis_block.inflation = inflation.clone();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GenesisBlock {
|
impl GenesisBlock {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
accounts: &[(Pubkey, Account)],
|
accounts: &[(Pubkey, Account)],
|
||||||
|
@ -123,16 +208,15 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_genesis_block() {
|
fn test_genesis_block() {
|
||||||
let mint_keypair = Keypair::new();
|
let mint_keypair = Keypair::new();
|
||||||
let block = GenesisBlock::new(
|
let block = Builder::new()
|
||||||
&[
|
.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()))])
|
||||||
(Pubkey::new_rand(), Account::new(1, 0, &Pubkey::default())),
|
.native_instruction_processor("hi", Pubkey::new_rand())
|
||||||
],
|
.build();
|
||||||
&[("hi".to_string(), Pubkey::new_rand())],
|
|
||||||
);
|
|
||||||
assert_eq!(block.accounts.len(), 2);
|
assert_eq!(block.accounts.len(), 2);
|
||||||
assert!(block.accounts.iter().any(
|
assert!(block.accounts.iter().any(
|
||||||
|(pubkey, account)| *pubkey == mint_keypair.pubkey() && account.lamports == 10_000
|
|(pubkey, account)| *pubkey == mint_keypair.pubkey() && account.lamports == 10_000
|
||||||
|
|
Loading…
Reference in New Issue