Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Commit

Permalink
add testing
Browse files Browse the repository at this point in the history
  • Loading branch information
greged93 committed Apr 17, 2024
1 parent 7b8e3ca commit 8c9247f
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 9 deletions.
1 change: 0 additions & 1 deletion .trunk/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@
plugins
user_trunk.yaml
user.yaml
tmp
22 changes: 22 additions & 0 deletions src/test_utils/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,28 @@ pub async fn erc20(#[future] katana: Katana) -> (Katana, KakarotEvmContract) {
(katana, contract)
}

#[cfg(any(test, feature = "arbitrary", feature = "testing"))]
#[fixture]
#[awt]
pub async fn plain_opcodes(#[future] counter: (Katana, KakarotEvmContract)) -> (Katana, KakarotEvmContract) {
use ethers::abi::Address;

let katana = counter.0;
let counter = counter.1;
let eoa = katana.eoa();
let counter_address = Address::from_slice(&counter.evm_address.to_bytes_be()[12..]);
let contract = eoa
.deploy_evm_contract(
Some("PlainOpcodes"),
(
Token::Address(counter_address), // counter address
),
)
.await
.expect("Failed to deploy ERC20 contract");
(katana, contract)
}

/// This fixture creates a new test environment on Katana.
#[cfg(any(test, feature = "arbitrary", feature = "testing"))]
#[fixture]
Expand Down
75 changes: 73 additions & 2 deletions src/test_utils/katana/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod genesis;

use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;

Expand All @@ -8,12 +9,19 @@ use katana_primitives::block::GasPrices;
use katana_primitives::chain::ChainId;
use katana_primitives::genesis::json::GenesisJson;
use katana_primitives::genesis::Genesis;
use mongodb::bson::doc;
use mongodb::options::{UpdateModifications, UpdateOptions};
use reth_primitives::U256;
use starknet::providers::jsonrpc::HttpTransport;
use starknet::providers::JsonRpcClient;

use crate::eth_provider::provider::EthDataProvider;
use crate::eth_provider::database::types::{header::StoredHeader, transaction::StoredTransaction};
use crate::eth_provider::utils::into_filter;
use crate::eth_provider::{
constant::{HASH_PADDING, U64_PADDING},
provider::EthDataProvider,
};
use crate::test_utils::eoa::KakarotEOA;
use std::collections::HashMap;

#[cfg(any(test, feature = "arbitrary", feature = "testing"))]
use {
Expand Down Expand Up @@ -148,6 +156,69 @@ impl<'a> Katana {
&self.sequencer
}

// TODO: improve
pub async fn add_transactions_with_header_to_database(&self, txs: Vec<Transaction>, bn: u64) {
let provider = self.eth_provider();
let database = provider.database();

let block_number = format!("0x{:x}", bn);
let base_fee_per_gas = txs.iter().map(|tx| tx.max_fee_per_gas.unwrap_or_default()).max();
let padded_block_number = format!("0x{:0>width$}", &block_number[2..], width = U64_PADDING);

let tx_collection = database.inner().collection::<StoredTransaction>("transactions");
for tx in txs {
let filter = into_filter("tx.hash", &tx.hash, HASH_PADDING);
database
.update_one::<StoredTransaction>(tx.into(), filter, true)
.await
.expect("Failed to update transaction in database");
}
tx_collection
.update_many(
doc! {"tx.blockNumber": &block_number},
UpdateModifications::Document(doc! {"$set": {"tx.blockNumber": &padded_block_number}}),
UpdateOptions::builder().upsert(true).build(),
)
.await
.expect("Failed to update block number");

let header_collection = database.inner().collection::<StoredHeader>("headers");
let header = reth_rpc_types::Header {
number: Some(U256::from(bn)),
hash: Some(B256::random()),
parent_hash: Default::default(),
nonce: Default::default(),
logs_bloom: Default::default(),
transactions_root: Default::default(),
state_root: Default::default(),
receipts_root: Default::default(),
difficulty: Default::default(),
total_difficulty: Default::default(),
extra_data: Default::default(),
gas_limit: U256::MAX,
gas_used: Default::default(),
timestamp: Default::default(),
uncles_hash: Default::default(),
miner: Default::default(),
mix_hash: Default::default(),
base_fee_per_gas,
withdrawals_root: Default::default(),
excess_blob_gas: Default::default(),
parent_beacon_block_root: Default::default(),
blob_gas_used: Default::default(),
};
let filter = into_filter("header.number", &bn, U64_PADDING);
database.update_one(StoredHeader { header }, filter, true).await.expect("Failed to update header in database");
header_collection
.update_one(
doc! {"header.number": block_number},
UpdateModifications::Document(doc! {"$set": {"header.number": padded_block_number}}),
UpdateOptions::builder().upsert(true).build(),
)
.await
.expect("Failed to update block number");
}

/// Retrieves the first stored transaction
pub fn first_transaction(&self) -> Option<Transaction> {
self.mock_data
Expand Down
68 changes: 62 additions & 6 deletions tests/trace_api.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,77 @@
#![cfg(feature = "testing")]
use kakarot_rpc::test_utils::fixtures::{katana, setup};
use kakarot_rpc::eth_provider::provider::EthereumProvider;
use kakarot_rpc::test_utils::eoa::Eoa;
use kakarot_rpc::test_utils::evm_contract::{EvmContract, KakarotEvmContract};
use kakarot_rpc::test_utils::fixtures::{plain_opcodes, setup};
use kakarot_rpc::test_utils::katana::Katana;
use kakarot_rpc::test_utils::rpc::start_kakarot_rpc_server;
use reth_primitives::{U256, U8};
use reth_rpc_types::trace::parity::LocalizedTransactionTrace;
use reth_rpc_types::Signature;
use rstest::*;
use serde_json::{json, Value};

const TRACING_BLOCK_NUMBER: u64 = 0x2;
const TRANSACTIONS_COUNT: usize = 2;

#[rstest]
#[awt]
#[tokio::test(flavor = "multi_thread")]
async fn test_trace_block(#[future] katana: Katana, _setup: ()) {
async fn test_trace_block(#[future] plain_opcodes: (Katana, KakarotEvmContract), _setup: ()) {
let katana = plain_opcodes.0;
let plain_opcodes = plain_opcodes.1;
let (server_addr, server_handle) =
start_kakarot_rpc_server(&katana).await.expect("Error setting up Kakarot RPC server");

// Get the first transaction from the mock data.
let tx = &katana.first_transaction().unwrap();
let eoa = katana.eoa();
let eoa_address = eoa.evm_address().expect("Failed to get eoa address");
let nonce: u64 = eoa.nonce().await.expect("Failed to get nonce").to();
let chain_id = eoa.eth_provider().chain_id().await.expect("Failed to get chain id").unwrap_or_default();

// Push 10 RPC transactions into the database.
let mut txs = Vec::with_capacity(TRANSACTIONS_COUNT);
let max_fee_per_gas = 10;
let max_priority_fee_per_gas = 1;
for i in 0..TRANSACTIONS_COUNT {
// We want to trace the "createCounterAndInvoke" which does a CREATE followed by a CALL.
let tx = plain_opcodes
.prepare_call_transaction(
"createCounterAndInvoke",
(),
nonce + i as u64,
0,
chain_id.to(),
max_fee_per_gas,
max_priority_fee_per_gas,
)
.expect("Failed to prepare call transaction");
// Sign the transaction and convert it to a RPC transaction.
let tx_signed = eoa.sign_transaction(tx.clone()).expect("Failed to sign transaction");
let tx = reth_rpc_types::Transaction {
transaction_type: Some(U8::from(2)),
nonce: tx.nonce(),
hash: tx_signed.hash(),
to: tx.to(),
from: eoa_address,
block_number: Some(U256::from(TRACING_BLOCK_NUMBER)),
chain_id: tx.chain_id(),
gas: U256::from(tx.gas_limit()),
input: tx.input().clone(),
signature: Some(Signature {
r: tx_signed.signature().r,
s: tx_signed.signature().s,
v: U256::from(tx_signed.signature().v(Some(chain_id.to()))),
y_parity: Some(reth_rpc_types::Parity(tx_signed.signature().odd_y_parity)),
}),
max_fee_per_gas: Some(U256::from(max_fee_per_gas)),
gas_price: Some(U256::from(max_fee_per_gas)),
max_priority_fee_per_gas: Some(U256::from(max_priority_fee_per_gas)),
value: tx.value(),
..Default::default()
};
txs.push(tx);
}
katana.add_transactions_with_header_to_database(txs, TRACING_BLOCK_NUMBER).await;

let reqwest_client = reqwest::Client::new();
let res = reqwest_client
Expand All @@ -25,7 +82,7 @@ async fn test_trace_block(#[future] katana: Katana, _setup: ()) {
{
"jsonrpc":"2.0",
"method":"trace_block",
"params":[format!("0x{:064x}", tx.block_hash.unwrap_or_default())],
"params":[format!("0x{:016x}", TRACING_BLOCK_NUMBER)],
"id":1,
}
)
Expand All @@ -35,7 +92,6 @@ async fn test_trace_block(#[future] katana: Katana, _setup: ()) {
.await
.expect("Failed to call Debug RPC");
let response = res.text().await.expect("Failed to get response body");
dbg!(response.clone());
let raw: Value = serde_json::from_str(&response).expect("Failed to deserialize response body");
let traces: Option<Vec<LocalizedTransactionTrace>> =
serde_json::from_value(raw["result"].clone()).expect("Failed to deserialize result");
Expand Down

0 comments on commit 8c9247f

Please sign in to comment.