From 56379e7615f42f1cab3ec0afa8956983fd85b12e Mon Sep 17 00:00:00 2001 From: greged93 <82421016+greged93@users.noreply.github.com> Date: Thu, 22 Feb 2024 13:07:10 +0100 Subject: [PATCH] fix: copy hive binary + automatic deployment (#781) * copy hive binary * add dev allocation to genesis * fix automatic deploy --- .trunk/trunk.yaml | 2 +- docker/rpc/Dockerfile | 1 + src/bin/hive_genesis.rs | 30 +++++----------------------- src/bin/katana_genesis.rs | 1 + src/eth_provider/constant.rs | 3 +++ src/eth_provider/provider.rs | 16 ++++++++------- src/main.rs | 10 ++++++++++ src/test_utils/eoa.rs | 1 + src/test_utils/katana/genesis.rs | 30 +++++++++++++++++++++++++++- src/test_utils/katana/mod.rs | 4 ++-- tests/eth_provider.rs | 34 ++++++++++++++++++++++++++------ 11 files changed, 90 insertions(+), 42 deletions(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index a42eca2e4..43fc2a8f3 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -31,7 +31,7 @@ lint: - taplo@0.8.1 - terrascan@1.18.11 - trivy@0.49.1 - - trufflehog@3.67.6 + - trufflehog@3.67.7 - yamllint@1.35.1 ignore: - linters: [ALL] diff --git a/docker/rpc/Dockerfile b/docker/rpc/Dockerfile index da64e99f5..315b6fcbe 100644 --- a/docker/rpc/Dockerfile +++ b/docker/rpc/Dockerfile @@ -101,6 +101,7 @@ WORKDIR /usr/src/app # Copy the built binary from the previous container COPY --from=builder /usr/src/rpc/target/release/kakarot-rpc /usr/local/bin +COPY --from=builder /usr/src/rpc/target/release/kakarot-rpc-hive /usr/local/bin COPY --from=builder /usr/src/rpc/target/release/hive_genesis /usr/local/bin # Expose the port that the RPC server will run on diff --git a/src/bin/hive_genesis.rs b/src/bin/hive_genesis.rs index cb44dea84..1143a7ae4 100644 --- a/src/bin/hive_genesis.rs +++ b/src/bin/hive_genesis.rs @@ -1,8 +1,5 @@ use dotenv::dotenv; use kakarot_rpc::test_utils::{hive::HiveGenesisConfig, katana::genesis::KatanaGenesisBuilder}; -use katana_primitives::genesis::{ - allocation::DevAllocationsGenerator, constant::DEFAULT_PREFUNDED_ACCOUNT_BALANCE, json::GenesisAccountJson, -}; use starknet_crypto::FieldElement; use std::{env::var, path::Path}; @@ -16,7 +13,10 @@ fn main() { Path::new(&var("HIVE_GENESIS_PATH").expect("Failed to load HIVE_GENESIS_PATH var")).to_path_buf(); // Read all the classes. - let builder = KatanaGenesisBuilder::default().load_classes(kakarot_contracts_path); + let mut builder = KatanaGenesisBuilder::default().load_classes(kakarot_contracts_path); + + // Add dev allocations. + builder = builder.with_dev_allocation(10); // Read the hive genesis. let hive_genesis_content = std::fs::read_to_string(hive_genesis_path).expect("Failed to read hive genesis file"); @@ -24,29 +24,9 @@ fn main() { serde_json::from_str(&hive_genesis_content).expect("Failed to parse hive genesis json"); // Convert the hive genesis to a katana genesis. - let mut genesis_json = + let genesis_json = hive_genesis.try_into_genesis_json(builder.clone()).expect("Failed to convert hive genesis to katana genesis"); - // Add dev allocations. - let dev_allocations = DevAllocationsGenerator::new(10) - .with_balance(DEFAULT_PREFUNDED_ACCOUNT_BALANCE) - .generate() - .into_iter() - .map(|(address, account)| { - ( - address, - GenesisAccountJson { - public_key: account.public_key, - balance: Some(account.balance), - nonce: account.nonce, - class: None, - storage: account.storage.clone(), - }, - ) - }) - .collect::>(); - genesis_json.accounts.extend(dev_allocations); - let builder = builder.with_kakarot(FieldElement::ZERO).expect("Failed to set up Kakarot"); let manifest = builder.manifest(); diff --git a/src/bin/katana_genesis.rs b/src/bin/katana_genesis.rs index d0ec9e43d..3bb536642 100644 --- a/src/bin/katana_genesis.rs +++ b/src/bin/katana_genesis.rs @@ -32,6 +32,7 @@ fn main() { .with_kakarot(*COINBASE_ADDRESS) .expect("Failed to set up Kakarot"); builder = builder.with_eoa(pk).expect("Failed to set up EOA").fund(pk, U256::from(u128::MAX)).unwrap(); + builder = builder.with_dev_allocation(10); let manifest = builder.manifest(); diff --git a/src/eth_provider/constant.rs b/src/eth_provider/constant.rs index b940c99c9..11382c3db 100644 --- a/src/eth_provider/constant.rs +++ b/src/eth_provider/constant.rs @@ -13,7 +13,9 @@ use { signers::{LocalWallet, SigningKey}, }, starknet_crypto::FieldElement, + std::sync::Arc, std::{env::var, str::FromStr, sync::OnceLock}, + tokio::sync::Mutex, }; #[cfg(feature = "hive")] @@ -34,4 +36,5 @@ lazy_static! { *CHAIN_ID.get().expect("Missing chain ID"), ExecutionEncoding::New ); + pub static ref DEPLOY_WALLET_NONCE: Arc> = Arc::new(Mutex::new(FieldElement::ZERO)); } diff --git a/src/eth_provider/provider.rs b/src/eth_provider/provider.rs index b349689a7..0cfd396e0 100644 --- a/src/eth_provider/provider.rs +++ b/src/eth_provider/provider.rs @@ -456,8 +456,7 @@ where // If the contract is not found, we need to deploy it. #[cfg(feature = "hive")] { - use crate::eth_provider::constant::{CHAIN_ID, DEPLOY_WALLET}; - use starknet::accounts::Account; + use crate::eth_provider::constant::{CHAIN_ID, DEPLOY_WALLET, DEPLOY_WALLET_NONCE}; use starknet::accounts::Call; use starknet::accounts::Execution; use starknet::core::types::BlockTag; @@ -478,12 +477,12 @@ where }], &*DEPLOY_WALLET, ); - let nonce = self - .starknet_provider - .get_nonce(StarknetBlockId::Tag(BlockTag::Latest), DEPLOY_WALLET.address()) - .await?; + + let mut nonce = DEPLOY_WALLET_NONCE.lock().await; + let current_nonce = *nonce; + let tx = execution - .nonce(nonce) + .nonce(current_nonce) .max_fee(FieldElement::from(u64::MAX)) .prepared() .map_err(|err| eyre::eyre!(err.to_string()))? @@ -491,6 +490,9 @@ where .await .map_err(|err| eyre::eyre!(err.to_string()))?; self.starknet_provider.add_invoke_transaction(tx).await?; + + *nonce += 1u8.into(); + drop(nonce); }; } diff --git a/src/main.rs b/src/main.rs index d2fbdb46f..0c9696336 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,6 +50,16 @@ async fn main() -> Result<()> { DatabaseOptions::builder().read_concern(ReadConcern::MAJORITY).write_concern(WriteConcern::MAJORITY).build(), )); + // Get the deployer nonce and set the value in the DEPLOY_WALLET_NONCE + #[cfg(feature = "hive")] + { + use kakarot_rpc::eth_provider::constant::{DEPLOY_WALLET, DEPLOY_WALLET_NONCE}; + use starknet::accounts::ConnectedAccount; + let deployer_nonce = DEPLOY_WALLET.get_nonce().await?; + let mut nonce = DEPLOY_WALLET_NONCE.lock().await; + *nonce = deployer_nonce; + } + let kakarot_rpc_module = match starknet_provider { StarknetProvider::JsonRpcClient(starknet_provider) => { let starknet_provider = Arc::new(starknet_provider); diff --git a/src/test_utils/eoa.rs b/src/test_utils/eoa.rs index 0bcb0aa57..153a45319 100644 --- a/src/test_utils/eoa.rs +++ b/src/test_utils/eoa.rs @@ -52,6 +52,7 @@ pub trait Eoa { } } +#[derive(Clone)] pub struct KakarotEOA { pub private_key: B256, pub eth_provider: Arc>, diff --git a/src/test_utils/katana/genesis.rs b/src/test_utils/katana/genesis.rs index e5c41f2f6..155968133 100644 --- a/src/test_utils/katana/genesis.rs +++ b/src/test_utils/katana/genesis.rs @@ -11,7 +11,10 @@ use ethers::types::U256; use eyre::{eyre, Result}; use katana_primitives::block::GasPrices; use katana_primitives::contract::{StorageKey, StorageValue}; +use katana_primitives::genesis::allocation::DevAllocationsGenerator; use katana_primitives::genesis::constant::DEFAULT_FEE_TOKEN_ADDRESS; +use katana_primitives::genesis::constant::DEFAULT_PREFUNDED_ACCOUNT_BALANCE; +use katana_primitives::genesis::json::GenesisAccountJson; use katana_primitives::genesis::json::{FeeTokenConfigJson, GenesisJson}; use katana_primitives::{ contract::ContractAddress, @@ -56,6 +59,7 @@ pub struct KatanaGenesisBuilder { classes: Vec, class_hashes: HashMap, contracts: HashMap, + accounts: HashMap, fee_token_storage: HashMap, cache: HashMap, status: PhantomData, @@ -68,12 +72,35 @@ impl KatanaGenesisBuilder { classes: self.classes, class_hashes: self.class_hashes, contracts: self.contracts, + accounts: self.accounts, fee_token_storage: self.fee_token_storage, cache: self.cache, status: PhantomData::, } } + pub fn with_dev_allocation(mut self, amount: u16) -> Self { + let dev_allocations = DevAllocationsGenerator::new(amount) + .with_balance(DEFAULT_PREFUNDED_ACCOUNT_BALANCE) + .generate() + .into_iter() + .map(|(address, account)| { + ( + address, + GenesisAccountJson { + public_key: account.public_key, + balance: Some(account.balance), + nonce: account.nonce, + class: None, + storage: account.storage.clone(), + }, + ) + }); + self.accounts.extend(dev_allocations); + + self + } + fn kakarot_class_hash(&self) -> Result { self.class_hashes.get("kakarot").cloned().ok_or(eyre!("Missing Kakarot class hash")) } @@ -102,6 +129,7 @@ impl Default for KatanaGenesisBuilder { classes: vec![], class_hashes: HashMap::new(), contracts: HashMap::new(), + accounts: HashMap::new(), fee_token_storage: HashMap::new(), cache: HashMap::new(), status: PhantomData::, @@ -284,7 +312,7 @@ impl KatanaGenesisBuilder { class: None, }, universal_deployer: None, - accounts: HashMap::new(), + accounts: self.accounts, contracts: self.contracts, }) } diff --git a/src/test_utils/katana/mod.rs b/src/test_utils/katana/mod.rs index 7508b43b9..db78ff50b 100644 --- a/src/test_utils/katana/mod.rs +++ b/src/test_utils/katana/mod.rs @@ -88,8 +88,8 @@ impl Katana { self.eoa.eth_provider.clone() } - pub const fn eoa(&self) -> &KakarotEOA>> { - &self.eoa + pub fn eoa(&self) -> KakarotEOA>> { + self.eoa.clone() } /// allow(dead_code) is used because this function is used in tests, diff --git a/tests/eth_provider.rs b/tests/eth_provider.rs index 55abe0b38..cc4c633d4 100644 --- a/tests/eth_provider.rs +++ b/tests/eth_provider.rs @@ -264,19 +264,41 @@ async fn test_fee_history(#[future] katana: Katana, _setup: ()) { #[tokio::test(flavor = "multi_thread")] #[cfg(feature = "hive")] async fn test_predeploy_eoa(#[future] katana: Katana, _setup: ()) { + use futures::future::join_all; use kakarot_rpc::test_utils::eoa::KakarotEOA; use reth_primitives::B256; + use starknet::providers::Provider; + // Given let eoa = katana.eoa(); let eth_provider = katana.eth_provider(); - let other_eoa = KakarotEOA::new(B256::from_str(&format!("0x{:0>64}", "0abde1")).unwrap(), eth_provider.clone()); + let starknet_provider = eth_provider.starknet_provider(); + let other_eoa_1 = KakarotEOA::new(B256::from_str(&format!("0x{:0>64}", "0abde1")).unwrap(), eth_provider.clone()); + let other_eoa_2 = KakarotEOA::new(B256::from_str(&format!("0x{:0>64}", "0abde2")).unwrap(), eth_provider.clone()); - // When + let evm_address = eoa.evm_address().unwrap(); let balance_before = eth_provider.balance(eoa.evm_address().unwrap(), None).await.unwrap(); - eoa.transfer(other_eoa.evm_address().unwrap(), 1).await.expect("Failed to transfer funds to other eoa"); - other_eoa.transfer(eoa.evm_address().unwrap(), 1).await.expect("Failed to transfer funds back to eoa"); - let balance_after = eth_provider.balance(eoa.evm_address().unwrap(), None).await.unwrap(); + eoa.transfer(other_eoa_1.evm_address().unwrap(), 1).await.expect("Failed to transfer funds to other eoa 1"); + // Sleep for 2 seconds to let the transaction pass + tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; + eoa.transfer(other_eoa_2.evm_address().unwrap(), 2).await.expect("Failed to transfer funds to other eoa 2"); + // Sleep for 2 seconds to let the transaction pass + tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; + + // When + let t1 = tokio::task::spawn(async move { + other_eoa_1.transfer(evm_address, 1).await.expect("Failed to transfer funds back to eoa"); + }); + let t2 = tokio::task::spawn(async move { + other_eoa_2.transfer(evm_address, 1).await.expect("Failed to transfer funds back to eoa"); + }); + join_all([t1, t2]).await; // Then - assert_eq!(balance_after, balance_before); + // Await all transactions to pass + while starknet_provider.block_number().await.unwrap() < 6 { + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + } + let balance_after = eth_provider.balance(evm_address, None).await.unwrap(); + assert_eq!(balance_after, balance_before - U256::from(1)); }