Block merging - conflict resolution - peek

WIP

Scope

A place to gather brilliant thoughts regarding using peek in conflict resolution.

Problem statement

The current implementation of conflict resolution for blocks lives https://github.com/rchain/rchain/blob/dev/casper/src/main/scala/coop/rchain/casper/EstimatorHelper.scala and boils down to

b1AncestorChannels.intersect(b2AncestorChannels).nonEmpty

Two validators V1 and V2 are deploying rholang.

The first step for this mechanism to work is to charge for a deploy (move rev from deployers vault to validators vault)

This means looking up deployers vault from the vault map (held by the RevVault contract).

The way rholang currently deals with this action is by generating a consume and a produce (destroy, create new).

Since there is no way of knowing if the data changed or not - the new values diverge as they were created by different validators - this will conflict and create a contention point.

But rholang will be able to 'peek' - deliver the value without modifying the content of the tuplespace.

Now this means that the log will contain a COMM event that is marked as 'peek' which essentially means "I can safely ignore conflicts with other peeks on this channel".

Open topics

  • how should the COMM event marker look like?


Peek with trie merging

Problem statement

This writeup is a follow up to an ongoing discussion regarding "conflicts during rev transfers".

Two types of change need to be identified:

  • data updated (consumed and then replaced with a different value)
  • data read (consumed and replaced with the same value, this is essentially peek)

To be able to track the 1st case the random part of a term is used.

The second part is tricky: on one hand it is inefficient to change the random part of a piece of data every time it's read but at the same time this allows the system to track execution paths (event log).

This has been proven problematic when a "hacked peek" was introduced in Registry (https://github.com/rchain/rchain/pull/1817).

Current implementation of RSpace requires external sources to point out that a value is peeked (rholang syntax) and it depends on the above sequence number to be able to properly replay deploys.


All of the above is discussed because of one goal: merge blocks that collide on same channels.

High level overview of the scenario discussed:

User A transfers rev to User B using validator V1. This results in:

  • block B1_1 being created
  • respective balances changing
  • validators V1 receiving payment for handling transfer 

User C transfers rev to User D using validator V2. This results in:

  • block B2_1 being created
  • respective balances changing
  • validators V2 receiving payment for handling transfer 

both blocks contain data on moving rev and at some point in the chain there will be a need to merge the separate states.

Currently the block merging rules will fail this attempt for various reasons, which all boil down:

  • a channel can be modified in one block at a time

This restriction can be further specified as:

  • data that was read and not modified still appears as modified as it's random state changed (rspace is unaware of this distinction)
  • persistent continuations being invoked (data sent to them) create a trace that is being ignored (the event log holds information that these events can be safely ignored but the conflict resolution is not making use of it)

To address the first limitation peek was proposed and partially implemented.

The second limitation needs to be solved in merging rules.


A new approach has been proposed that could solve a larger class of problems than peek:

RSpace could track the data part during contract execution and identify what changed and what didn't. It would still produce an event log but it could then intervene on checkpoint creation essentially making the peeked data be transparent (reverting the value and the random part to the initial value). This makes the conflict resolution rules that are needed for contracts pretty straight forward - anything marked by RSpace as "changed" will can be a conflict, the rest can be safely ignored.

This boils down to:

block B1_1 and B1_2 from the previous example would represent only the states of the rev vault balances that changed during respective deployments, ignoring most of the data fetching.

The event logs would be easily prunable enabling a simple check (channels B1_1 do not intersect with B1_2? it's ok to merge).


The upside is that this keeps the rules contained in one spot and makes the a "one layer" concern. It also enables a straight forward implementation of trie merging in the tuplespace.

The downsides are:

  • it's very unclear what the ramifications might be
  • RSpace needs to be aware of a lot of stuff (how to reroll random part, what is data, continuation, how to separate those, how to track change)
  • this solves a piece of the general merging rules, not all of them, and it might block solving other ones
  • it seems that the solution is in the wrong layer