diff --git a/Cargo.lock b/Cargo.lock index 0521158a..70d9fcca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2545,7 +2545,7 @@ dependencies = [ [[package]] name = "orga" version = "0.3.1" -source = "git+https://github.com/nomic-io/orga.git?rev=8e180ff2a839de81152d8f65be98d18264fbfa14#8e180ff2a839de81152d8f65be98d18264fbfa14" +source = "git+https://github.com/nomic-io/orga.git?rev=c879e1fbf9df4133ca9df062f177aea6c32ea2c5#c879e1fbf9df4133ca9df062f177aea6c32ea2c5" dependencies = [ "abci2", "async-trait", @@ -2606,7 +2606,7 @@ dependencies = [ [[package]] name = "orga-macros" version = "0.3.1" -source = "git+https://github.com/nomic-io/orga.git?rev=8e180ff2a839de81152d8f65be98d18264fbfa14#8e180ff2a839de81152d8f65be98d18264fbfa14" +source = "git+https://github.com/nomic-io/orga.git?rev=c879e1fbf9df4133ca9df062f177aea6c32ea2c5#c879e1fbf9df4133ca9df062f177aea6c32ea2c5" dependencies = [ "darling", "heck 0.3.3", diff --git a/Cargo.toml b/Cargo.toml index 373720e9..7031a17a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ default-run = "nomic" [dependencies] bitcoin = { version = "0.29.2", features = ["serde", "rand"] } -orga = { git = "https://github.com/nomic-io/orga.git", rev = "8e180ff2a839de81152d8f65be98d18264fbfa14", features = [ +orga = { git = "https://github.com/nomic-io/orga.git", rev = "c879e1fbf9df4133ca9df062f177aea6c32ea2c5", features = [ "merk-verify", ] } thiserror = "1.0.30" diff --git a/rest/Cargo.lock b/rest/Cargo.lock index 82439159..a391823d 100644 --- a/rest/Cargo.lock +++ b/rest/Cargo.lock @@ -2356,6 +2356,7 @@ name = "nomic-rest" version = "0.1.0" dependencies = [ "base64 0.13.1", + "bech32", "chrono", "hex", "ibc", @@ -2365,6 +2366,7 @@ dependencies = [ "rocket", "serde", "serde_json", + "sha2 0.10.8", "tendermint 0.23.7", "tendermint-proto 0.23.9", "tendermint-rpc 0.23.7", @@ -2521,7 +2523,7 @@ dependencies = [ [[package]] name = "orga" version = "0.3.1" -source = "git+https://github.com/nomic-io/orga.git?rev=8e180ff2a839de81152d8f65be98d18264fbfa14#8e180ff2a839de81152d8f65be98d18264fbfa14" +source = "git+https://github.com/nomic-io/orga.git?rev=c879e1fbf9df4133ca9df062f177aea6c32ea2c5#c879e1fbf9df4133ca9df062f177aea6c32ea2c5" dependencies = [ "abci2", "async-trait", @@ -2582,7 +2584,7 @@ dependencies = [ [[package]] name = "orga-macros" version = "0.3.1" -source = "git+https://github.com/nomic-io/orga.git?rev=8e180ff2a839de81152d8f65be98d18264fbfa14#8e180ff2a839de81152d8f65be98d18264fbfa14" +source = "git+https://github.com/nomic-io/orga.git?rev=c879e1fbf9df4133ca9df062f177aea6c32ea2c5#c879e1fbf9df4133ca9df062f177aea6c32ea2c5" dependencies = [ "darling", "heck 0.3.3", diff --git a/rest/Cargo.toml b/rest/Cargo.toml index 274de36a..19399d05 100644 --- a/rest/Cargo.toml +++ b/rest/Cargo.toml @@ -24,3 +24,5 @@ serde_json = "1.0.78" lazy_static = "1.4.0" tokio = "1.19.2" chrono = { version = "0.4.31", features = ["serde"] } +sha2 = "0.10.6" +bech32 = { version = "0.9.1" } diff --git a/rest/src/main.rs b/rest/src/main.rs index c4fc77f9..7d6af425 100644 --- a/rest/src/main.rs +++ b/rest/src/main.rs @@ -28,6 +28,8 @@ use ibc_proto::ibc::core::client::v1::IdentifiedClientState; use ibc_proto::ibc::core::connection::v1::ConnectionEnd as RawConnectionEnd; use ibc_proto::ibc::lightclients::tendermint::v1::ClientState as RawTmClientState; +use bech32::ToBase32; +use sha2::Digest; use tendermint_proto::types::CommitSig as RawCommitSig; use tendermint_rpc as tm; use tm::Client as _; @@ -995,6 +997,99 @@ async fn slashing_params() -> Value { }) } +async fn get_signing_infos() -> Vec { + let client = tm::HttpClient::new(app_host()).unwrap(); + + let all_validators: Vec = app_client() + .query(|app: InnerApp| app.staking.all_validators()) + .await + .unwrap(); + + let all_keys: Vec<_> = app_client() + .query(|app: InnerApp| app.staking.consensus_keys()) + .await + .unwrap(); + + let last_signed_blocks = app_client() + .query(|app: InnerApp| app.staking.last_signed_blocks()) + .await + .unwrap(); + + let latest_block_response = client.latest_block().await.unwrap(); + let latest_block: u64 = latest_block_response.block.header.height.value(); + + let mut signing_infos = vec![]; + + for validator in all_validators { + let cons_key = all_keys + .iter() + .find(|entry| (**entry).0 == validator.address.into()) + .map(|entry| (*entry).1) + .unwrap(); + + let mut hasher = sha2::Sha256::new(); + hasher.update(cons_key); + let hash = hasher.finalize().to_vec()[..20].to_vec(); + + let address = bech32::encode( + "nomicvalcons", + hash.to_vec().to_base32(), + bech32::Variant::Bech32, + ) + .unwrap(); + + let last_signed_block: u64 = last_signed_blocks + .iter() + .find(|entry| (**entry).0 == validator.address.into()) + .map(|entry| (*entry).1) + .unwrap() + .unwrap_or(latest_block); + + let skipped_blocks: u64 = latest_block - last_signed_block; + + signing_infos.push(json!({ + "address": address, + "start_height": "0", // TODO: fix, + "index_offset": "0", // TODO: fix, + "jailed_until": Utc.timestamp_opt(validator.jailed_until.unwrap_or(0), 0) + .unwrap() + .format("%Y-%m-%dT%H:%M:%SZ") + .to_string(), + "tombstoned": validator.tombstoned, + "missed_blocks_counter": skipped_blocks.to_string(), + })) + } + + signing_infos +} + +#[get("/cosmos/slashing/v1beta1/signing_infos")] +async fn signing_infos() -> Value { + let signing_infos: Vec<_> = get_signing_infos().await; + + json!({ + "info": signing_infos, + "pagination": { + "next_key": null, + "total": signing_infos.len().to_string(), + } + }) +} + +#[get("/cosmos/slashing/v1beta1/signing_infos/")] +async fn signing_info(cons_addr: &str) -> Value { + let signing_infos: Vec<_> = get_signing_infos().await; + + let signing_info = signing_infos + .iter() + .find(|value| (**value).get("address").unwrap() == cons_addr) + .unwrap(); + + json!({ + "val_signing_info": signing_info + }) +} + fn parse_block(res: tendermint_rpc::endpoint::block::Response) -> Value { let last_commit = res.block.last_commit.unwrap(); let signatures: Vec<_> = last_commit @@ -1070,7 +1165,9 @@ async fn block(height: u32) -> Value { } fn parse_validator_set(res: tendermint_rpc::endpoint::validators::Response) -> Value { - let validators: Vec<_> = res.validators.iter() + let validators: Vec<_> = res + .validators + .iter() .map(|validator| -> Value { json!({ "address": validator.address, @@ -1098,10 +1195,7 @@ fn parse_validator_set(res: tendermint_rpc::endpoint::validators::Response) -> V async fn latest_validator_set() -> Value { let client = tm::HttpClient::new(app_host()).unwrap(); - let block = client - .latest_block() - .await - .unwrap(); + let block = client.latest_block().await.unwrap(); let res = client .validators(block.block.header.height, tendermint_rpc::Paging::All) @@ -1392,6 +1486,8 @@ fn rocket() -> _ { validator, staking_params, slashing_params, + signing_infos, + signing_info, latest_block, block, latest_validator_set,