Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(katana): messaging e2e test #1925

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6a11b1d
-Runner creation
fabrobles92 May 4, 2024
1a5f775
L2 -> L1 messaging
fabrobles92 May 5, 2024
fd99511
clippy and fmt
fabrobles92 May 5, 2024
438dced
style
kariy May 6, 2024
bd2d71b
apply kari's cool formatting
kariy May 6, 2024
f7e830c
fmt
kariy May 6, 2024
4dcb1b7
Applying more change from Code review
fabrobles92 May 15, 2024
20fb000
tests
kariy May 18, 2024
ed2bae1
Merge remote-tracking branch 'origin/main' into katana/Messaging-Intr…
fabrobles92 May 20, 2024
fe95f29
Merge remote-tracking branch 'origin/main' into katana/Messaging-Intr…
fabrobles92 May 24, 2024
122fa28
Delete debug from Sol! and not used B256
fabrobles92 May 26, 2024
2990cf9
Merge remote-tracking branch 'origin/main' into katana/Messaging-Intr…
fabrobles92 May 27, 2024
d51cb51
Cleaning cargo.lock
fabrobles92 May 29, 2024
e1766f9
Merge remote-tracking branch 'origin/main' into katana/Messaging-Intr…
fabrobles92 May 29, 2024
758ce41
Add new option to Katnna Runner Config
fabrobles92 Jun 2, 2024
6548532
Merge remote-tracking branch 'origin/main' into katana/Messaging-Intr…
fabrobles92 Jun 3, 2024
1da68bb
consume message and check msg fee
kariy Jun 10, 2024
a1641ee
clippy and fmt
kariy Jun 10, 2024
866aa6a
- Use alloy Anvil Binding Object to spawn an instance
fabrobles92 Jun 11, 2024
22cfff7
Add step to install anvil in Dockerfile
fabrobles92 Jun 11, 2024
a72ed8a
Remove profile local from Anvil installation command
fabrobles92 Jun 11, 2024
0ce7e88
Merge remote-tracking branch 'origin/main' into katana/Messaging-Intr…
fabrobles92 Jun 12, 2024
5d691f4
Delete step to install anvil
fabrobles92 Jun 12, 2024
7f64bb8
Point CI to devcontainer that has Anvil installed
fabrobles92 Jun 12, 2024
7187343
Update Alloy
fabrobles92 Jun 13, 2024
dcdebce
merge main + fix L1HandlerTxHash
glihm Jun 22, 2024
f71f05f
merge main
glihm Jun 22, 2024
9e1ed0d
fix: fix test with pre-computed tx hash
glihm Jun 22, 2024
c6bcd1d
ci: increment cores for clippy
glihm Jun 22, 2024
6785aa7
ci: pre-build latest sozo to re-use in jobs
glihm Jun 22, 2024
b4d3f65
ci: fix missing dependency
glihm Jun 22, 2024
e368c33
ci: fix missing x permission
glihm Jun 22, 2024
5fd834e
ci: remove unused cached to save time
glihm Jun 22, 2024
cb0e662
restore lockfile
kariy Jun 24, 2024
dbfe622
revert l1 handler tx hash computation changes
kariy Jun 24, 2024
28db6b4
revert some changes
kariy Jun 24, 2024
d1df5f5
revert test case
kariy Jun 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,058 changes: 1,013 additions & 45 deletions Cargo.lock

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion crates/katana/rpc/rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ repository.workspace = true
version.workspace = true

[dependencies]
dojo-world = { workspace = true }
alloy = { git = "https://github.com/alloy-rs/alloy", rev = "7128c53"}
dojo-metrics.workspace = true
katana-core.workspace = true
katana-executor.workspace = true
Expand All @@ -16,7 +18,7 @@ katana-rpc-api.workspace = true
katana-rpc-types-builder.workspace = true
katana-rpc-types.workspace = true
katana-tasks.workspace = true

tempfile = "3.8.1"
anyhow.workspace = true
flate2.workspace = true
futures.workspace = true
Expand All @@ -34,6 +36,7 @@ tokio.workspace = true
tower = { version = "0.4.13", features = [ "full" ] }
tower-http = { version = "0.4.1", features = [ "full" ] }
tracing.workspace = true
cainome.workspace = true

[dev-dependencies]
assert_matches = "1.5.0"
Expand All @@ -42,4 +45,5 @@ cairo-lang-starknet-classes.workspace = true
dojo-test-utils.workspace = true
jsonrpsee = { workspace = true, features = [ "client" ] }
katana-rpc-api = { workspace = true, features = [ "client" ] }
katana-runner.workspace = true
url.workspace = true
212 changes: 210 additions & 2 deletions crates/katana/rpc/rpc/tests/starknet.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
use std::fs::{self};
use std::fs::{self, File};
use std::io::Write;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;

use alloy::primitives::{Address, Uint, U256};
use alloy::sol;
use cainome::cairo_serde::EthAddress;
use cainome::rs::abigen;
use dojo_test_utils::sequencer::{get_default_test_starknet_config, TestSequencer};
use dojo_world::utils::TransactionWaiter;
use katana_core::sequencer::SequencerConfig;
use katana_runner::{AnvilRunner, KatanaRunner, KatanaRunnerConfig};
use serde_json::json;
use starknet::accounts::{Account, Call, ConnectedAccount};
use starknet::contract::ContractFactory;
use starknet::core::types::contract::legacy::LegacyContractClass;
use starknet::core::types::{
BlockId, BlockTag, DeclareTransactionReceipt, FieldElement, MaybePendingTransactionReceipt,
TransactionFinalityStatus, TransactionReceipt,
Transaction, TransactionFinalityStatus, TransactionReceipt,
};
use starknet::core::utils::{get_contract_address, get_selector_from_name};
use starknet::macros::felt;
use starknet::providers::Provider;
use tempfile::tempdir;

mod common;

Expand Down Expand Up @@ -174,3 +186,199 @@ async fn test_send_declare_and_deploy_legacy_contract() {

sequencer.stop().expect("failed to stop sequencer");
}

sol!(
#[allow(missing_docs)]
#[sol(rpc)]
StarknetContract,
"tests/test_data/solidity/StarknetMessagingLocalCompiled.json"
);

sol!(
#[allow(missing_docs)]
#[sol(rpc)]
Contract1,
"tests/test_data/solidity/Contract1Compiled.json"
);

abigen!(CairoMessagingContract, "crates/katana/rpc/rpc/tests/test_data/cairo_l1_msg_contract.json");

#[tokio::test(flavor = "multi_thread")]
async fn test_messaging_l1_l2() {
// Prepare Anvil + Messaging Contracts
let anvil_runner = AnvilRunner::new().await.unwrap();

let contract_strk = StarknetContract::deploy(anvil_runner.provider()).await.unwrap();
let strk_address = contract_strk.address();

assert_eq!(
contract_strk.address(),
&Address::from_str("0x5fbdb2315678afecb367f032d93f642f64180aa3").unwrap()
);

let contract_c1 = Contract1::deploy(anvil_runner.provider(), *strk_address).await.unwrap();

assert_eq!(
contract_c1.address(),
&Address::from_str("0xe7f1725e7734ce288f8367e1bb143e90bb3f0512").unwrap()
);

// Prepare Katana + Messaging Contract
let messagin_config = json!({
"chain": "ethereum",
"rpc_url": anvil_runner.endpoint,
"contract_address": contract_strk.address().to_string(),
"sender_address": anvil_runner.address(),
"private_key": anvil_runner.secret_key(),
"interval": 2,
"from_block": 0
});
let serialized_json = &messagin_config.to_string();

let dir = tempdir().expect("Error creating temp dir");
let file_path = dir.path().join("temp-anvil-messaging.json");

// Write JSON string to a tempfile
let mut file = File::create(&file_path).expect("Error creating temp file");
file.write_all(serialized_json.as_bytes()).expect("Failed to write to file");

let katana_runner = KatanaRunner::new_with_config(KatanaRunnerConfig {
n_accounts: 2,
disable_fee: false,
block_time: None,
port: None,
program_name: None,
run_name: None,
messaging: Some(file_path.to_str().unwrap().to_string()),
})
.unwrap();
let starknet_account = katana_runner.account(0);

let path: PathBuf = PathBuf::from("tests/test_data/cairo_l1_msg_contract.json");
let (contract, compiled_class_hash) =
common::prepare_contract_declaration_params(&path).unwrap();

let class_hash = contract.class_hash();
let res =
starknet_account.declare(Arc::new(contract), compiled_class_hash).send().await.unwrap();

let receipt = TransactionWaiter::new(res.transaction_hash, starknet_account.provider())
.with_tx_status(TransactionFinalityStatus::AcceptedOnL2)
.await
.expect("Invalid tx receipt");

// Following 2 asserts are to make sure contract declaration went through and was processed
// successfully
assert_eq!(receipt.finality_status(), &TransactionFinalityStatus::AcceptedOnL2);

assert!(
starknet_account
.provider()
.get_class(BlockId::Tag(BlockTag::Latest), class_hash)
.await
.is_ok()
);

let contract_factory = ContractFactory::new(class_hash, &starknet_account);

let transaction = contract_factory
.deploy(vec![], FieldElement::ZERO, false)
.send()
.await
.expect("Unable to deploy contract");

// wait for the tx to be mined
TransactionWaiter::new(transaction.transaction_hash, starknet_account.provider())
.with_tx_status(TransactionFinalityStatus::AcceptedOnL2)
.await
.expect("Invalid tx receipt");

let contract_address =
get_contract_address(FieldElement::ZERO, res.class_hash, &[], FieldElement::ZERO);

assert_eq!(
contract_address,
felt!("0x033d18fcfd3ae75ae4e8a275ce649220ed718b68dc53425b388fedcdbeab5097")
);

// Messaging between L1 -> L2
let builder = contract_c1
.sendMessage(
U256::from_str("0x033d18fcfd3ae75ae4e8a275ce649220ed718b68dc53425b388fedcdbeab5097")
.unwrap(),
U256::from_str("0x005421de947699472df434466845d68528f221a52fce7ad2934c5dae2e1f1cdc")
.unwrap(),
vec![U256::from(123)],
)
.gas(12000000)
.value(Uint::from(1));

let receipt = builder
.send()
.await
.expect("Error Await pending transaction")
.get_receipt()
.await
.expect("Error getting transaction receipt");

assert!(receipt.status());

// wait for the tx to be mined (Using delay cause the transaction is sent from L1 and is
// received in L2)
tokio::time::sleep(Duration::from_millis(WAIT_TX_DELAY_MILLIS)).await;

let tx = starknet_account
.provider()
.get_transaction_by_block_id_and_index(BlockId::Tag(BlockTag::Latest), 0)
.await
.unwrap();

match tx {
Transaction::L1Handler(ref l1_handler_transaction) => {
let calldata = &l1_handler_transaction.calldata;

assert_eq!(
tx.transaction_hash(),
&felt!("0x00c33cc113afc56bc878034908472770cb13eda6ad8ad91feb25fd4e5c9196a0")
);

assert_eq!(FieldElement::to_string(&calldata[1]), "123")
}
_ => {
panic!("Error, No L1handler transaction")
}
}

// Messaging between L2 -> L1
let cairo_messaging_contract = CairoMessagingContract::new(contract_address, &starknet_account);
let tx = cairo_messaging_contract
.send_message_value(
&EthAddress::from(
FieldElement::from_str(contract_c1.address().to_string().as_str()).unwrap(),
),
&FieldElement::from(2u8),
)
.send()
.await
.expect("Call to send_message_value failed");

TransactionWaiter::new(tx.transaction_hash, starknet_account.provider())
.with_tx_status(TransactionFinalityStatus::AcceptedOnL2)
.await
.expect("Invalid tx receipt");

let builder = contract_c1
.consumeMessage(
U256::from_str(contract_address.to_string().as_str()).unwrap(),
vec![U256::from(2)],
)
.value(Uint::from(1))
.gas(12000000)
.nonce(4);

// Wait for the message to reach L1
tokio::time::sleep(Duration::from_millis(8000)).await;

let tx_receipt = builder.send().await.unwrap().get_receipt().await.unwrap();
assert!(tx_receipt.status());
fabrobles92 marked this conversation as resolved.
Show resolved Hide resolved
}
Loading
Loading