FA-75051 / CRDT convergence / Open access
Bounded counter with rights transfer: a transfer is recorded in the reverse direction · case 01
The donor gains rights and the recipient loses them.
ROOT CAUSE
The transfer key is built as recipient>donor.
VERIFIED REPAIR
Record a move from r to to under the key "r>to".
Unsuccessful approach: Also crediting the recipient as an increment inflates the counter value by the transferred amount.
Case contract
Replicas share maps P (increments by replica), D (decrements by replica) and T ("from>to" transferred rights). A replica's rights are its own P minus its own D plus transfers to it minus transfers from it, all read from its local view. ["inc", r, k] grows P[r]; ["dec", r, k] and ["move", r, to, k] are rejected (event index recorded) unless rights >= k. ["sync", s, d] folds s's maps into d by maximum. Return values (sum P - sum D), rights, and rejected indices.
Why this case matters
Bounded counters keep a global non-negativity invariant without coordination by escrowing rights per replica.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events, replicas):
P = {r: {} for r in replicas}
D = {r: {} for r in replicas}
T = {r: {} for r in replicas}
rejected = []
def rights(r):
own = P[r].get(r, 0) - D[r].get(r, 0)
incoming = sum(v for k, v in T[r].items() if k.split('>')[1] == r)
outgoing = sum(v for k, v in T[r].items() if k.split('>')[0] == r)
return own + incoming - outgoing
for i, ev in enumerate(events):
kind = ev[0]
if kind == 'sync':
s, d = ev[1], ev[2]
for src, dst in ((P[s], P[d]), (D[s], D[d]), (T[s], T[d])):
for k, v in src.items():
dst[k] = max(dst.get(k, 0), v)
elif kind == 'inc':
P[ev[1]][ev[1]] = P[ev[1]].get(ev[1], 0) + ev[2]
elif kind == 'dec':
r, k = ev[1], ev[2]
if rights(r) < k:
rejected.append(i)
else:
D[r][r] = D[r].get(r, 0) + k
else:
r, to, k = ev[1], ev[2], ev[3]
if rights(r) < k:
rejected.append(i)
else:
key = to + '>' + r
T[r][key] = T[r].get(key, 0) + k
return {'values': [sum(P[r].values()) - sum(D[r].values()) for r in replicas], 'rights': [rights(r) for r in replicas], 'rejected': rejected}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
1: [('each replica spends only its own rights', [[['inc', 'a', 2], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 2]], ['a', 'b', 'c']], {'values': [0, 2, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 4], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [2, 2, 0], 'rights': [2, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 2], ['move', 'a', 'c', 1], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 1], ['dec', 'c', 1], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 1], ['dec', 'b', 1], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 1], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [4, 4, 3], 'rights': [1, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [2, 5, 2], 'rights': [2, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 1], ['dec', 'c', 4], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
2: [('each replica spends only its own rights', [[['inc', 'a', 3], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 3]], ['a', 'b', 'c']], {'values': [0, 3, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 5], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'rights': [3, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 4], ['move', 'a', 'c', 2], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 2], ['dec', 'c', 2], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [2, 0, 2], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 2], ['dec', 'b', 2], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [5, 5, 3], 'rights': [2, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 6], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [3, 6, 3], 'rights': [3, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 2], ['dec', 'c', 5], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
3: [('each replica spends only its own rights', [[['inc', 'a', 4], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 4]], ['a', 'b', 'c']], {'values': [0, 4, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 6], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'rights': [4, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 6], ['move', 'a', 'c', 3], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 3], ['dec', 'c', 3], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [3, 0, 3], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 3], ['dec', 'b', 3], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 3], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [6, 6, 3], 'rights': [3, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 7], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [4, 7, 4], 'rights': [4, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 3], ['dec', 'c', 6], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
4: [('each replica spends only its own rights', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 5]], ['a', 'b', 'c']], {'values': [0, 5, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 7], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'rights': [5, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 8], ['move', 'a', 'c', 4], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 4], ['dec', 'c', 4], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [4, 0, 4], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 4], ['dec', 'b', 4], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 4], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [7, 7, 3], 'rights': [4, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 8], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [5, 8, 5], 'rights': [5, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 4], ['dec', 'c', 7], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
5: [('each replica spends only its own rights', [[['inc', 'a', 6], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 6]], ['a', 'b', 'c']], {'values': [0, 6, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 8], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'rights': [6, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 10], ['move', 'a', 'c', 5], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 5], ['dec', 'c', 5], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [5, 0, 5], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 5], ['dec', 'b', 5], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 5], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [8, 8, 3], 'rights': [5, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 9], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [6, 9, 6], 'rights': [6, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 5], ['dec', 'c', 8], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
}[N]
for label, args, expected in cases:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| each replica spends only its own rights | {'rejected': [2], 'rights': [0, 0, 0], 'values': [0, 2, 0]} | {'rejected': [2], 'rights': [0, 0, 0], 'values': [0, 2, 0]} | Passed |
| transferred rights can be spent | {'rejected': [3], 'rights': [6, -2, 0], 'values': [4, 4, 0]} | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 2, 0]} | Failed |
| outgoing transfers reduce rights | {'rejected': [], 'rights': [2, 0, 0], 'values': [0, 0, 0]} | {'rejected': [2], 'rights': [0, 0, 0], 'values': [2, 0, 0]} | Failed |
| concurrent spending cannot go negative | {'rejected': [5, 6], 'rights': [2, 0, -1], 'values': [1, 1, 2]} | {'rejected': [6], 'rights': [0, 0, 0], 'values': [1, 0, 1]} | Failed |
| rights exhausted exactly | {'rejected': [2, 3], 'rights': [0, 0, 0], 'values': [0, 0, 0]} | {'rejected': [2, 3], 'rights': [0, 0, 0], 'values': [0, 0, 0]} | Passed |
| decrements propagate by sync | {'rejected': [], 'rights': [1, 0, 3], 'values': [4, 4, 3]} | {'rejected': [], 'rights': [1, 0, 3], 'values': [4, 4, 3]} | Passed |
| stale peer does not undo local decrements | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 5, 2]} | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 5, 2]} | Passed |
| transfer received before own increments | {'rejected': [4, 5], 'rights': [7, 0, -2], 'values': [4, 0, 5]} | {'rejected': [5], 'rights': [1, 0, 0], 'values': [4, 0, 1]} | Failed |
SHA-256 / 2400e468f4e7720ace12ce842339f9f1d36060092baa8155fc35568c5e6f923b
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events, replicas):
P = {r: {} for r in replicas}
D = {r: {} for r in replicas}
T = {r: {} for r in replicas}
rejected = []
def rights(r):
own = P[r].get(r, 0) - D[r].get(r, 0)
incoming = sum(v for k, v in T[r].items() if k.split('>')[1] == r)
outgoing = sum(v for k, v in T[r].items() if k.split('>')[0] == r)
return own + incoming - outgoing
for i, ev in enumerate(events):
kind = ev[0]
if kind == 'sync':
s, d = ev[1], ev[2]
for src, dst in ((P[s], P[d]), (D[s], D[d]), (T[s], T[d])):
for k, v in src.items():
dst[k] = max(dst.get(k, 0), v)
elif kind == 'inc':
P[ev[1]][ev[1]] = P[ev[1]].get(ev[1], 0) + ev[2]
elif kind == 'dec':
r, k = ev[1], ev[2]
if rights(r) < k:
rejected.append(i)
else:
D[r][r] = D[r].get(r, 0) + k
else:
r, to, k = ev[1], ev[2], ev[3]
if rights(r) < k:
rejected.append(i)
else:
key = r + '>' + to
T[r][key] = T[r].get(key, 0) + k
P[r][to] = P[r].get(to, 0) + k
return {'values': [sum(P[r].values()) - sum(D[r].values()) for r in replicas], 'rights': [rights(r) for r in replicas], 'rejected': rejected}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
1: [('each replica spends only its own rights', [[['inc', 'a', 2], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 2]], ['a', 'b', 'c']], {'values': [0, 2, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 4], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [2, 2, 0], 'rights': [2, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 2], ['move', 'a', 'c', 1], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 1], ['dec', 'c', 1], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 1], ['dec', 'b', 1], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 1], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [4, 4, 3], 'rights': [1, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [2, 5, 2], 'rights': [2, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 1], ['dec', 'c', 4], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
2: [('each replica spends only its own rights', [[['inc', 'a', 3], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 3]], ['a', 'b', 'c']], {'values': [0, 3, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 5], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'rights': [3, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 4], ['move', 'a', 'c', 2], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 2], ['dec', 'c', 2], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [2, 0, 2], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 2], ['dec', 'b', 2], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [5, 5, 3], 'rights': [2, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 6], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [3, 6, 3], 'rights': [3, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 2], ['dec', 'c', 5], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
3: [('each replica spends only its own rights', [[['inc', 'a', 4], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 4]], ['a', 'b', 'c']], {'values': [0, 4, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 6], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'rights': [4, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 6], ['move', 'a', 'c', 3], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 3], ['dec', 'c', 3], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [3, 0, 3], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 3], ['dec', 'b', 3], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 3], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [6, 6, 3], 'rights': [3, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 7], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [4, 7, 4], 'rights': [4, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 3], ['dec', 'c', 6], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
4: [('each replica spends only its own rights', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 5]], ['a', 'b', 'c']], {'values': [0, 5, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 7], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'rights': [5, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 8], ['move', 'a', 'c', 4], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 4], ['dec', 'c', 4], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [4, 0, 4], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 4], ['dec', 'b', 4], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 4], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [7, 7, 3], 'rights': [4, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 8], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [5, 8, 5], 'rights': [5, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 4], ['dec', 'c', 7], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
5: [('each replica spends only its own rights', [[['inc', 'a', 6], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 6]], ['a', 'b', 'c']], {'values': [0, 6, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 8], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'rights': [6, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 10], ['move', 'a', 'c', 5], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 5], ['dec', 'c', 5], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [5, 0, 5], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 5], ['dec', 'b', 5], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 5], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [8, 8, 3], 'rights': [5, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 9], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [6, 9, 6], 'rights': [6, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 5], ['dec', 'c', 8], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
}[N]
for label, args, expected in cases:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| each replica spends only its own rights | {'rejected': [2], 'rights': [0, 0, 0], 'values': [0, 2, 0]} | {'rejected': [2], 'rights': [0, 0, 0], 'values': [0, 2, 0]} | Passed |
| transferred rights can be spent | {'rejected': [], 'rights': [2, 2, 0], 'values': [4, 4, 0]} | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 2, 0]} | Failed |
| outgoing transfers reduce rights | {'rejected': [2], 'rights': [0, 0, 0], 'values': [4, 0, 0]} | {'rejected': [2], 'rights': [0, 0, 0], 'values': [2, 0, 0]} | Failed |
| concurrent spending cannot go negative | {'rejected': [6], 'rights': [0, 0, 1], 'values': [2, 1, 2]} | {'rejected': [6], 'rights': [0, 0, 0], 'values': [1, 0, 1]} | Failed |
| rights exhausted exactly | {'rejected': [2, 3], 'rights': [0, 0, 0], 'values': [0, 0, 0]} | {'rejected': [2, 3], 'rights': [0, 0, 0], 'values': [0, 0, 0]} | Passed |
| decrements propagate by sync | {'rejected': [], 'rights': [1, 0, 3], 'values': [4, 4, 3]} | {'rejected': [], 'rights': [1, 0, 3], 'values': [4, 4, 3]} | Passed |
| stale peer does not undo local decrements | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 5, 2]} | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 5, 2]} | Passed |
| transfer received before own increments | {'rejected': [], 'rights': [1, 0, 2], 'values': [7, 0, 5]} | {'rejected': [5], 'rights': [1, 0, 0], 'values': [4, 0, 1]} | Failed |
SHA-256 / f17e6e44bee3c8788e0bdf2ec38978e09c7304ec1781b290b72297e1a7007fb7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events, replicas):
P = {r: {} for r in replicas}
D = {r: {} for r in replicas}
T = {r: {} for r in replicas}
rejected = []
def rights(r):
own = P[r].get(r, 0) - D[r].get(r, 0)
incoming = sum(v for k, v in T[r].items() if k.split('>')[1] == r)
outgoing = sum(v for k, v in T[r].items() if k.split('>')[0] == r)
return own + incoming - outgoing
for i, ev in enumerate(events):
kind = ev[0]
if kind == 'sync':
s, d = ev[1], ev[2]
for src, dst in ((P[s], P[d]), (D[s], D[d]), (T[s], T[d])):
for k, v in src.items():
dst[k] = max(dst.get(k, 0), v)
elif kind == 'inc':
P[ev[1]][ev[1]] = P[ev[1]].get(ev[1], 0) + ev[2]
elif kind == 'dec':
r, k = ev[1], ev[2]
if rights(r) < k:
rejected.append(i)
else:
D[r][r] = D[r].get(r, 0) + k
else:
r, to, k = ev[1], ev[2], ev[3]
if rights(r) < k:
rejected.append(i)
else:
key = r + '>' + to
T[r][key] = T[r].get(key, 0) + k
return {'values': [sum(P[r].values()) - sum(D[r].values()) for r in replicas], 'rights': [rights(r) for r in replicas], 'rejected': rejected}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
1: [('each replica spends only its own rights', [[['inc', 'a', 2], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 2]], ['a', 'b', 'c']], {'values': [0, 2, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 4], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [2, 2, 0], 'rights': [2, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 2], ['move', 'a', 'c', 1], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 1], ['dec', 'c', 1], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 1], ['dec', 'b', 1], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 1], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [4, 4, 3], 'rights': [1, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [2, 5, 2], 'rights': [2, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 1], ['dec', 'c', 4], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
2: [('each replica spends only its own rights', [[['inc', 'a', 3], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 3]], ['a', 'b', 'c']], {'values': [0, 3, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 5], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'rights': [3, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 4], ['move', 'a', 'c', 2], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 2], ['dec', 'c', 2], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [2, 0, 2], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 2], ['dec', 'b', 2], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [5, 5, 3], 'rights': [2, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 6], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [3, 6, 3], 'rights': [3, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 2], ['dec', 'c', 5], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
3: [('each replica spends only its own rights', [[['inc', 'a', 4], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 4]], ['a', 'b', 'c']], {'values': [0, 4, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 6], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'rights': [4, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 6], ['move', 'a', 'c', 3], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 3], ['dec', 'c', 3], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [3, 0, 3], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 3], ['dec', 'b', 3], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 3], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [6, 6, 3], 'rights': [3, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 7], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [4, 7, 4], 'rights': [4, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 3], ['dec', 'c', 6], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
4: [('each replica spends only its own rights', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 5]], ['a', 'b', 'c']], {'values': [0, 5, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 7], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'rights': [5, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 8], ['move', 'a', 'c', 4], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 4], ['dec', 'c', 4], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [4, 0, 4], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 4], ['dec', 'b', 4], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 4], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [7, 7, 3], 'rights': [4, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 8], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [5, 8, 5], 'rights': [5, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 4], ['dec', 'c', 7], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
5: [('each replica spends only its own rights', [[['inc', 'a', 6], ['sync', 'a', 'b'], ['dec', 'b', 1], ['dec', 'a', 6]], ['a', 'b', 'c']], {'values': [0, 6, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('transferred rights can be spent', [[['inc', 'a', 8], ['move', 'a', 'b', 2], ['sync', 'a', 'b'], ['dec', 'b', 2], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'rights': [6, 0, 0], 'rejected': []}), ('outgoing transfers reduce rights', [[['inc', 'a', 3], ['move', 'a', 'b', 2], ['dec', 'a', 2], ['dec', 'a', 1]], ['a', 'b', 'c']], {'values': [2, 0, 0], 'rights': [0, 0, 0], 'rejected': [2]}), ('concurrent spending cannot go negative', [[['inc', 'a', 10], ['move', 'a', 'c', 5], ['sync', 'a', 'b'], ['sync', 'a', 'c'], ['dec', 'a', 5], ['dec', 'c', 5], ['dec', 'b', 1], ['sync', 'a', 'b'], ['sync', 'c', 'b']], ['a', 'b', 'c']], {'values': [5, 0, 5], 'rights': [0, 0, 0], 'rejected': [6]}), ('rights exhausted exactly', [[['inc', 'b', 5], ['dec', 'b', 5], ['dec', 'b', 1], ['move', 'b', 'a', 1]], ['a', 'b', 'c']], {'values': [0, 0, 0], 'rights': [0, 0, 0], 'rejected': [2, 3]}), ('decrements propagate by sync', [[['inc', 'c', 5], ['sync', 'c', 'a'], ['dec', 'c', 2], ['sync', 'c', 'a'], ['inc', 'a', 5], ['sync', 'a', 'b']], ['a', 'b', 'c']], {'values': [8, 8, 3], 'rights': [5, 0, 3], 'rejected': []}), ('stale peer does not undo local decrements', [[['inc', 'a', 9], ['sync', 'a', 'b'], ['dec', 'a', 3], ['sync', 'b', 'a'], ['sync', 'a', 'c']], ['a', 'b', 'c']], {'values': [6, 9, 6], 'rights': [6, 0, 0], 'rejected': []}), ('transfer received before own increments', [[['inc', 'a', 4], ['move', 'a', 'c', 3], ['sync', 'a', 'c'], ['inc', 'c', 5], ['dec', 'c', 8], ['move', 'c', 'b', 1]], ['a', 'b', 'c']], {'values': [4, 0, 1], 'rights': [1, 0, 0], 'rejected': [5]})],
}[N]
for label, args, expected in cases:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| each replica spends only its own rights | {'rejected': [2], 'rights': [0, 0, 0], 'values': [0, 2, 0]} | {'rejected': [2], 'rights': [0, 0, 0], 'values': [0, 2, 0]} | Passed |
| transferred rights can be spent | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 2, 0]} | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 2, 0]} | Passed |
| outgoing transfers reduce rights | {'rejected': [2], 'rights': [0, 0, 0], 'values': [2, 0, 0]} | {'rejected': [2], 'rights': [0, 0, 0], 'values': [2, 0, 0]} | Passed |
| concurrent spending cannot go negative | {'rejected': [6], 'rights': [0, 0, 0], 'values': [1, 0, 1]} | {'rejected': [6], 'rights': [0, 0, 0], 'values': [1, 0, 1]} | Passed |
| rights exhausted exactly | {'rejected': [2, 3], 'rights': [0, 0, 0], 'values': [0, 0, 0]} | {'rejected': [2, 3], 'rights': [0, 0, 0], 'values': [0, 0, 0]} | Passed |
| decrements propagate by sync | {'rejected': [], 'rights': [1, 0, 3], 'values': [4, 4, 3]} | {'rejected': [], 'rights': [1, 0, 3], 'values': [4, 4, 3]} | Passed |
| stale peer does not undo local decrements | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 5, 2]} | {'rejected': [], 'rights': [2, 0, 0], 'values': [2, 5, 2]} | Passed |
| transfer received before own increments | {'rejected': [5], 'rights': [1, 0, 0], 'values': [4, 0, 1]} | {'rejected': [5], 'rights': [1, 0, 0], 'values': [4, 0, 1]} | Passed |
SHA-256 / b87c210c4293d4ab02737f7b6c918b67e86525d6334352c297c386b21237da12
Verification & scope
A deterministic, bounded teaching model of one replicated data type with stipulated operation and merge rules; it is not a production CRDT library and makes no claim of conformance to any specific published design. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:49:02.455594+00:00.
Case digest / 4c8c19f5419f72250e34884526de113c5dc55aed4f24711a83bfb935d2f1999a