From 9dcd199ea90f954ae2a5f7cf6e21d88a7596a6cc Mon Sep 17 00:00:00 2001 From: Farhad Shabani Date: Fri, 25 Aug 2023 23:38:59 -0700 Subject: [PATCH] imp: chain handler refinement --- .../src/contexts/builder.rs | 2 +- .../relayer-cosmos-mock/src/contexts/chain.rs | 86 +++++++++++++------ .../src/contexts/runtime.rs | 6 ++ crates/relayer-cosmos-mock/src/impls/chain.rs | 2 +- .../relayer-cosmos-mock/src/impls/handler.rs | 58 +++---------- .../relayer-cosmos-mock/src/traits/handler.rs | 9 +- .../relayer-cosmos-mock/src/types/status.rs | 2 +- crates/relayer-cosmos-mock/src/util/dummy.rs | 7 +- 8 files changed, 89 insertions(+), 83 deletions(-) diff --git a/crates/relayer-cosmos-mock/src/contexts/builder.rs b/crates/relayer-cosmos-mock/src/contexts/builder.rs index 4b9b5abf18..87a679037d 100644 --- a/crates/relayer-cosmos-mock/src/contexts/builder.rs +++ b/crates/relayer-cosmos-mock/src/contexts/builder.rs @@ -57,7 +57,7 @@ impl MockCosmosBuilder { let c_clone = c.clone(); let handle = tokio::spawn(async move { - c_clone.run().await.unwrap(); + c_clone.run().await; }); self.handlers.push(handle); diff --git a/crates/relayer-cosmos-mock/src/contexts/chain.rs b/crates/relayer-cosmos-mock/src/contexts/chain.rs index f33ab30d07..9f1092e623 100644 --- a/crates/relayer-cosmos-mock/src/contexts/chain.rs +++ b/crates/relayer-cosmos-mock/src/contexts/chain.rs @@ -21,21 +21,23 @@ use ibc::core::Msg; use ibc::core::ValidationContext; use ibc::Any; use ibc::Height; + +use tendermint::time::Time; +use tendermint_testgen::light_block::TmLightBlock; use tendermint_testgen::Generator; +use tendermint_testgen::LightBlock; use std::sync::Arc; use std::sync::Mutex; use std::time::Duration; -use tendermint::chain::Id; -use tendermint_testgen::LightBlock; - use super::runtime::MockClock; use crate::contexts::runtime::MockRuntimeContext; use crate::traits::endpoint::Endpoint; use crate::types::error::Error; use crate::types::status::ChainStatus; use crate::util::dummy::dummy_signer; +use crate::util::dummy::generate_rand_app_hash; use crate::util::mutex::MutexUtil; #[derive(Clone)] @@ -43,11 +45,11 @@ pub struct MockCosmosChain { /// Chain identifier pub chain_id: ChainId, /// Current chain status - pub current_state: Arc>, + pub current_status: Arc>, /// Chain application pub app: BaseCoinApp, /// Chain blocks - pub blocks: Arc>>, + pub blocks: Arc>>, /// Chain runtime pub runtime: MockRuntimeContext, } @@ -77,22 +79,22 @@ impl MockCosmosChain { let runtime = MockRuntimeContext::new(clock.clone()); - let genesis_height = 1; - - let genesis_block = LightBlock::new_default(genesis_height); - - let current_state = Arc::new(Mutex::new(ChainStatus::new( - Height::new(chain_id.revision_number(), genesis_height).unwrap(), - clock.get_timestamp(), + let current_status = Arc::new(Mutex::new(ChainStatus::new( + Height::new(chain_id.revision_number(), 1).expect("never fails"), + Time::now().into(), ))); - Self { + let chain = Self { chain_id, - current_state, + current_status, app, - blocks: Arc::new(Mutex::new(vec![genesis_block])), + blocks: Arc::new(Mutex::new(vec![])), runtime, - } + }; + + chain.grow_blocks(); + + chain } pub fn chain_id(&self) -> &ChainId { @@ -104,17 +106,52 @@ impl MockCosmosChain { } pub fn get_current_timestamp(&self) -> Timestamp { - self.current_state.acquire_mutex().timestamp + self.current_status.acquire_mutex().timestamp } pub fn get_current_height(&self) -> Height { - self.current_state.acquire_mutex().height + self.current_status.acquire_mutex().height } pub fn ibc_context(&self) -> IbcContext> { self.app.ibc().ctx() } + pub fn grow_blocks(&self) { + let mut blocks = self.blocks.acquire_mutex(); + + let height = blocks.len() as u64 + 1; + + let current_time = Time::now(); + + let mut tm_light_block = LightBlock::new_default_with_time_and_chain_id( + self.chain_id.to_string(), + current_time, + height, + ) + .generate() + .expect("failed to generate light block"); + + tm_light_block.signed_header.header.app_hash = generate_rand_app_hash(); + + let header_hash = tm_light_block.signed_header.header.hash(); + + tm_light_block.signed_header.commit.block_id.hash = header_hash; + + blocks.push(tm_light_block); + + self.runtime.clock.set_timestamp(current_time); + + let current_status = ChainStatus::new( + Height::new(self.chain_id.revision_number(), height).expect("invalid height"), + current_time.into(), + ); + + let mut last_status = self.current_status.acquire_mutex(); + + *last_status = current_status; + } + pub async fn build_msg_create_client(&self) -> Result { let tm_client_state = ClientState::new( self.chain_id.clone(), @@ -149,18 +186,13 @@ impl MockCosmosChain { let client_id = ClientId::new(client_type(), client_counter)?; - let last_block = self.blocks.acquire_mutex().last().unwrap().clone(); - - let mut tm_light_block = last_block.generate().map_err(Error::source)?; - - tm_light_block.signed_header.header.chain_id = - Id::try_from(self.chain_id.to_string()).unwrap(); + let last_light_block = self.blocks.acquire_mutex().last().unwrap().clone(); let header = Header { - signed_header: tm_light_block.signed_header, - validator_set: tm_light_block.validators, + signed_header: last_light_block.signed_header, + validator_set: last_light_block.validators, trusted_height: self.get_current_height(), - trusted_next_validator_set: tm_light_block.next_validators, + trusted_next_validator_set: last_light_block.next_validators, }; let msg_update_client = MsgUpdateClient { diff --git a/crates/relayer-cosmos-mock/src/contexts/runtime.rs b/crates/relayer-cosmos-mock/src/contexts/runtime.rs index 3e583d0526..a8303ca96c 100644 --- a/crates/relayer-cosmos-mock/src/contexts/runtime.rs +++ b/crates/relayer-cosmos-mock/src/contexts/runtime.rs @@ -3,6 +3,7 @@ use core::time::Duration; use ibc::core::timestamp::Timestamp; use std::ops::Add; use std::sync::Mutex; +use tendermint::Time; use crate::types::error::Error; use crate::util::mutex::MutexUtil; @@ -41,8 +42,13 @@ impl Default for MockClock { } impl MockClock { + pub fn set_timestamp(&self, time: Time) { + *self.timestamp.acquire_mutex() = time.into(); + } + pub fn increment_timestamp(&self, duration: Duration) -> Result<(), Error> { let mut locked_timestamp = self.timestamp.acquire_mutex(); + *locked_timestamp = locked_timestamp.add(duration).map_err(|_| { Error::invalid(format!( "overflow when adding {} to {:?}", diff --git a/crates/relayer-cosmos-mock/src/impls/chain.rs b/crates/relayer-cosmos-mock/src/impls/chain.rs index 3cc4e16d29..d49d415ece 100644 --- a/crates/relayer-cosmos-mock/src/impls/chain.rs +++ b/crates/relayer-cosmos-mock/src/impls/chain.rs @@ -222,7 +222,7 @@ impl HasChainStatusType for MockCosmosChain { #[async_trait] impl CanQueryChainStatus for MockCosmosChain { async fn query_chain_status(&self) -> Result { - Ok(self.current_state.lock().unwrap().clone()) + Ok(self.current_status.lock().unwrap().clone()) } } diff --git a/crates/relayer-cosmos-mock/src/impls/handler.rs b/crates/relayer-cosmos-mock/src/impls/handler.rs index 839385af4c..23a6673bab 100644 --- a/crates/relayer-cosmos-mock/src/impls/handler.rs +++ b/crates/relayer-cosmos-mock/src/impls/handler.rs @@ -1,17 +1,15 @@ use crate::contexts::chain::MockCosmosChain; use crate::traits::handler::ChainHandler; use crate::types::error::Error; -use crate::types::status::ChainStatus; use crate::util::conversion::convert_tm_to_ics_merkle_proof; -use crate::util::dummy::generate_rand_app_hash; use crate::util::dummy::genesis_app_state; use crate::util::mutex::MutexUtil; use basecoin_app::modules::types::IdentifiedModule; use basecoin_store::context::ProvableStore; use basecoin_store::context::Store; - use basecoin_store::utils::SharedRwExt; + use ibc::core::events::IbcEvent; use ibc::core::ics23_commitment::commitment::CommitmentProofBytes; use ibc::core::ics24_host::path::Path; @@ -25,10 +23,7 @@ use tendermint::v0_37::abci::request::InitChain; use tendermint::v0_37::abci::request::Query; use tendermint::v0_37::abci::Request as AbciRequest; use tendermint::v0_37::abci::Response as AbciResponse; -use tendermint::AppHash; use tendermint_testgen::consensus::default_consensus_params; -use tendermint_testgen::Generator; -use tendermint_testgen::LightBlock; use tower::Service; use async_trait::async_trait; @@ -54,33 +49,26 @@ impl ChainHandler for MockCosmosChain { app.call(AbciRequest::InitChain(request)) .await .expect("failed to initialize chain"); + + // Generates the genesis block + self.grow_blocks(); } - async fn begin_block(&self) -> Result<(), Error> { + async fn begin_block(&self) { let last_block = self.blocks.acquire_mutex().last().unwrap().clone(); - let mut header = last_block - .header - .unwrap() - .generate() - .map_err(Error::source)?; - - header.app_hash = AppHash::try_from(generate_rand_app_hash()).map_err(Error::source)?; - let mut events = Vec::new(); let mut modules = self.app.modules.write_access(); for IdentifiedModule { id: _, module } in modules.iter_mut() { - let event = module.begin_block(&header); + let event = module.begin_block(&last_block.signed_header.header); events.extend(event); } - - Ok(()) } /// Commits the chain state. - async fn commit(&self) -> Result<(), Error> { + async fn commit(&self) { let mut modules = self.app.modules.write_access(); for IdentifiedModule { id, module } in modules.iter_mut() { @@ -100,42 +88,18 @@ impl ChainHandler for MockCosmosChain { state.commit().expect("failed to commit to state"); - let current_revision_height = state.current_height(); - - let current_height = Height::new(self.chain_id.revision_number(), current_revision_height) - .expect("failed to create pending height"); - - // Update blocks - { - let mut blocks = self.blocks.acquire_mutex(); - - blocks.push(LightBlock::new_default(current_revision_height)); - } - - // Update current chain status - { - let mut current_state = self.current_state.acquire_mutex(); - - *current_state = ChainStatus::new(current_height, current_state.timestamp); - } - - Ok(()) + self.grow_blocks(); } - async fn run(&self) -> Result<(), Error> { + async fn run(&self) { self.init().await; - // Grow blocks every one second loop { - self.begin_block().await?; + self.begin_block().await; tokio::time::sleep(Duration::from_millis(1000)).await; - self.runtime - .clock - .increment_timestamp(Duration::from_millis(1000))?; - - self.commit().await?; + self.commit().await; } } diff --git a/crates/relayer-cosmos-mock/src/traits/handler.rs b/crates/relayer-cosmos-mock/src/traits/handler.rs index e194181b16..335101e7c5 100644 --- a/crates/relayer-cosmos-mock/src/traits/handler.rs +++ b/crates/relayer-cosmos-mock/src/traits/handler.rs @@ -2,7 +2,8 @@ use async_trait::async_trait; use ibc::core::events::IbcEvent; use ibc::core::ics23_commitment::commitment::CommitmentProofBytes; use ibc::core::ics24_host::path::Path; -use ibc::{Any, Height}; +use ibc::Any; +use ibc::Height; use crate::types::error::Error; @@ -10,11 +11,11 @@ use crate::types::error::Error; pub trait ChainHandler { async fn init(&self); - async fn begin_block(&self) -> Result<(), Error>; + async fn begin_block(&self); - async fn commit(&self) -> Result<(), Error>; + async fn commit(&self); - async fn run(&self) -> Result<(), Error>; + async fn run(&self); async fn submit_messages(&self, msgs: Vec) -> Result>, Error>; diff --git a/crates/relayer-cosmos-mock/src/types/status.rs b/crates/relayer-cosmos-mock/src/types/status.rs index 74b0b2e680..dc11ad135e 100644 --- a/crates/relayer-cosmos-mock/src/types/status.rs +++ b/crates/relayer-cosmos-mock/src/types/status.rs @@ -1,7 +1,7 @@ use ibc::core::timestamp::Timestamp; use ibc::Height; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct ChainStatus { pub timestamp: Timestamp, pub height: Height, diff --git a/crates/relayer-cosmos-mock/src/util/dummy.rs b/crates/relayer-cosmos-mock/src/util/dummy.rs index 0466bf2c22..68136f4936 100644 --- a/crates/relayer-cosmos-mock/src/util/dummy.rs +++ b/crates/relayer-cosmos-mock/src/util/dummy.rs @@ -2,6 +2,7 @@ use ibc::Signer; use rand::RngCore; use sha2::Digest; use sha2::Sha256; +use tendermint::AppHash; pub fn genesis_app_state() -> serde_json::Value { serde_json::json!({ @@ -42,12 +43,14 @@ pub fn dummy_signer() -> Signer { Signer::from("cosmos000000000000000000000000000000000000000".to_string()) } -pub fn generate_rand_app_hash() -> Vec { +pub fn generate_rand_app_hash() -> AppHash { let mut rng = rand::thread_rng(); let mut data = vec![0u8; 32]; rng.fill_bytes(&mut data); - Sha256::digest(&data).to_vec() + let value = Sha256::digest(&data).to_vec(); + + AppHash::try_from(value).expect("invalid app hash") }