Skip to content

Commit

Permalink
records-txs
Browse files Browse the repository at this point in the history
Signed-off-by: Sean Young <sean@mess.org>
  • Loading branch information
seanyoung committed Mar 30, 2024
1 parent e56d314 commit c22d75f
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 12 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion ledger-tool/src/ledger_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub fn load_and_process_ledger_or_exit(
process_options: ProcessOptions,
snapshot_archive_path: Option<PathBuf>,
incremental_snapshot_archive_path: Option<PathBuf>,
transaction_status_sender: Option<TransactionStatusSender>,
) -> (Arc<RwLock<BankForks>>, Option<StartingSnapshotHashes>) {
load_and_process_ledger(
arg_matches,
Expand All @@ -108,6 +109,7 @@ pub fn load_and_process_ledger_or_exit(
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
transaction_status_sender,
)
.unwrap_or_else(|err| {
eprintln!("Exiting. Failed to load and process ledger: {err}");
Expand All @@ -122,6 +124,7 @@ pub fn load_and_process_ledger(
process_options: ProcessOptions,
snapshot_archive_path: Option<PathBuf>,
incremental_snapshot_archive_path: Option<PathBuf>,
transaction_status_sender: Option<TransactionStatusSender>,
) -> Result<(Arc<RwLock<BankForks>>, Option<StartingSnapshotHashes>), LoadAndProcessLedgerError> {
let bank_snapshots_dir = if blockstore.is_primary_access() {
blockstore.ledger_path().join("snapshot")
Expand Down Expand Up @@ -387,7 +390,7 @@ pub fn load_and_process_ledger(
Some(transaction_status_service),
)
} else {
(None, None)
(transaction_status_sender, None)
};

let result = blockstore_processor::process_blockstore_from_root(
Expand Down
127 changes: 119 additions & 8 deletions ledger-tool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,17 @@ use {
solana_ledger::{
blockstore::{create_new_ledger, Blockstore},
blockstore_options::{AccessType, LedgerColumnOptions},
blockstore_processor::ProcessSlotCallback,
blockstore_processor::{
ProcessSlotCallback, TransactionStatusMessage, TransactionStatusSender,
},
use_snapshot_archives_at_startup,
},
solana_measure::{measure, measure::Measure},
solana_runtime::{
bank::{bank_hash_details, Bank, RewardCalculationEvent},
bank::{
bank_hash_details::{self, BankHashSlotDetails, BankHashTransaction},
Bank, RewardCalculationEvent,
},
bank_forks::BankForks,
snapshot_archive_info::SnapshotArchiveInfoGetter,
snapshot_bank_utils,
Expand All @@ -73,6 +78,7 @@ use {
transaction::{MessageHash, SanitizedTransaction, SimpleAddressLoader},
},
solana_stake_program::{points::PointValue, stake_state},
solana_transaction_status::UiInstruction,
solana_unified_scheduler_pool::DefaultSchedulerPool,
solana_vote_program::{
self,
Expand All @@ -83,6 +89,7 @@ use {
ffi::OsStr,
fs::File,
io::{self, Write},
mem::swap,
num::NonZeroUsize,
path::{Path, PathBuf},
process::{exit, Command, Stdio},
Expand Down Expand Up @@ -1080,7 +1087,7 @@ fn main() {
Arg::with_name("record_slots_config")
.long("record-slots-config")
.default_value("hash-only")
.possible_values(&["hash-only", "accounts"])
.possible_values(&["hash-only", "accounts", "tx", "tx-accounts"])
.requires("record_slots")
.help("In the slot recording, include bank details or not"),
),
Expand Down Expand Up @@ -1609,6 +1616,7 @@ fn main() {
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
None,
);

println!(
Expand All @@ -1634,6 +1642,7 @@ fn main() {
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
None,
);
println!("{}", &bank_forks.read().unwrap().working_bank().hash());
}
Expand Down Expand Up @@ -1666,6 +1675,9 @@ fn main() {
exit(1);
}

let mut transaction_status_sender = None;
let mut tx_receiver = None;

let (slot_callback, record_slots_file, recorded_slots) = if arg_matches
.occurrences_of("record_slots")
> 0
Expand All @@ -1677,19 +1689,33 @@ fn main() {
exit(1);
});

let include_bank =
let (include_bank, include_tx) =
match arg_matches.value_of("record_slots_config").unwrap() {
"hash-only" => false,
"accounts" => true,
"hash-only" => (false, false),
"tx" => (false, true),
"accounts" => (true, false),
"tx-accounts" => (true, true),
_ => unreachable!(),
};

let slot_hashes = Arc::new(Mutex::new(Vec::new()));

if include_tx {
let (sender, receiver) = crossbeam_channel::unbounded();

transaction_status_sender = Some(TransactionStatusSender { sender });

let slots = Arc::clone(&slot_hashes);

tx_receiver = Some(std::thread::spawn(move || {
record_transactions(receiver, slots);
}));
}

let slot_callback = Arc::new({
let slots = Arc::clone(&slot_hashes);
move |bank: &Bank| {
let slot_details = if include_bank {
let mut details = if include_bank {
bank_hash_details::BankHashSlotDetails::try_from(bank).unwrap()
} else {
bank_hash_details::BankHashSlotDetails {
Expand All @@ -1699,7 +1725,21 @@ fn main() {
}
};

slots.lock().unwrap().push(slot_details);
let mut slots = slots.lock().unwrap();

if let Some(recorded_slot) =
slots.iter_mut().find(|f| f.slot == details.slot)
{
// copy all fields except transactions
swap(
&mut recorded_slot.transactions,
&mut details.transactions,
);

*recorded_slot = details;
} else {
slots.push(details);
}
}
});

Expand Down Expand Up @@ -1776,6 +1816,7 @@ fn main() {
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
transaction_status_sender,
);

if print_accounts_stats {
Expand All @@ -1791,6 +1832,10 @@ fn main() {
.ok();
}

if let Some(tx_receiver) = tx_receiver {
tx_receiver.join().unwrap();
}

if let Some(recorded_slots_file) = record_slots_file {
if let Ok(recorded_slots) = recorded_slots.clone().unwrap().lock() {
let bank_hashes =
Expand Down Expand Up @@ -1833,6 +1878,7 @@ fn main() {
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
None,
);

let dot = graph_forks(&bank_forks.read().unwrap(), &graph_config);
Expand Down Expand Up @@ -2006,6 +2052,7 @@ fn main() {
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
None,
);
let mut bank = bank_forks
.read()
Expand Down Expand Up @@ -2399,6 +2446,7 @@ fn main() {
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
None,
);
let bank = bank_forks.read().unwrap().working_bank();

Expand Down Expand Up @@ -2451,6 +2499,7 @@ fn main() {
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
None,
);
let bank_forks = bank_forks.read().unwrap();
let slot = bank_forks.working_bank().slot();
Expand Down Expand Up @@ -2973,3 +3022,65 @@ fn main() {
measure_total_execution_time.stop();
info!("{}", measure_total_execution_time);
}

fn record_transactions(
recv: crossbeam_channel::Receiver<TransactionStatusMessage>,
slots: Arc<Mutex<Vec<BankHashSlotDetails>>>,
) {
for tsm in recv {
if let TransactionStatusMessage::Batch(batch) = tsm {
let slot = batch.bank.slot();

assert_eq!(batch.transactions.len(), batch.execution_results.len());

let transactions: Vec<_> = batch
.transactions
.iter()
.enumerate()
.map(|(no, tx)| {
let message = tx.message();

let accounts: Vec<String> = message
.account_keys()
.iter()
.map(|acc| acc.to_string())
.collect();

let instructions = message
.instructions()
.iter()
.map(|ix| UiInstruction::parse(ix, &message.account_keys(), None))
.collect();

let execution_results = batch.execution_results[no].clone();

let is_simple_vote_tx = tx.is_simple_vote_transaction();

BankHashTransaction {
accounts,
instructions,
is_simple_vote_tx,
execution_results,
index: batch.transaction_indexes[no],
}
})
.collect();

let mut slots = slots.lock().unwrap();

if let Some(recorded_slot) = slots.iter_mut().find(|f| f.slot == slot) {
recorded_slot.transactions.extend(transactions);
} else {
slots.push(BankHashSlotDetails {
slot,
transactions,
..Default::default()
});
}
}
}

for slot in slots.lock().unwrap().iter_mut() {
slot.transactions.sort_by(|a, b| a.index.cmp(&b.index));
}
}
1 change: 1 addition & 0 deletions ledger-tool/src/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ fn load_blockstore(ledger_path: &Path, arg_matches: &ArgMatches<'_>) -> Arc<Bank
process_options,
snapshot_archive_path,
incremental_snapshot_archive_path,
None,
);
let bank = bank_forks.read().unwrap().working_bank();
bank
Expand Down
2 changes: 2 additions & 0 deletions programs/sbf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ solana-sdk = { workspace = true }
solana-stake-program = { workspace = true }
solana-svm = { workspace = true }
solana-system-program = { workspace = true }
solana-transaction-status = { workspace = true }
solana-version = { workspace = true }
solana-vote = { workspace = true }
solana-vote-program = { workspace = true }
Expand Down
15 changes: 15 additions & 0 deletions runtime/src/bank/bank_hash_details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use {
hash::Hash,
pubkey::Pubkey,
},
solana_svm::transaction_results::TransactionExecutionDetails,
solana_transaction_status::UiInstruction,
std::str::FromStr,
};

Expand Down Expand Up @@ -65,6 +67,15 @@ impl BankHashDetails {
}
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, Default)]
pub struct BankHashTransaction {
pub index: usize,
pub accounts: Vec<String>,
pub instructions: Vec<UiInstruction>,
pub is_simple_vote_tx: bool,
pub execution_results: Option<TransactionExecutionDetails>,
}

/// The components that go into a bank hash calculation for a single bank/slot.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize, Default)]
pub struct BankHashSlotDetails {
Expand All @@ -85,6 +96,9 @@ pub struct BankHashSlotDetails {
#[serde(skip_serializing_if = "bankhashaccounts_is_empty")]
#[serde(default)]
pub accounts: BankHashAccounts,
#[serde(skip_serializing_if = "Vec::is_empty")]
#[serde(default)]
pub transactions: Vec<BankHashTransaction>,
}

fn u64_is_zero(val: &u64) -> bool {
Expand Down Expand Up @@ -113,6 +127,7 @@ impl BankHashSlotDetails {
signature_count,
last_blockhash: last_blockhash.to_string(),
accounts,
transactions: Vec::new(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions svm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ edition = { workspace = true }
itertools = { workspace = true }
log = { workspace = true }
percentage = { workspace = true }
serde = { workspace = true }
solana-bpf-loader-program = { workspace = true }
solana-frozen-abi = { workspace = true }
solana-frozen-abi-macro = { workspace = true }
Expand Down
Loading

0 comments on commit c22d75f

Please sign in to comment.