Skip to content
Snippets Groups Projects
Commit 61d83356 authored by Hugo Trentesaux's avatar Hugo Trentesaux
Browse files

add genesis hash and current block checks

parent 6b9bf55a
No related branches found
No related tags found
No related merge requests found
...@@ -26,6 +26,8 @@ with derivations: ...@@ -26,6 +26,8 @@ with derivations:
## Commands ## Commands
```sh ```sh
# get duniter current block
gcli current-block
# get balance of test1 account # get balance of test1 account
gcli --address 5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa get-balance gcli --address 5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa get-balance
# get information about test1 identity (needs indexer) # get information about test1 identity (needs indexer)
...@@ -36,7 +38,14 @@ gcli --secret "pipe paddle ketchup filter life ice feel embody glide quantum rid ...@@ -36,7 +38,14 @@ gcli --secret "pipe paddle ketchup filter life ice feel embody glide quantum rid
## Indexer commands ## Indexer commands
These commands uniquely relate with indexer You can check first that indexer is on the same network as Duniter node:
```sh
# check if indexer is on the same chain as duniter
gcli check-indexer-against-blockchain
```
The following commands uniquely relate with indexer.
```sh ```sh
# show latest indexer indexed block # show latest indexer indexed block
......
...@@ -15,3 +15,9 @@ query LatestBlock { ...@@ -15,3 +15,9 @@ query LatestBlock {
value value
} }
} }
query GenesisHash {
block(where: {number: {_eq: 0}}) {
hash
}
}
use crate::*; use crate::*;
use indexer::Indexer;
// data derived from command arguments // data derived from command arguments
...@@ -24,6 +25,8 @@ pub struct Data { ...@@ -24,6 +25,8 @@ pub struct Data {
pub token_symbol: String, pub token_symbol: String,
// genesis hash // genesis hash
pub genesis_hash: Hash, pub genesis_hash: Hash,
// indexer genesis hash
pub indexer_genesis_hash: Hash,
} }
/// system properties defined in client specs /// system properties defined in client specs
...@@ -146,6 +149,11 @@ impl Data { ...@@ -146,6 +149,11 @@ impl Data {
.unwrap(); .unwrap();
Ok(self) Ok(self)
} }
/// get indexer genesis hash
pub async fn fetch_indexer_genesis_hash(mut self) -> Result<Self, anyhow::Error> {
self.indexer_genesis_hash = self.indexer().fetch_genesis_hash().await?;
Ok(self)
}
/// get properties /// get properties
pub async fn fetch_system_properties(mut self) -> Result<Self, anyhow::Error> { pub async fn fetch_system_properties(mut self) -> Result<Self, anyhow::Error> {
let system_properties = self.client().rpc().system_properties().await?; let system_properties = self.client().rpc().system_properties().await?;
......
...@@ -28,6 +28,13 @@ pub struct IdentityPubkeyByName; ...@@ -28,6 +28,13 @@ pub struct IdentityPubkeyByName;
)] )]
pub struct LatestBlock; pub struct LatestBlock;
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "res/indexer-schema.json",
query_path = "res/indexer-queries.graphql"
)]
pub struct GenesisHash;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Indexer { pub struct Indexer {
pub gql_client: reqwest::Client, pub gql_client: reqwest::Client,
...@@ -61,7 +68,7 @@ impl Indexer { ...@@ -61,7 +68,7 @@ impl Indexer {
.and_then(|data| data.identity_by_pk.map(|idty| idty.pubkey))) .and_then(|data| data.identity_by_pk.map(|idty| idty.pubkey)))
} }
/// fetch latest block /// fetch latest block number
pub async fn fetch_latest_block(&self) -> Result<u64, anyhow::Error> { pub async fn fetch_latest_block(&self) -> Result<u64, anyhow::Error> {
Ok(post_graphql::<LatestBlock, _>( Ok(post_graphql::<LatestBlock, _>(
&self.gql_client, &self.gql_client,
...@@ -80,29 +87,58 @@ impl Indexer { ...@@ -80,29 +87,58 @@ impl Indexer {
.as_u64() .as_u64()
.unwrap()) // must be a Number of blocks .unwrap()) // must be a Number of blocks
} }
/// fetch genesis hash
pub async fn fetch_genesis_hash(&self) -> Result<Hash, anyhow::Error> {
Ok(post_graphql::<GenesisHash, _>(
&self.gql_client,
self.gql_url.clone(),
genesis_hash::Variables {},
)
.await?
.data
.unwrap() // must have a data field
.block
.first()
.unwrap() // must have one and only one block matching request
.hash
.clone()
.parse::<Hash>()
.unwrap())
}
} }
#[derive(Clone, Default, Debug, clap::Parser)] #[derive(Clone, Default, Debug, clap::Parser)]
pub enum IndexerSubcommand { pub enum Subcommand {
#[default] #[default]
/// Show indexer endpoint /// Show indexer endpoint
ShowEndpoint, ShowEndpoint,
/// Fetch latest indexed block /// Fetch latest indexed block
LatestBlock, LatestBlock,
/// Fetch genesis block hash
GenesisHash,
} }
pub async fn handle_command(data: Data, command: IndexerSubcommand) -> anyhow::Result<()> { pub async fn handle_command(data: Data, command: Subcommand) -> anyhow::Result<()> {
// build indexer because it is needed for all subcommands
let data = data.build_indexer()?; let data = data.build_indexer()?;
// match subcommand
match command { match command {
IndexerSubcommand::ShowEndpoint => { Subcommand::ShowEndpoint => {
println!("indexer endpoint: {}", data.indexer().gql_url); println!("indexer endpoint: {}", data.indexer().gql_url);
} }
IndexerSubcommand::LatestBlock => { Subcommand::LatestBlock => {
println!( println!(
"latest indexed block is: {}", "latest indexed block is: {}",
data.indexer().fetch_latest_block().await? data.indexer().fetch_latest_block().await?
); );
} }
Subcommand::GenesisHash => {
println!(
"hash of genesis block is: {}",
data.indexer().fetch_genesis_hash().await?
);
}
}; };
Ok(()) Ok(())
......
...@@ -7,7 +7,6 @@ mod keys; ...@@ -7,7 +7,6 @@ mod keys;
use clap::Parser; use clap::Parser;
use codec::Encode; use codec::Encode;
use data::*; use data::*;
use indexer::*;
use keys::*; use keys::*;
use serde::Deserialize; use serde::Deserialize;
use sp_core::{sr25519::Pair, Pair as _, H256}; use sp_core::{sr25519::Pair, Pair as _, H256};
...@@ -251,9 +250,13 @@ pub enum Subcommand { ...@@ -251,9 +250,13 @@ pub enum Subcommand {
UpdateKeys, UpdateKeys,
/// Get information about runtime /// Get information about runtime
RuntimeInfo, RuntimeInfo,
/// Check current block
CurrentBlock,
/// Check that indexer and node are on the same network
CheckIndexerAgainstBlockchain,
/// Indexer subcommands /// Indexer subcommands
#[clap(subcommand)] #[clap(subcommand)]
Indexer(IndexerSubcommand), Indexer(indexer::Subcommand),
} }
#[tokio::main(flavor = "current_thread")] #[tokio::main(flavor = "current_thread")]
...@@ -567,6 +570,43 @@ async fn main() -> Result<(), GcliError> { ...@@ -567,6 +570,43 @@ async fn main() -> Result<(), GcliError> {
data = data.build_client().await.fetch_system_properties().await?; data = data.build_client().await.fetch_system_properties().await?;
commands::runtime::runtime_info(data).await; commands::runtime::runtime_info(data).await;
} }
Subcommand::CurrentBlock => {
data = data.build_client().await;
println!(
"current block: {}",
data.client()
.storage()
.fetch(&runtime::storage().system().number(), None)
.await?
.unwrap()
);
}
Subcommand::CheckIndexerAgainstBlockchain => {
data = data
.build_client()
.await
.build_indexer()?
.fetch_genesis_hash()
.await?
.fetch_indexer_genesis_hash()
.await?;
if data.genesis_hash == data.indexer_genesis_hash {
println!(
"{} and {} have the same genesis hash: {}",
data.args.url,
data.indexer().gql_url,
data.genesis_hash
);
} else {
println!(
"⚠️ {} ({}) and {} ({}) do not share same genesis",
data.args.url,
data.genesis_hash,
data.indexer().gql_url,
data.indexer_genesis_hash
);
}
}
Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand).await?, Subcommand::Indexer(subcommand) => indexer::handle_command(data, subcommand).await?,
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment