diff --git a/client/src/config.rs b/client/src/config.rs index a24249a..9fca77f 100644 --- a/client/src/config.rs +++ b/client/src/config.rs @@ -40,6 +40,9 @@ pub struct AppConfig { /// The parent hash of the start_block pub prev_hash: String, + /// (Optional) For testnet, the block with the last legacy raw transaction (missing estimate_gas and ram_payer fields) + pub last_legacy_raw_tx: Option, + /// Start block to start with, should be at or before the first block of the execution node pub evm_start_block: u32, @@ -75,6 +78,7 @@ impl From<&AppConfig> for TranslatorConfig { evm_start_block: config.evm_start_block, evm_stop_block: config.evm_stop_block, prev_hash: config.prev_hash.clone(), + last_legacy_raw_tx: config.last_legacy_raw_tx, validate_hash: config.validate_hash.clone(), http_endpoint: config.chain_endpoint.clone(), ship_endpoint: config.ship_endpoint.clone(), diff --git a/translator/src/block.rs b/translator/src/block.rs index 6da4e13..52865d3 100644 --- a/translator/src/block.rs +++ b/translator/src/block.rs @@ -1,8 +1,8 @@ use crate::transaction::TelosEVMTransaction; use crate::types::env::{ANTELOPE_EPOCH_MS, ANTELOPE_INTERVAL_MS, DEFAULT_GAS_LIMIT}; use crate::types::evm_types::{ - AccountRow, AccountStateRow, CreateAction, EvmContractConfigRow, OpenWalletAction, - PrintedReceipt, RawAction, SetRevisionAction, TransferAction, WithdrawAction, + AccountRow, AccountStateRow, CreateAction, EvmContractConfigRow, LegacyRawAction, + OpenWalletAction, PrintedReceipt, RawAction, SetRevisionAction, TransferAction, WithdrawAction, }; use crate::types::names::*; use crate::types::ship_types::{ @@ -14,7 +14,7 @@ use alloy_consensus::constants::{EMPTY_OMMER_ROOT_HASH, EMPTY_ROOT_HASH}; use alloy_consensus::{Header, Transaction, TxEnvelope}; use alloy_eips::eip2718::Encodable2718; use alloy_rlp::Encodable; -use antelope::chain::checksum::Checksum256; +use antelope::chain::checksum::{Checksum160, Checksum256}; use antelope::chain::name::Name; use antelope::serializer::Packer; use reth_primitives::ReceiptWithBloom; @@ -103,6 +103,7 @@ pub struct ProcessingEVMBlock { pub new_wallets: Vec, pub lib_num: u32, pub lib_hash: Checksum256, + pub use_legacy_raw_action: bool, } #[derive(Clone, Debug)] @@ -119,6 +120,30 @@ pub struct TelosEVMBlock { pub extra_fields: TelosEngineAPIExtraFields, } +#[derive(Clone, Debug)] +pub struct RawActionValues { + pub tx: Vec, + pub sender: Option, +} + +impl From for RawActionValues { + fn from(value: LegacyRawAction) -> Self { + Self { + tx: value.tx, + sender: value.sender, + } + } +} + +impl From for RawActionValues { + fn from(value: RawAction) -> Self { + Self { + tx: value.tx, + sender: value.sender, + } + } +} + impl TelosEVMBlock { pub fn lib_evm_num(&self, chain_id: &ChainId) -> u32 { self.lib_num.saturating_sub(chain_id.block_delta()) @@ -137,6 +162,13 @@ impl TelosEVMBlock { } } +pub fn decodeRawActionValues(encoded: &[u8], use_legacy_raw_action: bool) -> RawActionValues { + match use_legacy_raw_action { + true => decode::(encoded).into(), + false => decode::(encoded).into(), + } +} + pub fn decode(raw: &[u8]) -> T { let mut result = T::default(); result.unpack(raw); @@ -152,6 +184,7 @@ impl ProcessingEVMBlock { lib_num: u32, lib_hash: Checksum256, result: GetBlocksResultV0, + use_legacy_raw_action: bool, ) -> Self { Self { block_num, @@ -161,6 +194,7 @@ impl ProcessingEVMBlock { lib_hash, chain_id, result, + use_legacy_raw_action, signed_block: None, block_traces: None, contract_rows: None, @@ -255,13 +289,17 @@ impl ProcessingEVMBlock { self.new_gas_price = Some((self.transactions.len() as u64, gas_price)); } 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()); + let raw: RawActionValues = + decodeRawActionValues(&action.data(), self.use_legacy_raw_action); + let mut 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 - ); + if !self.use_legacy_raw_action { + panic!( + "No printed receipt found for raw action in block: {}", + self.block_num + ); + } + printed_receipt = Some(PrintedReceipt::default()); } let transaction_result = TelosEVMTransaction::from_raw_action( self.chain_id, diff --git a/translator/src/tasks/final_processor.rs b/translator/src/tasks/final_processor.rs index e0994d2..d45b875 100644 --- a/translator/src/tasks/final_processor.rs +++ b/translator/src/tasks/final_processor.rs @@ -160,11 +160,11 @@ pub async fn final_processor( .collect(), ); - let prev_ship_hash = block.prev_block_hash.map(|hash| hash.as_string()); + let prev_ship_hash = block.prev_block_hash.map(|hash| hash.as_string()); let completed_block = TelosEVMBlock { block_num: evm_block_num, block_hash, - ship_hash: block.block_hash.as_string(), + ship_hash: block.block_hash.as_string(), prev_ship_hash, lib_num: block.lib_num, lib_hash: block.lib_hash.as_string(), diff --git a/translator/src/tasks/raw_deserializer.rs b/translator/src/tasks/raw_deserializer.rs index 530e008..7bc26a1 100644 --- a/translator/src/tasks/raw_deserializer.rs +++ b/translator/src/tasks/raw_deserializer.rs @@ -83,14 +83,19 @@ pub async fn raw_deserializer( ShipResult::GetBlocksResultV0(r) => { unackd_blocks += 1; if let Some(b) = &r.this_block { + let use_legacy_raw_action = config + .last_legacy_raw_tx + .map(|n| b.block_num <= n) + .unwrap_or(false); let block = ProcessingEVMBlock::new( config.chain_id.0, b.block_num, b.block_id, - r.prev_block.as_ref().map(|b| b.block_id), + r.prev_block.as_ref().map(|b| b.block_id), r.last_irreversible.block_num, r.last_irreversible.block_id, r.clone(), + use_legacy_raw_action, ); debug!("Block #{} sending to block deserializer...", b.block_num); block_deserializer_tx.send(block).await?; diff --git a/translator/src/transaction.rs b/translator/src/transaction.rs index 2c48324..3eb08c7 100644 --- a/translator/src/transaction.rs +++ b/translator/src/transaction.rs @@ -1,3 +1,4 @@ +use crate::block::RawActionValues; use crate::rlp::telos_rlp_decode::TelosTxDecodable; use crate::types::evm_types::{PrintedReceipt, RawAction, TransferAction, WithdrawAction}; use crate::types::translator_types::NameToAddressCache; @@ -40,7 +41,7 @@ impl TelosEVMTransaction { _chain_id: u64, trx_index: usize, block_hash: Checksum256, - raw: RawAction, + raw: RawActionValues, receipt: PrintedReceipt, ) -> Result { // TODO: Check for unsigned transactions and handle correctly diff --git a/translator/src/translator.rs b/translator/src/translator.rs index f3a6843..dd4f017 100644 --- a/translator/src/translator.rs +++ b/translator/src/translator.rs @@ -18,6 +18,7 @@ pub fn default_channel_size() -> usize { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TranslatorConfig { pub chain_id: ChainId, + pub last_legacy_raw_tx: Option, pub evm_start_block: u32, pub evm_stop_block: Option, pub prev_hash: String, diff --git a/translator/src/types/env.rs b/translator/src/types/env.rs index 63d8e22..ba7d2ac 100644 --- a/translator/src/types/env.rs +++ b/translator/src/types/env.rs @@ -17,6 +17,7 @@ lazy_static! { pub static ref MAINNET_GENESIS_CONFIG: TranslatorConfig = TranslatorConfig { chain_id: 40.into(), + last_legacy_raw_tx: None, evm_start_block: 37, evm_stop_block: None, @@ -32,56 +33,62 @@ lazy_static! { block_message_channel_size: default_channel_size(), final_message_channel_size: default_channel_size() }; - pub static ref MAINNET_DEPLOY_CONFIG: TranslatorConfig = TranslatorConfig { - chain_id: 40.into(), - - evm_start_block: 180698860, - evm_stop_block: None, - - prev_hash: "757720a8e51c63ef1d4f907d6569dacaa965e91c2661345902de18af11f81063".to_string(), - validate_hash: Some( - "ed58397aca4c7ce2117fae8093bdced8f01d47855a46bb5ad6e4df4a93e8ee27".to_string() - ), - - http_endpoint: String::from("http://127.0.0.1:8888"), - ship_endpoint: String::from("ws://127.0.0.1:29999"), - - raw_message_channel_size: default_channel_size(), - block_message_channel_size: default_channel_size(), - final_message_channel_size: default_channel_size() - }; - pub static ref TESTNET_GENESIS_CONFIG: TranslatorConfig = TranslatorConfig { - chain_id: 41.into(), - - evm_start_block: 58, - evm_stop_block: None, - - prev_hash: ZERO_HASH_HEX.to_string(), - validate_hash: Some( - "1f42e34c53aa45b4bb0a8fc20cb98ba1f0663ef1d581995c56f9f2314b837a35".to_string() - ), - - http_endpoint: String::from("http://127.0.0.1:8888"), - ship_endpoint: String::from("ws://127.0.0.1:29999"), - - raw_message_channel_size: default_channel_size(), - block_message_channel_size: default_channel_size(), - final_message_channel_size: default_channel_size() - }; - pub static ref TESTNET_DEPLOY_CONFIG: TranslatorConfig = TranslatorConfig { - chain_id: 41.into(), - - evm_start_block: 136393814, - evm_stop_block: None, - - prev_hash: "8e149fd918bad5a4adfe6f17478e46643f7db7292a2b7b9247f48dc85bdeec94".to_string(), - validate_hash: None, - - http_endpoint: String::from("http://127.0.0.1:8888"), - ship_endpoint: String::from("ws://127.0.0.1:29999"), - - raw_message_channel_size: default_channel_size(), - block_message_channel_size: default_channel_size(), - final_message_channel_size: default_channel_size() - }; + // TODO: Add this back when/if we support starting at deploy block + // pub static ref MAINNET_DEPLOY_CONFIG: TranslatorConfig = TranslatorConfig { + // chain_id: 40.into(), + // + // last_legacy_raw_tx: None, + // evm_start_block: 180698860, + // evm_stop_block: None, + // + // prev_hash: "757720a8e51c63ef1d4f907d6569dacaa965e91c2661345902de18af11f81063".to_string(), + // validate_hash: Some( + // "ed58397aca4c7ce2117fae8093bdced8f01d47855a46bb5ad6e4df4a93e8ee27".to_string() + // ), + // + // http_endpoint: String::from("http://127.0.0.1:8888"), + // ship_endpoint: String::from("ws://127.0.0.1:29999"), + // + // raw_message_channel_size: default_channel_size(), + // block_message_channel_size: default_channel_size(), + // final_message_channel_size: default_channel_size() + // }; + // pub static ref TESTNET_GENESIS_CONFIG: TranslatorConfig = TranslatorConfig { + // chain_id: 41.into(), + // + // // TODO: Figure out this number + // last_legacy_raw_tx: Some(), + // evm_start_block: 58, + // evm_stop_block: None, + // + // prev_hash: ZERO_HASH_HEX.to_string(), + // validate_hash: Some( + // "1f42e34c53aa45b4bb0a8fc20cb98ba1f0663ef1d581995c56f9f2314b837a35".to_string() + // ), + // + // http_endpoint: String::from("http://127.0.0.1:8888"), + // ship_endpoint: String::from("ws://127.0.0.1:29999"), + // + // raw_message_channel_size: default_channel_size(), + // block_message_channel_size: default_channel_size(), + // final_message_channel_size: default_channel_size() + // }; + // pub static ref TESTNET_DEPLOY_CONFIG: TranslatorConfig = TranslatorConfig { + // chain_id: 41.into(), + // + // // TODO: Figure out this number, likely on testnet we need to also start much earlier than 136mil + // last_legacy_raw_tx: Some(1234), + // evm_start_block: 136393814, + // evm_stop_block: None, + // + // prev_hash: "8e149fd918bad5a4adfe6f17478e46643f7db7292a2b7b9247f48dc85bdeec94".to_string(), + // validate_hash: None, + // + // http_endpoint: String::from("http://127.0.0.1:8888"), + // ship_endpoint: String::from("ws://127.0.0.1:29999"), + // + // raw_message_channel_size: default_channel_size(), + // block_message_channel_size: default_channel_size(), + // final_message_channel_size: default_channel_size() + // }; } diff --git a/translator/src/types/evm_types.rs b/translator/src/types/evm_types.rs index 5609c9a..a3c00df 100644 --- a/translator/src/types/evm_types.rs +++ b/translator/src/types/evm_types.rs @@ -12,6 +12,12 @@ use antelope::util::hex_to_bytes; use antelope::StructPacker; use serde::{Deserialize, Deserializer, Serialize}; +#[derive(Debug, Clone, Default, Serialize, Deserialize, StructPacker)] +pub struct LegacyRawAction { + pub tx: Vec, + pub sender: Option, +} + #[derive(Debug, Clone, Default, Serialize, Deserialize, StructPacker)] pub struct RawAction { pub ram_payer: Name, @@ -103,7 +109,7 @@ pub struct CreateAction { pub data: String, } -#[derive(Debug, Clone, Default, Deserialize)] +#[derive(Debug, Clone, Deserialize)] pub struct PrintedReceipt { pub charged_gas: String, pub trx_index: u16, @@ -119,6 +125,23 @@ pub struct PrintedReceipt { // pub itxs: any[], // Define struct for this } +impl Default for PrintedReceipt { + fn default() -> Self { + PrintedReceipt { + charged_gas: "".to_string(), + trx_index: 0, + block: 0, + status: 0, + epoch: 0, + createdaddr: "".to_string(), + gasused: "5208".to_string(), + logs: vec![], + output: "".to_string(), + errors: None, + } + } +} + fn deserialize_logs<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, diff --git a/translator/tests/block_headers.rs b/translator/tests/block_headers.rs index a398eb0..e236117 100644 --- a/translator/tests/block_headers.rs +++ b/translator/tests/block_headers.rs @@ -64,7 +64,7 @@ async fn generate_block( chain_id, block_num, block_pos.block_id, - None, + None, // Block is always final block_num, block_pos.block_id, diff --git a/translator/tests/decode_block.rs b/translator/tests/decode_block.rs index 32f52af..c21d501 100644 --- a/translator/tests/decode_block.rs +++ b/translator/tests/decode_block.rs @@ -21,7 +21,7 @@ fn decode_block() { 1, b.block_num, Checksum256::default(), - None, + None, b.block_num, Checksum256::default(), r.clone(),