diff --git a/translator/src/block.rs b/translator/src/block.rs index 4fe994a..ee7bf0f 100644 --- a/translator/src/block.rs +++ b/translator/src/block.rs @@ -17,6 +17,7 @@ use alloy_rlp::Encodable; use antelope::chain::checksum::Checksum256; use antelope::chain::name::Name; use antelope::serializer::Packer; +use eyre::eyre; use reth_primitives::ReceiptWithBloom; use reth_rpc_types::ExecutionPayloadV1; use reth_telos_rpc_engine_api::structs::TelosEngineAPIExtraFields; @@ -239,7 +240,7 @@ impl ProcessingEVMBlock { &mut self, action: Box, native_to_evm_cache: &NameToAddressCache, - ) { + ) -> eyre::Result<()> { let action_name = action.action_name(); let action_account = action.action_account(); let action_receiver = action.receiver(); @@ -255,28 +256,25 @@ impl ProcessingEVMBlock { } else if action_account == EOSIO_EVM && action_name == RAW { // Normally signed EVM transaction let raw: RawAction = decode(&action.data()); - let printed_receipt = PrintedReceipt::from_console(action.console()); - if printed_receipt.is_none() { - panic!( - "No printed receipt found for raw action in block: {}", - self.block_num - ); - } - let transaction_result = TelosEVMTransaction::from_raw_action( + let printed_receipt = + PrintedReceipt::from_console(action.console()).ok_or_else(|| { + eyre::eyre!( + "No printed receipt found for raw action in block: {}", + self.block_num + ) + })?; + + let transaction = TelosEVMTransaction::from_raw_action( self.chain_id, self.transactions.len(), self.block_hash, raw, - printed_receipt.unwrap(), + printed_receipt, ) - .await; + .await?; - match transaction_result { - Ok(transaction) => self.add_transaction(transaction), - Err(e) => { - panic!("Error handling action. Error: {}", e); - } - } + self.add_transaction(transaction); + return Ok(()); } else if action_account == EOSIO_EVM && action_name == WITHDRAW { // Withdrawal from EVM let withdraw_action: WithdrawAction = decode(&action.data()); @@ -287,7 +285,7 @@ impl ProcessingEVMBlock { withdraw_action, native_to_evm_cache, ) - .await; + .await?; self.add_transaction(transaction); } else if action_account == EOSIO_TOKEN && action_name == TRANSFER @@ -298,7 +296,7 @@ impl ProcessingEVMBlock { if transfer_action.to.n != EOSIO_EVM || SYSTEM_ACCOUNTS.contains(&transfer_action.from.n) { - return; + return Ok(()); } let transaction = TelosEVMTransaction::from_transfer( @@ -308,7 +306,7 @@ impl ProcessingEVMBlock { transfer_action, native_to_evm_cache, ) - .await; + .await?; self.add_transaction(transaction); } else if action_account == EOSIO_EVM && action_name == DORESOURCES { let config_delta_row = self @@ -339,6 +337,7 @@ impl ProcessingEVMBlock { wallet_action, )); } + Ok(()) } pub async fn generate_evm_data( @@ -346,7 +345,7 @@ impl ProcessingEVMBlock { parent_hash: FixedBytes<32>, block_delta: u32, native_to_evm_cache: &NameToAddressCache, - ) -> (Header, ExecutionPayloadV1) { + ) -> eyre::Result<(Header, ExecutionPayloadV1)> { if self.signed_block.is_none() || self.block_traces.is_none() || self.contract_rows.is_none() @@ -395,13 +394,13 @@ impl ProcessingEVMBlock { let traces = self.block_traces.clone().unwrap_or_default(); - for t in traces { - match t { - TransactionTrace::V0(t) => { - for action in t.action_traces { - self.handle_action(Box::new(action), native_to_evm_cache) - .await; - } + for TransactionTrace::V0(t) in traces { + for action in t.action_traces { + if let Err(e) = self + .handle_action(Box::new(action), native_to_evm_cache) + .await + { + return Err(eyre!("Error handling the action. {}", e)); } } } @@ -497,7 +496,7 @@ impl ProcessingEVMBlock { transactions, }; - (header, exec_payload) + Ok((header, exec_payload)) } } diff --git a/translator/src/tasks/final_processor.rs b/translator/src/tasks/final_processor.rs index bdc291a..8524807 100644 --- a/translator/src/tasks/final_processor.rs +++ b/translator/src/tasks/final_processor.rs @@ -114,7 +114,7 @@ pub async fn final_processor( let (header, exec_payload) = block .generate_evm_data(parent_hash, block_delta, &native_to_evm_cache) - .await; + .await?; let block_hash = exec_payload.block_hash; @@ -151,7 +151,7 @@ pub async fn final_processor( blocks_sec, trx_sec ); - //info!("Block map is {} long", block_map.len()); + unlogged_blocks = 0; unlogged_transactions = 0; last_log = Instant::now(); @@ -177,7 +177,7 @@ pub async fn final_processor( DecodedRow::AccountState(removed, acc_state_diff, scope) => { statediffs_accountstate.push(TelosAccountStateTableRow { removed, - address: native_to_evm_cache.get_index(scope.n).await.unwrap(), + address: native_to_evm_cache.get_index(scope.n).await?, key: U256::from_be_slice(&acc_state_diff.key.data), value: U256::from_be_slice(&acc_state_diff.value.data), }); @@ -197,8 +197,7 @@ pub async fn final_processor( U256::from_be_slice( native_to_evm_cache .get(create_action.account.value()) - .await - .unwrap() + .await? .as_slice(), ), )), diff --git a/translator/src/transaction.rs b/translator/src/transaction.rs index 2c48324..746385d 100644 --- a/translator/src/transaction.rs +++ b/translator/src/transaction.rs @@ -107,15 +107,12 @@ impl TelosEVMTransaction { block_hash: Checksum256, action: TransferAction, native_to_evm_cache: &NameToAddressCache, - ) -> Self { + ) -> eyre::Result { let address: Address = if action.memo.len() == ADDRESS_HEX_SIZE && action.memo.starts_with("0x") { - action.memo.parse().unwrap() + action.memo.parse()? } else { - native_to_evm_cache - .get(action.from.n) - .await - .expect("Failed to get address") + native_to_evm_cache.get(action.from.n).await? }; let value = U256::from(action.quantity.amount()) * U256::from(100_000_000_000_000i64); @@ -135,7 +132,7 @@ impl TelosEVMTransaction { let mut raw: Vec = vec![]; tx_legacy.encode_with_signature_fields(&sig, &mut raw); let envelope = TxEnvelope::Legacy(signed_legacy); - TelosEVMTransaction { + Ok(TelosEVMTransaction { envelope, receipt: PrintedReceipt { charged_gas: "".to_string(), @@ -149,7 +146,7 @@ impl TelosEVMTransaction { output: "".to_string(), errors: None, }, - } + }) } pub async fn from_withdraw_no_cache( @@ -196,15 +193,15 @@ impl TelosEVMTransaction { block_hash: Checksum256, action: WithdrawAction, native_to_evm_cache: &NameToAddressCache, - ) -> Self { - let address = native_to_evm_cache - .get(action.to.n) - .await - .expect("Failed to get address"); - TelosEVMTransaction::from_withdraw_no_cache( + ) -> eyre::Result { + let address = native_to_evm_cache.get(action.to.n).await?; + + let telos_evm_transactions = TelosEVMTransaction::from_withdraw_no_cache( chain_id, trx_index, block_hash, action, address, ) - .await + .await; + + Ok(telos_evm_transactions) } pub fn hash(&self) -> &B256 { diff --git a/translator/src/types/translator_types.rs b/translator/src/types/translator_types.rs index 0f2af2f..0a4c2d2 100644 --- a/translator/src/types/translator_types.rs +++ b/translator/src/types/translator_types.rs @@ -41,85 +41,85 @@ impl NameToAddressCache { } } - pub async fn get(&self, name: u64) -> Option
{ + pub async fn get(&self, name: u64) -> eyre::Result
{ let evm_contract = Name::from_u64(EOSIO_EVM); let address = Name::from_u64(name).as_string(); let cached = self.cache.get(&name); debug!("getting {address} cache hit = {:?}", cached.is_some()); - if cached.is_some() { - return cached; - } - - let mut i = 0u8; - while i <= MAX_RETRY { - info!("Fetching address {address} try {i}"); - let account_result: eyre::Result> = self - .get_account_address(name, evm_contract, IndexPosition::TERTIARY) - .await; - - match account_result { - Ok(account_result) => { - if let Some(account_row) = account_result.rows.first() { - let address = Address::from(account_row.address.data); - self.cache.insert(name, address); - self.index_cache.insert(account_row.index, address); - return Some(address); - } else { - warn!("Got empty rows for {address}, retry attempt {i}"); + if let Some(cached) = cached { + Ok(cached) + } else { + let mut i = 0u8; + while i <= MAX_RETRY { + info!("Fetching address {address} try {i}"); + let account_result: eyre::Result> = self + .get_account_address(name, evm_contract, IndexPosition::TERTIARY) + .await; + + match account_result { + Ok(account_result) => { + if let Some(account_row) = account_result.rows.first() { + let address = Address::from(account_row.address.data); + self.cache.insert(name, address); + self.index_cache.insert(account_row.index, address); + return Ok(address); + } else { + warn!("Got empty rows for {address}, retry attempt {i}"); + } + } + Err(e) => { + warn!("Error {e} fetching {address}, retry attempt {i}"); } } - Err(e) => { - warn!("Error {e} fetching {address}, retry attempt {i}"); - } + + sleep(BASE_DELAY * 2u32.pow(i as u32)).await; + i += 1; } - sleep(BASE_DELAY * 2u32.pow(i as u32)).await; - i += 1; + error!("Could not get account after {i} attempts for {address}"); + Err(eyre!("Can not get account retries for {address}")) } - - error!("Could not get account after {i} attempts for {address}"); - None } - pub async fn get_index(&self, index: u64) -> Option
{ + pub async fn get_index(&self, index: u64) -> eyre::Result
{ let evm_contract = Name::from_u64(EOSIO_EVM); let cached = self.index_cache.get(&index); debug!("getting index {index} cache hit = {:?}", cached.is_some()); - if cached.is_some() { - return cached; - } - - let mut i = 0u8; - while i <= MAX_RETRY { - info!("Fetching index {index} try {i}"); - let account_result: eyre::Result> = self - .get_account_address(index, evm_contract, IndexPosition::PRIMARY) - .await; - - match account_result { - Ok(account_result) => { - if let Some(account_row) = account_result.rows.first() { - let address = Address::from(account_row.address.data); - self.cache.insert(index, address); - self.index_cache.insert(account_row.index, address); - return Some(address); - } else { - warn!("Got empty rows for index {index}, retry attempt {i}"); + if let Some(cached) = cached { + Ok(cached) + } else { + let mut i = 0u8; + while i <= MAX_RETRY { + info!("Fetching index {index} try {i}"); + let account_result: eyre::Result> = self + .get_account_address(index, evm_contract, IndexPosition::PRIMARY) + .await; + + match account_result { + Ok(account_result) => { + if let Some(account_row) = account_result.rows.first() { + let address = Address::from(account_row.address.data); + self.cache.insert(index, address); + self.index_cache.insert(account_row.index, address); + return Ok(address); + } else { + warn!("Got empty rows for index {index}, retry attempt {i}"); + } + } + Err(e) => { + warn!("Error {e} fetching index {index}, retry attempt {i}"); } } - Err(e) => { - warn!("Error {e} fetching index {index}, retry attempt {i}"); - } - } - sleep(BASE_DELAY * 2u32.pow(i as u32)).await; - i += 1; + sleep(BASE_DELAY * 2u32.pow(i as u32)).await; + i += 1; + } + error!("Could not get account after {i} attempts for index {index}"); + Err(eyre!("Can not get account retries for index {index}")) } - error!("Could not get account after {i} attempts for index {index}"); - None } pub async fn get_account_address( diff --git a/translator/tests/block_headers.rs b/translator/tests/block_headers.rs index e236117..205713f 100644 --- a/translator/tests/block_headers.rs +++ b/translator/tests/block_headers.rs @@ -98,22 +98,27 @@ async fn genesis_mainnet() { block.deserialize(); - let (header, payload) = block + if let Ok((header, payload)) = block .generate_evm_data( zero_bytes, evm_chain_id_mainnet.block_delta(), &native_to_evm_cache, ) - .await; - - println!("genesis: {:#?}", header); - println!("hash: {:#?}", payload.block_hash); - - assert_eq!( - payload.block_hash, - FixedBytes::from_hex("36fe7024b760365e3970b7b403e161811c1e626edd68460272fcdfa276272563") + .await + { + println!("genesis: {:#?}", header); + println!("hash: {:#?}", payload.block_hash); + + assert_eq!( + payload.block_hash, + FixedBytes::from_hex( + "36fe7024b760365e3970b7b403e161811c1e626edd68460272fcdfa276272563" + ) .unwrap() - ); + ); + } else { + panic!("Failed to generate evm data"); + } } #[tokio::test] @@ -136,19 +141,22 @@ async fn deploy_mainnet() { block.deserialize(); - let (header, payload) = block + if let Ok((header, payload)) = block .generate_evm_data( parent_hash, evm_chain_id_mainnet.block_delta(), &native_to_evm_cache, ) - .await; - - println!("genesis: {:#?}", header); - println!("hash: {:#?}", payload.block_hash); - - assert_eq!( - payload.block_hash, - FixedBytes::from_hex(MAINNET_DEPLOY_CONFIG.validate_hash.clone().unwrap()).unwrap() - ); + .await + { + println!("genesis: {:#?}", header); + println!("hash: {:#?}", payload.block_hash); + + assert_eq!( + payload.block_hash, + FixedBytes::from_hex(MAINNET_DEPLOY_CONFIG.validate_hash.clone().unwrap()).unwrap() + ); + } else { + panic!("Failed to generate evm data"); + } } diff --git a/translator/tests/transactions.rs b/translator/tests/transactions.rs index 32e0f18..e3df6e5 100644 --- a/translator/tests/transactions.rs +++ b/translator/tests/transactions.rs @@ -24,7 +24,8 @@ async fn test_deposit() { }, &NameToAddressCache::new(APIClient::default()), ) - .await; + .await + .unwrap(); assert_eq!( trx.hash().to_string(),