diff --git a/light-clients/ics07-tendermint/Cargo.toml b/light-clients/ics07-tendermint/Cargo.toml index 9b81bbccc..158462848 100644 --- a/light-clients/ics07-tendermint/Cargo.toml +++ b/light-clients/ics07-tendermint/Cargo.toml @@ -40,7 +40,7 @@ prost = { version = "0.11", default-features = false } bytes = { version = "1.1.0", default-features = false } subtle-encoding = { version = "0.5", default-features = false } flex-error = { version = "0.4.4", default-features = false } -tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } +tendermint = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false, features = ["rust-crypto"] } tendermint-proto = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } tendermint-light-client-verifier = { git = "https://github.com/informalsystems/tendermint-rs", rev = "e81f7bf23d63ffbcd242381d1ce5e35da3515ff1", default-features = false } sha2 = { version = "0.10", optional = true, default-features = false } diff --git a/light-clients/ics07-tendermint/src/lib.rs b/light-clients/ics07-tendermint/src/lib.rs index ea868b686..941431d98 100644 --- a/light-clients/ics07-tendermint/src/lib.rs +++ b/light-clients/ics07-tendermint/src/lib.rs @@ -42,6 +42,7 @@ pub mod client_state; pub mod consensus_state; pub mod error; pub mod merkle; +pub mod utils; #[cfg(any(test, feature = "mocks"))] pub mod mock; #[cfg(any(test, feature = "mocks"))] diff --git a/light-clients/ics07-tendermint/src/utils.rs b/light-clients/ics07-tendermint/src/utils.rs new file mode 100644 index 000000000..77f7fc0f4 --- /dev/null +++ b/light-clients/ics07-tendermint/src/utils.rs @@ -0,0 +1,70 @@ +use tendermint::{block::{signed_header::SignedHeader, Commit, CommitSig}, signature::Signature, PublicKey, crypto::default::signature::Verifier}; + +use crate::client_message::Header; + +use tendermint::crypto::signature::Verifier as _; + + + +/// Utilty function that: +/// - collects {signature, pubkey, msg} from every validator that successfuly signed a block so that +/// - there's consensus (voting power > 2/3) and +/// - size of the validators that succesfully voted equals the circuit size + +pub fn collect_signatures_for_finalized_block(header: Header, circuit_size: usize) -> Option)>> { + + let Header {validator_set, + signed_header: SignedHeader{ + header, commit: Commit{signatures, ..} + ,..}, .. + } = header; + + let total_voting_power = validator_set.total_voting_power().value(); + + // 1. order by voting power + + // filter by valid signatures + let mut validator_info_signed_block = signatures.iter().filter(|commit| matches!(commit, CommitSig::BlockIdFlagCommit{..})) + .flat_map(|commit| match commit { + CommitSig::BlockIdFlagCommit { validator_address, signature, .. } if signature.is_some() => { + match validator_set.validators().iter().find(|info| *validator_address == info.address ) { + None => None, + Some(info) => Some((info.pub_key, signature.clone().unwrap(), commit, info.power)) + } + + } + _ => unreachable!() + } + ) + .collect::>(); + +// order by power DESC +validator_info_signed_block.sort_by(|(_, _, _, power_a), (_, _, _, power_b)| power_b.value().cmp(&power_a.value())); + +let result = validator_info_signed_block.into_iter().fold((0u64, vec![]), |mut acc, (pubkey, signature, _commit, power)| { + if acc.0 * 3 > 2*total_voting_power && acc.1.len() == circuit_size { + acc + } else { + // TOOD: commit has to become bytes, I guess? How to do so? + // let msg = commit; + let msg = vec![0u8]; + + if Verifier::verify(pubkey, msg.as_ref(), &signature).is_ok() { + acc.1.push((pubkey, signature, msg.to_vec())); + acc.0 += power.value(); + } + acc + } + + }); + +if result.0 * 3 > 2*total_voting_power && result.1.len() == circuit_size { + Some(result.1) +} else { + None +} +} + +// fn check_block_is_final() { + +// } \ No newline at end of file