FA-481 / Consensus / Open access
Promise a proposal ballot: A prepare message targets a different consensus instance · case 01
The acceptor prepare operation is admitted even though a prepare message targets a different consensus instance.
ROOT CAUSE
The admission path omits the slot scope invariant while validating the other operation preconditions.
VERIFIED REPAIR
Require r['slot_scope'][0] == r['slot_scope'][1] together with every other stated precondition before accepting the operation.
Unsuccessful approach: Adding the slot scope check repairs the reported defect, but replacing the adjacent promise durable check loses that independent invariant.
Case contract
Return a Boolean admission decision for promise a proposal ballot. The record r must satisfy all of: tuple(r['ballot_floor'][0]) >= tuple(r['ballot_floor'][1]); r['slot_scope'][0] == r['slot_scope'][1]; r['promise_durable'] is True; r['accepted_attached'][0] is None or r['accepted_attached'][1] == r['accepted_attached'][0]; r['configuration_epoch'][0] == r['configuration_epoch'][1]. Extra tracing fields are ignored; validation does not mutate the record.
Why this case matters
A deterministic local contract for consensus. Each negative fixture violates exactly one invariant. No transport timing, persistence, cryptographic verification, or full protocol implementation is claimed.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(r):
return (tuple(r['ballot_floor'][0]) >= tuple(r['ballot_floor'][1])) and (r['promise_durable'] is True) and (r['accepted_attached'][0] is None or r['accepted_attached'][1] == r['accepted_attached'][0]) and (r['configuration_epoch'][0] == r['configuration_epoch'][1])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
r = {'ballot_floor': [[5, 2], [5, 1]], 'slot_scope': ['s1', 's1'], 'promise_durable': True, 'accepted_attached': ['chosen', 'chosen'], 'configuration_epoch': [3, 3]}
check('valid operation', solve(r), True)
check('An acceptor promises a ballot below its durable promise', solve(dict(r, **{'ballot_floor': [[4, 9], [5, 1]]})), False)
check('A prepare message targets a different consensus instance', solve(dict(r, **{'slot_scope': ['s2', 's1']})), False)
check('A promise response escapes before its durable write', solve(dict(r, **{'promise_durable': False})), False)
check('The response omits an already accepted value', solve(dict(r, **{'accepted_attached': ['chosen', None]})), False)
check('A prepare is counted under the wrong voting epoch', solve(dict(r, **{'configuration_epoch': [2, 3]})), False)
check('unrelated tracing metadata', solve(dict(r, trace='run-'+str(N))), True)
check('repeat validation is pure', solve(r), True)
invalid = {'ballot_floor': [[4, 9], [5, 1]], 'slot_scope': ['s2', 's1'], 'promise_durable': False, 'accepted_attached': ['chosen', None], 'configuration_epoch': [2, 3]}
keys = list(invalid)
pair = {keys[N % len(keys)]: invalid[keys[N % len(keys)]], keys[(N+1) % len(keys)]: invalid[keys[(N+1) % len(keys)]]}
check('two independent violations in variant', solve(dict(r, **pair)), False)
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 |
|---|---|---|---|
| valid operation | True | True | Passed |
| An acceptor promises a ballot below its durable promise | False | False | Passed |
| A prepare message targets a different consensus instance | True | False | Failed |
| A promise response escapes before its durable write | False | False | Passed |
| The response omits an already accepted value | False | False | Passed |
| A prepare is counted under the wrong voting epoch | False | False | Passed |
| unrelated tracing metadata | True | True | Passed |
| repeat validation is pure | True | True | Passed |
| two independent violations in variant | False | False | Passed |
SHA-256 / 2008265e391042785fe49a3bfc15fbd4ade9d0113ca3676bca63c8f12b8b84a3
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(r):
return (tuple(r['ballot_floor'][0]) >= tuple(r['ballot_floor'][1])) and (r['slot_scope'][0] == r['slot_scope'][1]) and (r['accepted_attached'][0] is None or r['accepted_attached'][1] == r['accepted_attached'][0]) and (r['configuration_epoch'][0] == r['configuration_epoch'][1])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
r = {'ballot_floor': [[5, 2], [5, 1]], 'slot_scope': ['s1', 's1'], 'promise_durable': True, 'accepted_attached': ['chosen', 'chosen'], 'configuration_epoch': [3, 3]}
check('valid operation', solve(r), True)
check('An acceptor promises a ballot below its durable promise', solve(dict(r, **{'ballot_floor': [[4, 9], [5, 1]]})), False)
check('A prepare message targets a different consensus instance', solve(dict(r, **{'slot_scope': ['s2', 's1']})), False)
check('A promise response escapes before its durable write', solve(dict(r, **{'promise_durable': False})), False)
check('The response omits an already accepted value', solve(dict(r, **{'accepted_attached': ['chosen', None]})), False)
check('A prepare is counted under the wrong voting epoch', solve(dict(r, **{'configuration_epoch': [2, 3]})), False)
check('unrelated tracing metadata', solve(dict(r, trace='run-'+str(N))), True)
check('repeat validation is pure', solve(r), True)
invalid = {'ballot_floor': [[4, 9], [5, 1]], 'slot_scope': ['s2', 's1'], 'promise_durable': False, 'accepted_attached': ['chosen', None], 'configuration_epoch': [2, 3]}
keys = list(invalid)
pair = {keys[N % len(keys)]: invalid[keys[N % len(keys)]], keys[(N+1) % len(keys)]: invalid[keys[(N+1) % len(keys)]]}
check('two independent violations in variant', solve(dict(r, **pair)), False)
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 |
|---|---|---|---|
| valid operation | True | True | Passed |
| An acceptor promises a ballot below its durable promise | False | False | Passed |
| A prepare message targets a different consensus instance | False | False | Passed |
| A promise response escapes before its durable write | True | False | Failed |
| The response omits an already accepted value | False | False | Passed |
| A prepare is counted under the wrong voting epoch | False | False | Passed |
| unrelated tracing metadata | True | True | Passed |
| repeat validation is pure | True | True | Passed |
| two independent violations in variant | False | False | Passed |
SHA-256 / 76949ad62241c34364f972227d016d548375c253ba386d16c4a60e68c2ad8fc7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(r):
return (tuple(r['ballot_floor'][0]) >= tuple(r['ballot_floor'][1])) and (r['slot_scope'][0] == r['slot_scope'][1]) and (r['promise_durable'] is True) and (r['accepted_attached'][0] is None or r['accepted_attached'][1] == r['accepted_attached'][0]) and (r['configuration_epoch'][0] == r['configuration_epoch'][1])
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
r = {'ballot_floor': [[5, 2], [5, 1]], 'slot_scope': ['s1', 's1'], 'promise_durable': True, 'accepted_attached': ['chosen', 'chosen'], 'configuration_epoch': [3, 3]}
check('valid operation', solve(r), True)
check('An acceptor promises a ballot below its durable promise', solve(dict(r, **{'ballot_floor': [[4, 9], [5, 1]]})), False)
check('A prepare message targets a different consensus instance', solve(dict(r, **{'slot_scope': ['s2', 's1']})), False)
check('A promise response escapes before its durable write', solve(dict(r, **{'promise_durable': False})), False)
check('The response omits an already accepted value', solve(dict(r, **{'accepted_attached': ['chosen', None]})), False)
check('A prepare is counted under the wrong voting epoch', solve(dict(r, **{'configuration_epoch': [2, 3]})), False)
check('unrelated tracing metadata', solve(dict(r, trace='run-'+str(N))), True)
check('repeat validation is pure', solve(r), True)
invalid = {'ballot_floor': [[4, 9], [5, 1]], 'slot_scope': ['s2', 's1'], 'promise_durable': False, 'accepted_attached': ['chosen', None], 'configuration_epoch': [2, 3]}
keys = list(invalid)
pair = {keys[N % len(keys)]: invalid[keys[N % len(keys)]], keys[(N+1) % len(keys)]: invalid[keys[(N+1) % len(keys)]]}
check('two independent violations in variant', solve(dict(r, **pair)), False)
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 |
|---|---|---|---|
| valid operation | True | True | Passed |
| An acceptor promises a ballot below its durable promise | False | False | Passed |
| A prepare message targets a different consensus instance | False | False | Passed |
| A promise response escapes before its durable write | False | False | Passed |
| The response omits an already accepted value | False | False | Passed |
| A prepare is counted under the wrong voting epoch | False | False | Passed |
| unrelated tracing metadata | True | True | Passed |
| repeat validation is pure | True | True | Passed |
| two independent violations in variant | False | False | Passed |
SHA-256 / 6fda7f5600af25833ae2df8b1d1264351e333deb380f24081686c0e68fc05297
Verification & scope
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:36:53.191921+00:00.
Case digest / ebf51925676d62910ac571dbfc86ec07f89bd79cf3659796454155f1ec4bb8af