Channel checkpointing in ForceMove

Channel checkpointing like this is quite elegant, as it can be used to accomplish the same thing as respond, respondWithAlternative, and refute. IE. you could have an even smaller ForceMove protocol than the current one, with just forceMove, checkpoint and conclude.

On top of that, consider the following channel with participants [Alice, Eve]. Suppose they each hold states 99 and 100

  1. Eve maliciously calls forceMove(s10) with an old state.
  2. Alice calls refute(s99) in transaction tx1
  3. Eve sees tx2 and front-runs a transaction tx2 containing respond(s11)
  4. tx1 reverts, since the channel is now open
  5. Eve then repeats this with turn 11,12,…

In the current ForceMove protocol, this lets Eve block the channel for a duration roughly equal to the latest turn number times the challenge expiration duration. With checkpoint, Alice can stop this attack by calling checkpoint([s99, s100]).

It might also be worth modifying the requirements for refute to increment Eve’s turnNumberRecord, and then clear the challenge if it exists. This would mean that tx1 would not revert in 4, and Alice would not have to subsequently call checkpoint in a second transaction to block the above attack.

There is still benefit to having respond and refute:

  • when calling respond, you only have to check one valid transition and signature, so it’s more gas-efficient than calling checkpoint
  • when calling refute, the adjudicator has the option to penalize the challenger

The checkpoint method could be written to detect these two scenarios and react accordingly, but that would complicate the implementation and would not be as gas-efficient as the bespoke functions.

1 Like