Skip to content

Commit

Permalink
old-faithful-proto: add mod decode (#106)
Browse files Browse the repository at this point in the history
  • Loading branch information
fanatid authored Jul 3, 2024
1 parent 3c52cdf commit d7cfd84
Show file tree
Hide file tree
Showing 7 changed files with 372 additions and 0 deletions.
59 changes: 59 additions & 0 deletions 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ bs58 = "0.5.0"
cbor = "0.4.1"
cid = "0.11.0"
colored = "2.1.0"
const-hex = "1.12.0"
crc = "3.0.1"
crossbeam-channel = "0.5.8"
fnv = "1.0.7"
Expand Down
11 changes: 11 additions & 0 deletions old-faithful-proto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,20 @@ edition = "2021"
publish = false

[dependencies]
anyhow = { workspace = true }
bincode = { workspace = true }
prost = { workspace = true }
prost_011 = { workspace = true }
serde = { workspace = true }
solana-sdk = { workspace = true }
solana-storage-proto = { workspace = true }
solana-transaction-status = { workspace = true }
tonic = { workspace = true }

[dev-dependencies]
const-hex = { workspace = true }
serde_json = { workspace = true }

[build-dependencies]
anyhow = { workspace = true }
protobuf-src = { workspace = true }
Expand Down
154 changes: 154 additions & 0 deletions old-faithful-proto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,157 @@ pub use {prost, tonic};
pub mod proto {
tonic::include_proto!("old_faithful");
}

pub mod decode {
use {
super::{
proto,
solana::{StoredConfirmedBlockRewards, StoredConfirmedBlockTransactionStatusMeta},
},
anyhow::Context,
prost_011::Message,
solana_sdk::{
hash::{Hash, HASH_BYTES},
transaction::VersionedTransaction,
},
solana_storage_proto::convert::generated,
solana_transaction_status::{
ConfirmedBlock, ConfirmedTransactionWithStatusMeta, Reward, TransactionStatusMeta,
TransactionWithStatusMeta, VersionedTransactionWithStatusMeta,
},
};

pub fn confirmed_block(block: &proto::BlockResponse) -> anyhow::Result<ConfirmedBlock> {
let previous_blockhash = <[u8; HASH_BYTES]>::try_from(block.previous_blockhash.clone())
.map_err(|_error| anyhow::anyhow!("failed to decode previous_blockhash"))?;
let blockhash = <[u8; HASH_BYTES]>::try_from(block.blockhash.clone())
.map_err(|_error| anyhow::anyhow!("failed to decode blockhash"))?;

let rewards: Vec<Reward> = match generated::Rewards::decode(block.rewards.as_ref()) {
Ok(rewards) => rewards.into(),
Err(_error) => bincode::deserialize::<StoredConfirmedBlockRewards>(&block.rewards)
.context("failed to decode bincode of Vec<Reward>")?
.into_iter()
.map(Into::into)
.collect(),
};

Ok(ConfirmedBlock {
previous_blockhash: Hash::new_from_array(previous_blockhash).to_string(),
blockhash: Hash::new_from_array(blockhash).to_string(),
parent_slot: block.parent_slot,
transactions: block
.transactions
.iter()
.map(versioned_transaction)
.collect::<Result<Vec<_>, _>>()?,
rewards,
block_time: Some(block.block_time),
block_height: Some(block.block_height),
})
}

pub fn confirmed_transaction(
tx: &proto::TransactionResponse,
) -> anyhow::Result<ConfirmedTransactionWithStatusMeta> {
versioned_transaction(
tx.transaction
.as_ref()
.ok_or_else(|| anyhow::anyhow!("failed to get Transaction"))?,
)
.map(|tx_with_meta| ConfirmedTransactionWithStatusMeta {
slot: tx.slot,
tx_with_meta,
block_time: Some(tx.block_time),
})
}

pub fn versioned_transaction(
tx: &proto::Transaction,
) -> anyhow::Result<TransactionWithStatusMeta> {
let transaction: VersionedTransaction = bincode::deserialize(&tx.transaction)
.context("failed to decode VersionedTransaction")?;

let meta: TransactionStatusMeta =
match generated::TransactionStatusMeta::decode(tx.meta.as_ref()) {
Ok(meta) => meta
.try_into()
.context("failed to decode protobuf of TransactionStatusMeta")?,
Err(_error) => {
bincode::deserialize::<StoredConfirmedBlockTransactionStatusMeta>(&tx.meta)
.context("failed to decode bincode of TransactionStatusMeta")?
.into()
}
};

Ok(TransactionWithStatusMeta::Complete(
VersionedTransactionWithStatusMeta { transaction, meta },
))
}
}

mod solana {
use {
serde::{Deserialize, Serialize},
solana_sdk::{message::v0::LoadedAddresses, transaction::TransactionError},
solana_transaction_status::{Reward, TransactionStatusMeta},
};

#[derive(Serialize, Deserialize)]
pub struct StoredConfirmedBlockTransactionStatusMeta {
err: Option<TransactionError>,
fee: u64,
pre_balances: Vec<u64>,
post_balances: Vec<u64>,
}

impl From<StoredConfirmedBlockTransactionStatusMeta> for TransactionStatusMeta {
fn from(value: StoredConfirmedBlockTransactionStatusMeta) -> Self {
let StoredConfirmedBlockTransactionStatusMeta {
err,
fee,
pre_balances,
post_balances,
} = value;
let status = match &err {
None => Ok(()),
Some(err) => Err(err.clone()),
};
Self {
status,
fee,
pre_balances,
post_balances,
inner_instructions: None,
log_messages: None,
pre_token_balances: None,
post_token_balances: None,
rewards: None,
loaded_addresses: LoadedAddresses::default(),
return_data: None,
compute_units_consumed: None,
}
}
}

pub type StoredConfirmedBlockRewards = Vec<StoredConfirmedBlockReward>;

#[derive(Serialize, Deserialize)]
pub struct StoredConfirmedBlockReward {
pubkey: String,
lamports: i64,
}

impl From<StoredConfirmedBlockReward> for Reward {
fn from(value: StoredConfirmedBlockReward) -> Self {
let StoredConfirmedBlockReward { pubkey, lamports } = value;
Self {
pubkey,
lamports,
post_balance: 0,
reward_type: None,
commission: None,
}
}
}
}
Loading

0 comments on commit d7cfd84

Please sign in to comment.