diff --git a/Cargo.lock b/Cargo.lock index 51bf0c891..a6a9f833a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4100,6 +4100,7 @@ name = "solana-ledger-tool" version = "0.24.0" dependencies = [ "assert_cmd 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "histogram 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 46c7dc677..7c73b9a01 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -121,7 +121,7 @@ impl JsonRpcRequestProcessor { ) -> Result> { Ok(self .bank(commitment) - .get_program_accounts(&program_id) + .get_program_accounts(Some(&program_id)) .into_iter() .map(|(pubkey, account)| RpcKeyedAccount { pubkey: pubkey.to_string(), diff --git a/ledger-tool/Cargo.toml b/ledger-tool/Cargo.toml index bc9e94c65..e63563251 100644 --- a/ledger-tool/Cargo.toml +++ b/ledger-tool/Cargo.toml @@ -9,6 +9,7 @@ license = "Apache-2.0" homepage = "https://solana.com/" [dependencies] +bs58 = "0.3.0" clap = "2.33.0" histogram = "*" serde_json = "1.0.46" diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index 0d4483fb7..627079abb 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -692,6 +692,13 @@ fn main() { .takes_value(true) .help("Output directory for the snapshot"), ) + ).subcommand( + SubCommand::with_name("print-accounts") + .about("Print account contents after processing in the ledger") + .arg(&no_snapshot_arg) + .arg(&account_paths_arg) + .arg(&halt_at_slot_arg) + .arg(&hard_forks_arg) ).subcommand( SubCommand::with_name("prune") .about("Prune the ledger at the block height") @@ -933,6 +940,51 @@ fn main() { } } } + ("print-accounts", Some(arg_matches)) => { + let dev_halt_at_slot = value_t!(arg_matches, "halt_at_slot", Slot).ok(); + let process_options = ProcessOptions { + dev_halt_at_slot, + new_hard_forks: hardforks_of(arg_matches, "hard_forks"), + poh_verify: false, + ..ProcessOptions::default() + }; + let genesis_config = open_genesis_config(&ledger_path); + match load_bank_forks(arg_matches, &ledger_path, &genesis_config, process_options) { + Ok((bank_forks, bank_forks_info, _leader_schedule_cache)) => { + let slot = dev_halt_at_slot.unwrap_or_else(|| { + if bank_forks_info.len() > 1 { + eprintln!("Error: multiple forks present"); + exit(1); + } + bank_forks_info[0].bank_slot + }); + + let bank = bank_forks.get(slot).unwrap_or_else(|| { + eprintln!("Error: Slot {} is not available", slot); + exit(1); + }); + + let accounts: Vec<_> = bank + .get_program_accounts(None) + .into_iter() + .filter(|(pubkey, _account)| !solana_sdk::sysvar::is_sysvar_id(pubkey)) + .collect(); + + println!("---"); + for (pubkey, account) in accounts.into_iter() { + println!("{}:", pubkey); + println!(" - lamports: {}", account.lamports); + println!(" - owner: '{}'", account.owner); + println!(" - executable: {}", account.executable); + println!(" - data: '{}'", bs58::encode(account.data).into_string()); + } + } + Err(err) => { + eprintln!("Failed to load ledger: {:?}", err); + exit(1); + } + } + } ("prune", Some(arg_matches)) => { if let Some(prune_file_path) = arg_matches.value_of("slot_list") { let blockstore = open_blockstore(&ledger_path); diff --git a/runtime/src/accounts.rs b/runtime/src/accounts.rs index c135f0216..7306988be 100644 --- a/runtime/src/accounts.rs +++ b/runtime/src/accounts.rs @@ -387,13 +387,16 @@ impl Accounts { pub fn load_by_program( &self, ancestors: &HashMap, - program_id: &Pubkey, + program_id: Option<&Pubkey>, ) -> Vec<(Pubkey, Account)> { self.accounts_db.scan_accounts( ancestors, |collector: &mut Vec<(Pubkey, Account)>, option| { if let Some(data) = option - .filter(|(_, account, _)| account.owner == *program_id && account.lamports != 0) + .filter(|(_, account, _)| { + (program_id.is_none() || Some(&account.owner) == program_id) + && account.lamports != 0 + }) .map(|(pubkey, account, _slot)| (*pubkey, account)) { collector.push(data) diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 99ae021f7..d03465bd2 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1746,7 +1746,7 @@ impl Bank { .map(|(acc, _slot)| acc) } - pub fn get_program_accounts(&self, program_id: &Pubkey) -> Vec<(Pubkey, Account)> { + pub fn get_program_accounts(&self, program_id: Option<&Pubkey>) -> Vec<(Pubkey, Account)> { self.rc .accounts .load_by_program(&self.ancestors, program_id) @@ -4743,11 +4743,24 @@ mod tests { #[test] fn test_bank_get_program_accounts() { - let (genesis_config, _mint_keypair) = create_genesis_config(500); + let (genesis_config, mint_keypair) = create_genesis_config(500); let parent = Arc::new(Bank::new(&genesis_config)); - let bank0 = Arc::new(new_from_parent(&parent)); + let genesis_accounts: Vec<_> = parent.get_program_accounts(None); + assert!( + genesis_accounts + .iter() + .any(|(pubkey, _)| *pubkey == mint_keypair.pubkey()), + "mint pubkey not found" + ); + assert!( + genesis_accounts + .iter() + .any(|(pubkey, _)| solana_sdk::sysvar::is_sysvar_id(pubkey)), + "no sysvars found" + ); + let bank0 = Arc::new(new_from_parent(&parent)); let pubkey0 = Pubkey::new_rand(); let program_id = Pubkey::new(&[2; 32]); let account0 = Account::new(1, 0, &program_id); @@ -4761,11 +4774,11 @@ mod tests { let bank1 = Arc::new(new_from_parent(&bank0)); bank1.squash(); assert_eq!( - bank0.get_program_accounts(&program_id), + bank0.get_program_accounts(Some(&program_id)), vec![(pubkey0, account0.clone())] ); assert_eq!( - bank1.get_program_accounts(&program_id), + bank1.get_program_accounts(Some(&program_id)), vec![(pubkey0, account0.clone())] ); assert_eq!( @@ -4784,8 +4797,8 @@ mod tests { let bank3 = Arc::new(new_from_parent(&bank2)); bank3.squash(); - assert_eq!(bank1.get_program_accounts(&program_id).len(), 2); - assert_eq!(bank3.get_program_accounts(&program_id).len(), 2); + assert_eq!(bank1.get_program_accounts(Some(&program_id)).len(), 2); + assert_eq!(bank3.get_program_accounts(Some(&program_id)).len(), 2); } #[test]