wormhole
wormhole copied to clipboard
As an integrator, I want to get signed EVM messages at and earlier than finality
Expected Behavior
For chains which feature finality but not instant finality (Ethereum, Moonbeam, Polygon, etc), I should have the option to accept the risk of emitting a message prior to finality. For chains that have explicit block statuses, e.g. how post-merge Ethereum has Unfinalized and Unfinalized (Safe), I should be able to specify at which status I want my message emitted.
Furthermore, the default postMessage behavior should be to wait for finality and not longer. It doesn't make sense to wait for 1 block after a finalized block. This would make explainer pages like https://book.wormhole.com/reference/contracts.html#blockchain-finality-recommendations only necessary for advanced integrators who want to go faster, into unsafe territory.
Current Behavior
The EVM watcher puts all messages into a pending queue, which only releases messages after their block + consistency has been finalized. Even on the lowest consistency, 1, chains in which blocks are final require waiting until the following final block.
Possible Solution
Given that the existing EVM spec has consistency as a uint8, a 'magic number' could be specified to represent these special state exceptions for chains. For example:
200= Unfinalized201= Unfinalized (Safe), only applicable to Ethereum
Then, when the watcher receives a message with the consistency set to 200, it could instantly publish it instead of adding it to the pending queue. To handle achieving faster finality without unnecessarily waiting additional blocks, for any other values the watcher could use minConfirmations (and probably rename that finalityConfirmations or something). This could be set to 0 for all chains except for BSC which 15 is recommended.
That leaves the only odd case of 201 on Ethereum. Since every epoch should yield a new final batch and a safe batch, the watcher could leave the "Safe" number 201 which could be checked in the pending loop on new blocks and fall into a new, special path which uses getBlock("safe").
I propose allocating the entire range of 200-255 (inclusive) of consistency_level for magic numbers and have the guardians not process any messages with consistency_level in that range where a magic number has not been allocated. (on all chains). We should also check if there are any xApps who are actively using values in that range (I hope not). I also propose not using the same magic number across multiple chains, e.g. if 201 means "safe" on Ethereum, guardians should not process messages with the value 201 originating on other chains.
What do you think of adding a special magic value (maybe zero) that is valid across all chains and would default to the Wormhole recommendations for ensured consensus specific to each chain, i.e. the values here: https://book.wormhole.com/reference/contracts.html#blockchain-finality-recommendations.
That way, integrators have a secure default, which is very convenient for deploying the same code on multiple chains.
Q: I'm curious what you think consistency_level in the range of 1-32 should map to after making this change. I think it should map to the amount of blocks after "latest", i.e. not wait for eth "safe" to be reached. This could have unintended consequences for xApps already deployed, so we'd need to announce this change well in advance and give time to xApps to upgrade.
In summary I'm proposing the following course of action:
- [ ] Define a range of numbers that will be reserved for magic values: 200-255 (inclusive).
- [ ] Define consistency_level = 0 to be the default value and a magic number mapping to a conservative recommendation for finality on each chain.
- [ ] Check that no xApp is using any of these reserved magic numbers today.
- [ ] Allocate specific magic numbers to map to these new concepts of finality from the various chains. Stop processing VAAs for any consistency_level that is within the range of magic numbers but has not been allocated to a specific meaning.
- [ ] Update the Guardian watchers to respect these new magic numbers.
- [ ] Socialize these new “magic numbers” with xDap developers, such that they can make informed decisions about how the consistency level would affect their project. We could provide recommendations based on risks of that particular protocol.
- [ ] Set a reasonable deadline for all xApps to review these protocol changes, make an informed decision and deploy any desired changes.
- [ ] After the deadline has passed, drop the minimum finality requirements currently defined in various watchers.
What do you think of adding a special magic value (maybe zero) that is valid across all chains and would default to the Wormhole recommendations for ensured consensus specific to each chain, i.e. the values here: https://book.wormhole.com/reference/contracts.html#blockchain-finality-recommendations.
That way, integrators have a secure default, which is very convenient for deploying the same code on multiple chains.
Personally, I'd prefer any non-reserved value to be safe - the only tricky one is BSC 🤔
Q: I'm curious what you think consistency_level in the range of 1-32 should map to after making this change. I think it should map to the amount of blocks after "latest", i.e. not wait for eth "safe" to be reached. This could have unintended consequences for xApps already deployed, so we'd need to announce this change well in advance and give time to xApps to upgrade.
Quick note, Eth waits for "finalized" not "safe". Outside of BSC, setting any number here is rather irrelevant or wouldn't do the right thing, so I'm not keen on maintaining the existing functionality. Instead, I suggest all values should simply be treated as 'finalized + 0`
I believe there was a reason that 0 should not be set for consistency (maybe because it's a default uninitialized value) and it's also kinda odd to me that 0 would be finalized but 1 wouldn't be. @hendrikhofstadt can opine.
But do you think there are xApps who might want to go even faster on Ethereum than "safe", i.e. n blocks where 0<=n<32.
I could think of a scenario where an xApp only cares about making sure that the message was validated on chain and doesn't care about consensus.
An example would be Pyth, although Pyth is not emitting from Ethereum.
But do you think there are xApps who might want to go even faster on Ethereum than "safe", i.e.
nblocks where0<=n<32. I could think of a scenario where an xApp only cares about making sure that the message was validated on chain and doesn't care about consensus. An example would be Pyth, although Pyth is not emitting from Ethereum.
I assume you're using 32 here because that's an epoch? Absolutely folks want to go faster, that's why my original suggestion here was 200 = "as soon as the watcher sees it". I honestly don't see a great cause for waiting, like, 3 blocks instead of just 1. Seems like on Eth today you want your options to be:
- Immediate
- Safe
- Finalized
which would map to
- 200 = Immediate
- 201 = Safe
- anything else = Finalized
I propose allocating the entire range of 200-255 (inclusive) of consistency_level for magic numbers and have the guardians not process any messages with consistency_level in that range where a magic number has not been allocated. (on all chains). We should also check if there are any xApps who are actively using values in that range (I hope not). I also propose not using the same magic number across multiple chains, e.g. if 201 means "safe" on Ethereum, guardians should not process messages with the value 201 originating on other chains.
I wonder if 55 levels may not be enough if we are reserving, potentially, 2+ per chain. I wonder if we can group chains together. eg. 200 => immediate for Eth and all EVMs, 210 => immediate for all cosmwasm chains?
I propose allocating the entire range of 200-255 (inclusive) of consistency_level for magic numbers and have the guardians not process any messages with consistency_level in that range where a magic number has not been allocated. (on all chains). We should also check if there are any xApps who are actively using values in that range (I hope not). I also propose not using the same magic number across multiple chains, e.g. if 201 means "safe" on Ethereum, guardians should not process messages with the value 201 originating on other chains.
I wonder if 55 levels may not be enough if we are reserving, potentially, 2+ per chain. I wonder if we can group chains together. eg. 200 => immediate for Eth and all EVMs, 210 => immediate for all cosmwasm chains?
@panoel this is only applicable to EVM chains, since this is specific to the EVM watcher. The core Solidity contract has this consistencyLevel parameter on the publishMessage function, which does not exist on every implementation (e.g. cosmwasm's PostMessage has no equivalent as Tendermint has instant finality). Similarly, Solana has its own enum system where 0 is confirmed and 1 is finalized. That said, I expect most EVM chains will not have that many permutations of these concepts and we can certainly reuse the enums across chains - so 200 would mean publish immediately on all chains that use the EVM watcher / Solidity contracts, and 201 would mean safe for all chains that have that concept (currently only Ethereum, though more may follow this RPC API) and default to finalized if not.