optics-monorepo
optics-monorepo copied to clipboard
How to track a message through the Home and Replica contracts?
I know we talked about this on the meeting already, but somehow I can't piece it together again. In the interest of transparency, I figure I move the convo here.
When I enqueue a message through the TokenBridge xApp, how can I track its "status" on the receiving domain/replica?
I vaguely remember that I was supposed to parse out the sequence number, but I don't remember why. Was tracking the leaf (keccak of message) and its message status on the replica not sufficient?
Unrelatedly, I was curious about the use of the nextToProcess
variable? I see it assigned, but never really used?
Oh, was it because messages are likely to be proveAndProcess
ed and therefore the thing to track is actually the root of the tree in which the message first appears?
- poll the replica to see if
await replica.confirmAt(newRoot) >= now
. if 0, the root is unknown. if set, it's the time at which the message is eligible for processing. - poll
await replica.messages(leafHash)
for the message status
nextToProcess
is externalized to agents to simplify implementation
Thanks for the prompt response.
How do I determine the root of the enqueue? It's not part of the emitted event as far as I can tell? Do I have to make the view call right after the tx? It technically won't give me "the" root of my message right, it could be an arbitrary root after "my root"?
What do I do if the updater doesn't call Replica#update
with my root but with any root after mine?
Also, I don't know if it's related, but with the current event emission, it is impossible to track the transaction that will process the message on the replica correct? As in if I want to show the etherscan tx that results in the transfer on the receiving domain, I don't think I can easily do it?
These are all problems for a standalone tx indexer, which we have not yet written
So for the TokenBridge GUI, what would you recommend for "tracking" a transfer of a token? just do the polling of 2)?
yeah, that'll work
to find the root containing a message, use eth_getLogs
Update events starting from the block in which the TX was confirmed.
If an Update event occurs in the block, compare tx indices. Accept the Update if its index is later than the enqueue
Otherwise sort returned logs by block height and take the first
🙏 for the convenience events. Quick comment: (hope you don't mind me adding them here since the PR already merged). Even with the root in the Dispatch
event, it will still be challenging to "track" the root update on the Replica since it could be any root after "our root" that is being updated on the Replica right? Put differently, our root may never appear again, either on Home or Replica (other than technically when it gets dequeued on Home)? (all this is assuming that the updater will not update every single root, but batch roots)
"the successor of the current root" is a sufficient heuristic. Only breaks in uncommon race conditions
How do I determine whether a given root is a successor of the current root?
you use the Update
event
Sorry I must be missing something, but what if the root prior to the message is A, the root of our message is B and then the root of a message after us is C. If there is an update event from A -> C, wouldn't we be unable to find an update involving B? Or are you saying that in practice, updaters will always update every single root and not batch?
why do you need to know anything about B when C necessarily includes it?
How do I know that C is a successor of B? Or put differently, how do I know for a given Update
whether it includes my root if its not equal to either _oldRoot
or _newRoot
?
"the successor of the current root" is a sufficient heuristic. Only breaks in uncommon race conditions
How do I know that C is a successor of B
because the Dispatch
event with root C will be emitted after the Dispatch
event with root B
not necessarily the most elegant interface, i will readily admit
here's how you can do this as a xApp developer:
- when you enqueue the message, check the
Dispatch
event and storelatestUpdatedRoot
andmessageHash
- get the
Update
event on the Home wherelatestUpdatedRoot (from original Dispatch event) == oldRoot (2nd indexed param on Update event)
- this means your message has been included in the update on the Home domain - get the
Update
event on the Replica wherelatestUpdatedRoot (from original Dispatch event) == oldRoot (2nd indexed param on Update event)
- this means your message has been relayed to the destination domain - get the
Process
event on the Replica wheremessageHash (from original Dispatch event) == messageHash (1st indexed param on Process event)
- this means your message has been processed on the destination domain - the second arg,success
, is true if the call was executed successfully or false if there was a revert at the contract level
Note: in 2, 3, and 4 when I say "get" the event, there are two possible methods:
- setup an event listener that is triggered whenever new events are fired, and check each to see if it is the event in question
- poll for the event in question at regular intervals
@anna-carroll @prestwich Do you think we should include this issue in the #599 Epic or is it fine to fully document this post-release?
ideally we build out a whole TS lib for accessing optics that does this for you automagically. but that's a future future. in the meantime, add this to documentation