Skip to content

Commit

Permalink
imp: chain handler refinement
Browse files Browse the repository at this point in the history
  • Loading branch information
Farhad-Shabani committed Aug 26, 2023
1 parent fc18085 commit 9dcd199
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 83 deletions.
2 changes: 1 addition & 1 deletion crates/relayer-cosmos-mock/src/contexts/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
86 changes: 59 additions & 27 deletions crates/relayer-cosmos-mock/src/contexts/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,33 +21,35 @@ 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)]
pub struct MockCosmosChain {
/// Chain identifier
pub chain_id: ChainId,
/// Current chain status
pub current_state: Arc<Mutex<ChainStatus>>,
pub current_status: Arc<Mutex<ChainStatus>>,
/// Chain application
pub app: BaseCoinApp<InMemoryStore>,
/// Chain blocks
pub blocks: Arc<Mutex<Vec<LightBlock>>>,
pub blocks: Arc<Mutex<Vec<TmLightBlock>>>,
/// Chain runtime
pub runtime: MockRuntimeContext,
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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<RevertibleStore<InMemoryStore>> {
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<Any, Error> {
let tm_client_state = ClientState::new(
self.chain_id.clone(),
Expand Down Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions crates/relayer-cosmos-mock/src/contexts/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {:?}",
Expand Down
2 changes: 1 addition & 1 deletion crates/relayer-cosmos-mock/src/impls/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ impl HasChainStatusType for MockCosmosChain {
#[async_trait]
impl CanQueryChainStatus for MockCosmosChain {
async fn query_chain_status(&self) -> Result<Self::ChainStatus, Self::Error> {
Ok(self.current_state.lock().unwrap().clone())
Ok(self.current_status.lock().unwrap().clone())
}
}

Expand Down
58 changes: 11 additions & 47 deletions crates/relayer-cosmos-mock/src/impls/handler.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand All @@ -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() {
Expand All @@ -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;
}
}

Expand Down
9 changes: 5 additions & 4 deletions crates/relayer-cosmos-mock/src/traits/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ 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;

#[async_trait]
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<Any>) -> Result<Vec<Vec<IbcEvent>>, Error>;

Expand Down
2 changes: 1 addition & 1 deletion crates/relayer-cosmos-mock/src/types/status.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
7 changes: 5 additions & 2 deletions crates/relayer-cosmos-mock/src/util/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!({
Expand Down Expand Up @@ -42,12 +43,14 @@ pub fn dummy_signer() -> Signer {
Signer::from("cosmos000000000000000000000000000000000000000".to_string())
}

pub fn generate_rand_app_hash() -> Vec<u8> {
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")
}

0 comments on commit 9dcd199

Please sign in to comment.