Skip to content

Commit

Permalink
add transaction relayer to Kakarot EOA for tests (#1382)
Browse files Browse the repository at this point in the history
* add transaction relayer to Kakarot EOA for tests

* Update kakarot submodule to commit +4b2139dcf7ab33ee94680275f77cd944524a0477

* wip

* fix tests

* clean up

* add file back

* add file back

* fmt

* fix some tests

* add asdf to ci

* fix clippy

* fix test dirty

* fix tests with katana_empty

* fix send raw transaction test

* fix comments

* Update kakarot submodule to tag v0.8.9
  • Loading branch information
tcoratger authored Sep 23, 2024
1 parent 18e1c65 commit 4061385
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 84 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/rust_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,20 @@ jobs:
with:
path: .venv
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
- name: Install asdf & tools
uses: asdf-vm/actions/setup@v3
- name: install scarb
run: |
asdf plugin add scarb
asdf install scarb 2.6.5
asdf install scarb 0.7.0
- name: Setup the Kakarot submodule
run: make setup
# Create dump
- name: Create dump
run: ./scripts/make_with_env.sh katana-genesis
- name: Test code
run: make test

# We skip the hive tests for now, will be fixed in the next PR.

# # Inspired by Reth CI.
Expand Down
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/kakarot
Submodule kakarot updated 176 files
13 changes: 11 additions & 2 deletions src/bin/hive_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
use alloy_rlp::Decodable;
use kakarot_rpc::{
into_via_try_wrapper,
providers::{eth_provider::starknet::relayer::LockedRelayer, sn_provider::StarknetProvider},
providers::{
eth_provider::{constant::RPC_CONFIG, starknet::relayer::LockedRelayer},
sn_provider::StarknetProvider,
},
};
use reth_primitives::{bytes::Buf, Block, BlockBody, BytesMut};
use starknet::{
Expand Down Expand Up @@ -62,7 +65,13 @@ async fn main() -> eyre::Result<()> {
let relayer_balance = into_via_try_wrapper!(relayer_balance)?;

let current_nonce = Mutex::new(Felt::ZERO);
let mut relayer = LockedRelayer::new(current_nonce.lock().await, relayer_address, relayer_balance);
let mut relayer = LockedRelayer::new(
current_nonce.lock().await,
relayer_address,
relayer_balance,
JsonRpcClient::new(HttpTransport::new(RPC_CONFIG.network_url.clone())),
starknet_provider.chain_id().await.expect("failed to fetch chain id"),
);

for (block_number, body) in bodies.into_iter().enumerate() {
while starknet_provider.block_number().await? < block_number as u64 {
Expand Down
2 changes: 1 addition & 1 deletion src/models/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub fn transaction_data_to_starknet_calldata(
relayer_address, // OutsideExecution caller
Felt::ZERO, // OutsideExecution nonce
Felt::ZERO, // OutsideExecution execute_after
Felt::MAX, // OutsideExecution execute_before
Felt::from(u32::MAX), // OutsideExecution execute_before
Felt::ONE, // call_array_len
*KAKAROT_ADDRESS, // CallArray to
*ETH_SEND_TRANSACTION, // CallArray selector
Expand Down
45 changes: 33 additions & 12 deletions src/pool/mempool.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
#![allow(clippy::significant_drop_tightening)]

use super::validate::KakarotTransactionValidator;
use crate::{client::EthClient, into_via_try_wrapper, providers::eth_provider::starknet::relayer::LockedRelayer};
use crate::{
client::EthClient,
into_via_try_wrapper,
providers::eth_provider::{constant::RPC_CONFIG, starknet::relayer::LockedRelayer},
};
use futures::future::select_all;
use reth_primitives::{BlockId, IntoRecoveredTransaction, U256};
use reth_transaction_pool::{
blobstore::NoopBlobStore, CoinbaseTipOrdering, EthPooledTransaction, Pool, TransactionOrigin, TransactionPool,
};
use serde_json::Value;
use starknet::core::types::{BlockTag, Felt};
use starknet::{
core::types::{BlockTag, Felt},
providers::{jsonrpc::HttpTransport, JsonRpcClient},
};
use std::{collections::HashMap, fs::File, io::Read, str::FromStr, sync::Arc, time::Duration};
use tokio::{runtime::Handle, sync::Mutex};

Expand Down Expand Up @@ -96,7 +103,7 @@ impl<SP: starknet::providers::Provider + Send + Sync + Clone + 'static> AccountM
let transaction = self.eth_client.mempool().get(best_hash);
if transaction.is_none() {
// Probably a race condition here
continue
continue;
}
let transaction = transaction.expect("not None");

Expand All @@ -110,23 +117,31 @@ impl<SP: starknet::providers::Provider + Send + Sync + Clone + 'static> AccountM
if maybe_relayer.is_err() {
// If we fail to fetch a relayer, we need to re-insert the transaction in the pool
tracing::error!(target: "account_manager", err = ?maybe_relayer.unwrap(), "failed to fetch relayer");
let _ = self.eth_client.mempool().add_transaction(TransactionOrigin::Local, transaction.transaction.clone()).await;
return
let _ = self
.eth_client
.mempool()
.add_transaction(TransactionOrigin::Local, transaction.transaction.clone())
.await;
return;
}
let mut relayer = maybe_relayer.expect("maybe_lock is not error");

// Send the Ethereum transaction using the relayer
let transaction_signed = transaction.to_recovered_transaction().into_signed();
let transaction_signed = transaction.to_recovered_transaction().into_signed();
let res = relayer.relay_transaction(&transaction_signed).await;
if res.is_err() {
// If the relayer failed to relay the transaction, we need to reposition it in the mempool
let _ = self.eth_client.mempool().add_transaction(TransactionOrigin::Local, transaction.transaction.clone()).await;
return
// If the relayer failed to relay the transaction, we need to reposition it in the mempool
let _ = self
.eth_client
.mempool()
.add_transaction(TransactionOrigin::Local, transaction.transaction.clone())
.await;
return;
}

// Increment account_nonce after sending a transaction
let nonce = relayer.nonce_mut();
*nonce= *nonce + 1;
*nonce = *nonce + 1;
});
}

Expand All @@ -136,7 +151,7 @@ impl<SP: starknet::providers::Provider + Send + Sync + Clone + 'static> AccountM
}

/// Returns the next available account from the manager.
async fn lock_account(&self) -> eyre::Result<LockedRelayer<'_>>
pub async fn lock_account(&self) -> eyre::Result<LockedRelayer<'_, JsonRpcClient<HttpTransport>>>
where
SP: starknet::providers::Provider + Send + Sync + Clone + 'static,
{
Expand Down Expand Up @@ -166,7 +181,13 @@ impl<SP: starknet::providers::Provider + Send + Sync + Clone + 'static> AccountM
}

let balance = into_via_try_wrapper!(balance)?;
let account = LockedRelayer::new(guard, *account_address, balance);
let account = LockedRelayer::new(
guard,
*account_address,
balance,
JsonRpcClient::new(HttpTransport::new(RPC_CONFIG.network_url.clone())),
self.eth_client.starknet_provider().chain_id().await.expect("Failed to get chain id"),
);

// Return the account address and the guard on the nonce
return Ok(account);
Expand Down
32 changes: 17 additions & 15 deletions src/providers/eth_provider/starknet/relayer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
models::transaction::transaction_data_to_starknet_calldata,
providers::eth_provider::{
constant::{CHAIN_ID, RPC_CONFIG},
error::{SignatureError, TransactionError},
provider::EthApiResult,
starknet::kakarot_core::{starknet_address, EXECUTE_FROM_OUTSIDE},
Expand All @@ -11,7 +10,7 @@ use reth_primitives::TransactionSigned;
use starknet::{
accounts::{Account, ExecutionEncoding, ExecutionV1, SingleOwnerAccount},
core::types::Felt,
providers::{jsonrpc::HttpTransport, JsonRpcClient},
providers::Provider,
signers::{LocalWallet, SigningKey},
};
use std::{env::var, ops::Deref, str::FromStr, sync::LazyLock};
Expand All @@ -28,24 +27,24 @@ static RELAYER_SIGNER: LazyLock<LocalWallet> = LazyLock::new(|| {
/// A relayer holding a lock on a mutex on an account and connected to the Starknet network.
/// The relayer is used to sign transactions and broadcast them on the network.
#[derive(Debug)]
pub struct LockedRelayer<'a> {
pub struct LockedRelayer<'a, SP: Provider + Send + Sync> {
/// The account used to sign and broadcast the transaction
account: SingleOwnerAccount<JsonRpcClient<HttpTransport>, LocalWallet>,
account: SingleOwnerAccount<SP, LocalWallet>,
/// The balance of the relayer
balance: Felt,
/// The locked nonce held by the relayer
nonce: MutexGuard<'a, Felt>,
}

impl<'a> LockedRelayer<'a> {
pub fn new(lock: MutexGuard<'a, Felt>, address: Felt, balance: Felt) -> Self {
let relayer = SingleOwnerAccount::new(
JsonRpcClient::new(HttpTransport::new(RPC_CONFIG.network_url.clone())),
RELAYER_SIGNER.clone(),
address,
*CHAIN_ID.get().expect("Failed to get chain id"),
ExecutionEncoding::Legacy,
);
impl<'a, SP> LockedRelayer<'a, SP>
where
SP: Provider + Send + Sync,
{
/// Create a new relayer with the provided Starknet provider, address, balance and nonce.
pub fn new(lock: MutexGuard<'a, Felt>, address: Felt, balance: Felt, provider: SP, chain_id: Felt) -> Self {
let relayer =
SingleOwnerAccount::new(provider, RELAYER_SIGNER.clone(), address, chain_id, ExecutionEncoding::New);

Self { account: relayer, balance, nonce: lock }
}

Expand Down Expand Up @@ -84,8 +83,11 @@ impl<'a> LockedRelayer<'a> {
}
}

impl<'a> Deref for LockedRelayer<'a> {
type Target = SingleOwnerAccount<JsonRpcClient<HttpTransport>, LocalWallet>;
impl<'a, SP> Deref for LockedRelayer<'a, SP>
where
SP: Provider + Send + Sync,
{
type Target = SingleOwnerAccount<SP, LocalWallet>;

fn deref(&self) -> &Self::Target {
&self.account
Expand Down
Loading

0 comments on commit 4061385

Please sign in to comment.