Skip to content

Commit 2646828

Browse files
authored
Merge pull request #72 from Blobscan/refactor/reorgs-handling
refactor: refactor chain reorgs handling
2 parents 5e51c75 + 36577be commit 2646828

File tree

16 files changed

+1163
-298
lines changed

16 files changed

+1163
-298
lines changed

Cargo.lock

+81-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

88
[dependencies]
9-
async-trait = "0.1.66"
9+
async-trait = "0.1.80"
10+
dyn-clone = "1.0.17"
1011
dotenv = "0.15.0"
1112
envy = "0.4.2"
1213
ethers = "1.0.2"
@@ -34,3 +35,6 @@ anyhow = { version = "1.0.70", features = ["backtrace"] }
3435
thiserror = "1.0.40"
3536
sentry = { version = "0.31.2", features = ["debug-images"] }
3637
sentry-tracing = "0.31.2"
38+
39+
[dev-dependencies]
40+
mockall = "0.12.1"

src/clients/beacon/errors.rs

Whitespace-only changes.

src/clients/beacon/mod.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1+
use std::fmt::Debug;
2+
13
use anyhow::Context as AnyhowContext;
4+
use async_trait::async_trait;
25
use backoff::ExponentialBackoff;
6+
37
use reqwest::{Client, Url};
48
use reqwest_eventsource::EventSource;
59

10+
#[cfg(test)]
11+
use mockall::automock;
12+
613
use crate::{
714
clients::{beacon::types::BlockHeaderResponse, common::ClientResult},
815
json_get,
@@ -24,6 +31,15 @@ pub struct Config {
2431
pub exp_backoff: Option<ExponentialBackoff>,
2532
}
2633

34+
#[async_trait]
35+
#[cfg_attr(test, automock)]
36+
pub trait CommonBeaconClient: Send + Sync + Debug {
37+
async fn get_block(&self, block_id: &BlockId) -> ClientResult<Option<Block>>;
38+
async fn get_block_header(&self, block_id: &BlockId) -> ClientResult<Option<BlockHeader>>;
39+
async fn get_blobs(&self, block_id: &BlockId) -> ClientResult<Option<Vec<Blob>>>;
40+
fn subscribe_to_events(&self, topics: &[Topic]) -> ClientResult<EventSource>;
41+
}
42+
2743
impl BeaconClient {
2844
pub fn try_with_client(client: Client, config: Config) -> ClientResult<Self> {
2945
let base_url = Url::parse(&format!("{}/eth/", config.base_url))
@@ -36,8 +52,11 @@ impl BeaconClient {
3652
exp_backoff,
3753
})
3854
}
55+
}
3956

40-
pub async fn get_block(&self, block_id: &BlockId) -> ClientResult<Option<Block>> {
57+
#[async_trait]
58+
impl CommonBeaconClient for BeaconClient {
59+
async fn get_block(&self, block_id: &BlockId) -> ClientResult<Option<Block>> {
4160
let path = format!("v2/beacon/blocks/{}", { block_id.to_detailed_string() });
4261
let url = self.base_url.join(path.as_str())?;
4362

@@ -47,7 +66,7 @@ impl BeaconClient {
4766
})
4867
}
4968

50-
pub async fn get_block_header(&self, block_id: &BlockId) -> ClientResult<Option<BlockHeader>> {
69+
async fn get_block_header(&self, block_id: &BlockId) -> ClientResult<Option<BlockHeader>> {
5170
let path = format!("v1/beacon/headers/{}", { block_id.to_detailed_string() });
5271
let url = self.base_url.join(path.as_str())?;
5372

@@ -63,7 +82,7 @@ impl BeaconClient {
6382
})
6483
}
6584

66-
pub async fn get_blobs(&self, block_id: &BlockId) -> ClientResult<Option<Vec<Blob>>> {
85+
async fn get_blobs(&self, block_id: &BlockId) -> ClientResult<Option<Vec<Blob>>> {
6786
let path = format!("v1/beacon/blob_sidecars/{}", {
6887
block_id.to_detailed_string()
6988
});
@@ -75,7 +94,7 @@ impl BeaconClient {
7594
})
7695
}
7796

78-
pub fn subscribe_to_events(&self, topics: &[Topic]) -> ClientResult<EventSource> {
97+
fn subscribe_to_events(&self, topics: &[Topic]) -> ClientResult<EventSource> {
7998
let topics = topics
8099
.iter()
81100
.map(|topic| topic.into())

src/clients/beacon/types.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::{fmt, str::FromStr};
33
use ethers::types::{Bytes, H256};
44
use serde::{Deserialize, Serialize};
55

6-
#[derive(Serialize, Debug, Clone)]
6+
#[derive(Serialize, Debug, Clone, PartialEq)]
77
pub enum BlockId {
88
Head,
99
Finalized,
@@ -16,7 +16,6 @@ pub enum BlockId {
1616
pub enum Topic {
1717
Head,
1818
FinalizedCheckpoint,
19-
ChainReorg,
2019
}
2120

2221
#[derive(Deserialize, Debug)]
@@ -80,15 +79,6 @@ pub struct BlockHeaderMessage {
8079
pub slot: u32,
8180
}
8281

83-
#[derive(Deserialize, Debug)]
84-
pub struct ChainReorgEventData {
85-
pub old_head_block: H256,
86-
#[serde(deserialize_with = "deserialize_number")]
87-
pub slot: u32,
88-
#[serde(deserialize_with = "deserialize_number")]
89-
pub depth: u32,
90-
}
91-
9282
#[derive(Deserialize, Debug)]
9383
pub struct HeadEventData {
9484
#[serde(deserialize_with = "deserialize_number")]
@@ -161,7 +151,6 @@ impl FromStr for BlockId {
161151
impl From<&Topic> for String {
162152
fn from(value: &Topic) -> Self {
163153
match value {
164-
Topic::ChainReorg => String::from("chain_reorg"),
165154
Topic::Head => String::from("head"),
166155
Topic::FinalizedCheckpoint => String::from("finalized_checkpoint"),
167156
}

src/clients/blobscan/mod.rs

+32-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
use std::fmt::Debug;
2+
3+
use async_trait::async_trait;
14
use backoff::ExponentialBackoff;
25
use chrono::TimeDelta;
36
use reqwest::{Client, Url};
47

8+
#[cfg(test)]
9+
use mockall::automock;
10+
511
use crate::{
612
clients::{blobscan::types::ReorgedSlotsResponse, common::ClientResult},
713
json_get, json_put,
@@ -18,6 +24,24 @@ use self::{
1824
mod jwt_manager;
1925

2026
pub mod types;
27+
28+
#[async_trait]
29+
#[cfg_attr(test, automock)]
30+
pub trait CommonBlobscanClient: Send + Sync + Debug {
31+
fn try_with_client(client: Client, config: Config) -> ClientResult<Self>
32+
where
33+
Self: Sized;
34+
async fn index(
35+
&self,
36+
block: Block,
37+
transactions: Vec<Transaction>,
38+
blobs: Vec<Blob>,
39+
) -> ClientResult<()>;
40+
async fn handle_reorged_slots(&self, slots: &[u32]) -> ClientResult<u32>;
41+
async fn update_sync_state(&self, sync_state: BlockchainSyncState) -> ClientResult<()>;
42+
async fn get_sync_state(&self) -> ClientResult<Option<BlockchainSyncState>>;
43+
}
44+
2145
#[derive(Debug, Clone)]
2246
pub struct BlobscanClient {
2347
base_url: Url,
@@ -32,8 +56,10 @@ pub struct Config {
3256
pub exp_backoff: Option<ExponentialBackoff>,
3357
}
3458

35-
impl BlobscanClient {
36-
pub fn try_with_client(client: Client, config: Config) -> ClientResult<Self> {
59+
#[async_trait]
60+
61+
impl CommonBlobscanClient for BlobscanClient {
62+
fn try_with_client(client: Client, config: Config) -> ClientResult<Self> {
3763
let base_url = Url::parse(&format!("{}/", config.base_url))?;
3864
let jwt_manager = JWTManager::new(JWTManagerConfig {
3965
secret_key: config.secret_key,
@@ -50,7 +76,7 @@ impl BlobscanClient {
5076
})
5177
}
5278

53-
pub async fn index(
79+
async fn index(
5480
&self,
5581
block: Block,
5682
transactions: Vec<Transaction>,
@@ -67,7 +93,7 @@ impl BlobscanClient {
6793
json_put!(&self.client, url, token, &req).map(|_: Option<()>| ())
6894
}
6995

70-
pub async fn handle_reorged_slots(&self, slots: &[u32]) -> ClientResult<u32> {
96+
async fn handle_reorged_slots(&self, slots: &[u32]) -> ClientResult<u32> {
7197
let url = self.base_url.join("indexer/reorged-slots")?;
7298
let token = self.jwt_manager.get_token()?;
7399
let req = ReorgedSlotsRequest {
@@ -78,15 +104,15 @@ impl BlobscanClient {
78104
.map(|res: Option<ReorgedSlotsResponse>| res.unwrap().total_updated_slots)
79105
}
80106

81-
pub async fn update_sync_state(&self, sync_state: BlockchainSyncState) -> ClientResult<()> {
107+
async fn update_sync_state(&self, sync_state: BlockchainSyncState) -> ClientResult<()> {
82108
let url = self.base_url.join("blockchain-sync-state")?;
83109
let token = self.jwt_manager.get_token()?;
84110
let req: BlockchainSyncStateRequest = sync_state.into();
85111

86112
json_put!(&self.client, url, token, &req).map(|_: Option<()>| ())
87113
}
88114

89-
pub async fn get_sync_state(&self) -> ClientResult<Option<BlockchainSyncState>> {
115+
async fn get_sync_state(&self) -> ClientResult<Option<BlockchainSyncState>> {
90116
let url = self.base_url.join("blockchain-sync-state")?;
91117
json_get!(
92118
&self.client,

src/clients/blobscan/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub struct BlockchainSyncStateResponse {
7171
pub last_upper_synced_slot: Option<u32>,
7272
}
7373

74-
#[derive(Debug)]
74+
#[derive(Debug, PartialEq)]
7575
pub struct BlockchainSyncState {
7676
pub last_finalized_block: Option<u32>,
7777
pub last_lower_synced_slot: Option<u32>,

0 commit comments

Comments
 (0)