diff --git a/Cargo.lock b/Cargo.lock index d1c239b017..75f11c2d63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -968,7 +968,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -979,7 +979,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -1080,6 +1080,23 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7a806ac6c8307b929df4645776290a50ee2aac754ad09d8bdf73391309e43af" +dependencies = [ + "ark-ff-asm 0.6.0", + "ark-ff-macros 0.6.0", + "ark-serialize 0.6.0", + "ark-std 0.6.0", + "digest 0.10.7", + "educe", + "num-bigint 0.4.6", + "num-traits", + "zeroize", +] + [[package]] name = "ark-ff-asm" version = "0.3.0" @@ -1110,6 +1127,16 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "ark-ff-asm" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1479009684adc073dff49a1025d3a7065b317a9ead25aaaca38cdc70058ba8a2" +dependencies = [ + "quote", + "syn 2.0.118", +] + [[package]] name = "ark-ff-macros" version = "0.3.0" @@ -1148,6 +1175,19 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "ark-ff-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0691ed21ef00ef89c1e9bda832eba493dda3ec2f8d892fb25b705f73f06bb8" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "ark-serialize" version = "0.3.0" @@ -1181,6 +1221,30 @@ dependencies = [ "num-bigint 0.4.6", ] +[[package]] +name = "ark-serialize" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a74dd304fd536fb95d0a328e72be759209cc496a9da094c5bc56e5fea4f9e86b" +dependencies = [ + "ark-serialize-derive", + "ark-std 0.6.0", + "digest 0.10.7", + "num-bigint 0.4.6", + "serde_with", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f153690697a2b91e5e1251ff98411ee5371500a111a0fd317a70e588eb300f9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "ark-std" version = "0.3.0" @@ -1211,6 +1275,16 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "ark-std" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367c9c827ed431bff6868b7aa926e05b16eb46603cc8b6e768e4a5553fa1d155" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -4671,7 +4745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6558,7 +6632,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -8416,14 +8490,15 @@ dependencies = [ [[package]] name = "ruint" -version = "1.17.2" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" +checksum = "f5e99bff0393163bb25029a6af25d3d8d202ba5b5438a74d1bd8789f5c822970" dependencies = [ "alloy-rlp", "ark-ff 0.3.0", "ark-ff 0.4.2", "ark-ff 0.5.0", + "ark-ff 0.6.0", "bytes", "fastrlp 0.3.1", "fastrlp 0.4.0", @@ -8516,7 +8591,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -8575,7 +8650,7 @@ dependencies = [ "security-framework 3.5.1", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -9306,7 +9381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -11754,7 +11829,7 @@ dependencies = [ "cfg-if", "libc", "psm", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -11931,7 +12006,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -13084,7 +13159,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/crates/ethrpc/src/alloy/wallet.rs b/crates/ethrpc/src/alloy/wallet.rs index 054b55cb6e..8a7e795b74 100644 --- a/crates/ethrpc/src/alloy/wallet.rs +++ b/crates/ethrpc/src/alloy/wallet.rs @@ -3,25 +3,25 @@ use { alloy_network::{Ethereum, EthereumWallet, Network, NetworkWallet, TxSigner}, alloy_primitives::Address, alloy_signer::Signature, - alloy_transport::impl_future, - std::{sync::Arc, thread}, - tokio::sync::RwLock, + std::{ + ops::Deref, + sync::{Arc, RwLock}, + }, }; /// A mutable version of [`EthereumWallet`], cheaply cloneable (through /// [`Arc`]). -/// -/// Requires a tokio runtime to be present, otherwise operations will panic. +// We also wrap the inner [`EthereumWallet`] in an [`Arc`] because +// we don't want to deep clone the entire thing every time we need to +// sign something. #[derive(Debug, Clone, Default)] -pub struct MutWallet(Arc>); +pub struct MutWallet(Arc>>); impl MutWallet { pub fn new(wallet: EthereumWallet) -> Self { - Self(Arc::new(RwLock::new(wallet))) + Self(Arc::new(RwLock::new(Arc::new(wallet)))) } -} -impl MutWallet { /// Calls the inner [`EthereumWallet`]'s /// [`register_signer`](EthereumWallet::register_signer), if no default /// signer has been setup (i.e. the wallet was created using @@ -30,57 +30,36 @@ impl MutWallet { where S: TxSigner + Send + Sync + 'static, { - self.handle_blocking_operation(move |wallet| { - // If the wallet is created using MutWallet::default(), there will not be - // default signer; this stops us from *not* using `.from` (since it - // is filled with the default signer). At the same time, we can't - // constantly register new default signers, because it breaks the caller's - // expectations. As such, if the current default signer address is - // the default address (0x000...000) we register the signer as the - // default one. - let register_default = { - let r_lock = wallet.0.blocking_read(); - let default_address = - >::default_signer_address(&r_lock); - - default_address == Address::default() - }; - - let mut w_lock = wallet.0.blocking_write(); - if register_default { - w_lock.register_default_signer(signer); - } else { - w_lock.register_signer(signer); - } - }); - } + // If the wallet is created using MutWallet::default(), there will not be + // default signer; this stops us from *not* using `.from` (since it + // is filled with the default signer). At the same time, we can't + // constantly register new default signers, because it breaks the caller's + // expectations. As such, if the current default signer address is + // the default address (0x000...000) we register the signer as the + // default one. + let mut w_lock = self.0.write().unwrap(); + let default_address = + >::default_signer_address(&w_lock); - /// Handles blocking operations such as the - /// [`blocking_read`](RwLock::blocking_read) - /// and [`blocking_write`](RwLock::blocking_write). - /// - /// This function *will panic* in case there is no runtime present, or the - /// runtime flavor is not `current_thread` or `multi_thread`. - // This function is necessary to handle the blocking lock operations under - // required by synchronous function calls which are problematic when the runtime - // flavour is `current_thread` (which will panic when blocked by certain - // operations). - fn handle_blocking_operation(&self, f: F) -> R - where - F: FnOnce(Self) -> R + Send + 'static, - R: Send + 'static, - { - let wallet = self.clone(); - let rt = tokio::runtime::Handle::current(); - - match rt.runtime_flavor() { - tokio::runtime::RuntimeFlavor::CurrentThread => thread::spawn(move || f(wallet)) - .join() - .expect("failed to join thread"), - tokio::runtime::RuntimeFlavor::MultiThread => { - tokio::task::block_in_place(move || f(wallet)) - } - _ => panic!("unsupported runtime flavor"), + // Using `Arc::make_mut()` here will never lead to a scenario + // where multiple clones of the original [`MutWallet`] have + // different sets of signers. + // We use a write lock to ensure that only 1 caller can add + // a signer at a time avoiding race conditions. + // Also we only ever implicitly give out clones of the inner + // `Arc` in `sign_transaction_from()` but it's + // impossible to extract the `Arc` out of the + // returned future. + // That means the worst that could happen is that `Arc::make_mut()` + // makes a deep clone instead of just modifying the only `Arc` + // instance in existence. + // But in practice this will never happen because we generally + // first add all signers to the [`MutWallet`] before we start + // signing transactions. + if default_address.is_zero() { + Arc::make_mut(&mut w_lock).register_default_signer(signer); + } else { + Arc::make_mut(&mut w_lock).register_signer(signer); } } } @@ -93,41 +72,33 @@ where /// in [`NetworkWallet::sign_transaction_from`] when no specific signer is /// specified. fn default_signer_address(&self) -> Address { - self.handle_blocking_operation(|wallet| { - let r_lock = wallet.0.blocking_read(); - >::default_signer_address(&r_lock) - }) + let r_lock = self.0.read().unwrap(); + >::default_signer_address(&r_lock) } /// Return true if the signer contains a credential for the given address. fn has_signer_for(&self, address: &Address) -> bool { - let address = *address; - self.handle_blocking_operation(move |wallet| { - let r_lock = wallet.0.blocking_read(); - >::has_signer_for(&r_lock, &address) - }) + let r_lock = self.0.read().unwrap(); + >::has_signer_for(&r_lock, address) } /// Return an iterator of all signer addresses. fn signer_addresses(&self) -> impl Iterator { - self.handle_blocking_operation(move |wallet| { - let r_lock = wallet.0.blocking_read(); - >::signer_addresses(&r_lock).collect::>() - }) - .into_iter() + let r_lock = self.0.read().unwrap(); + >::signer_addresses(&r_lock) + .collect::>() + .into_iter() } /// Asynchronously sign an unsigned transaction, with a specified /// credential. #[doc(alias = "sign_tx_from")] - fn sign_transaction_from( + async fn sign_transaction_from( &self, sender: Address, tx: N::UnsignedTx, - ) -> impl_future!(>) { - async move { - let r_lock = self.0.read().await; - >::sign_transaction_from(&r_lock, sender, tx).await - } + ) -> alloy_signer::Result { + let wallet = Arc::clone(self.0.read().unwrap().deref()); + >::sign_transaction_from(&wallet, sender, tx).await } }