diff --git a/.changelog/unreleased/improvements/1343-add-app-hash-field-to-testgen-header.md b/.changelog/unreleased/improvements/1343-add-app-hash-field-to-testgen-header.md new file mode 100644 index 000000000..ca73fa4b2 --- /dev/null +++ b/.changelog/unreleased/improvements/1343-add-app-hash-field-to-testgen-header.md @@ -0,0 +1,3 @@ +- `[tendermint-testgen]` Add `app_hash` field to testgen `Header` and implement + convenient method for default `LightBlock` construction from `Header` + ([\#1343](https://github.com/informalsystems/tendermint-rs/issues/1343)) diff --git a/p2p/src/secret_connection.rs b/p2p/src/secret_connection.rs index 163c509d0..6f8b7a6f3 100644 --- a/p2p/src/secret_connection.rs +++ b/p2p/src/secret_connection.rs @@ -108,7 +108,9 @@ impl Handshake { &mut self, remote_eph_pubkey: EphemeralPublic, ) -> Result, Error> { - let Some(local_eph_privkey) = self.state.local_eph_privkey.take() else { return Err(Error::missing_secret()) }; + let Some(local_eph_privkey) = self.state.local_eph_privkey.take() else { + return Err(Error::missing_secret()); + }; let local_eph_pubkey = EphemeralPublic::from(&local_eph_privkey); // Compute common shared secret. diff --git a/testgen/src/header.rs b/testgen/src/header.rs index cd7050532..95e9edf18 100644 --- a/testgen/src/header.rs +++ b/testgen/src/header.rs @@ -36,6 +36,10 @@ pub struct Header { pub proposer: Option, #[options(help = "last block id hash (default: Hash::None)")] pub last_block_id_hash: Option, + #[options(help = "application hash (default: AppHash(vec![])")] + #[serde(default, with = "app_hash_serde")] + #[serde(skip_serializing_if = "Option::is_none")] + pub app_hash: Option, } // Serialize and deserialize time only up to second precision for integration with MBT. @@ -64,6 +68,25 @@ where m_secs.serialize(serializer) } +// Serialize and deserialize the `Option`, delegating to the `AppHash` +// serialization/deserialization into/from hexstring. +mod app_hash_serde { + use super::*; + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + where + D: Deserializer<'de>, + { + tendermint::serializers::apphash::deserialize(deserializer).map(Some) + } + + pub fn serialize(value: &Option, serializer: S) -> Result + where + S: Serializer, + { + tendermint::serializers::apphash::serialize(value.as_ref().unwrap(), serializer) + } +} + impl Header { pub fn new(validators: &[Validator]) -> Self { Header { @@ -74,6 +97,7 @@ impl Header { time: None, proposer: None, last_block_id_hash: None, + app_hash: None, } } set_option!(validators, &[Validator], Some(validators.to_vec())); @@ -87,6 +111,7 @@ impl Header { set_option!(time, Time); set_option!(proposer, usize); set_option!(last_block_id_hash, Hash); + set_option!(app_hash, AppHash); pub fn next(&self) -> Self { let height = self.height.expect("Missing previous header's height"); @@ -108,6 +133,7 @@ impl Header { time: Some((time + Duration::from_secs(1)).unwrap()), proposer: self.proposer, // TODO: proposer must be incremented last_block_id_hash: Some(last_block_id_hash), + app_hash: self.app_hash.clone(), } } } @@ -133,6 +159,7 @@ impl Generator for Header { time: self.time.or(default.time), proposer: self.proposer.or(default.proposer), last_block_id_hash: self.last_block_id_hash.or(default.last_block_id_hash), + app_hash: self.app_hash.or(default.app_hash), } } @@ -185,7 +212,7 @@ impl Generator for Header { validators_hash, next_validators_hash: next_valset.hash(), consensus_hash: validators_hash, // TODO: currently not clear how to produce a valid hash - app_hash: AppHash::from_hex_upper("").unwrap(), + app_hash: self.app_hash.clone().unwrap_or_default(), last_results_hash: None, evidence_hash: None, proposer_address, diff --git a/testgen/src/light_block.rs b/testgen/src/light_block.rs index c6cea5ab7..7dab39912 100644 --- a/testgen/src/light_block.rs +++ b/testgen/src/light_block.rs @@ -95,15 +95,7 @@ impl LightBlock { .next_validators(&validators) .time(Time::from_unix_timestamp(height as i64, 0).unwrap()); // just wanted to initialize time with some value - let commit = Commit::new(header.clone(), 1); - - Self { - header: Some(header), - commit: Some(commit), - validators: Some(validators.to_vec()), - next_validators: Some(validators.to_vec()), - provider: Some(default_peer_id()), - } + Self::new_default_with_header(header) } pub fn new_default_with_time_and_chain_id(chain_id: String, time: Time, height: u64) -> Self { @@ -117,13 +109,15 @@ impl LightBlock { .next_validators(&validators) .time(time); - let commit = Commit::new(header.clone(), 1); + Self::new_default_with_header(header) + } + pub fn new_default_with_header(header: Header) -> Self { Self { - header: Some(header), - commit: Some(commit), - validators: Some(validators.to_vec()), - next_validators: Some(validators.to_vec()), + header: Some(header.clone()), + commit: Some(Commit::new(header.clone(), 1)), + validators: header.validators.clone(), + next_validators: header.validators, provider: Some(default_peer_id()), } }