Support Debug Bank (#13017)

This commit is contained in:
Ryo Onodera 2020-10-21 01:05:45 +09:00 committed by GitHub
parent 6c55aaf4c7
commit c0675968b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 81 additions and 14 deletions

View File

@ -156,7 +156,7 @@ mod tests {
.get(&deserialized_bank.slot()) .get(&deserialized_bank.slot())
.unwrap() .unwrap()
.clone(); .clone();
assert!(*bank == deserialized_bank); assert_eq!(*bank, deserialized_bank);
let slot_snapshot_paths = snapshot_utils::get_snapshot_paths(&snapshot_path); let slot_snapshot_paths = snapshot_utils::get_snapshot_paths(&snapshot_path);

View File

@ -30,7 +30,7 @@ use solana_sdk::{
program_utils::limited_deserialize, program_utils::limited_deserialize,
pubkey::Pubkey, pubkey::Pubkey,
}; };
use std::{cell::RefCell, rc::Rc, sync::Arc}; use std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc};
use thiserror::Error; use thiserror::Error;
solana_sdk::declare_builtin!( solana_sdk::declare_builtin!(
@ -214,6 +214,14 @@ impl InstructionMeter for ThisInstructionMeter {
pub struct BPFExecutor { pub struct BPFExecutor {
executable: Box<dyn Executable<BPFError>>, executable: Box<dyn Executable<BPFError>>,
} }
// Well, implement Debug for solana_rbpf::vm::Executable in solana-rbpf...
impl Debug for BPFExecutor {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "BPFExecutor({:p})", self)
}
}
impl Executor for BPFExecutor { impl Executor for BPFExecutor {
fn execute( fn execute(
&self, &self,

View File

@ -17,7 +17,10 @@ use crate::{
instruction_recorder::InstructionRecorder, instruction_recorder::InstructionRecorder,
log_collector::LogCollector, log_collector::LogCollector,
message_processor::{Executors, MessageProcessor}, message_processor::{Executors, MessageProcessor},
process_instruction::{Executor, ProcessInstruction, ProcessInstructionWithContext}, process_instruction::{
ErasedProcessInstruction, ErasedProcessInstructionWithContext, Executor,
ProcessInstruction, ProcessInstructionWithContext,
},
rent_collector::RentCollector, rent_collector::RentCollector,
stakes::Stakes, stakes::Stakes,
status_cache::{SlotDelta, StatusCache}, status_cache::{SlotDelta, StatusCache},
@ -139,7 +142,31 @@ pub enum Entrypoint {
Loader(ProcessInstructionWithContext), Loader(ProcessInstructionWithContext),
} }
#[derive(Clone)] impl fmt::Debug for Entrypoint {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
#[derive(Debug)]
enum EntrypointForDebug {
Program(String),
Loader(String),
}
// rustc doesn't compile due to bug without this work around
// https://github.com/rust-lang/rust/issues/50280
// https://users.rust-lang.org/t/display-function-pointer/17073/2
let entrypoint = match self {
Entrypoint::Program(instruction) => EntrypointForDebug::Program(format!(
"{:p}",
*instruction as ErasedProcessInstruction
)),
Entrypoint::Loader(instruction) => EntrypointForDebug::Loader(format!(
"{:p}",
*instruction as ErasedProcessInstructionWithContext
)),
};
write!(f, "{:?}", entrypoint)
}
}
#[derive(Clone, Debug)]
pub struct Builtin { pub struct Builtin {
pub name: String, pub name: String,
pub id: Pubkey, pub id: Pubkey,
@ -156,7 +183,7 @@ impl Builtin {
} }
/// Copy-on-write holder of CachedExecutors /// Copy-on-write holder of CachedExecutors
#[derive(AbiExample, Default)] #[derive(AbiExample, Debug, Default)]
struct CowCachedExecutors { struct CowCachedExecutors {
shared: bool, shared: bool,
executors: Arc<RwLock<CachedExecutors>>, executors: Arc<RwLock<CachedExecutors>>,
@ -200,7 +227,7 @@ impl AbiExample for Builtin {
} }
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Builtins { pub struct Builtins {
/// Builtin programs that are always available /// Builtin programs that are always available
pub genesis_builtins: Vec<Builtin>, pub genesis_builtins: Vec<Builtin>,
@ -212,6 +239,7 @@ pub struct Builtins {
const MAX_CACHED_EXECUTORS: usize = 100; // 10 MB assuming programs are around 100k const MAX_CACHED_EXECUTORS: usize = 100; // 10 MB assuming programs are around 100k
/// LFU Cache of executors /// LFU Cache of executors
#[derive(Debug)]
struct CachedExecutors { struct CachedExecutors {
max: usize, max: usize,
executors: HashMap<Pubkey, (AtomicU64, Arc<dyn Executor>)>, executors: HashMap<Pubkey, (AtomicU64, Arc<dyn Executor>)>,
@ -289,7 +317,7 @@ impl CachedExecutors {
} }
} }
#[derive(Default)] #[derive(Default, Debug)]
pub struct BankRc { pub struct BankRc {
/// where all the Accounts are stored /// where all the Accounts are stored
pub accounts: Arc<Accounts>, pub accounts: Arc<Accounts>,
@ -330,7 +358,7 @@ impl BankRc {
} }
} }
#[derive(Default, AbiExample)] #[derive(Default, Debug, AbiExample)]
pub struct StatusCacheRc { pub struct StatusCacheRc {
/// where all the Accounts are stored /// where all the Accounts are stored
/// A cache of signature statuses /// A cache of signature statuses
@ -411,7 +439,7 @@ impl HashAgeKind {
// Bank's common fields shared by all supported snapshot versions for deserialization. // Bank's common fields shared by all supported snapshot versions for deserialization.
// Sync fields with BankFieldsToSerialize! This is paired with it. // Sync fields with BankFieldsToSerialize! This is paired with it.
// All members are made public to remain Bank's members private and to make versioned deserializer workable on this // All members are made public to remain Bank's members private and to make versioned deserializer workable on this
#[derive(Clone, Default)] #[derive(Clone, Debug, Default)]
pub(crate) struct BankFieldsToDeserialize { pub(crate) struct BankFieldsToDeserialize {
pub(crate) blockhash_queue: BlockhashQueue, pub(crate) blockhash_queue: BlockhashQueue,
pub(crate) ancestors: Ancestors, pub(crate) ancestors: Ancestors,
@ -558,7 +586,7 @@ pub struct RewardInfo {
/// Manager for the state of all accounts and programs after processing its entries. /// Manager for the state of all accounts and programs after processing its entries.
/// AbiExample is needed even without Serialize/Deserialize; actual (de-)serialization /// AbiExample is needed even without Serialize/Deserialize; actual (de-)serialization
/// are implemented elsewhere for versioning /// are implemented elsewhere for versioning
#[derive(AbiExample, Default)] #[derive(AbiExample, Debug, Default)]
pub struct Bank { pub struct Bank {
/// References to accounts, parent and signature status /// References to accounts, parent and signature status
pub rc: BankRc, pub rc: BankRc,
@ -9319,6 +9347,7 @@ mod tests {
} }
} }
#[derive(Debug)]
struct TestExecutor {} struct TestExecutor {}
impl Executor for TestExecutor { impl Executor for TestExecutor {
fn execute( fn execute(
@ -9972,4 +10001,34 @@ mod tests {
)) ))
); );
} }
#[test]
fn test_debug_bank() {
let (genesis_config, _mint_keypair) = create_genesis_config(50000);
let mut bank = Bank::new(&genesis_config);
bank.finish_init(&genesis_config, None);
let debug = format!("{:#?}", bank);
assert!(!debug.is_empty());
}
#[test]
fn test_debug_entrypoint() {
fn mock_process_instruction(
_program_id: &Pubkey,
_keyed_accounts: &[KeyedAccount],
_data: &[u8],
) -> std::result::Result<(), InstructionError> {
Ok(())
}
fn mock_ix_processor(
_pubkey: &Pubkey,
_ka: &[KeyedAccount],
_data: &[u8],
_context: &mut dyn InvokeContext,
) -> std::result::Result<(), InstructionError> {
Ok(())
}
assert!(!format!("{:?}", Entrypoint::Program(mock_process_instruction)).is_empty());
assert!(!format!("{:?}", Entrypoint::Loader(mock_ix_processor)).is_empty());
}
} }

View File

@ -112,7 +112,7 @@ lazy_static! {
} }
/// `FeatureSet` holds the set of currently active/inactive runtime features /// `FeatureSet` holds the set of currently active/inactive runtime features
#[derive(AbiExample, Clone)] #[derive(AbiExample, Debug, Clone)]
pub struct FeatureSet { pub struct FeatureSet {
pub active: HashSet<Pubkey>, pub active: HashSet<Pubkey>,
pub inactive: HashSet<Pubkey>, pub inactive: HashSet<Pubkey>,

View File

@ -1679,7 +1679,7 @@ mod tests {
_ka: &[KeyedAccount], _ka: &[KeyedAccount],
_data: &[u8], _data: &[u8],
_context: &mut dyn InvokeContext, _context: &mut dyn InvokeContext,
) -> std::result::Result<(), InstructionError> { ) -> Result<(), InstructionError> {
Ok(()) Ok(())
} }
let program_id = Pubkey::new_rand(); let program_id = Pubkey::new_rand();

View File

@ -8,7 +8,7 @@ use solana_sdk::{
message::Message, message::Message,
pubkey::Pubkey, pubkey::Pubkey,
}; };
use std::{cell::RefCell, rc::Rc, sync::Arc}; use std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc};
// Prototype of a native loader entry point // Prototype of a native loader entry point
/// ///
@ -174,7 +174,7 @@ pub trait Logger {
} }
/// Program executor /// Program executor
pub trait Executor: Send + Sync { pub trait Executor: Debug + Send + Sync {
/// Execute the program /// Execute the program
fn execute( fn execute(
&self, &self,