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

Add create-token integration test #716

Merged
merged 11 commits into from
Aug 24, 2023
14 changes: 12 additions & 2 deletions examples/demo-rollup/src/rollup.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::net::SocketAddr;
use std::str::FromStr;

use anyhow::Context;
Expand All @@ -13,6 +14,7 @@ use sov_rollup_interface::services::da::DaService;
use sov_rollup_interface::zk::Zkvm;
use sov_state::storage::Storage;
use sov_stf_runner::{from_toml_path, RollupConfig, RunnerConfig, StateTransitionRunner};
use tokio::sync::oneshot;
use tracing::debug;

#[cfg(feature = "experimental")]
Expand Down Expand Up @@ -67,7 +69,15 @@ pub async fn new_rollup_with_celestia_da(

impl<Vm: Zkvm, DA: DaService<Error = anyhow::Error> + Clone> Rollup<Vm, DA> {
/// Runs the rollup.
pub async fn run(mut self) -> Result<(), anyhow::Error> {
pub async fn run(self) -> Result<(), anyhow::Error> {
self.run_and_report_rpc_port(None).await
}

/// Runs the rollup. Reports rpc port to the caller using the provided channel.
pub async fn run_and_report_rpc_port(
mut self,
channel: Option<oneshot::Sender<SocketAddr>>,
) -> Result<(), anyhow::Error> {
let storage = self.app.get_storage();
let mut methods = get_rpc_methods::<DefaultContext>(storage);

Expand All @@ -90,7 +100,7 @@ impl<Vm: Zkvm, DA: DaService<Error = anyhow::Error> + Clone> Rollup<Vm, DA> {
self.genesis_config,
)?;

runner.start_rpc_server(methods).await;
runner.start_rpc_server(methods, channel).await;
runner.run().await?;

Ok(())
Expand Down
2 changes: 2 additions & 0 deletions examples/demo-rollup/src/test_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@ fn full_tx_json(
}

proptest!(
// Reduce the cases from 256 to 100 to speed up these tests
#![proptest_config(proptest::prelude::ProptestConfig::with_cases(100))]
#[test]
fn proptest_get_head((slots, _, total_num_batches) in arb_slots(10, 10)){
let last_slot = slots.last().unwrap();
Expand Down
71 changes: 12 additions & 59 deletions examples/demo-rollup/tests/evm_integration_tests.rs
Original file line number Diff line number Diff line change
@@ -1,65 +1,18 @@
mod test_helpers;
use std::fs::remove_dir_all;
use std::path::PathBuf;
use std::net::SocketAddr;
use std::str::FromStr;

use demo_stf::app::App;
use ethers_core::abi::Address;
use ethers_core::k256::ecdsa::SigningKey;
use ethers_core::types::transaction::eip2718::TypedTransaction;
use ethers_core::types::Eip1559TransactionRequest;
use ethers_middleware::SignerMiddleware;
use ethers_providers::{Http, Middleware, Provider};
use ethers_signers::{LocalWallet, Signer, Wallet};
use risc0_adapter::host::Risc0Verifier;
use sov_demo_rollup::{get_genesis_config, initialize_ledger, Rollup};
use sov_rollup_interface::mocks::{MockAddress, MockDaService};
use sov_stf_runner::{RollupConfig, RpcConfig, RunnerConfig, StorageConfig};
use test_helpers::SimpleStorageContract;
use test_helpers::{start_rollup, SimpleStorageContract};

const MAX_FEE_PER_GAS: u64 = 100000001;

fn create_mock_da_rollup(rollup_config: RollupConfig<()>) -> Rollup<Risc0Verifier, MockDaService> {
let _ = remove_dir_all(&rollup_config.storage.path);
let ledger_db = initialize_ledger(rollup_config.storage.path.clone());
let sequencer_da_address = MockAddress { addr: [99; 32] };
let da_service = MockDaService::new(sequencer_da_address);

let app = App::new(rollup_config.storage);

let genesis_config = get_genesis_config(sequencer_da_address);

Rollup {
app,
da_service,
ledger_db,
runner_config: rollup_config.runner,
genesis_config,
}
}

async fn start_rollup() {
let mut mock_path = PathBuf::from("tests");
mock_path.push("test_data");
mock_path.push("tmp");
mock_path.push("mocks");

let rollup_config = RollupConfig {
storage: StorageConfig { path: mock_path },
runner: RunnerConfig {
start_height: 0,
rpc_config: RpcConfig {
bind_host: "127.0.0.1".into(),
bind_port: 12345,
},
},
da: (),
};

let rollup = create_mock_da_rollup(rollup_config);
rollup.run().await.unwrap();
}

struct TestClient {
chain_id: u64,
from_addr: Address,
Expand All @@ -74,9 +27,10 @@ impl TestClient {
key: Wallet<SigningKey>,
from_addr: Address,
contract: SimpleStorageContract,
rpc_addr: std::net::SocketAddr,
) -> Self {
let endpoint = format!("http://localhost:{}", 12345);
let provider = Provider::try_from(endpoint).unwrap();
let provider =
Provider::try_from(&format!("http://localhost:{}", rpc_addr.port())).unwrap();

let client = SignerMiddleware::new_with_provider_chain(provider, key)
.await
Expand Down Expand Up @@ -161,7 +115,7 @@ impl TestClient {
}
}

async fn send_tx_test_to_eth() -> Result<(), Box<dyn std::error::Error>> {
async fn send_tx_test_to_eth(rpc_address: SocketAddr) -> Result<(), Box<dyn std::error::Error>> {
let chain_id: u64 = 1;
let key = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
.parse::<LocalWallet>()
Expand All @@ -172,23 +126,22 @@ async fn send_tx_test_to_eth() -> Result<(), Box<dyn std::error::Error>> {

let from_addr = Address::from_str("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266").unwrap();

let test_client = TestClient::new_demo_rollup_client(chain_id, key, from_addr, contract).await;
let test_client =
TestClient::new_demo_rollup_client(chain_id, key, from_addr, contract, rpc_address).await;
test_client.execute().await
}

#[tokio::test]
async fn tx_tests() -> Result<(), anyhow::Error> {
let (tx, rx) = tokio::sync::oneshot::channel();
let (port_tx, port_rx) = tokio::sync::oneshot::channel();

let rollup_task = tokio::spawn(async {
tx.send(()).unwrap();
start_rollup().await;
start_rollup(port_tx).await;
});

// Wait for rollup task to start:
let _ = rx.await;

send_tx_test_to_eth().await.unwrap();
let port = port_rx.await.unwrap();
send_tx_test_to_eth(port).await.unwrap();
rollup_task.abort();
Ok(())
}
66 changes: 66 additions & 0 deletions examples/demo-rollup/tests/module_system_integration_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
mod test_helpers;
use std::net::SocketAddr;

use borsh::BorshSerialize;
use demo_stf::app::DefaultPrivateKey;
use demo_stf::runtime::RuntimeCall;
use jsonrpsee::core::client::ClientT;
use jsonrpsee::http_client::{HttpClient, HttpClientBuilder};
use sov_modules_api::default_context::DefaultContext;
use sov_modules_api::transaction::Transaction;
use sov_modules_api::{PrivateKey, Spec};
use test_helpers::start_rollup;

struct TestClient {
preston-evans98 marked this conversation as resolved.
Show resolved Hide resolved
client: HttpClient,
}

impl TestClient {
pub fn new(endpoint: &str) -> Self {
let client = HttpClientBuilder::default().build(endpoint).unwrap();
Self { client }
}
pub async fn send_transaction(
&self,
tx: Transaction<DefaultContext>,
) -> Result<(), anyhow::Error> {
let batch = vec![tx.try_to_vec()?];
let response: String = self.client.request("sequencer_publishBatch", batch).await?;
println!("response: {:?}", response);
Ok(())
}
}

async fn send_test_create_token_tx(rpc_address: SocketAddr) -> Result<(), anyhow::Error> {
let key = DefaultPrivateKey::generate();
let address: <DefaultContext as Spec>::Address = key.to_address();

let msg = RuntimeCall::bank(sov_bank::CallMessage::<DefaultContext>::CreateToken {
salt: 0,
token_name: "test-token".to_string(),
initial_balance: 1000,
minter_address: address,
authorized_minters: vec![],
});
let tx = Transaction::<DefaultContext>::new_signed_tx(&key, msg.try_to_vec().unwrap(), 0);

let client = TestClient::new(&format!("http://localhost:{}", rpc_address.port()));

client.send_transaction(tx).await
}

preston-evans98 marked this conversation as resolved.
Show resolved Hide resolved
#[tokio::test]
async fn tx_tests() -> Result<(), anyhow::Error> {
let (port_tx, port_rx) = tokio::sync::oneshot::channel();

let rollup_task = tokio::spawn(async {
start_rollup(port_tx).await;
});

// Wait for rollup task to start:
let port = port_rx.await.unwrap();

send_test_create_token_tx(port).await?;
preston-evans98 marked this conversation as resolved.
Show resolved Hide resolved
rollup_task.abort();
Ok(())
}
51 changes: 51 additions & 0 deletions examples/demo-rollup/tests/test_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
use std::fs::remove_dir_all;
use std::net::SocketAddr;
use std::path::PathBuf;

use demo_stf::app::App;
use ethers_contract::BaseContract;
use ethers_core::abi::Abi;
use ethers_core::types::Bytes;
use revm::primitives::{ExecutionResult, Output};
use risc0_adapter::host::Risc0Verifier;
use sov_demo_rollup::{get_genesis_config, initialize_ledger, Rollup};
use sov_rollup_interface::mocks::{MockAddress, MockDaService};
use sov_stf_runner::{RollupConfig, RpcConfig, RunnerConfig, StorageConfig};
use tokio::sync::oneshot;

#[allow(dead_code)]
pub(crate) fn output(result: ExecutionResult) -> bytes::Bytes {
Expand Down Expand Up @@ -31,6 +39,49 @@ fn make_contract_from_abi(path: PathBuf) -> BaseContract {
BaseContract::from(abi)
}

fn create_mock_da_rollup(rollup_config: RollupConfig<()>) -> Rollup<Risc0Verifier, MockDaService> {
let _ = remove_dir_all(&rollup_config.storage.path);
let ledger_db = initialize_ledger(rollup_config.storage.path.clone());
let sequencer_da_address = MockAddress { addr: [99; 32] };
let da_service = MockDaService::new(sequencer_da_address);

let app = App::new(rollup_config.storage);

let genesis_config = get_genesis_config(sequencer_da_address);

Rollup {
app,
da_service,
ledger_db,
runner_config: rollup_config.runner,
genesis_config,
}
}

pub async fn start_rollup(rpc_reporting_channel: oneshot::Sender<SocketAddr>) {
let mut mock_path = PathBuf::from("tests");
mock_path.push("test_data");
mock_path.push("tmp");
mock_path.push("mocks");
neysofu marked this conversation as resolved.
Show resolved Hide resolved

let rollup_config = RollupConfig {
storage: StorageConfig { path: mock_path },
runner: RunnerConfig {
start_height: 0,
rpc_config: RpcConfig {
bind_host: "127.0.0.1".into(),
bind_port: 0,
},
},
da: (),
};
let rollup = create_mock_da_rollup(rollup_config);
rollup
.run_and_report_rpc_port(Some(rpc_reporting_channel))
.await
.unwrap();
}

#[allow(dead_code)]
pub(crate) struct SimpleStorageContract {
bytecode: Bytes,
Expand Down
14 changes: 12 additions & 2 deletions full-node/sov-stf-runner/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use sov_rollup_interface::da::{BlobReaderTrait, DaSpec};
use sov_rollup_interface::services::da::DaService;
use sov_rollup_interface::stf::StateTransitionFunction;
use sov_rollup_interface::zk::Zkvm;
use tokio::sync::oneshot;
use tracing::{debug, info};

type StateRoot<ST, Vm, DA> = <ST as StateTransitionFunction<
Expand Down Expand Up @@ -99,15 +100,24 @@ where
}

/// Starts a RPC server with provided rpc methods.
pub async fn start_rpc_server(&self, methods: RpcModule<()>) {
pub async fn start_rpc_server(
&self,
methods: RpcModule<()>,
channel: Option<oneshot::Sender<SocketAddr>>,
) {
let listen_address = self.listen_address;
let _handle = tokio::spawn(async move {
let server = jsonrpsee::server::ServerBuilder::default()
.build([listen_address].as_ref())
.await
.unwrap();

info!("Starting RPC server at {} ", server.local_addr().unwrap());
let bound_address = server.local_addr().unwrap();
if let Some(channel) = channel {
channel.send(bound_address).unwrap();
}
info!("Starting RPC server at {} ", &bound_address);

let _server_handle = server.start(methods).unwrap();
futures::future::pending::<()>().await;
});
Expand Down