diff --git a/Cargo.lock b/Cargo.lock index fe62eb9..694b04d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10503,6 +10503,7 @@ dependencies = [ "account", "bytes", "ethereum", + "fp-rpc", "futures 0.3.28", "futures-timer", "hex", diff --git a/client/authorship/Cargo.toml b/client/authorship/Cargo.toml index ee9941a..de5181b 100644 --- a/client/authorship/Cargo.toml +++ b/client/authorship/Cargo.toml @@ -20,6 +20,7 @@ prometheus-endpoint = { workspace = true } sc-block-builder = { workspace = true } sc-client-api = { workspace = true } sc-proposer-metrics = { workspace = true } +fp-rpc = { workspace = true } sc-telemetry = { workspace = true } sc-transaction-pool-api = { workspace = true } sp-api = { workspace = true } diff --git a/client/authorship/src/authorship.rs b/client/authorship/src/authorship.rs index 3bd3dac..377b884 100644 --- a/client/authorship/src/authorship.rs +++ b/client/authorship/src/authorship.rs @@ -49,6 +49,10 @@ use sc_proposer_metrics::{EndProposingReason, MetricsLink as PrometheusMetrics}; use sp_core::crypto::KeyTypeId; use sp_keystore::{Keystore, KeystorePtr}; use stbl_primitives_fee_compatible_api::CompatibleFeeApi; +use fp_rpc::EthereumRuntimeRPCApi; +use sp_runtime::Saturating; + + /// Default block size limit in bytes used by [`Proposer`]. /// @@ -259,6 +263,7 @@ where + 'static, C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> + BlockBuilderApi<Block> + + fp_rpc::EthereumRuntimeRPCApi<Block> + stbl_primitives_fee_compatible_api::CompatibleFeeApi<Block, AccountId> + stbl_primitives_zero_gas_transactions_api::ZeroGasTransactionApi<Block>, PR: ProofRecording, @@ -305,6 +310,7 @@ where + 'static, C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> + BlockBuilderApi<Block> + + fp_rpc::EthereumRuntimeRPCApi<Block> + stbl_primitives_fee_compatible_api::CompatibleFeeApi<Block, AccountId> + stbl_primitives_zero_gas_transactions_api::ZeroGasTransactionApi<Block>, PR: ProofRecording, @@ -367,6 +373,7 @@ where + 'static, C::Api: ApiExt<Block, StateBackend = backend::StateBackendFor<B, Block>> + BlockBuilderApi<Block> + + fp_rpc::EthereumRuntimeRPCApi<Block> + stbl_primitives_fee_compatible_api::CompatibleFeeApi<Block, AccountId> + stbl_primitives_zero_gas_transactions_api::ZeroGasTransactionApi<Block>, PR: ProofRecording, @@ -437,7 +444,6 @@ where let http_client = reqwest::Client::new(); let mut request = Box::pin(http_client.post(zero_gas_tx_pool).send().fuse()); let mut timeout = Box::pin(futures_timer::Delay::new(std::time::Duration::from_millis(500)).fuse()); - let result_response_raw_zero = select! { res = request => { @@ -475,18 +481,48 @@ where } else { None }; - - // If we pull successfully from the zero gas transaction pool, we will try to push them to the block - if let Some(raw_zero_gas_transactions) = raw_zero_gas_transactions_option { + + let reason = if let Some(raw_zero_gas_transactions) = raw_zero_gas_transactions_option { let mut pending_raw_zero_gas_transactions = raw_zero_gas_transactions.transactions.into_iter(); - + + let chain_id = self + .client + .runtime_api() + .chain_id(self.parent_hash).expect("Could not get chain id"); + + let current_block = self.parent_number.saturated_into::<u32>().saturating_add(1); + + let message: Vec<u8> = b"I consent to validate to execute zero gas transactions in block " + .iter() + .chain(current_block.to_string().as_bytes().iter()) + .chain(b" on chain ") + .chain(chain_id.to_string().as_bytes().iter()) + .cloned() + .collect(); + + let keys = Keystore::ecdsa_public_keys( + &*self.keystore, + KeyTypeId::try_from("aura").unwrap_or_default(), + ); + let public = keys[0].clone().into(); + + let eip191_message = stbl_tools::eth::build_eip191_message_hash(message.clone()); + + let signed_hash = Keystore::ecdsa_sign_prehashed( + &*self.keystore, + KeyTypeId::try_from("aura").unwrap_or_default(), + &public, + &eip191_message.as_fixed_bytes(), + ).expect("Could not sign the Ethereum transaction hash").expect("Could not sign the Ethereum transaction hash"); + loop { let pending_hex_string_tx = if let Some(tx) = pending_raw_zero_gas_transactions.next() { tx } else { + debug!("No more transactions in the zero gas transaction pool"); break EndProposingReason::NoMoreTransactions; }; @@ -498,7 +534,7 @@ where ); break EndProposingReason::HitDeadline; } - + let pending_raw_tx = if let Ok(pending_raw_tx) = hex::decode(pending_hex_string_tx) { pending_raw_tx } @@ -507,38 +543,6 @@ where }; let ethereum_transaction: ethereum::TransactionV2 = ethereum::EnvelopedDecodable::decode(&pending_raw_tx).unwrap(); - - - let keys = Keystore::ecdsa_public_keys( - &*self.keystore, - KeyTypeId::try_from("aura").unwrap_or_default(), - ); - - - let public = keys[0].clone().into(); - let hash = ethereum_transaction.hash(); - let hash_string = hex::encode(hash.as_bytes()); - - - let mut message: Vec<u8> = Vec::new(); - message.extend_from_slice(b"I consent to validate the transaction for free: 0x"); - message.extend_from_slice(hash_string.as_bytes()); - - let eip191_message = stbl_tools::eth::build_eip191_message_hash(message.clone()); - - let signed_hash_option = Keystore::ecdsa_sign_prehashed( - &*self.keystore, - KeyTypeId::try_from("aura").unwrap_or_default(), - &public, - &eip191_message.as_fixed_bytes(), - ).expect("Could not sign the Ethereum transaction hash"); - - let signed_hash = if let Some(signed_hash) = signed_hash_option { - signed_hash - } - else { - continue; - }; let pending_tx = if let Ok(pending_tx) = self .client @@ -549,9 +553,7 @@ where else { continue; }; - - - + let block_size = block_builder.estimate_block_size(self.include_proof_in_block_size_estimation); @@ -605,7 +607,7 @@ where } } }; - } + }; let mut unqueue_invalid = Vec::new(); let mut t1 = self.transaction_pool.ready_at(self.parent_number).fuse(); diff --git a/pallets/zero-gas-transactions/src/lib.rs b/pallets/zero-gas-transactions/src/lib.rs index b6e9a45..2261900 100644 --- a/pallets/zero-gas-transactions/src/lib.rs +++ b/pallets/zero-gas-transactions/src/lib.rs @@ -23,6 +23,7 @@ pub mod pallet { use sp_core::U256; use sp_std::vec; use sp_std::vec::Vec; + use parity_scale_codec::alloc::string::ToString; pub use fp_rpc::TransactionStatus; @@ -36,7 +37,7 @@ pub mod pallet { pub type SponsorNonce<T: Config> = StorageMap<_, Blake2_128Concat, H160, u64, ValueQuery>; #[pallet::config] - pub trait Config: frame_system::Config + pallet_evm::Config + pallet_ethereum::Config { + pub trait Config: frame_system::Config<BlockNumber = u32> + pallet_evm::Config + pallet_ethereum::Config { type RuntimeCall: Parameter + GetDispatchInfo; type UserFeeTokenController: UserFeeTokenController; } @@ -64,7 +65,6 @@ pub mod pallet { let current_block_validator = <pallet_evm::Pallet<T>>::find_author(); Self::ensure_zero_gas_transaction( - transaction.clone(), current_block_validator, validator_signature.clone(), ) @@ -118,7 +118,6 @@ pub mod pallet { let current_block_validator = <pallet_evm::Pallet<T>>::find_author(); Self::ensure_zero_gas_transaction( - transaction.clone(), current_block_validator, validator_signature, ) @@ -196,12 +195,14 @@ pub mod pallet { } fn ensure_zero_gas_transaction( - transaction: pallet_ethereum::Transaction, expected_validator: H160, validator_signature: Vec<u8>, ) -> Result<(), ()> { + let chain_id = T::ChainId::get(); + let block_number = <frame_system::Pallet<T>>::block_number(); + let zero_gas_trx_internal_message: Vec<u8> = - Self::get_zero_gas_transaction_signing_message(transaction.clone()); + Self::get_zero_gas_transaction_signing_message(block_number, chain_id); let eip191_message = stbl_tools::eth::build_eip191_message_hash(zero_gas_trx_internal_message); @@ -216,16 +217,16 @@ pub mod pallet { } pub fn get_zero_gas_transaction_signing_message( - trx: pallet_ethereum::Transaction, + block_number: u32, + chain_id: u64, ) -> Vec<u8> { - let mut message: Vec<u8> = Vec::new(); - - let trx_hash = trx.hash(); - let trx_bytes_hash = trx_hash.as_bytes(); - let trx_hash_string = hex::encode(trx_bytes_hash); - - message.extend_from_slice(b"I consent to validate the transaction for free: 0x"); - message.extend_from_slice(trx_hash_string.as_bytes()); + let mut message: Vec<u8> = b"I consent to validate to execute zero gas transactions in block " + .iter() + .chain(block_number.to_string().as_bytes().iter()) + .chain(b" on chain ") + .chain(chain_id.to_string().as_bytes().iter()) + .cloned() + .collect(); return message; } @@ -245,5 +246,6 @@ pub mod pallet { return Some(H160::from_slice(&result[12..32])); } + } }