From cb99c666318b8523070dc95f08f7986c2f544017 Mon Sep 17 00:00:00 2001 From: Erim Date: Wed, 30 Oct 2024 16:35:15 +0300 Subject: [PATCH] rlp and eip1559 --- .snfoundry_cache/.prev_tests_failed | 1 - src/accounts/base.cairo | 8 +++ src/utils.cairo | 1 + src/utils/serialization.cairo | 20 ++------ src/utils/transaction/eip1559.cairo | 80 +++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 17 deletions(-) create mode 100644 src/utils/transaction/eip1559.cairo diff --git a/.snfoundry_cache/.prev_tests_failed b/.snfoundry_cache/.prev_tests_failed index 9af8425..6226f49 100644 --- a/.snfoundry_cache/.prev_tests_failed +++ b/.snfoundry_cache/.prev_tests_failed @@ -1,2 +1 @@ -rosettacontracts::utils::serialization::tests::test_chunks_deserialize tests::factory_tests::deploy_check_initials diff --git a/src/accounts/base.cairo b/src/accounts/base.cairo index 21ae00e..7001994 100644 --- a/src/accounts/base.cairo +++ b/src/accounts/base.cairo @@ -25,6 +25,9 @@ pub mod RosettaAccount { }; use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess}; use rosettacontracts::accounts::utils::{is_valid_eth_signature, Secp256k1PointStorePacking, pubkey_to_eth_address}; + use rosettacontracts::utils::serialization::{deserialize_bytes}; + use rosettacontracts::utils::rlp::{RLPType, RLPTrait, RLPItem, RLPHelpersTrait}; + use rosettacontracts::utils::transaction::eip1559::{Eip1559, Eip1559Trait}; pub mod Errors { pub const INVALID_CALLER: felt252 = 'Rosetta: invalid caller'; @@ -142,6 +145,11 @@ pub mod RosettaAccount { // TODO verify transaction with eth address not pub key // Kakarot calldata ile transactionu bir daha olusturup verify etmeye calismis let public_key: EthPublicKey = self.ethereum_public_key.read(); + + let deserialized_signature = deserialize_bytes(signature).unwrap(); + let mut rlp_decoded_transaction = RLPTrait::decode(deserialized_signature.span()).unwrap(); + let eip1559_transaction = Eip1559Trait::decode_fields(ref rlp_decoded_transaction).unwrap(); + is_valid_eth_signature(hash, public_key, signature) } } diff --git a/src/utils.cairo b/src/utils.cairo index 706f393..7e7a203 100644 --- a/src/utils.cairo +++ b/src/utils.cairo @@ -10,6 +10,7 @@ pub mod traits; pub mod eth_address; pub mod transaction { + pub mod eip1559; pub mod eip2930; pub mod common; } diff --git a/src/utils/serialization.cairo b/src/utils/serialization.cairo index 85e16b8..fb5d615 100644 --- a/src/utils/serialization.cairo +++ b/src/utils/serialization.cairo @@ -66,28 +66,16 @@ fn compute_y_parity(v: u128, chain_id: u64) -> Option { return Option::None; } -use crate::utils::helpers::{u256_to_bytes_array, split_word}; -// TODO complete word splitting -pub fn deserialize_and_split_bytes(self: Span) -> Array { - let mut bytes: Array = Default::default(); - - for item in self { - split_word((*item).into(), 16, ref bytes); - - }; - - bytes -} #[cfg(test)] mod tests { - use crate::utils::serialization::{deserialize_and_split_bytes}; + use crate::utils::serialization::{deserialize_bytes}; #[test] - fn test_chunks_deserialize() { - let arr = array![0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF, 0xABC]; + fn test_bytes_deserialize() { + let arr = array![0xFF, 0xAB]; - let deserialized_bytes = deserialize_and_split_bytes(arr.span()); + let deserialized_bytes = deserialize_bytes(arr.span()).unwrap(); assert_eq!(*deserialized_bytes.at(0), 0xFF); } diff --git a/src/utils/transaction/eip1559.cairo b/src/utils/transaction/eip1559.cairo new file mode 100644 index 0000000..945ff37 --- /dev/null +++ b/src/utils/transaction/eip1559.cairo @@ -0,0 +1,80 @@ +use crate::utils::transaction::common::{TxKind}; +use crate::utils::transaction::eip2930::{AccessListItem}; +use crate::utils::traits::SpanDefault; +use crate::utils::rlp::{RLPItem, RLPHelpersTrait}; +use crate::errors::{EthTransactionError, RLPError, RLPErrorTrait}; + +#[derive(Copy, Drop, Debug, Default, PartialEq, Serde)] +pub struct Eip1559 { + pub chain_id: u64, + pub nonce: u64, + pub gas_limit: u64, + pub max_fee_per_gas: u128, + pub max_priority_fee_per_gas: u128, + pub to: TxKind, + pub value: u256, + pub access_list: Span, + pub input: Span, +} + +#[generate_trait] +pub impl _impl of Eip1559Trait { + /// Decodes the RLP-encoded fields into a TxEip1559 struct. + /// + /// # Arguments + /// + /// * `data` - A span of RLPItems containing the encoded transaction fields + /// + /// # Returns + /// + /// A Result containing either the decoded TxEip1559 struct or an EthTransactionError + fn decode_fields(ref data: Span) -> Result { + let boxed_fields = data + .multi_pop_front::<9>() + .ok_or(EthTransactionError::RLPError(RLPError::InputTooShort))?; + let [ + chain_id_encoded, + nonce_encoded, + max_priority_fee_per_gas_encoded, + max_fee_per_gas_encoded, + gas_limit_encoded, + to_encoded, + value_encoded, + input_encoded, + access_list_encoded + ] = + (*boxed_fields) + .unbox(); + + let chain_id = chain_id_encoded.parse_u64_from_string().map_err()?; + let nonce = nonce_encoded.parse_u64_from_string().map_err()?; + let max_priority_fee_per_gas = max_priority_fee_per_gas_encoded + .parse_u128_from_string() + .map_err()?; + let max_fee_per_gas = max_fee_per_gas_encoded.parse_u128_from_string().map_err()?; + let gas_limit = gas_limit_encoded.parse_u64_from_string().map_err()?; + let to = to_encoded.try_parse_address_from_string().map_err()?; + let value = value_encoded.parse_u256_from_string().map_err()?; + let input = input_encoded.parse_bytes_from_string().map_err()?; + let access_list = access_list_encoded.parse_access_list().map_err()?; + + let txkind_to = match to { + Option::Some(to) => { TxKind::Call(to) }, + Option::None => { TxKind::Create } + }; + + Result::Ok( + Eip1559 { + chain_id, + nonce, + max_priority_fee_per_gas, + max_fee_per_gas, + gas_limit, + to: txkind_to, + value, + access_list, + input, + } + ) + } +} \ No newline at end of file