From cd235aa11b115e0762abe37ffeb985d3acfe50bc Mon Sep 17 00:00:00 2001 From: Kirill Fomichev Date: Thu, 14 Nov 2024 12:09:37 +0200 Subject: [PATCH] proto: change error type in mod `convert_from` (#457) --- CHANGELOG.md | 1 + yellowstone-grpc-proto/src/lib.rs | 213 +++++++++++++++--------------- 2 files changed, 107 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cac52036..dd2d16bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ The minor version will be incremented upon a breaking change and the patch versi - proto: add txn_signature filter ([#445](https://github.com/rpcpool/yellowstone-grpc/pull/445)) - geyser: limit length of filter name ([#448](https://github.com/rpcpool/yellowstone-grpc/pull/448)) - examples: add progress bar to client tool ([#456](https://github.com/rpcpool/yellowstone-grpc/pull/456)) +- proto: change error type in mod `convert_from` ([#457](https://github.com/rpcpool/yellowstone-grpc/pull/457)) ### Breaking diff --git a/yellowstone-grpc-proto/src/lib.rs b/yellowstone-grpc-proto/src/lib.rs index 1c83762d..6bf96447 100644 --- a/yellowstone-grpc-proto/src/lib.rs +++ b/yellowstone-grpc-proto/src/lib.rs @@ -36,7 +36,7 @@ pub mod convert_to { }, pubkey::Pubkey, signature::Signature, - transaction::SanitizedTransaction, + transaction::{SanitizedTransaction, TransactionError}, transaction_context::TransactionReturnData, }, solana_transaction_status::{ @@ -62,11 +62,7 @@ pub mod convert_to { header: Some(create_header(&message.header)), account_keys: create_pubkeys(&message.account_keys), recent_blockhash: message.recent_blockhash.to_bytes().into(), - instructions: message - .instructions - .iter() - .map(create_instruction) - .collect(), + instructions: create_instructions(&message.instructions), versioned: false, address_table_lookups: vec![], }, @@ -137,12 +133,7 @@ pub mod convert_to { return_data, compute_units_consumed, } = meta; - let err = match status { - Ok(()) => None, - Err(err) => Some(proto::TransactionError { - err: bincode::serialize(&err).expect("transaction error to serialize to bytes"), - }), - }; + let err = create_transaction_error(status); let inner_instructions_none = inner_instructions.is_none(); let inner_instructions = inner_instructions .as_deref() @@ -182,6 +173,17 @@ pub mod convert_to { } } + pub fn create_transaction_error( + status: &Result<(), TransactionError>, + ) -> Option { + match status { + Ok(()) => None, + Err(err) => Some(proto::TransactionError { + err: bincode::serialize(&err).expect("transaction error to serialize to bytes"), + }), + } + } + pub fn create_inner_instructions_vec( ixs: &[InnerInstructions], ) -> Vec { @@ -296,20 +298,15 @@ pub mod convert_from { }, }; - fn ensure_some(maybe_value: Option, message: impl Into) -> Result { - match maybe_value { - Some(value) => Ok(value), - None => Err(message.into()), - } - } + type CreateResult = Result; - pub fn create_block(block: proto::SubscribeUpdateBlock) -> Result { + pub fn create_block(block: proto::SubscribeUpdateBlock) -> CreateResult { let mut transactions = vec![]; for tx in block.transactions { transactions.push(create_tx_with_meta(tx)?); } - let block_rewards = ensure_some(block.rewards, "failed to get rewards")?; + let block_rewards = block.rewards.ok_or("failed to get rewards")?; let mut rewards = vec![]; for reward in block_rewards.rewards { rewards.push(create_reward(reward)?); @@ -322,22 +319,28 @@ pub mod convert_from { transactions, rewards, num_partitions: block_rewards.num_partitions.map(|msg| msg.num_partitions), - block_time: Some(ensure_some( - block.block_time.map(|wrapper| wrapper.timestamp), - "failed to get block_time", - )?), - block_height: Some(ensure_some( - block.block_height.map(|wrapper| wrapper.block_height), - "failed to get block_height", - )?), + block_time: Some( + block + .block_time + .map(|wrapper| wrapper.timestamp) + .ok_or("failed to get block_time")?, + ), + block_height: Some( + block + .block_height + .map(|wrapper| wrapper.block_height) + .ok_or("failed to get block_height")?, + ), }) } pub fn create_tx_with_meta( tx: proto::SubscribeUpdateTransactionInfo, - ) -> Result { - let meta = ensure_some(tx.meta, "failed to get transaction meta")?; - let tx = ensure_some(tx.transaction, "failed to get transaction transaction")?; + ) -> CreateResult { + let meta = tx.meta.ok_or("failed to get transaction meta")?; + let tx = tx + .transaction + .ok_or("failed to get transaction transaction")?; Ok(TransactionWithStatusMeta::Complete( VersionedTransactionWithStatusMeta { @@ -347,50 +350,48 @@ pub mod convert_from { )) } - pub fn create_tx_versioned(tx: proto::Transaction) -> Result { + pub fn create_tx_versioned(tx: proto::Transaction) -> CreateResult { let mut signatures = Vec::with_capacity(tx.signatures.len()); for signature in tx.signatures { signatures.push(match Signature::try_from(signature.as_slice()) { Ok(signature) => signature, - Err(_error) => return Err("failed to parse Signature".to_owned()), + Err(_error) => return Err("failed to parse Signature"), }); } Ok(VersionedTransaction { signatures, - message: create_message(ensure_some(tx.message, "failed to get message")?)?, + message: create_message(tx.message.ok_or("failed to get message")?)?, }) } - pub fn create_message(message: proto::Message) -> Result { - let header = ensure_some(message.header, "failed to get MessageHeader")?; + pub fn create_message(message: proto::Message) -> CreateResult { + let header = message.header.ok_or("failed to get MessageHeader")?; let header = MessageHeader { - num_required_signatures: ensure_some( - header.num_required_signatures.try_into().ok(), - "failed to parse num_required_signatures", - )?, - num_readonly_signed_accounts: ensure_some( - header.num_readonly_signed_accounts.try_into().ok(), - "failed to parse num_readonly_signed_accounts", - )?, - num_readonly_unsigned_accounts: ensure_some( - header.num_readonly_unsigned_accounts.try_into().ok(), - "failed to parse num_readonly_unsigned_accounts", - )?, + num_required_signatures: header + .num_required_signatures + .try_into() + .map_err(|_| "failed to parse num_required_signatures")?, + num_readonly_signed_accounts: header + .num_readonly_signed_accounts + .try_into() + .map_err(|_| "failed to parse num_readonly_signed_accounts")?, + num_readonly_unsigned_accounts: header + .num_readonly_unsigned_accounts + .try_into() + .map_err(|_| "failed to parse num_readonly_unsigned_accounts")?, }; if message.recent_blockhash.len() != HASH_BYTES { - return Err("failed to parse hash".to_owned()); + return Err("failed to parse hash"); } Ok(if message.versioned { let mut address_table_lookups = Vec::with_capacity(message.address_table_lookups.len()); for table in message.address_table_lookups { address_table_lookups.push(MessageAddressTableLookup { - account_key: ensure_some( - Pubkey::try_from(table.account_key.as_slice()).ok(), - "failed to parse Pubkey", - )?, + account_key: Pubkey::try_from(table.account_key.as_slice()) + .map_err(|_| "failed to parse Pubkey")?, writable_indexes: table.writable_indexes, readonly_indexes: table.readonly_indexes, }); @@ -415,18 +416,18 @@ pub mod convert_from { pub fn create_message_instructions( ixs: Vec, - ) -> Result, String> { + ) -> CreateResult> { ixs.into_iter().map(create_message_instruction).collect() } pub fn create_message_instruction( ix: proto::CompiledInstruction, - ) -> Result { + ) -> CreateResult { Ok(CompiledInstruction { - program_id_index: ensure_some( - ix.program_id_index.try_into().ok(), - "failed to decode CompiledInstruction.program_id_index)", - )?, + program_id_index: ix + .program_id_index + .try_into() + .map_err(|_| "failed to decode CompiledInstruction.program_id_index)")?, accounts: ix.accounts, data: ix.data, }) @@ -434,7 +435,7 @@ pub mod convert_from { pub fn create_tx_meta( meta: proto::TransactionStatusMeta, - ) -> Result { + ) -> CreateResult { let meta_status = match create_tx_error(meta.err.as_ref())? { Some(err) => Err(err), None => Ok(()), @@ -462,12 +463,10 @@ pub mod convert_from { return_data: if meta.return_data_none { None } else { - let data = ensure_some(meta.return_data, "failed to get return_data")?; + let data = meta.return_data.ok_or("failed to get return_data")?; Some(TransactionReturnData { - program_id: ensure_some( - Pubkey::try_from(data.program_id.as_slice()).ok(), - "failed to parse program_id", - )?, + program_id: Pubkey::try_from(data.program_id.as_slice()) + .map_err(|_| "failed to parse program_id")?, data: data.data, }) }, @@ -477,32 +476,29 @@ pub mod convert_from { pub fn create_tx_error( err: Option<&proto::TransactionError>, - ) -> Result, String> { - ensure_some( - err.map(|err| bincode::deserialize::(&err.err)) - .transpose() - .ok(), - "failed to decode TransactionError", - ) + ) -> CreateResult> { + err.map(|err| bincode::deserialize::(&err.err)) + .transpose() + .map_err(|_| "failed to decode TransactionError") } pub fn create_meta_inner_instructions( ixs: Vec, - ) -> Result, String> { + ) -> CreateResult> { ixs.into_iter().map(create_meta_inner_instruction).collect() } pub fn create_meta_inner_instruction( ix: proto::InnerInstructions, - ) -> Result { + ) -> CreateResult { let mut instructions = vec![]; for ix in ix.instructions { instructions.push(InnerInstruction { instruction: CompiledInstruction { - program_id_index: ensure_some( - ix.program_id_index.try_into().ok(), - "failed to decode CompiledInstruction.program_id_index)", - )?, + program_id_index: ix + .program_id_index + .try_into() + .map_err(|_| "failed to decode CompiledInstruction.program_id_index)")?, accounts: ix.accounts, data: ix.data, }, @@ -510,15 +506,15 @@ pub mod convert_from { }); } Ok(InnerInstructions { - index: ensure_some( - ix.index.try_into().ok(), - "failed to decode InnerInstructions.index", - )?, + index: ix + .index + .try_into() + .map_err(|_| "failed to decode InnerInstructions.index")?, instructions, }) } - pub fn create_rewards_obj(rewards: proto::Rewards) -> Result { + pub fn create_rewards_obj(rewards: proto::Rewards) -> CreateResult { Ok(RewardsAndNumPartitions { rewards: rewards .rewards @@ -529,15 +525,14 @@ pub mod convert_from { }) } - pub fn create_reward(reward: proto::Reward) -> Result { + pub fn create_reward(reward: proto::Reward) -> CreateResult { Ok(Reward { pubkey: reward.pubkey, lamports: reward.lamports, post_balance: reward.post_balance, - reward_type: match ensure_some( - proto::RewardType::try_from(reward.reward_type).ok(), - "failed to parse reward_type", - )? { + reward_type: match proto::RewardType::try_from(reward.reward_type) + .map_err(|_| "failed to parse reward_type")? + { proto::RewardType::Unspecified => None, proto::RewardType::Fee => Some(RewardType::Fee), proto::RewardType::Rent => Some(RewardType::Rent), @@ -547,32 +542,36 @@ pub mod convert_from { commission: if reward.commission.is_empty() { None } else { - Some(ensure_some( - reward.commission.parse().ok(), - "failed to parse reward commission", - )?) + Some( + reward + .commission + .parse() + .map_err(|_| "failed to parse reward commission")?, + ) }, }) } pub fn create_token_balances( balances: Vec, - ) -> Result, String> { + ) -> CreateResult> { let mut vec = Vec::with_capacity(balances.len()); for balance in balances { - let ui_amount = ensure_some(balance.ui_token_amount, "failed to get ui_token_amount")?; + let ui_amount = balance + .ui_token_amount + .ok_or("failed to get ui_token_amount")?; vec.push(TransactionTokenBalance { - account_index: ensure_some( - balance.account_index.try_into().ok(), - "failed to parse account_index", - )?, + account_index: balance + .account_index + .try_into() + .map_err(|_| "failed to parse account_index")?, mint: balance.mint, ui_token_amount: UiTokenAmount { ui_amount: Some(ui_amount.ui_amount), - decimals: ensure_some( - ui_amount.decimals.try_into().ok(), - "failed to parse decimals", - )?, + decimals: ui_amount + .decimals + .try_into() + .map_err(|_| "failed to parse decimals")?, amount: ui_amount.amount, ui_amount_string: ui_amount.ui_amount_string, }, @@ -586,27 +585,27 @@ pub mod convert_from { pub fn create_loaded_addresses( writable: Vec>, readonly: Vec>, - ) -> Result { + ) -> CreateResult { Ok(LoadedAddresses { writable: create_pubkey_vec(writable)?, readonly: create_pubkey_vec(readonly)?, }) } - pub fn create_pubkey_vec(pubkeys: Vec>) -> Result, String> { + pub fn create_pubkey_vec(pubkeys: Vec>) -> CreateResult> { pubkeys .iter() .map(|pubkey| create_pubkey(pubkey.as_slice())) .collect() } - pub fn create_pubkey(pubkey: &[u8]) -> Result { - ensure_some(Pubkey::try_from(pubkey).ok(), "failed to parse Pubkey") + pub fn create_pubkey(pubkey: &[u8]) -> CreateResult { + Pubkey::try_from(pubkey).map_err(|_| "failed to parse Pubkey") } pub fn create_account( account: proto::SubscribeUpdateAccountInfo, - ) -> Result<(Pubkey, Account), String> { + ) -> CreateResult<(Pubkey, Account)> { let pubkey = create_pubkey(&account.pubkey)?; let account = Account { lamports: account.lamports,