Remove transaction encoding from storage layer (#12404)

This commit is contained in:
Justin Starry 2020-09-24 13:10:29 +08:00 committed by GitHub
parent 215bbe85d8
commit 731a943239
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 270 additions and 335 deletions

View File

@ -35,7 +35,7 @@ use solana_sdk::{
transaction::{self, Transaction},
};
use solana_transaction_status::{
ConfirmedBlock, ConfirmedTransaction, TransactionStatus, UiTransactionEncoding,
EncodedConfirmedBlock, EncodedConfirmedTransaction, TransactionStatus, UiTransactionEncoding,
};
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
use std::{
@ -248,7 +248,7 @@ impl RpcClient {
self.send(RpcRequest::GetClusterNodes, Value::Null)
}
pub fn get_confirmed_block(&self, slot: Slot) -> ClientResult<ConfirmedBlock> {
pub fn get_confirmed_block(&self, slot: Slot) -> ClientResult<EncodedConfirmedBlock> {
self.get_confirmed_block_with_encoding(slot, UiTransactionEncoding::Json)
}
@ -256,7 +256,7 @@ impl RpcClient {
&self,
slot: Slot,
encoding: UiTransactionEncoding,
) -> ClientResult<ConfirmedBlock> {
) -> ClientResult<EncodedConfirmedBlock> {
self.send(RpcRequest::GetConfirmedBlock, json!([slot, encoding]))
}
@ -326,7 +326,7 @@ impl RpcClient {
&self,
signature: &Signature,
encoding: UiTransactionEncoding,
) -> ClientResult<ConfirmedTransaction> {
) -> ClientResult<EncodedConfirmedTransaction> {
self.send(
RpcRequest::GetConfirmedTransaction,
json!([signature.to_string(), encoding]),

View File

@ -1092,7 +1092,7 @@ mod tests {
system_transaction,
transaction::TransactionError,
};
use solana_transaction_status::{EncodedTransaction, TransactionWithStatusMeta};
use solana_transaction_status::TransactionWithStatusMeta;
use std::{sync::atomic::Ordering, thread::sleep};
#[test]
@ -2038,36 +2038,26 @@ mod tests {
transaction_status_service.join().unwrap();
let confirmed_block = blockstore.get_confirmed_block(bank.slot(), None).unwrap();
let confirmed_block = blockstore.get_confirmed_block(bank.slot()).unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for TransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let EncodedTransaction::Json(transaction) = transaction {
if transaction.signatures[0] == success_signature.to_string() {
let meta = meta.unwrap();
assert_eq!(meta.err, None);
assert_eq!(meta.status, Ok(()));
} else if transaction.signatures[0] == ix_error_signature.to_string() {
let meta = meta.unwrap();
assert_eq!(
meta.err,
Some(TransactionError::InstructionError(
0,
InstructionError::Custom(1)
))
);
assert_eq!(
meta.status,
Err(TransactionError::InstructionError(
0,
InstructionError::Custom(1)
))
);
} else {
assert_eq!(meta, None);
}
if transaction.signatures[0] == success_signature {
let meta = meta.unwrap();
assert_eq!(meta.status, Ok(()));
} else if transaction.signatures[0] == ix_error_signature {
let meta = meta.unwrap();
assert_eq!(
meta.status,
Err(TransactionError::InstructionError(
0,
InstructionError::Custom(1)
))
);
} else {
assert_eq!(meta, None);
}
}
}

View File

@ -1992,7 +1992,7 @@ pub(crate) mod tests {
system_transaction,
transaction::TransactionError,
};
use solana_transaction_status::{EncodedTransaction, TransactionWithStatusMeta};
use solana_transaction_status::TransactionWithStatusMeta;
use solana_vote_program::{
vote_state::{VoteState, VoteStateVersions},
vote_transaction,
@ -2732,36 +2732,26 @@ pub(crate) mod tests {
blockstore.clone(),
);
let confirmed_block = blockstore.get_confirmed_block(slot, None).unwrap();
let confirmed_block = blockstore.get_confirmed_block(slot).unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for TransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let EncodedTransaction::Json(transaction) = transaction {
if transaction.signatures[0] == signatures[0].to_string() {
let meta = meta.unwrap();
assert_eq!(meta.err, None);
assert_eq!(meta.status, Ok(()));
} else if transaction.signatures[0] == signatures[1].to_string() {
let meta = meta.unwrap();
assert_eq!(
meta.err,
Some(TransactionError::InstructionError(
0,
InstructionError::Custom(1)
))
);
assert_eq!(
meta.status,
Err(TransactionError::InstructionError(
0,
InstructionError::Custom(1)
))
);
} else {
assert_eq!(meta, None);
}
if transaction.signatures[0] == signatures[0] {
let meta = meta.unwrap();
assert_eq!(meta.status, Ok(()));
} else if transaction.signatures[0] == signatures[1] {
let meta = meta.unwrap();
assert_eq!(
meta.status,
Err(TransactionError::InstructionError(
0,
InstructionError::Custom(1)
))
);
} else {
assert_eq!(meta, None);
}
}
}

View File

@ -61,7 +61,7 @@ use solana_sdk::{
};
use solana_stake_program::stake_state::StakeState;
use solana_transaction_status::{
ConfirmedBlock, ConfirmedTransaction, TransactionStatus, UiTransactionEncoding,
EncodedConfirmedBlock, EncodedConfirmedTransaction, TransactionStatus, UiTransactionEncoding,
};
use solana_vote_program::vote_state::{VoteState, MAX_LOCKOUT_HISTORY};
use spl_token_v2_0::{
@ -612,7 +612,7 @@ impl JsonRpcRequestProcessor {
&self,
slot: Slot,
encoding: Option<UiTransactionEncoding>,
) -> Result<Option<ConfirmedBlock>> {
) -> Result<Option<EncodedConfirmedBlock>> {
let encoding = encoding.unwrap_or(UiTransactionEncoding::Json);
if self.config.enable_rpc_transaction_history
&& slot
@ -622,17 +622,20 @@ impl JsonRpcRequestProcessor {
.unwrap()
.highest_confirmed_root()
{
let result = self.blockstore.get_confirmed_block(slot, Some(encoding));
let result = self.blockstore.get_confirmed_block(slot);
if result.is_err() {
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
return Ok(self
.runtime_handle
.block_on(bigtable_ledger_storage.get_confirmed_block(slot, encoding))
.ok());
.block_on(bigtable_ledger_storage.get_confirmed_block(slot))
.ok()
.map(|confirmed_block| confirmed_block.encode(encoding)));
}
}
self.check_slot_cleaned_up(&result, slot)?;
Ok(result.ok())
Ok(result
.ok()
.map(|confirmed_block| confirmed_block.encode(encoding)))
} else {
Err(RpcCustomError::BlockNotAvailable { slot }.into())
}
@ -808,12 +811,12 @@ impl JsonRpcRequestProcessor {
&self,
signature: Signature,
encoding: Option<UiTransactionEncoding>,
) -> Option<ConfirmedTransaction> {
) -> Option<EncodedConfirmedTransaction> {
let encoding = encoding.unwrap_or(UiTransactionEncoding::Json);
if self.config.enable_rpc_transaction_history {
match self
.blockstore
.get_confirmed_transaction(signature, Some(encoding))
.get_confirmed_transaction(signature)
.unwrap_or(None)
{
Some(confirmed_transaction) => {
@ -824,18 +827,16 @@ impl JsonRpcRequestProcessor {
.unwrap()
.highest_confirmed_root()
{
return Some(confirmed_transaction);
return Some(confirmed_transaction.encode(encoding));
}
}
None => {
if let Some(bigtable_ledger_storage) = &self.bigtable_ledger_storage {
return self
.runtime_handle
.block_on(
bigtable_ledger_storage
.get_confirmed_transaction(&signature, encoding),
)
.unwrap_or(None);
.block_on(bigtable_ledger_storage.get_confirmed_transaction(&signature))
.unwrap_or(None)
.map(|confirmed| confirmed.encode(encoding));
}
}
}
@ -1660,7 +1661,7 @@ pub trait RpcSol {
meta: Self::Metadata,
slot: Slot,
encoding: Option<UiTransactionEncoding>,
) -> Result<Option<ConfirmedBlock>>;
) -> Result<Option<EncodedConfirmedBlock>>;
#[rpc(meta, name = "getBlockTime")]
fn get_block_time(&self, meta: Self::Metadata, slot: Slot) -> Result<Option<UnixTimestamp>>;
@ -1679,7 +1680,7 @@ pub trait RpcSol {
meta: Self::Metadata,
signature_str: String,
encoding: Option<UiTransactionEncoding>,
) -> Result<Option<ConfirmedTransaction>>;
) -> Result<Option<EncodedConfirmedTransaction>>;
#[rpc(meta, name = "getConfirmedSignaturesForAddress")]
fn get_confirmed_signatures_for_address(
@ -2308,7 +2309,7 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata,
slot: Slot,
encoding: Option<UiTransactionEncoding>,
) -> Result<Option<ConfirmedBlock>> {
) -> Result<Option<EncodedConfirmedBlock>> {
debug!("get_confirmed_block rpc request received: {:?}", slot);
meta.get_confirmed_block(slot, encoding)
}
@ -2335,7 +2336,7 @@ impl RpcSol for RpcSolImpl {
meta: Self::Metadata,
signature_str: String,
encoding: Option<UiTransactionEncoding>,
) -> Result<Option<ConfirmedTransaction>> {
) -> Result<Option<EncodedConfirmedTransaction>> {
debug!(
"get_confirmed_transaction rpc request received: {:?}",
signature_str
@ -2563,7 +2564,9 @@ pub mod tests {
timing::slot_duration_from_slots_per_year,
transaction::{self, TransactionError},
};
use solana_transaction_status::{EncodedTransaction, TransactionWithStatusMeta, UiMessage};
use solana_transaction_status::{
EncodedTransaction, EncodedTransactionWithStatusMeta, UiMessage,
};
use solana_vote_program::{
vote_instruction,
vote_state::{Vote, VoteInit, MAX_LOCKOUT_HISTORY},
@ -4532,12 +4535,12 @@ pub mod tests {
let res = io.handle_request_sync(&req, meta.clone());
let result: Value = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let confirmed_block: Option<ConfirmedBlock> =
let confirmed_block: Option<EncodedConfirmedBlock> =
serde_json::from_value(result["result"].clone()).unwrap();
let confirmed_block = confirmed_block.unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for TransactionWithStatusMeta { transaction, meta } in
for EncodedTransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let EncodedTransaction::Json(transaction) = transaction {
@ -4576,12 +4579,12 @@ pub mod tests {
let res = io.handle_request_sync(&req, meta);
let result: Value = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
let confirmed_block: Option<ConfirmedBlock> =
let confirmed_block: Option<EncodedConfirmedBlock> =
serde_json::from_value(result["result"].clone()).unwrap();
let confirmed_block = confirmed_block.unwrap();
assert_eq!(confirmed_block.transactions.len(), 3);
for TransactionWithStatusMeta { transaction, meta } in
for EncodedTransactionWithStatusMeta { transaction, meta } in
confirmed_block.transactions.into_iter()
{
if let EncodedTransaction::LegacyBinary(transaction) = transaction {

View File

@ -7,7 +7,7 @@ use solana_clap_utils::{
use solana_cli_output::display::println_transaction;
use solana_ledger::{blockstore::Blockstore, blockstore_db::AccessType};
use solana_sdk::{clock::Slot, pubkey::Pubkey, signature::Signature};
use solana_transaction_status::UiTransactionEncoding;
use solana_transaction_status::ConfirmedBlock;
use std::{
path::Path,
process::exit,
@ -51,9 +51,7 @@ async fn block(slot: Slot) -> Result<(), Box<dyn std::error::Error>> {
.await
.map_err(|err| format!("Failed to connect to storage: {:?}", err))?;
let block = bigtable
.get_confirmed_block(slot, UiTransactionEncoding::Base64)
.await?;
let block = bigtable.get_confirmed_block(slot).await?;
println!("Slot: {}", slot);
println!("Parent Slot: {}", block.parent_slot);
@ -65,11 +63,11 @@ async fn block(slot: Slot) -> Result<(), Box<dyn std::error::Error>> {
if !block.rewards.is_empty() {
println!("Rewards: {:?}", block.rewards);
}
for (index, transaction_with_meta) in block.transactions.iter().enumerate() {
for (index, transaction_with_meta) in block.transactions.into_iter().enumerate() {
println!("Transaction {}:", index);
println_transaction(
&transaction_with_meta.transaction.decode().unwrap(),
&transaction_with_meta.meta,
&transaction_with_meta.transaction,
&transaction_with_meta.meta.map(|meta| meta.into()),
" ",
);
}
@ -96,22 +94,15 @@ async fn confirm(signature: &Signature, verbose: bool) -> Result<(), Box<dyn std
let transaction_status = bigtable.get_signature_status(signature).await?;
if verbose {
match bigtable
.get_confirmed_transaction(signature, UiTransactionEncoding::Base64)
.await
{
match bigtable.get_confirmed_transaction(signature).await {
Ok(Some(confirmed_transaction)) => {
println!(
"\nTransaction executed in slot {}:",
confirmed_transaction.slot
);
println_transaction(
&confirmed_transaction
.transaction
.transaction
.decode()
.expect("Successful decode"),
&confirmed_transaction.transaction.meta,
&confirmed_transaction.transaction.transaction,
&confirmed_transaction.transaction.meta.map(|m| m.into()),
" ",
);
}
@ -138,7 +129,7 @@ pub async fn transaction_history(
) -> Result<(), Box<dyn std::error::Error>> {
let bigtable = solana_storage_bigtable::LedgerStorage::new(true).await?;
let mut loaded_block: Option<(Slot, solana_transaction_status::ConfirmedBlock)> = None;
let mut loaded_block: Option<(Slot, ConfirmedBlock)> = None;
while limit > 0 {
let results = bigtable
.get_confirmed_signatures_for_address(
@ -188,11 +179,8 @@ pub async fn transaction_history(
}
Some(transaction_with_meta) => {
println_transaction(
&transaction_with_meta
.transaction
.decode()
.expect("Successful decode"),
&transaction_with_meta.meta,
&transaction_with_meta.transaction,
&transaction_with_meta.meta.clone().map(|m| m.into()),
" ",
);
}
@ -200,10 +188,7 @@ pub async fn transaction_history(
break;
}
}
match bigtable
.get_confirmed_block(result.slot, UiTransactionEncoding::Base64)
.await
{
match bigtable.get_confirmed_block(result.slot).await {
Err(err) => {
println!(" Unable to get confirmed transaction details: {}", err);
break;

View File

@ -135,10 +135,7 @@ pub async fn upload_confirmed_blocks(
break;
}
let _ = match blockstore.get_confirmed_block(
*slot,
Some(solana_transaction_status::UiTransactionEncoding::Base64),
) {
let _ = match blockstore.get_confirmed_block(*slot) {
Ok(confirmed_block) => sender.send((*slot, Some(confirmed_block))),
Err(err) => {
warn!(

View File

@ -37,9 +37,8 @@ use solana_sdk::{
transaction::Transaction,
};
use solana_transaction_status::{
ConfirmedBlock, ConfirmedTransaction, ConfirmedTransactionStatusWithSignature,
EncodedTransaction, Rewards, TransactionStatusMeta, TransactionWithStatusMeta,
UiTransactionEncoding, UiTransactionStatusMeta,
ConfirmedBlock, ConfirmedTransaction, ConfirmedTransactionStatusWithSignature, Rewards,
TransactionStatusMeta, TransactionWithStatusMeta,
};
use solana_vote_program::vote_instruction::VoteInstruction;
use std::{
@ -1646,11 +1645,7 @@ impl Blockstore {
Ok(root_iterator.next().unwrap_or_default())
}
pub fn get_confirmed_block(
&self,
slot: Slot,
encoding: Option<UiTransactionEncoding>,
) -> Result<ConfirmedBlock> {
pub fn get_confirmed_block(&self, slot: Slot) -> Result<ConfirmedBlock> {
datapoint_info!(
"blockstore-rpc-api",
("method", "get_confirmed_block".to_string(), String)
@ -1661,7 +1656,6 @@ impl Blockstore {
if *lowest_cleanup_slot > 0 && *lowest_cleanup_slot >= slot {
return Err(BlockstoreError::SlotCleanedUp);
}
let encoding = encoding.unwrap_or(UiTransactionEncoding::Json);
if self.is_root(slot) {
let slot_meta_cf = self.db.column::<cf::SlotMeta>();
let slot_meta = match slot_meta_cf.get(slot)? {
@ -1697,11 +1691,8 @@ impl Blockstore {
previous_blockhash: previous_blockhash.to_string(),
blockhash: blockhash.to_string(),
parent_slot: slot_meta.parent_slot,
transactions: self.map_transactions_to_statuses(
slot,
encoding,
slot_transaction_iterator,
),
transactions: self
.map_transactions_to_statuses(slot, slot_transaction_iterator),
rewards,
block_time,
};
@ -1714,19 +1705,16 @@ impl Blockstore {
fn map_transactions_to_statuses<'a>(
&self,
slot: Slot,
encoding: UiTransactionEncoding,
iterator: impl Iterator<Item = Transaction> + 'a,
) -> Vec<TransactionWithStatusMeta> {
iterator
.map(|transaction| {
let signature = transaction.signatures[0];
let encoded_transaction = EncodedTransaction::encode(transaction, encoding);
TransactionWithStatusMeta {
transaction: encoded_transaction,
transaction,
meta: self
.read_transaction_status((signature, slot))
.expect("Expect database get to succeed")
.map(UiTransactionStatusMeta::from),
.expect("Expect database get to succeed"),
}
})
.collect()
@ -1902,7 +1890,6 @@ impl Blockstore {
pub fn get_confirmed_transaction(
&self,
signature: Signature,
encoding: Option<UiTransactionEncoding>,
) -> Result<Option<ConfirmedTransaction>> {
datapoint_info!(
"blockstore-rpc-api",
@ -1912,13 +1899,11 @@ impl Blockstore {
let transaction = self
.find_transaction_in_slot(slot, signature)?
.ok_or(BlockstoreError::TransactionStatusSlotMismatch)?; // Should not happen
let encoding = encoding.unwrap_or(UiTransactionEncoding::Json);
let encoded_transaction = EncodedTransaction::encode(transaction, encoding);
Ok(Some(ConfirmedTransaction {
slot,
transaction: TransactionWithStatusMeta {
transaction: encoded_transaction,
meta: Some(status.into()),
transaction,
meta: Some(status),
},
}))
} else {
@ -2019,27 +2004,23 @@ impl Blockstore {
match transaction_status {
None => return Ok(vec![]),
Some((slot, _)) => {
let confirmed_block = self
.get_confirmed_block(slot, Some(UiTransactionEncoding::Base64))
.map_err(|err| {
BlockstoreError::IO(IOError::new(
ErrorKind::Other,
format!("Unable to get confirmed block: {}", err),
))
})?;
let confirmed_block = self.get_confirmed_block(slot).map_err(|err| {
BlockstoreError::IO(IOError::new(
ErrorKind::Other,
format!("Unable to get confirmed block: {}", err),
))
})?;
// Load all signatures for the block
let mut slot_signatures: Vec<_> = confirmed_block
.transactions
.iter()
.into_iter()
.filter_map(|transaction_with_meta| {
if let Some(transaction) =
transaction_with_meta.transaction.decode()
{
transaction.signatures.into_iter().next()
} else {
None
}
transaction_with_meta
.transaction
.signatures
.into_iter()
.next()
})
.collect();
@ -2073,27 +2054,23 @@ impl Blockstore {
match transaction_status {
None => (0, HashSet::new()),
Some((slot, _)) => {
let confirmed_block = self
.get_confirmed_block(slot, Some(UiTransactionEncoding::Base64))
.map_err(|err| {
BlockstoreError::IO(IOError::new(
ErrorKind::Other,
format!("Unable to get confirmed block: {}", err),
))
})?;
let confirmed_block = self.get_confirmed_block(slot).map_err(|err| {
BlockstoreError::IO(IOError::new(
ErrorKind::Other,
format!("Unable to get confirmed block: {}", err),
))
})?;
// Load all signatures for the block
let mut slot_signatures: Vec<_> = confirmed_block
.transactions
.iter()
.into_iter()
.filter_map(|transaction_with_meta| {
if let Some(transaction) =
transaction_with_meta.transaction.decode()
{
transaction.signatures.into_iter().next()
} else {
None
}
transaction_with_meta
.transaction
.signatures
.into_iter()
.next()
})
.collect();
@ -5672,7 +5649,7 @@ pub mod tests {
.put_meta_bytes(slot - 1, &serialize(&parent_meta).unwrap())
.unwrap();
let expected_transactions: Vec<(Transaction, Option<UiTransactionStatusMeta>)> = entries
let expected_transactions: Vec<TransactionWithStatusMeta> = entries
.iter()
.cloned()
.filter(|entry| !entry.is_tick())
@ -5709,37 +5686,27 @@ pub mod tests {
},
)
.unwrap();
(
TransactionWithStatusMeta {
transaction,
Some(
TransactionStatusMeta {
status: Ok(()),
fee: 42,
pre_balances,
post_balances,
}
.into(),
),
)
meta: Some(TransactionStatusMeta {
status: Ok(()),
fee: 42,
pre_balances,
post_balances,
}),
}
})
.collect();
// Even if marked as root, a slot that is empty of entries should return an error
let confirmed_block_err = ledger.get_confirmed_block(slot - 1, None).unwrap_err();
let confirmed_block_err = ledger.get_confirmed_block(slot - 1).unwrap_err();
assert_matches!(confirmed_block_err, BlockstoreError::SlotNotRooted);
let confirmed_block = ledger.get_confirmed_block(slot, None).unwrap();
let confirmed_block = ledger.get_confirmed_block(slot).unwrap();
assert_eq!(confirmed_block.transactions.len(), 100);
let expected_block = ConfirmedBlock {
transactions: expected_transactions
.iter()
.cloned()
.map(|(tx, meta)| TransactionWithStatusMeta {
transaction: EncodedTransaction::encode(tx, UiTransactionEncoding::Json),
meta,
})
.collect(),
transactions: expected_transactions.clone(),
parent_slot: slot - 1,
blockhash: blockhash.to_string(),
previous_blockhash: Hash::default().to_string(),
@ -5750,18 +5717,11 @@ pub mod tests {
// root, but empty of entries. This is special handling for snapshot root slots.
assert_eq!(confirmed_block, expected_block);
let confirmed_block = ledger.get_confirmed_block(slot + 1, None).unwrap();
let confirmed_block = ledger.get_confirmed_block(slot + 1).unwrap();
assert_eq!(confirmed_block.transactions.len(), 100);
let mut expected_block = ConfirmedBlock {
transactions: expected_transactions
.iter()
.cloned()
.map(|(tx, meta)| TransactionWithStatusMeta {
transaction: EncodedTransaction::encode(tx, UiTransactionEncoding::Json),
meta,
})
.collect(),
transactions: expected_transactions,
parent_slot: slot,
blockhash: blockhash.to_string(),
previous_blockhash: blockhash.to_string(),
@ -5770,7 +5730,7 @@ pub mod tests {
};
assert_eq!(confirmed_block, expected_block);
let not_root = ledger.get_confirmed_block(slot + 2, None).unwrap_err();
let not_root = ledger.get_confirmed_block(slot + 2).unwrap_err();
assert_matches!(not_root, BlockstoreError::SlotNotRooted);
// Test block_time returns, if available
@ -5778,7 +5738,7 @@ pub mod tests {
ledger.blocktime_cf.put(slot + 1, &timestamp).unwrap();
expected_block.block_time = Some(timestamp);
let confirmed_block = ledger.get_confirmed_block(slot + 1, None).unwrap();
let confirmed_block = ledger.get_confirmed_block(slot + 1).unwrap();
assert_eq!(confirmed_block, expected_block);
drop(ledger);
@ -6434,7 +6394,7 @@ pub mod tests {
blockstore.insert_shreds(shreds, None, false).unwrap();
blockstore.set_roots(&[slot - 1, slot]).unwrap();
let expected_transactions: Vec<(Transaction, Option<UiTransactionStatusMeta>)> = entries
let expected_transactions: Vec<TransactionWithStatusMeta> = entries
.iter()
.cloned()
.filter(|entry| !entry.is_tick())
@ -6459,48 +6419,32 @@ pub mod tests {
},
)
.unwrap();
(
TransactionWithStatusMeta {
transaction,
Some(
TransactionStatusMeta {
status: Ok(()),
fee: 42,
pre_balances,
post_balances,
}
.into(),
),
)
meta: Some(TransactionStatusMeta {
status: Ok(()),
fee: 42,
pre_balances,
post_balances,
}),
}
})
.collect();
for (transaction, status) in expected_transactions.clone() {
let signature = transaction.signatures[0];
let encoded_transaction =
EncodedTransaction::encode(transaction, UiTransactionEncoding::Json);
let expected_transaction = ConfirmedTransaction {
slot,
transaction: TransactionWithStatusMeta {
transaction: encoded_transaction,
meta: status,
},
};
for transaction in expected_transactions.clone() {
let signature = transaction.transaction.signatures[0];
assert_eq!(
blockstore
.get_confirmed_transaction(signature, None)
.unwrap(),
Some(expected_transaction)
blockstore.get_confirmed_transaction(signature).unwrap(),
Some(ConfirmedTransaction { slot, transaction })
);
}
blockstore.run_purge(0, 2, PurgeType::PrimaryIndex).unwrap();
*blockstore.lowest_cleanup_slot.write().unwrap() = slot;
for (transaction, _) in expected_transactions {
for TransactionWithStatusMeta { transaction, .. } in expected_transactions {
let signature = transaction.signatures[0];
assert_eq!(
blockstore
.get_confirmed_transaction(signature, None)
.unwrap(),
blockstore.get_confirmed_transaction(signature).unwrap(),
None,
);
}
@ -6513,7 +6457,7 @@ pub mod tests {
blockstore.set_roots(&[0]).unwrap();
assert_eq!(
blockstore
.get_confirmed_transaction(Signature::default(), None)
.get_confirmed_transaction(Signature::default())
.unwrap(),
None
);
@ -6935,11 +6879,7 @@ pub mod tests {
vec![CompiledInstruction::new(1, &(), vec![0])],
));
let map = blockstore.map_transactions_to_statuses(
slot,
UiTransactionEncoding::Json,
transactions.into_iter(),
);
let map = blockstore.map_transactions_to_statuses(slot, transactions.into_iter());
assert_eq!(map.len(), 5);
for (x, m) in map.iter().take(4).enumerate() {
assert_eq!(m.meta.as_ref().unwrap().fee, x as u64);

View File

@ -7,7 +7,9 @@ use solana_sdk::{
pubkey::Pubkey, signature::Signature, transaction::Transaction,
};
use solana_stake_program::{stake_instruction::StakeInstruction, stake_state::Lockup};
use solana_transaction_status::{ConfirmedBlock, UiTransactionEncoding, UiTransactionStatusMeta};
use solana_transaction_status::{
EncodedConfirmedBlock, UiTransactionEncoding, UiTransactionStatusMeta,
};
use std::{collections::HashMap, thread::sleep, time::Duration};
pub type PubkeyString = String;
@ -244,7 +246,7 @@ fn process_transaction(
fn process_confirmed_block(
slot: Slot,
confirmed_block: ConfirmedBlock,
confirmed_block: EncodedConfirmedBlock,
accounts: &mut HashMap<PubkeyString, AccountInfo>,
) {
for rpc_transaction in confirmed_block.transactions {
@ -281,7 +283,7 @@ fn load_blocks(
rpc_client: &RpcClient,
start_slot: Slot,
end_slot: Slot,
) -> ClientResult<Vec<(Slot, ConfirmedBlock)>> {
) -> ClientResult<Vec<(Slot, EncodedConfirmedBlock)>> {
info!(
"Loading confirmed blocks between slots: {} - {}",
start_slot, end_slot

View File

@ -8,14 +8,10 @@ use solana_sdk::{
transaction::{Transaction, TransactionError},
};
use solana_transaction_status::{
ConfirmedBlock, ConfirmedTransaction, ConfirmedTransactionStatusWithSignature,
EncodedTransaction, Rewards, TransactionStatus, TransactionWithStatusMeta,
UiTransactionEncoding, UiTransactionStatusMeta,
};
use std::{
collections::HashMap,
convert::{TryFrom, TryInto},
ConfirmedBlock, ConfirmedTransaction, ConfirmedTransactionStatusWithSignature, Rewards,
TransactionStatus, TransactionStatusMeta, TransactionWithStatusMeta,
};
use std::collections::HashMap;
use thiserror::Error;
#[macro_use]
@ -91,35 +87,8 @@ struct StoredConfirmedBlock {
block_time: Option<UnixTimestamp>,
}
impl StoredConfirmedBlock {
fn into_confirmed_block(self, encoding: UiTransactionEncoding) -> ConfirmedBlock {
let StoredConfirmedBlock {
previous_blockhash,
blockhash,
parent_slot,
transactions,
rewards,
block_time,
} = self;
ConfirmedBlock {
previous_blockhash,
blockhash,
parent_slot,
transactions: transactions
.into_iter()
.map(|transaction| transaction.into_transaction_with_status_meta(encoding))
.collect(),
rewards,
block_time,
}
}
}
impl TryFrom<ConfirmedBlock> for StoredConfirmedBlock {
type Error = Error;
fn try_from(confirmed_block: ConfirmedBlock) -> Result<Self> {
impl From<ConfirmedBlock> for StoredConfirmedBlock {
fn from(confirmed_block: ConfirmedBlock) -> Self {
let ConfirmedBlock {
previous_blockhash,
blockhash,
@ -129,19 +98,36 @@ impl TryFrom<ConfirmedBlock> for StoredConfirmedBlock {
block_time,
} = confirmed_block;
let mut encoded_transactions = vec![];
for transaction in transactions.into_iter() {
encoded_transactions.push(transaction.try_into()?);
}
Ok(Self {
Self {
previous_blockhash,
blockhash,
parent_slot,
transactions: encoded_transactions,
transactions: transactions.into_iter().map(|tx| tx.into()).collect(),
rewards,
block_time,
})
}
}
}
impl From<StoredConfirmedBlock> for ConfirmedBlock {
fn from(confirmed_block: StoredConfirmedBlock) -> Self {
let StoredConfirmedBlock {
previous_blockhash,
blockhash,
parent_slot,
transactions,
rewards,
block_time,
} = confirmed_block;
Self {
previous_blockhash,
blockhash,
parent_slot,
transactions: transactions.into_iter().map(|tx| tx.into()).collect(),
rewards,
block_time,
}
}
}
@ -151,31 +137,21 @@ struct StoredConfirmedBlockTransaction {
meta: Option<StoredConfirmedBlockTransactionStatusMeta>,
}
impl StoredConfirmedBlockTransaction {
fn into_transaction_with_status_meta(
self,
encoding: UiTransactionEncoding,
) -> TransactionWithStatusMeta {
let StoredConfirmedBlockTransaction { transaction, meta } = self;
TransactionWithStatusMeta {
transaction: EncodedTransaction::encode(transaction, encoding),
meta: meta.map(|meta| meta.into()),
impl From<TransactionWithStatusMeta> for StoredConfirmedBlockTransaction {
fn from(value: TransactionWithStatusMeta) -> Self {
Self {
transaction: value.transaction,
meta: value.meta.map(|meta| meta.into()),
}
}
}
impl TryFrom<TransactionWithStatusMeta> for StoredConfirmedBlockTransaction {
type Error = Error;
fn try_from(value: TransactionWithStatusMeta) -> Result<Self> {
let TransactionWithStatusMeta { transaction, meta } = value;
Ok(Self {
transaction: transaction
.decode()
.ok_or(Error::UnsupportedTransactionEncoding)?,
meta: meta.map(|meta| meta.into()),
})
impl From<StoredConfirmedBlockTransaction> for TransactionWithStatusMeta {
fn from(value: StoredConfirmedBlockTransaction) -> Self {
Self {
transaction: value.transaction,
meta: value.meta.map(|meta| meta.into()),
}
}
}
@ -187,7 +163,7 @@ struct StoredConfirmedBlockTransactionStatusMeta {
post_balances: Vec<u64>,
}
impl From<StoredConfirmedBlockTransactionStatusMeta> for UiTransactionStatusMeta {
impl From<StoredConfirmedBlockTransactionStatusMeta> for TransactionStatusMeta {
fn from(value: StoredConfirmedBlockTransactionStatusMeta) -> Self {
let StoredConfirmedBlockTransactionStatusMeta {
err,
@ -200,7 +176,6 @@ impl From<StoredConfirmedBlockTransactionStatusMeta> for UiTransactionStatusMeta
Some(err) => Err(err.clone()),
};
Self {
err,
status,
fee,
pre_balances,
@ -209,17 +184,17 @@ impl From<StoredConfirmedBlockTransactionStatusMeta> for UiTransactionStatusMeta
}
}
impl From<UiTransactionStatusMeta> for StoredConfirmedBlockTransactionStatusMeta {
fn from(value: UiTransactionStatusMeta) -> Self {
let UiTransactionStatusMeta {
err,
impl From<TransactionStatusMeta> for StoredConfirmedBlockTransactionStatusMeta {
fn from(value: TransactionStatusMeta) -> Self {
let TransactionStatusMeta {
status,
fee,
pre_balances,
post_balances,
..
} = value;
Self {
err,
err: status.err(),
fee,
pre_balances,
post_balances,
@ -296,16 +271,12 @@ impl LedgerStorage {
}
/// Fetch the confirmed block from the desired slot
pub async fn get_confirmed_block(
&self,
slot: Slot,
encoding: UiTransactionEncoding,
) -> Result<ConfirmedBlock> {
pub async fn get_confirmed_block(&self, slot: Slot) -> Result<ConfirmedBlock> {
let mut bigtable = self.connection.client();
let block = bigtable
.get_bincode_cell::<StoredConfirmedBlock>("blocks", slot_to_key(slot))
.await?;
Ok(block.into_confirmed_block(encoding))
Ok(block.into())
}
pub async fn get_signature_status(&self, signature: &Signature) -> Result<TransactionStatus> {
@ -320,7 +291,6 @@ impl LedgerStorage {
pub async fn get_confirmed_transaction(
&self,
signature: &Signature,
encoding: UiTransactionEncoding,
) -> Result<Option<ConfirmedTransaction>> {
let mut bigtable = self.connection.client();
@ -348,8 +318,7 @@ impl LedgerStorage {
} else {
Ok(Some(ConfirmedTransaction {
slot,
transaction: bucket_block_transaction
.into_transaction_with_status_meta(encoding),
transaction: bucket_block_transaction.into(),
}))
}
}
@ -467,22 +436,16 @@ impl LedgerStorage {
) -> Result<()> {
let mut bytes_written = 0;
let mut by_addr: HashMap<Pubkey, Vec<TransactionByAddrInfo>> = HashMap::new();
let mut by_addr: HashMap<&Pubkey, Vec<TransactionByAddrInfo>> = HashMap::new();
let mut tx_cells = vec![];
for (index, transaction_with_meta) in confirmed_block.transactions.iter().enumerate() {
let err = transaction_with_meta
.meta
.as_ref()
.and_then(|meta| meta.err.clone());
let TransactionWithStatusMeta { meta, transaction } = transaction_with_meta;
let err = meta.as_ref().and_then(|meta| meta.status.clone().err());
let index = index as u32;
let transaction = transaction_with_meta
.transaction
.decode()
.expect("transaction decode failed");
let signature = transaction.signatures[0];
for address in transaction.message.account_keys {
for address in &transaction.message.account_keys {
if !is_sysvar_id(&address) {
by_addr
.entry(address)
@ -539,7 +502,7 @@ impl LedgerStorage {
// Store the block itself last, after all other metadata about the block has been
// successfully stored. This avoids partial uploaded blocks from becoming visible to
// `get_confirmed_block()` and `get_confirmed_blocks()`
let blocks_cells = [(slot_to_key(slot), confirmed_block.try_into()?)];
let blocks_cells = [(slot_to_key(slot), confirmed_block.into())];
bytes_written += self
.connection
.put_bincode_cells_with_retry::<StoredConfirmedBlock>("blocks", &blocks_cells)

View File

@ -165,6 +165,34 @@ pub struct ConfirmedBlock {
pub block_time: Option<UnixTimestamp>,
}
impl ConfirmedBlock {
pub fn encode(self, encoding: UiTransactionEncoding) -> EncodedConfirmedBlock {
EncodedConfirmedBlock {
previous_blockhash: self.previous_blockhash,
blockhash: self.blockhash,
parent_slot: self.parent_slot,
transactions: self
.transactions
.into_iter()
.map(|tx| tx.encode(encoding))
.collect(),
rewards: self.rewards,
block_time: self.block_time,
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedConfirmedBlock {
pub previous_blockhash: String,
pub blockhash: String,
pub parent_slot: Slot,
pub transactions: Vec<EncodedTransactionWithStatusMeta>,
pub rewards: Rewards,
pub block_time: Option<UnixTimestamp>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConfirmedTransaction {
@ -173,6 +201,23 @@ pub struct ConfirmedTransaction {
pub transaction: TransactionWithStatusMeta,
}
impl ConfirmedTransaction {
pub fn encode(self, encoding: UiTransactionEncoding) -> EncodedConfirmedTransaction {
EncodedConfirmedTransaction {
slot: self.slot,
transaction: self.transaction.encode(encoding),
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedConfirmedTransaction {
pub slot: Slot,
#[serde(flatten)]
pub transaction: EncodedTransactionWithStatusMeta,
}
/// A duplicate representation of a Transaction for pretty JSON serialization
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
@ -207,9 +252,25 @@ pub struct UiParsedMessage {
pub instructions: Vec<UiInstruction>,
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TransactionWithStatusMeta {
pub transaction: Transaction,
pub meta: Option<TransactionStatusMeta>,
}
impl TransactionWithStatusMeta {
fn encode(self, encoding: UiTransactionEncoding) -> EncodedTransactionWithStatusMeta {
EncodedTransactionWithStatusMeta {
transaction: EncodedTransaction::encode(self.transaction, encoding),
meta: self.meta.map(|meta| meta.into()),
}
}
}
#[derive(Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncodedTransactionWithStatusMeta {
pub transaction: EncodedTransaction,
pub meta: Option<UiTransactionStatusMeta>,
}

View File

@ -16,7 +16,7 @@ use solana_sdk::{
clock::Slot, hash::Hash, native_token::lamports_to_sol, program_utils::limited_deserialize,
pubkey::Pubkey,
};
use solana_transaction_status::{ConfirmedBlock, UiTransactionEncoding};
use solana_transaction_status::{EncodedConfirmedBlock, UiTransactionEncoding};
use solana_vote_program::vote_instruction::VoteInstruction;
use std::{
collections::HashMap,
@ -157,7 +157,11 @@ fn get_config() -> Config {
config
}
fn process_confirmed_block(notifier: &Notifier, slot: Slot, confirmed_block: ConfirmedBlock) {
fn process_confirmed_block(
notifier: &Notifier,
slot: Slot,
confirmed_block: EncodedConfirmedBlock,
) {
let break_program_id = "BrEAK7zGZ6dM71zUDACDqJnekihmwF15noTddWTsknjC"
.parse::<Pubkey>()
.unwrap();
@ -215,7 +219,7 @@ fn load_blocks(
rpc_client: &RpcClient,
start_slot: Slot,
end_slot: Slot,
) -> ClientResult<Vec<(Slot, ConfirmedBlock)>> {
) -> ClientResult<Vec<(Slot, EncodedConfirmedBlock)>> {
info!(
"Loading confirmed blocks between slots: {} - {}",
start_slot, end_slot