-
Notifications
You must be signed in to change notification settings - Fork 329
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
Update client may cause "new header has a time from the future" chain error #1445
Comments
Jacob was reporting this same error (osmosis-labs/osmosis#520 (comment)) potentially also on a sifchain channel, not really sure. Two questions:
|
I think it's fine and advisable for new clients. Existing clients would need to be upgraded.
It's not straightforward at exactly the place the error is issued but we will find a way to print more info. In the example in the description the third block 7988810 has client updates tx-es. When suggesting setting From hermes side we should consider the following:
|
Maybe the total clock_drift value when creating a client needs to consider the worst case, i.e. it should be: |
doh, just saw that empty block time is configurable via |
I'm not sure if it is necessary to do on chain. Taking into account the block time drift would require knowing the expected block time? We recently added an on chain parameter for this (so relayers could use that value). But to take this into account on chain for the light client, we would need to add a new parameter to the ClientState? That upgrade path currently is very difficult (it is IBC protocol breaking). In the short term, it is better to account for this in MaxClockDrift (although now this field is misleading) cc @AdityaSripal Re upgrading existing clients: Currently I'd say this is infeasible. The only two options are:
Regular client upgrades cannot be used since this is a custom field. I've been planning to open a issue/discussion around ignoring the |
We can just make it incumbent on the relayer who creates the client to set a Re: Upgrading existing clients Yes this is currently not possible. We explicitly prevent custom fields to change after the fact, to prevent the security parameters of a client changing after it has been created.
Regarding what Hermes can do immediately: You can either perform the check client side and only submit the header once it is no longer in the future |
Could you please provide more details on this?
This would be the local chain block time to be added to the client state drift....
I think we may as well wait for the next block since nothing can proceed if client update fails and it is as trivial as waiting for a fixed duration. |
yup, that's the plan |
03-connection now has an on-chain parameter MaxExpectedTimePerBlock. This is used to enforce block delays for packet processing. It is supposed to represent the maximum expected time it takes to produce a block (any duration longer than that specified should be an anomaly). It doesn't have a strong definition though, it is fairly arbitrary to pick the value for. The default is 30 seconds, which I expect most chains will likely use |
@ValarDragon this issue is basically all over. I first saw it over a month ago with osmo-regen, but have since seen it nearly everywhere -- and regardless of the relayer software being used. |
The best place to see |
Thanks! we will use a similar local testnet for testing the fix. |
Sorry for being late here. In the light client spec, If I am not wrong @ancazamfir was considering the following scenario: we consider a top header h at chain A, and a top header H at chain B, and we try to understand what is the condition under which header h will be considered acceptable from time perspective on the chain B. I don't see other way of making this work in any case unless relayer is checking top header time on chain B and making sure that the condition is satisfied. This is at least from theoretical perspective only sound in my view, as we could have period with no blocks on the chain B. In case you try to optimise for the normal case where blocks are continuously being produced on the both chains (normal case), we need to take into account that from the perspective of time of the latest block on the chain B time of the header on chain A is not too much in the future. For example, in the worst case if a header h is committed roughly at time
My point here is that even if we assume that blocks on both chains are produced continuously so we know what is the average block time, and bft times on both chains are in sync, we can still be in this scenario where destination chain still hasn't produced the latest block which time is close to now, while such block is produced on the source chain. In this case, no matter how we choose parameters, the client update might fail. Does this make sense or I am misunderstanding something? |
Thanks Zarko!
which means that herems could check before the update:
For this purpose I was proposing creating the client with a "
So the check would be: Now the question is what do we do in hermes if this check doesn't hold. The cause could be:
We could drop the header and return error. In most cases the effect will be that the event that triggered the update will be re-processed and will result in an update with a header at a different height. Another alternative is to create instead the client with drift
This one is tempting at first look as it avoids adding yet another configuration parameter and the pain of coming up with a good value. But... In either implementation we would alert the user that an in-the-future header was seen so the proposer's clock can be checked. |
@faddat Could you please paste a sample |
We are also seeing this issue with the golang relayer |
Crate
relayer
Summary of Bug
@mircea-c has reported that the following errors are seen once in a while when updating the
sifchain
client (07-tendermint-395
) oncosmoshub
:After looking at the sif chain configuration (client created with
clock_drift = 5sec
) and comparing block times (5-6 sec on sif, 7-13 sec on hub), the following seems to be the issue.Here is an example (
-
is 1 sec,b
are blocks on sif,B
are blocks on the hub).The steps are:
1 - an IBC event that requires a clientUpdate
2 - hermes starts to build the client update message and
3 - fetches the header
h
from sifchain (this happens for the header at event height + 1)4 - sends a simulate request to the hub (can happen on send_tx as well)
5 - the chain receives the request and creates a context with the latest header
H
on the hub6 - the client handler is called with that context and the message. Among other things it checks that the
h.timestamp
is not "in the future", i.e.H.timestamp + client_state.clock_drift > h.timestamp
(one 13 sec example on the hub:
h:7969646 - ts:16:31:24
h:7969647 - ts:16:31:37
)
One problem is that the
clock_drift
of 5 sec is not enough for clients of sifchain on the hub. But it might be appropriate for clients of sifchain on other chains. This in itself is a hint on the difficulty of sizing this properly. Also changing the configuration alone is not enough to fix the issue, it would require new clients, connections and channels to be created, and applications to switch to these.The other solution is to make hermes' update client code more robust. This issue is to investigate and if possible fix this on hermes side.
cc @adizere @romac
A number of ideas were mentioned, hermes could maybe perform the
H.timestamp + client_state.clock_drift > h.timestamp
check when updating tendermint clients, or drop the tx on the specific tx simulate (ortx_send()
) error ( (to be picked by the clear packet mechanism or retries for channel/ connection handshake).Version
all
Steps to Reproduce
We should be able to reproduce this with local setup, create two chains with different block times, create client with small clock_drift values.
Acceptance Criteria
Ideally this error should never be seen with correct headers. Impact on hermes operation should be minimal with "bad" headers, e.g. one that is in the long future.
For Admin Use
The text was updated successfully, but these errors were encountered: