Skip to content

ICS-004: Add weakly ordered packet semantics #872

Open
@ValarDragon

Description

@ValarDragon

ICS-004: Add weakly ordered packet semantics

Currently channels must be one of ordered and unordered. The current ordered channel, is really a "Totally ordered channel". Censorship resistance motivates a use case for a 'weakly ordered' channel. A weak ordering is a total ordering, but admits "ties". https://en.wikipedia.org/wiki/Weak_ordering

I've been using the verbage "partial ordering" for this idea in numerous irl discussions of the idea. The correct term is weak ordering, which can be understood as a partial ordering where "incomparable items" are all treated as equivalent for ordering purposes ('tied').

Motivating use case

The idea of weak ordering has use cases for both censorship resistance and IBC app correctness. For brevity, we focus on the censorship resistance use case.

A user believes that their tx T is being censored on chain B, and that they are not censored on chain A. Furthermore, assume there is a significant channel C between chain A and chain B, in which chain B would be negatively impacted if it was halted.

To increase the incentive for chain B to include T, the user would like to make an IBC packet P_T from A to B on channel C, which leads to the execution of T on chain B. This action should place a further constraint on the channel, that chain B (by state machine validity) will reject processing any channel C packet created after P_T from chain A, until P_T has been delivered to chain B. So any new packet on this channel is forced to come after P_T. Thus for chain B to continue to censor T, they must also censor every new packet from A to B on C, which by construction has high impact.

Thus chain B is sanctioned such that it is in a position where it must pick between:

  • executes tx T
  • Delay tx T further, along with all other interchain communiction from channel C
  • Commits a state machine validity violation (high cost, not an honest-but-curious fault)

Proposed channel communication semantics

The way this would look like at the communication layer, is we assign every packet a sequence_group. (Or equivalently, we can imagine parsing a sequence number S into (sequence_group, intra_group_sequence), and communicating necessary information to facilitate this). Suppose chain A's sequence_group for channel C is currently G. Then Chain A has the correctness guarantee that every subsequent outbound packet for this channel has sequence group >= G.

Whenever A increments the sequence group from G to G+1, it also communicates an integer k (typically 0 or 1), which sets a validity condition on chain B that "In order to process any tx in group G+1, we must have already processed at least k txs from group G".

We would need to maintain the number of packets processed from the last sequence group. For chain B to count a packet, it must get delivered to chain B (even if timed out), to prove that it got sent.

Both chain A and chain B maintain sequence groups for their inbound and outbound packets, just as they currently do for sequence numbers.

Satisfying the censorship resistance problem

To satisfy the censorship resistance issue, chain A has functionality that allows a user to atomically:

  • increment the sequence group to G+1, with k=0 (G+1 has no req'ts on number of G packets)
  • make 1 outbound tx (P_T), with massive timeout. (years)
  • increment the sequence group to G+2, with k=1 (G+2 txs can only be delivered after 1 G+1 packet is delivered).

Recall that every new tx created on this channel will be at a group >= G+2.

Thus the set of txs from A to B are:

{
    G:      "packets created before P_T"
    G + 1:  "P_T"
    G + 2:  "packets created after P_T"
}

There are no restrictions on Chain B's ability to process sequence group G txs, just by construction they all predate P_T. And then by the restriction, G+2 can only be processed after the G+1 packet is made, satisfying all of our desired guarantees.

Suggested App details

App considerations, that are not within the realm of the channel layer:

  • Chain A should require a notable charge for a user to create a sequence group increment with k != 1 on the primary channel, as this can reduce liveness even when theres no censorship, due to introduction of this blocking behavior.
  • Chain A should require that the G+1 packet has a notable chain-B acceptable fee attached. (Fee tips mean this is always fixable due to the channel being blocked, but this would reduce adversarial channel blocking). This requires reasoning about chain B's current fee rate, so not really doable until cosmos gets to more complex fee-markets.
  • Chain B's liveness for the channel requires allowing receiving IBC relays that only contain inbound packets that would time out.

Future discussion, that should be non-blocking

We would like more IBC-apps to opt-in get themselves onto the primary channel that will block / get this censorship resistance guarantee, while maintaining their own total-ordering within their sub-system semantics. For instance, we would want a given ICA account to be able to choose to get multi-plexed onto the main channel, and re-use the weak ordering for achieving its own total-ordering-for-an-account guarantee, while not forcing blocking behavior for other packets.

This is a feature that should not at all block the initial deployment of weak ordering. I view this (and allowing apps to be multi-plexed with their own weak ordering guarantees) as fully achievable via allowing more complex predicates for sequence group validity. The initial proposal is at least k txs included from last group. I believe you can achieve the ICA total-ordering guarantee by relaxing this predicate to Sequence group A requires at least k txs included from sequence group B. So if a particular ICA accounts last message was in group S, and we are currently in group G we would make the next ICA tx by atomically doing:

  • increment the current sequence group to G+1, whose restriction is k=1 from sequence group S
  • Make 1 packet for ICA outbound
  • increment the current sequence group to G+2, with no restriction on prior sequence groups. (k=0)

So there are no constraints with going to G+2 immediately. The only constraint checked here is on packets to G+1, which then depend on the S constraint being satisfied. In general, we can optimize s.t. we only need to check sequence group constraints until they have been satisfied once. This is because we can assume once a sequence group has been satisfied, it remains satisfied forever.

We should be able to as time goes on, be able to protocol-upgrade allow more complex predicates for sequence group validity than at least k txs included from last group .

Aside: Weak ordering use case for IBC app correctness

The IBC app correctness properties are relevant when:

  • app on chain A relies on getting communication to chain B in a particular order, over existing channels (necessary if token transfers are involved)
  • app on chain A itself requires a weakly ordered communication to chain B.

We can imagine an app that requests oracle updates from a provider, and then wants to make a swap that could only execute after its returned an oracle update. But we don't want any of this communication to block the rest of the communication channels.

Thanks @cwgoes @sunnya97 @AdityaSripal @nicolaslara for all the discussions / ideation leading to this proposal!

Metadata

Metadata

Assignees

No one assigned

    Labels

    featurePossible future feature.not plannedtaoTransport, authentication, & ordering layer.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions