Skip to content

Commit e4c488a

Browse files
committed
bridge_backend: Add initial client.
1 parent a2830c7 commit e4c488a

File tree

10 files changed

+139
-60
lines changed

10 files changed

+139
-60
lines changed

src/bridge_backend.rs

Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,40 @@
1+
use std::net::SocketAddr;
12
use std::path::PathBuf;
3+
use std::str::FromStr;
24
use std::sync::Arc;
35
use std::time::{Duration, Instant};
46

57
use anyhow::{bail, Context};
8+
use async_trait::async_trait;
69
use futures::TryStreamExt;
710
use tokio::process::Command;
11+
use tokio::time::sleep;
812

913
use super::config::BridgeBackendConfig;
1014
use super::docker::DockerEnv;
1115
use super::framework::TestContext;
12-
use super::node::{LogProvider, Node, Restart, SpawnOutput};
1316
use super::Result;
17+
use crate::bridge_backend_client::BridgeBackendClient;
1418
use crate::node::NodeKind;
15-
use crate::test_client::TestClient;
19+
use crate::traits::{ContainerSpawnOutput, LogProvider, Node, Restart, SpawnOutput};
1620

1721
pub struct BridgeBackendNode {
1822
spawn_output: SpawnOutput,
1923
pub config: BridgeBackendConfig,
2024
docker_env: Arc<Option<DockerEnv>>,
25+
client: BridgeBackendClient,
2126
}
2227

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

2733
Ok(Self {
2834
spawn_output,
2935
config: config.clone(),
3036
docker_env: docker,
37+
client: BridgeBackendClient::new(rpc_url).await?,
3138
})
3239
}
3340

@@ -41,11 +48,38 @@ impl BridgeBackendNode {
4148
None => <Self as Node>::spawn(config),
4249
}
4350
}
51+
52+
async fn wait_for_shutdown(&self) -> Result<()> {
53+
let timeout_duration = Duration::from_secs(30);
54+
let start = std::time::Instant::now();
55+
56+
while start.elapsed() < timeout_duration {
57+
if !self.is_process_running().await? {
58+
println!("Bridge backend has stopped successfully");
59+
return Ok(());
60+
}
61+
sleep(Duration::from_millis(200)).await;
62+
}
63+
64+
bail!("Timeout waiting for bridge backend to stop")
65+
}
66+
67+
async fn is_process_running(&self) -> Result<bool> {
68+
// let data_dir = &self.config.data_dir;
69+
// let output = Command::new("pgrep")
70+
// .args(["-f", &format!("bitcoind.*{}", data_dir.display())])
71+
// .output()
72+
// .await?;
73+
74+
// Ok(output.status.success())
75+
todo!()
76+
}
4477
}
4578

79+
#[async_trait]
4680
impl Node for BridgeBackendNode {
4781
type Config = BridgeBackendConfig;
48-
type Client = TestClient;
82+
type Client = BridgeBackendClient;
4983

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

90-
fn client(&self) -> &Self::Client {
91-
&self.client()
92-
}
93-
94124
fn config_mut(&mut self) -> &mut Self::Config {
95125
&mut self.config
96126
}
@@ -104,7 +134,7 @@ impl Node for BridgeBackendNode {
104134
.context("Failed to kill child process")?;
105135
Ok(())
106136
}
107-
SpawnOutput::Container(crate::node::ContainerSpawnOutput { id, .. }) => {
137+
SpawnOutput::Container(ContainerSpawnOutput { id, .. }) => {
108138
std::println!("Stopping container {id}");
109139
let docker = bollard::Docker::connect_with_local_defaults()
110140
.context("Failed to connect to Docker")?;
@@ -116,11 +146,21 @@ impl Node for BridgeBackendNode {
116146
}
117147
}
118148
}
149+
150+
fn client(&self) -> &Self::Client {
151+
&self.client
152+
}
153+
154+
fn env(&self) -> Vec<(&'static str, &'static str)> {
155+
// self.config.get_env()
156+
todo!()
157+
}
119158
}
120159

160+
#[async_trait]
121161
impl Restart for BridgeBackendNode {
122162
async fn wait_until_stopped(&mut self) -> Result<()> {
123-
self.client.stop().await?;
163+
// self.client.stop().await?;
124164
self.stop().await?;
125165

126166
match &self.spawn_output {
@@ -150,9 +190,6 @@ impl Restart for BridgeBackendNode {
150190

151191
self.wait_for_ready(None).await?;
152192

153-
// Reload wallets after restart
154-
self.load_wallets().await;
155-
156193
Ok(())
157194
}
158195
}
@@ -163,21 +200,21 @@ impl LogProvider for BridgeBackendNode {
163200
}
164201

165202
fn log_path(&self) -> PathBuf {
166-
self.config.data_dir.join("regtest").join("debug.log")
203+
todo!()
167204
}
168205
}
169206

170-
pub struct BitcoinNodeCluster {
207+
pub struct BridgeBackendNodeCluster {
171208
inner: Vec<BridgeBackendNode>,
172209
}
173210

174-
impl BitcoinNodeCluster {
211+
impl BridgeBackendNodeCluster {
175212
pub async fn new(ctx: &TestContext) -> Result<Self> {
176213
let n_nodes = ctx.config.test_case.n_nodes;
177214
let mut cluster = Self {
178215
inner: Vec::with_capacity(n_nodes),
179216
};
180-
for config in ctx.config.bitcoin.iter() {
217+
for config in ctx.config.bridge_backend.iter() {
181218
let node = BridgeBackendNode::new(config, Arc::clone(&ctx.docker)).await?;
182219
cluster.inner.push(node)
183220
}
@@ -193,42 +230,6 @@ impl BitcoinNodeCluster {
193230
Ok(())
194231
}
195232

196-
pub async fn wait_for_sync(&self, timeout: Duration) -> Result<()> {
197-
let start = Instant::now();
198-
while start.elapsed() < timeout {
199-
// let mut heights = HashSet::new();
200-
// for node in &self.inner {
201-
// let height = node.get_block_count().await?;
202-
// heights.insert(height);
203-
// }
204-
205-
// if heights.len() == 1 {
206-
return Ok(());
207-
// }
208-
209-
// sleep(Duration::from_secs(1)).await;
210-
}
211-
bail!("Nodes failed to sync within the specified timeout")
212-
}
213-
214-
// Connect all bitcoin nodes between them
215-
pub async fn connect_nodes(&self) -> Result<()> {
216-
for (i, from_node) in self.inner.iter().enumerate() {
217-
for (j, to_node) in self.inner.iter().enumerate() {
218-
if i != j {
219-
let ip = match &to_node.spawn_output {
220-
SpawnOutput::Container(container) => container.ip.clone(),
221-
_ => "127.0.0.1".to_string(),
222-
};
223-
224-
let add_node_arg = format!("{}:{}", ip, to_node.config.p2p_port);
225-
from_node.add_node(&add_node_arg).await?;
226-
}
227-
}
228-
}
229-
Ok(())
230-
}
231-
232233
pub fn get(&self, index: usize) -> Option<&BridgeBackendNode> {
233234
self.inner.get(index)
234235
}

src/bridge_backend_client.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use std::{net::SocketAddr, time::Duration};
2+
3+
use jsonrpsee::{
4+
http_client::{HttpClient, HttpClientBuilder},
5+
ws_client::{PingConfig, WsClient, WsClientBuilder},
6+
};
7+
8+
pub const MAX_FEE_PER_GAS: u128 = 1000000001;
9+
10+
pub struct BridgeBackendClient {
11+
http_client: HttpClient,
12+
ws_client: WsClient,
13+
pub rpc_addr: SocketAddr,
14+
}
15+
16+
impl BridgeBackendClient {
17+
pub async fn new(rpc_addr: SocketAddr) -> anyhow::Result<Self> {
18+
let http_host = format!("http://localhost:{}", rpc_addr.port());
19+
let ws_host = format!("ws://localhost:{}", rpc_addr.port());
20+
21+
let http_client = HttpClientBuilder::default()
22+
.request_timeout(Duration::from_secs(120))
23+
.build(http_host)?;
24+
25+
let ws_client = WsClientBuilder::default()
26+
.enable_ws_ping(PingConfig::default().inactive_limit(Duration::from_secs(10)))
27+
.build(ws_host)
28+
.await?;
29+
30+
Ok(Self {
31+
ws_client,
32+
http_client,
33+
rpc_addr,
34+
})
35+
}
36+
}

src/config/bridge_backend.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ pub struct BridgeBackendConfig {
4242
pub operator_urls: String,
4343
pub verifier_urls: String,
4444
pub aggregator_url: String,
45+
46+
// Non bridge backend.
47+
pub docker_image: Option<String>,
48+
pub env: Vec<(&'static str, &'static str)>,
49+
pub idx: usize,
4550
}
4651

4752
impl Default for BridgeBackendConfig {
@@ -79,6 +84,10 @@ impl Default for BridgeBackendConfig {
7984
operator_urls: "http://localhost:17007,http://localhost:17008,http://localhost:17009".to_string(),
8085
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(),
8186
aggregator_url: "http://localhost:17010".to_string(),
87+
88+
docker_image: None,
89+
env: Vec::new(),
90+
idx: 0,
8291
}
8392
}
8493
}

src/config/docker.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::path::PathBuf;
22

3-
use super::{BitcoinConfig, FullSequencerConfig};
3+
use super::{BitcoinConfig, BridgeBackendConfig, FullSequencerConfig};
44
use crate::utils::get_genesis_path;
55

66
#[derive(Debug)]
@@ -45,6 +45,24 @@ impl From<&BitcoinConfig> for DockerConfig {
4545
}
4646
}
4747

48+
impl From<&BridgeBackendConfig> for DockerConfig {
49+
fn from(v: &BridgeBackendConfig) -> Self {
50+
Self {
51+
ports: vec![v.port.try_into().unwrap()],
52+
image: v
53+
.docker_image
54+
.clone()
55+
.unwrap_or_else(|| "bitcoin/bitcoin:latest".to_string()),
56+
cmd: vec![],
57+
log_path: PathBuf::new(),
58+
volume: VolumeConfig {
59+
name: format!("bridge-backend-{}", v.idx),
60+
target: "/home/bridge_backend/.bridge_backend".to_string(),
61+
},
62+
}
63+
}
64+
}
65+
4866
impl From<&FullSequencerConfig> for DockerConfig {
4967
fn from(v: &FullSequencerConfig) -> Self {
5068
let args = vec![

src/config/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ mod utils;
99
use std::path::PathBuf;
1010

1111
pub use bitcoin::BitcoinConfig;
12-
pub use bridge_backend::BridgeBackendConfig;
1312
pub use bitcoin_da::service::BitcoinServiceConfig;
13+
pub use bridge_backend::BridgeBackendConfig;
1414
pub use citrea_sequencer::SequencerConfig;
1515
pub use docker::DockerConfig;
1616
pub use rollup::{default_rollup_config, RollupConfig};

src/config/test.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use super::{
2-
bitcoin::BitcoinConfig, test_case::TestCaseConfig, FullFullNodeConfig, FullProverConfig,
3-
FullSequencerConfig, BridgeBackendConfig
2+
bitcoin::BitcoinConfig, test_case::TestCaseConfig, BridgeBackendConfig, FullFullNodeConfig,
3+
FullProverConfig, FullSequencerConfig,
44
};
55

66
#[derive(Clone)]
77
pub struct TestConfig {
88
pub test_case: TestCaseConfig,
99
pub bitcoin: Vec<BitcoinConfig>,
10-
pub bridge_backend: BridgeBackendConfig,
10+
pub bridge_backend: Vec<BridgeBackendConfig>,
1111
pub sequencer: FullSequencerConfig,
1212
pub prover: FullProverConfig,
1313
pub full_node: FullFullNodeConfig,

src/docker.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl DockerEnv {
5151
test_case_id: &str,
5252
n_nodes: usize,
5353
) -> Result<HashSet<String>> {
54-
let volume_configs = vec![("bitcoin", n_nodes)];
54+
let volume_configs = vec![("bitcoin", n_nodes), ("bridge-backend", n_nodes)];
5555
let mut volumes = HashSet::new();
5656

5757
for (name, n) in volume_configs {

src/framework.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use super::{
1212
traits::{LogProvider, LogProviderErased, Node},
1313
Result,
1414
};
15-
use crate::{prover::Prover, utils::tail_file};
15+
use crate::{bridge_backend::BridgeBackendNodeCluster, prover::Prover, utils::tail_file};
1616

1717
pub struct TestContext {
1818
pub config: TestConfig,
@@ -36,6 +36,7 @@ impl TestContext {
3636
pub struct TestFramework {
3737
ctx: TestContext,
3838
pub bitcoin_nodes: BitcoinNodeCluster,
39+
pub bridge_backend_nodes: BridgeBackendNodeCluster,
3940
pub sequencer: Option<Sequencer>,
4041
pub prover: Option<Prover>,
4142
pub full_node: Option<FullNode>,
@@ -61,10 +62,12 @@ impl TestFramework {
6162
let ctx = TestContext::new(config).await;
6263

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

6567
// tokio::time::sleep(std::time::Duration::from_secs(30)).await;
6668
Ok(Self {
6769
bitcoin_nodes,
70+
bridge_backend_nodes,
6871
sequencer: None,
6972
prover: None,
7073
full_node: None,

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod bitcoin;
22
mod bridge_backend;
3+
pub mod bridge_backend_client;
34
pub mod client;
45
pub mod config;
56
mod docker;

0 commit comments

Comments
 (0)