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
Branches
Tags
1 merge request!5add features and refac data
......@@ -26,6 +26,8 @@ with derivations:
## Commands
```sh
# get duniter current block
gcli current-block
# get balance of test1 account
gcli --address 5FeggKqw2AbnGZF9Y9WPM2QTgzENS3Hit94Ewgmzdg5a3LNa get-balance
# get information about test1 identity (needs indexer)
......@@ -36,7 +38,14 @@ gcli --secret "pipe paddle ketchup filter life ice feel embody glide quantum rid
## 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
# show latest indexer indexed block
......
......@@ -15,3 +15,9 @@ query LatestBlock {
value
}
}
query GenesisHash {
block(where: {number: {_eq: 0}}) {
hash
}
}
use crate::*;
use indexer::Indexer;
// data derived from command arguments
......@@ -24,6 +25,8 @@ pub struct Data {
pub token_symbol: String,
// genesis hash
pub genesis_hash: Hash,
// indexer genesis hash
pub indexer_genesis_hash: Hash,
}
/// system properties defined in client specs
......@@ -146,6 +149,11 @@ impl Data {
.unwrap();
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
pub async fn fetch_system_properties(mut self) -> Result<Self, anyhow::Error> {
let system_properties = self.client().rpc().system_properties().await?;
......
......@@ -28,6 +28,13 @@ pub struct IdentityPubkeyByName;
)]
pub struct LatestBlock;
#[derive(GraphQLQuery)]
#[graphql(
schema_path = "res/indexer-schema.json",
query_path = "res/indexer-queries.graphql"
)]
pub struct GenesisHash;
#[derive(Clone, Debug)]
pub struct Indexer {
pub gql_client: reqwest::Client,
......@@ -61,7 +68,7 @@ impl Indexer {
.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> {
Ok(post_graphql::<LatestBlock, _>(
&self.gql_client,
......@@ -80,29 +87,58 @@ impl Indexer {
.as_u64()
.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)]
pub enum IndexerSubcommand {
pub enum Subcommand {
#[default]
/// Show indexer endpoint
ShowEndpoint,
/// Fetch latest indexed block
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()?;
// match subcommand
match command {
IndexerSubcommand::ShowEndpoint => {
Subcommand::ShowEndpoint => {
println!("indexer endpoint: {}", data.indexer().gql_url);
}
IndexerSubcommand::LatestBlock => {
Subcommand::LatestBlock => {
println!(
"latest indexed block is: {}",
data.indexer().fetch_latest_block().await?
);
}
Subcommand::GenesisHash => {
println!(
"hash of genesis block is: {}",
data.indexer().fetch_genesis_hash().await?
);
}
};
Ok(())
......
......@@ -7,7 +7,6 @@ mod keys;
use clap::Parser;
use codec::Encode;
use data::*;
use indexer::*;
use keys::*;
use serde::Deserialize;
use sp_core::{sr25519::Pair, Pair as _, H256};
......@@ -251,9 +250,13 @@ pub enum Subcommand {
UpdateKeys,
/// Get information about runtime
RuntimeInfo,
/// Check current block
CurrentBlock,
/// Check that indexer and node are on the same network
CheckIndexerAgainstBlockchain,
/// Indexer subcommands
#[clap(subcommand)]
Indexer(IndexerSubcommand),
Indexer(indexer::Subcommand),
}
#[tokio::main(flavor = "current_thread")]
......@@ -567,6 +570,43 @@ async fn main() -> Result<(), GcliError> {
data = data.build_client().await.fetch_system_properties().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?,
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment