Problem: Two or more RevVault transfers to the same RevVault are conflicting. This is a problem in general and in particular for the PoS contract since on every user deploy we want to make transfers to the same PoS vault.
The root cause of why two or more transfers to the same vault are conflicting, lies in NonNegativeNumber.rho
:
contract this(@"add", @x, success) = {
if (x >= 0) {
for(@v <- valueStore){
if (v + x >= v) {
valueStore!(v + x) | success!(true)
} else {
//overflow
valueStore!(v) | success!(false)
}
}
} else {
success!(false)
}
}
According to the C! C!
rule in the Mergeable Google Sheet, the add
contract conflicts because two different blocks that execute the add
contract would fight over consuming the value at valueStore
. This leads to different post states depending on which linear consume comes first.
Proposed solution:
It is easy to see from the add
contract that the C! C!
rule can be too strict.
There is no reason for the add
contract having to conflict since after each for(@v <- valueStore)
a send on valueStore
happens and addition is commutative.
However I am unsure how big the changes are that are required to detect the add
contract as non-conflicting.
-
Comm events would need to have some knowledge about Rholang syntax so that conflict detection can for example differentiate between:
for (@v <- valueStore) { valueStore!(...) }
(commutes with itself)for (@v <- valueStore) { Nil } | valueStore!(42)
(does not commute with itself)
-
Since the overflow case in the
add
contract does not commute, there needs to be a way to differentiate between the non-overflow produce (valueStore!(v + x)
) and the overflow produce (valueStore!(v)
). One way to do that would be to check if the underlying value increased. If it was increased, we had no overflow. If it stayed the same, there was an overflow and a conflict needs to be raised.
In the second bullet point the overflow could be made less conflict prone by leveraging peek syntax: