Skip to content

Commit

Permalink
bridge_backend: Add initial client.
Browse files Browse the repository at this point in the history
  • Loading branch information
ceyhunsen committed Oct 4, 2024
1 parent a2830c7 commit e4c488a
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 60 deletions.
105 changes: 53 additions & 52 deletions src/bridge_backend.rs
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
use std::net::SocketAddr;
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
use std::time::{Duration, Instant};

use anyhow::{bail, Context};
use async_trait::async_trait;
use futures::TryStreamExt;
use tokio::process::Command;
use tokio::time::sleep;

use super::config::BridgeBackendConfig;
use super::docker::DockerEnv;
use super::framework::TestContext;
use super::node::{LogProvider, Node, Restart, SpawnOutput};
use super::Result;
use crate::bridge_backend_client::BridgeBackendClient;
use crate::node::NodeKind;
use crate::test_client::TestClient;
use crate::traits::{ContainerSpawnOutput, LogProvider, Node, Restart, SpawnOutput};

pub struct BridgeBackendNode {
spawn_output: SpawnOutput,
pub config: BridgeBackendConfig,
docker_env: Arc<Option<DockerEnv>>,
client: BridgeBackendClient,
}

impl BridgeBackendNode {
pub async fn new(config: &BridgeBackendConfig, docker: Arc<Option<DockerEnv>>) -> Result<Self> {
let spawn_output = Self::spawn(config, &docker).await?;
let rpc_url = SocketAddr::from_str(&(config.host.clone() + &config.port.to_string()))?;

Ok(Self {
spawn_output,
config: config.clone(),
docker_env: docker,
client: BridgeBackendClient::new(rpc_url).await?,
})
}

Expand All @@ -41,11 +48,38 @@ impl BridgeBackendNode {
None => <Self as Node>::spawn(config),
}
}

async fn wait_for_shutdown(&self) -> Result<()> {
let timeout_duration = Duration::from_secs(30);
let start = std::time::Instant::now();

while start.elapsed() < timeout_duration {
if !self.is_process_running().await? {
println!("Bridge backend has stopped successfully");
return Ok(());
}
sleep(Duration::from_millis(200)).await;
}

bail!("Timeout waiting for bridge backend to stop")
}

async fn is_process_running(&self) -> Result<bool> {
// let data_dir = &self.config.data_dir;
// let output = Command::new("pgrep")
// .args(["-f", &format!("bitcoind.*{}", data_dir.display())])
// .output()
// .await?;

// Ok(output.status.success())
todo!()
}
}

#[async_trait]
impl Node for BridgeBackendNode {
type Config = BridgeBackendConfig;
type Client = TestClient;
type Client = BridgeBackendClient;

fn spawn(config: &Self::Config) -> Result<SpawnOutput> {
let env = config.get_env();
Expand Down Expand Up @@ -87,10 +121,6 @@ impl Node for BridgeBackendNode {
anyhow::bail!("Node failed to become ready within the specified timeout")
}

fn client(&self) -> &Self::Client {
&self.client()
}

fn config_mut(&mut self) -> &mut Self::Config {
&mut self.config
}
Expand All @@ -104,7 +134,7 @@ impl Node for BridgeBackendNode {
.context("Failed to kill child process")?;
Ok(())
}
SpawnOutput::Container(crate::node::ContainerSpawnOutput { id, .. }) => {
SpawnOutput::Container(ContainerSpawnOutput { id, .. }) => {
std::println!("Stopping container {id}");
let docker = bollard::Docker::connect_with_local_defaults()
.context("Failed to connect to Docker")?;
Expand All @@ -116,11 +146,21 @@ impl Node for BridgeBackendNode {
}
}
}

fn client(&self) -> &Self::Client {
&self.client
}

fn env(&self) -> Vec<(&'static str, &'static str)> {
// self.config.get_env()
todo!()
}
}

#[async_trait]
impl Restart for BridgeBackendNode {
async fn wait_until_stopped(&mut self) -> Result<()> {
self.client.stop().await?;
// self.client.stop().await?;
self.stop().await?;

match &self.spawn_output {
Expand Down Expand Up @@ -150,9 +190,6 @@ impl Restart for BridgeBackendNode {

self.wait_for_ready(None).await?;

// Reload wallets after restart
self.load_wallets().await;

Ok(())
}
}
Expand All @@ -163,21 +200,21 @@ impl LogProvider for BridgeBackendNode {
}

fn log_path(&self) -> PathBuf {
self.config.data_dir.join("regtest").join("debug.log")
todo!()
}
}

pub struct BitcoinNodeCluster {
pub struct BridgeBackendNodeCluster {
inner: Vec<BridgeBackendNode>,
}

impl BitcoinNodeCluster {
impl BridgeBackendNodeCluster {
pub async fn new(ctx: &TestContext) -> Result<Self> {
let n_nodes = ctx.config.test_case.n_nodes;
let mut cluster = Self {
inner: Vec::with_capacity(n_nodes),
};
for config in ctx.config.bitcoin.iter() {
for config in ctx.config.bridge_backend.iter() {
let node = BridgeBackendNode::new(config, Arc::clone(&ctx.docker)).await?;
cluster.inner.push(node)
}
Expand All @@ -193,42 +230,6 @@ impl BitcoinNodeCluster {
Ok(())
}

pub async fn wait_for_sync(&self, timeout: Duration) -> Result<()> {
let start = Instant::now();
while start.elapsed() < timeout {
// let mut heights = HashSet::new();
// for node in &self.inner {
// let height = node.get_block_count().await?;
// heights.insert(height);
// }

// if heights.len() == 1 {
return Ok(());
// }

// sleep(Duration::from_secs(1)).await;
}
bail!("Nodes failed to sync within the specified timeout")
}

// Connect all bitcoin nodes between them
pub async fn connect_nodes(&self) -> Result<()> {
for (i, from_node) in self.inner.iter().enumerate() {
for (j, to_node) in self.inner.iter().enumerate() {
if i != j {
let ip = match &to_node.spawn_output {
SpawnOutput::Container(container) => container.ip.clone(),
_ => "127.0.0.1".to_string(),
};

let add_node_arg = format!("{}:{}", ip, to_node.config.p2p_port);
from_node.add_node(&add_node_arg).await?;
}
}
}
Ok(())
}

pub fn get(&self, index: usize) -> Option<&BridgeBackendNode> {
self.inner.get(index)
}
Expand Down
36 changes: 36 additions & 0 deletions src/bridge_backend_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::{net::SocketAddr, time::Duration};

use jsonrpsee::{
http_client::{HttpClient, HttpClientBuilder},
ws_client::{PingConfig, WsClient, WsClientBuilder},
};

pub const MAX_FEE_PER_GAS: u128 = 1000000001;

pub struct BridgeBackendClient {
http_client: HttpClient,
ws_client: WsClient,
pub rpc_addr: SocketAddr,
}

impl BridgeBackendClient {
pub async fn new(rpc_addr: SocketAddr) -> anyhow::Result<Self> {
let http_host = format!("http://localhost:{}", rpc_addr.port());
let ws_host = format!("ws://localhost:{}", rpc_addr.port());

let http_client = HttpClientBuilder::default()
.request_timeout(Duration::from_secs(120))
.build(http_host)?;

let ws_client = WsClientBuilder::default()
.enable_ws_ping(PingConfig::default().inactive_limit(Duration::from_secs(10)))
.build(ws_host)
.await?;

Ok(Self {
ws_client,
http_client,
rpc_addr,
})
}
}
9 changes: 9 additions & 0 deletions src/config/bridge_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ pub struct BridgeBackendConfig {
pub operator_urls: String,
pub verifier_urls: String,
pub aggregator_url: String,

// Non bridge backend.
pub docker_image: Option<String>,
pub env: Vec<(&'static str, &'static str)>,
pub idx: usize,
}

impl Default for BridgeBackendConfig {
Expand Down Expand Up @@ -79,6 +84,10 @@ impl Default for BridgeBackendConfig {
operator_urls: "http://localhost:17007,http://localhost:17008,http://localhost:17009".to_string(),
verifier_urls: "http://localhost:17000,http://localhost:17001,http://localhost:17002,http://localhost:17003,http://localhost:17004,http://localhost:17005,http://localhost:17006".to_string(),
aggregator_url: "http://localhost:17010".to_string(),

docker_image: None,
env: Vec::new(),
idx: 0,
}
}
}
Expand Down
20 changes: 19 additions & 1 deletion src/config/docker.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;

use super::{BitcoinConfig, FullSequencerConfig};
use super::{BitcoinConfig, BridgeBackendConfig, FullSequencerConfig};
use crate::utils::get_genesis_path;

#[derive(Debug)]
Expand Down Expand Up @@ -45,6 +45,24 @@ impl From<&BitcoinConfig> for DockerConfig {
}
}

impl From<&BridgeBackendConfig> for DockerConfig {
fn from(v: &BridgeBackendConfig) -> Self {
Self {
ports: vec![v.port.try_into().unwrap()],
image: v
.docker_image
.clone()
.unwrap_or_else(|| "bitcoin/bitcoin:latest".to_string()),
cmd: vec![],
log_path: PathBuf::new(),
volume: VolumeConfig {
name: format!("bridge-backend-{}", v.idx),
target: "/home/bridge_backend/.bridge_backend".to_string(),
},
}
}
}

impl From<&FullSequencerConfig> for DockerConfig {
fn from(v: &FullSequencerConfig) -> Self {
let args = vec![
Expand Down
2 changes: 1 addition & 1 deletion src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ mod utils;
use std::path::PathBuf;

pub use bitcoin::BitcoinConfig;
pub use bridge_backend::BridgeBackendConfig;
pub use bitcoin_da::service::BitcoinServiceConfig;
pub use bridge_backend::BridgeBackendConfig;
pub use citrea_sequencer::SequencerConfig;
pub use docker::DockerConfig;
pub use rollup::{default_rollup_config, RollupConfig};
Expand Down
6 changes: 3 additions & 3 deletions src/config/test.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use super::{
bitcoin::BitcoinConfig, test_case::TestCaseConfig, FullFullNodeConfig, FullProverConfig,
FullSequencerConfig, BridgeBackendConfig
bitcoin::BitcoinConfig, test_case::TestCaseConfig, BridgeBackendConfig, FullFullNodeConfig,
FullProverConfig, FullSequencerConfig,
};

#[derive(Clone)]
pub struct TestConfig {
pub test_case: TestCaseConfig,
pub bitcoin: Vec<BitcoinConfig>,
pub bridge_backend: BridgeBackendConfig,
pub bridge_backend: Vec<BridgeBackendConfig>,
pub sequencer: FullSequencerConfig,
pub prover: FullProverConfig,
pub full_node: FullFullNodeConfig,
Expand Down
2 changes: 1 addition & 1 deletion src/docker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl DockerEnv {
test_case_id: &str,
n_nodes: usize,
) -> Result<HashSet<String>> {
let volume_configs = vec![("bitcoin", n_nodes)];
let volume_configs = vec![("bitcoin", n_nodes), ("bridge-backend", n_nodes)];
let mut volumes = HashSet::new();

for (name, n) in volume_configs {
Expand Down
5 changes: 4 additions & 1 deletion src/framework.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::{
traits::{LogProvider, LogProviderErased, Node},
Result,
};
use crate::{prover::Prover, utils::tail_file};
use crate::{bridge_backend::BridgeBackendNodeCluster, prover::Prover, utils::tail_file};

pub struct TestContext {
pub config: TestConfig,
Expand All @@ -36,6 +36,7 @@ impl TestContext {
pub struct TestFramework {
ctx: TestContext,
pub bitcoin_nodes: BitcoinNodeCluster,
pub bridge_backend_nodes: BridgeBackendNodeCluster,
pub sequencer: Option<Sequencer>,
pub prover: Option<Prover>,
pub full_node: Option<FullNode>,
Expand All @@ -61,10 +62,12 @@ impl TestFramework {
let ctx = TestContext::new(config).await;

let bitcoin_nodes = BitcoinNodeCluster::new(&ctx).await?;
let bridge_backend_nodes = BridgeBackendNodeCluster::new(&ctx).await?;

// tokio::time::sleep(std::time::Duration::from_secs(30)).await;
Ok(Self {
bitcoin_nodes,
bridge_backend_nodes,
sequencer: None,
prover: None,
full_node: None,
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod bitcoin;
mod bridge_backend;
pub mod bridge_backend_client;
pub mod client;
pub mod config;
mod docker;
Expand Down
Loading

0 comments on commit e4c488a

Please sign in to comment.