Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deterministic host timestamp #1771

Merged
merged 14 commits into from
Feb 8, 2022

Conversation

hu55a1n1
Copy link
Member

@hu55a1n1 hu55a1n1 commented Jan 14, 2022

Closes: cosmos/ibc-rs#57

Description

ChannelReader::host_timestamp() is now a provided method that fetches the latest host consensus state using ChannelReader::host_consensus_state() and uses it's timestamp.


PR author checklist:

  • Added changelog entry, using unclog.
  • Added tests: integration (for Hermes) or unit/mock tests (for modules).
  • Linked to GitHub issue.
  • Updated code comments and documentation (e.g., docs/).
  • Test with basecoin

Reviewer checklist:

  • Reviewed Files changed in the GitHub PR explorer.
  • Manually tested (in case integration/unit/mock tests are absent).

@hu55a1n1 hu55a1n1 marked this pull request as draft January 14, 2022 19:33
@hu55a1n1 hu55a1n1 marked this pull request as ready for review January 14, 2022 20:15
@romac romac marked this pull request as draft January 17, 2022 15:20
@hu55a1n1 hu55a1n1 force-pushed the hu55a1n1/1770-deterministic-host-timestamp branch from e1441a8 to 82d84e9 Compare January 17, 2022 19:25
@hu55a1n1
Copy link
Member Author

A number of tests are currently failing with ics02_client::error::InvalidConsensusStateTimestamp. I think this has to do with the way our mock chain ctx generates blocks. Currently, blocks are generated using the current timestamp. The mock chain should ideally have a block_time config param and should generate blocks with timestamps that differ by block_time duration.

@hu55a1n1 hu55a1n1 marked this pull request as ready for review January 19, 2022 10:43
let latest_consensus_state = self
.host_consensus_state(Height::zero())
.expect("host must have pending consensus state");
latest_consensus_state.timestamp()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a pending_block field just to mock the host timestamp? Would it work if we just get the latest block and add a fixed offset to the timestamp of the latest block?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviewing @Soares! This is an interesting observation. 👍 IMHO it is still helpful to keep a pending_block. I think by having a pending_block, the mock impl is closer to a real chain context impl and serves as a reference implementation. This makes it easier to convey the expectation that the chain context is in a state where it is ready to execute a pending block and also allows us to use the ClientReader::host_timestamp() provided trait method (just as it is expected to be used by a light client impl).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized that we don't treat the mock context as a ref impl, so your suggestions make sense. 👍 3b93cb8

);

let old_pending_block = replace(&mut self.pending_block, new_block);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not seem like we need the pending_block to have a cached next block. The only place I see it is used is in host_timestamp, which should be able to mock the time in other way. Here we can just generate the next block on the fly using the same time offset as used by host_timestamp.

Copy link
Member Author

@hu55a1n1 hu55a1n1 Feb 7, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! 👍 I also noticed that latest_height wasn't required since we can get the latest height from the history, and we expect the history to be non-empty -> https://github.com/informalsystems/ibc-rs/pull/1771/files#diff-a0183026217183d9147ad2c8fc0827f60c1e4354e9a2bed9da05f5f20fc501b6L842
So, I removed that as well. 04b2ff0

@@ -991,6 +1016,16 @@ impl ClientReader for MockContext {
self.latest_height
}

fn host_consensus_state(&self, height: Height) -> Result<AnyConsensusState, Ics02Error> {
if height.is_zero() {
return Ok(self.pending_block.clone().into());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should avoid using Height::zero() as the magic parameter for getting the latest height. If that is needed, it is better to define a separate method latest_host_consensus_state. There is also no need for the pending_block here. If it is needed, it looks like the mock context should be able to deterministically generate the next block, so no caching should be needed.

I also don't see host_consensus_state(Height::zero()) being used anywhere other than getting the host timestamp. So perhaps this is not needed if host_timestamp can be improved as suggested.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! 👍 4e4847e

Copy link
Contributor

@soareschen soareschen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@hu55a1n1 hu55a1n1 merged commit 241c184 into master Feb 8, 2022
@hu55a1n1 hu55a1n1 deleted the hu55a1n1/1770-deterministic-host-timestamp branch February 8, 2022 13:32
hu55a1n1 added a commit to hu55a1n1/hermes that referenced this pull request Sep 13, 2022
* Get host timestamp from latest host consensus state

* Add .changelog entry

* Fix store_update_time/height() impls

* Update mock context impl

* Use host_timestamp() instead of now

* Clarify the meaning of Height::zero() in host_consensus_state()

* Implement deterministic timestamps for Mock context

* Fix failing test

* Fix clippy warnings

* Avoid cloning MockContext pending_block

* Minor reformating

* Address review feedback

* Update ConnectionReader and ChannelReader traits for recent timestamp changes

* Remove latest_height from mock context
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handlers should use host's latest block's timestamp instead of host's timestamp
3 participants