L1 to L2 messaging retry mechanism
L1 to L2 messaging can fail due to:
- not enough gas (main reason)
- unusual state on L2
We need to build this mechanism avoiding losing asserts (locked on L1, but failed to mint on L2)
approach:
- in
validateprocess, add replay checking. We need to record failed_relay_msg in contract. Iffailed_realy_msg[hash(tx)] = true, we could replay it. It makes me confused that in Optimism, they hash the gas_amount, if we do that too, how could we replay it by increasing gas? After increasing gas amount, we shouldn't findfailed_realy_msg[hash(tx)] = true - checking it outside contract (
rooch_nodemay cheat, and other node may have inconsistent state if we will have decentralized deployment) - checking it in user's contract, we could provide module and functions but we could not control user's behaviors (we may use compiler/MoveVM to make such a promise).
- L1ToL2 tx does not need to pay gas because the gas has been charged on L1. The attacker can not use the L1ToL2 tx to DDoS.
- If the tx aborts on other conditions, there are bugs in the contract. We need to fix the bug and upgrade the contract.
- We need to record every successfully progressed L1ToL2 tx hash in the contract to avoid the replay attack.
Gas is burn on l1 it doesn't mean there is no gas needed on l2. The gas burn on l1 is according the estimate on l1. But what if user just give a very small min_gas_amount(which is l2 to cost) but call a very large function on l2. L2 need to check users has enough gas and ask user replay it with higher gas(also means burn more on l1) @jolestar
L1ToL2 tx does not need to pay gas because the gas has been charged on L1. The attacker can not use the L1ToL2 tx to DDoS.
If the tx aborts on other conditions, there are bugs in the contract. We need to fix the bug and upgrade the contract.
We need to record every successfully progressed L1ToL2 tx hash in the contract to avoid the replay attack.
For 3: the main issue here is after validating the event and get the move_action(user contract), the execution begins. So where to put the contract storing successful tx
Gas is burn on l1 it doesn't mean there is no gas needed on l2. The gas burn on l1 is according the estimate on l1. But what if user just give a very small min_gas_amount(which is l2 to cost) but call a very large function on l2. L2 need to check users has enough gas and ask user replay it with higher gas(also means burn more on l1) @jolestar
If this condition, the OutOfGas status tx should be treated as progressed successfully. The user needs to change the max_gas_amount(I still think the min_gas_amount should be max_gas_amount in L2 tx) and send it again.
For 3: the main issue here is after validating the event and get the move_action(user contract), the execution begins. So where to put the contract storing successful tax
In the post_execute function?
Gas is burn on l1 it doesn't mean there is no gas needed on l2. The gas burn on l1 is according the estimate on l1. But what if user just give a very small min_gas_amount(which is l2 to cost) but call a very large function on l2. L2 need to check users has enough gas and ask user replay it with higher gas(also means burn more on l1) @jolestar
If this condition, the OutOfGas status tx should be treated as progressed successfully. The user needs to change the max_gas_amount(I still think the
min_gas_amountshould bemax_gas_amountin L2 tx) and send it again.
It will be easier to estimate gas cost on l1 according to min gas amout. The min gas amount is just the target on l2's cost, so what we need to do on l1 is just adding extra process gas cost. If we use max amount, how to estimate l2 cost on l1?
In theory, retryable messaging is important when there is assert attached on it: L1 has locked assert, but mint is failed (because too low gas) on L2.
In practice, the default gas amount is far more than enough for assert transfer. We could add this mechanism after the whole data flow finished. Because it's a condition, it doesn't affect the main branch. @popcnt1