Skip to content

Commit f700c46

Browse files
authored
Merge pull request #1623 from input-output-hk/jpraynaud/1589-chain-observer-chain-point
Chain observer retrieves the current Chain Point
2 parents f3f401c + 3716318 commit f700c46

File tree

16 files changed

+179
-20
lines changed

16 files changed

+179
-20
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ As a minor extension, we have adopted a slightly different versioning convention
1515

1616
- Support incremental import for Cardano Transactions instead of scanning the whole immutable database for every signing round.
1717

18+
- Chain observers support the retrieval of the current Cardano chain point.
19+
1820
- Crates versions:
1921

2022
| Crate | Version |

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mithril-aggregator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.4.54"
3+
version = "0.4.55"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-aggregator/src/tools/mocks.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use async_trait::async_trait;
22
use mithril_common::chain_observer::{ChainAddress, ChainObserver, ChainObserverError, TxDatum};
33
use mithril_common::crypto_helper::{KESPeriod, OpCert};
4-
use mithril_common::entities::{Epoch, StakeDistribution};
4+
use mithril_common::entities::{ChainPoint, Epoch, StakeDistribution};
55
use mockall::mock;
66

77
mock! {
@@ -16,6 +16,8 @@ mock! {
1616

1717
async fn get_current_epoch(&self) -> Result<Option<Epoch>, ChainObserverError>;
1818

19+
async fn get_current_chain_point(&self) -> Result<Option<ChainPoint>, ChainObserverError>;
20+
1921
async fn get_current_stake_distribution(
2022
&self,
2123
) -> Result<Option<StakeDistribution>, ChainObserverError>;

mithril-common/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-common"
3-
version = "0.3.28"
3+
version = "0.3.29"
44
description = "Common types, interfaces, and utilities for Mithril nodes."
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-common/src/chain_observer/cli_observer.rs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use tokio::process::Command;
1212
use crate::chain_observer::interface::{ChainObserver, ChainObserverError};
1313
use crate::chain_observer::{ChainAddress, TxDatum};
1414
use crate::crypto_helper::{encode_bech32, KESPeriod, OpCert, SerDeShelleyFileFormat};
15-
use crate::entities::{Epoch, StakeDistribution};
15+
use crate::entities::{ChainPoint, Epoch, StakeDistribution};
1616
use crate::{CardanoNetwork, StdResult};
1717

1818
/// `CliRunner` trait defines the asynchronous methods
@@ -29,6 +29,8 @@ pub trait CliRunner {
2929
async fn launch_stake_snapshot_all_pools(&self) -> StdResult<String>;
3030
/// Launches the epoch info.
3131
async fn launch_epoch(&self) -> StdResult<String>;
32+
/// Launches the chain point.
33+
async fn launch_chain_point(&self) -> StdResult<String>;
3234
/// Launches the kes period.
3335
async fn launch_kes_period(&self, opcert_file: &str) -> StdResult<String>;
3436
}
@@ -114,6 +116,14 @@ impl CardanoCliRunner {
114116
command
115117
}
116118

119+
fn command_for_chain_point(&self) -> Command {
120+
let mut command = self.get_command();
121+
command.arg("query").arg("tip");
122+
self.post_config_command(&mut command);
123+
124+
command
125+
}
126+
117127
fn command_for_kes_period(&self, opcert_file: &str) -> Command {
118128
let mut command = self.get_command();
119129
command
@@ -240,6 +250,22 @@ impl CliRunner for CardanoCliRunner {
240250
}
241251
}
242252

253+
async fn launch_chain_point(&self) -> StdResult<String> {
254+
let output = self.command_for_chain_point().output().await?;
255+
256+
if output.status.success() {
257+
Ok(std::str::from_utf8(&output.stdout)?.trim().to_string())
258+
} else {
259+
let message = String::from_utf8_lossy(&output.stderr);
260+
261+
Err(anyhow!(
262+
"Error launching command {:?}, error = '{}'",
263+
self.command_for_chain_point(),
264+
message
265+
))
266+
}
267+
}
268+
243269
async fn launch_kes_period(&self, opcert_file: &str) -> StdResult<String> {
244270
let output = self.command_for_kes_period(opcert_file).output().await?;
245271

@@ -407,6 +433,27 @@ impl ChainObserver for CardanoCliChainObserver {
407433
}
408434
}
409435

436+
async fn get_current_chain_point(&self) -> Result<Option<ChainPoint>, ChainObserverError> {
437+
let output = self
438+
.cli_runner
439+
.launch_chain_point()
440+
.await
441+
.map_err(ChainObserverError::General)?;
442+
let v: Value = serde_json::from_str(&output)
443+
.with_context(|| format!("output was = '{output}'"))
444+
.map_err(ChainObserverError::InvalidContent)?;
445+
446+
if let Value::String(hash) = &v["hash"] {
447+
Ok(Some(ChainPoint {
448+
slot_number: v["slot"].as_u64().unwrap_or_default(),
449+
block_number: v["block"].as_u64().unwrap_or_default(),
450+
block_hash: hash.to_string(),
451+
}))
452+
} else {
453+
Ok(None)
454+
}
455+
}
456+
410457
async fn get_current_datums(
411458
&self,
412459
address: &ChainAddress,
@@ -485,6 +532,22 @@ mod tests {
485532
assert_eq!(Epoch(120), epoch);
486533
}
487534

535+
#[tokio::test]
536+
async fn test_get_current_chain_point() {
537+
let observer = CardanoCliChainObserver::new(Box::<TestCliRunner>::default());
538+
let chain_point = observer.get_current_chain_point().await.unwrap().unwrap();
539+
540+
assert_eq!(
541+
ChainPoint {
542+
slot_number: 25886617,
543+
block_number: 1270276,
544+
block_hash: "7383b17d7b05b0953cf0649abff60173995eb9febe556889333e20e1e5b7ca84"
545+
.to_string(),
546+
},
547+
chain_point
548+
);
549+
}
550+
488551
#[tokio::test]
489552
async fn test_cli_testnet_runner() {
490553
let runner = CardanoCliRunner::new(

mithril-common/src/chain_observer/fake_observer.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub struct FakeObserver {
1818
/// [get_current_epoch]: ChainObserver::get_current_epoch
1919
pub current_time_point: RwLock<Option<TimePoint>>,
2020

21+
/// The current chain point
22+
pub current_chain_point: RwLock<Option<ChainPoint>>,
23+
2124
/// A list of [TxDatum], used by [get_current_datums]
2225
///
2326
/// [get_current_datums]: ChainObserver::get_current_datums
@@ -30,6 +33,7 @@ impl FakeObserver {
3033
Self {
3134
signers: RwLock::new(vec![]),
3235
current_time_point: RwLock::new(current_time_point),
36+
current_chain_point: RwLock::new(None),
3337
datums: RwLock::new(vec![]),
3438
}
3539
}
@@ -52,6 +56,13 @@ impl FakeObserver {
5256
*signers = new_signers;
5357
}
5458

59+
/// Set the chain point that will use to compute the result of
60+
/// [get_current_chain_point][ChainObserver::get_current_chain_point].
61+
pub async fn set_current_chain_point(&self, new_current_chain_point: Option<ChainPoint>) {
62+
let mut current_chain_point = self.current_chain_point.write().await;
63+
*current_chain_point = new_current_chain_point;
64+
}
65+
5566
/// Set the datums that will use to compute the result of
5667
/// [get_current_datums][ChainObserver::get_current_datums].
5768
pub async fn set_datums(&self, new_datums: Vec<TxDatum>) {
@@ -88,6 +99,10 @@ impl ChainObserver for FakeObserver {
8899
.map(|time_point| time_point.epoch))
89100
}
90101

102+
async fn get_current_chain_point(&self) -> Result<Option<ChainPoint>, ChainObserverError> {
103+
Ok(self.current_chain_point.read().await.clone())
104+
}
105+
91106
async fn get_current_stake_distribution(
92107
&self,
93108
) -> Result<Option<StakeDistribution>, ChainObserverError> {
@@ -124,6 +139,21 @@ mod tests {
124139
assert_eq!(Some(time_point.epoch), current_epoch);
125140
}
126141

142+
#[tokio::test]
143+
async fn test_get_current_chain_point() {
144+
let fake_observer = FakeObserver::new(None);
145+
fake_observer
146+
.set_current_chain_point(Some(fake_data::chain_point()))
147+
.await;
148+
let chain_point = fake_observer.get_current_chain_point().await.unwrap();
149+
150+
assert_eq!(
151+
Some(fake_data::chain_point()),
152+
chain_point,
153+
"get current chain point should not fail"
154+
);
155+
}
156+
127157
#[tokio::test]
128158
async fn test_get_current_stake_distribution() {
129159
let fake_observer = FakeObserver::new(None);

mithril-common/src/chain_observer/interface.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ pub trait ChainObserver: Sync + Send {
3636
/// Retrieve the current epoch of the Cardano network
3737
async fn get_current_epoch(&self) -> Result<Option<Epoch>, ChainObserverError>;
3838

39+
/// Retrieve the current chain point of the Cardano network
40+
async fn get_current_chain_point(&self) -> Result<Option<ChainPoint>, ChainObserverError>;
41+
3942
/// Retrieve the current stake distribution of the Cardano network
4043
async fn get_current_stake_distribution(
4144
&self,

mithril-common/src/chain_observer/pallas_observer.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use std::{
2525
use crate::{
2626
chain_observer::{interface::*, ChainAddress, TxDatum},
2727
crypto_helper::{encode_bech32, KESPeriod, OpCert},
28-
entities::{Epoch, StakeDistribution},
28+
entities::{ChainPoint, Epoch, StakeDistribution},
2929
CardanoNetwork, StdResult,
3030
};
3131

@@ -384,6 +384,11 @@ impl ChainObserver for PallasChainObserver {
384384
Ok(Some(Epoch(epoch as u64)))
385385
}
386386

387+
async fn get_current_chain_point(&self) -> Result<Option<ChainPoint>, ChainObserverError> {
388+
// TODO: Implement get_current_chain_point with pallas
389+
todo!("Implement get_current_chain_point")
390+
}
391+
387392
async fn get_current_datums(
388393
&self,
389394
address: &ChainAddress,

mithril-common/src/chain_observer/test_cli_runner.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,23 @@ pool1qz2vzszautc2c8mljnqre2857dpmheq7kgt6vav0s38tvvhxm6w 1.051e-6
169169
Ok(output.to_string())
170170
}
171171

172+
/// launches the chain point info.
173+
async fn launch_chain_point(&self) -> StdResult<String> {
174+
let output = r#"
175+
{
176+
"block": 1270276,
177+
"epoch": 299,
178+
"era": "Conway",
179+
"hash": "7383b17d7b05b0953cf0649abff60173995eb9febe556889333e20e1e5b7ca84",
180+
"slot": 25886617,
181+
"slotInEpoch": 53017,
182+
"slotsToEpochEnd": 33383,
183+
"syncProgress": "100.00"
184+
}"#;
185+
186+
Ok(output.to_string())
187+
}
188+
172189
/// launches the kes period.
173190
async fn launch_kes_period(&self, _opcert_file: &str) -> StdResult<String> {
174191
let output = r#"

0 commit comments

Comments
 (0)