ι State Fork — Algorithm Extraction
Language-agnostic pseudocode extracted from Phoenix Python source.
Source file: fork.py (1308L).
1. ForkReason Enum (5 Values)
enum ForkReason:
RULE_VERSION_CONFLICT // Nodes disagree on which rule set is canonical
INVARIANT_VIOLATION // A state transition would violate a system invariant
CONSTITUTIONAL_VIOLATION // A transition violates an AX-01..AX-12 axiom
VOLUNTARY_EXIT // A participant explicitly chooses to fork off
GOVERNANCE_REJECTION // A governance proposal was rejected but a minority wants to apply it
2. ForkStatus Enum (4 Values)
enum ForkStatus:
ACTIVE // Fork is live; nodes on this fork process events normally
MERGED // Fork was reconciled back into parent; no longer independent
ABANDONED // Fork was abandoned; state frozen
FROZEN // Temporary suspension (e.g., during merge negotiation)
3. ForkIsolation Enum
enum ForkIsolation:
ISOLATED // No communication with parent fork; fully independent
READ_ONLY_PARENT // Can read parent state; cannot write to parent
BRIDGED // Bidirectional state visibility; merge protocol active
Isolation Mode Behavior
| Mode | Can Read Parent | Can Write Parent | Events Cross Fork | Merge Eligible |
|---|---|---|---|---|
| ISOLATED | No | No | No | Only via full merge protocol |
| READ_ONLY_PARENT | Yes | No | No (inbound only) | Yes — can initiate |
| BRIDGED | Yes | Conditional | Yes (with proof) | Yes — active negotiation |
4. GENESIS_FORK_ID
// The root fork identifier from which all forks descend
GENESIS_FORK_ID = sha256("phoenix-genesis-v1")
// Fixed constant; never changes
5. Fork ID Derivation
function derive_fork_id(parent_fork_id: bytes32, divergence_point: bytes32, reason: ForkReason) -> bytes32:
// Deterministic: same inputs always produce same fork ID
return sha256(parent_fork_id || divergence_point || encode_reason(reason))
// divergence_point = hash of the last common event before the fork
// reason encoded as 1-byte enum value
6. Fork Creation Algorithm
function create_fork(
parent_fork: Fork,
reason: ForkReason,
initiator: NodeId,
isolation: ForkIsolation,
context: State,
) -> Fork:
// 1. Determine divergence point
divergence_point = context.current_state_root
// 2. Derive new fork ID
new_fork_id = derive_fork_id(parent_fork.id, divergence_point, reason)
// 3. Snapshot parent state
fork_state = deep_copy(context.state)
fork_state.fork_id = new_fork_id
// 4. Apply isolation mode
fork_state.isolation = isolation
// 5. Register fork
new_fork = Fork {
id: new_fork_id,
parent_id: parent_fork.id,
divergence_point: divergence_point,
reason: reason,
status: ACTIVE,
isolation: isolation,
initiator: initiator,
created_epoch: context.current_epoch,
state: fork_state,
checkpoints: [],
}
fork_registry[new_fork_id] = new_fork
notify_peers(new_fork)
return new_fork
7. Checkpoint Structure
Checkpoints are used to periodically commit fork state for merge eligibility. They require 7-of-10 threshold signatures from the arbiter pool.
CHECKPOINT_THRESHOLD = 7
CHECKPOINT_TOTAL = 10
struct Checkpoint:
fork_id: bytes32
state_root: bytes32 // Merkle root of fork state at checkpoint
epoch: int64
event_count: int64
partial_sigs: PartialSig[] // collected arbiter signatures (need >= 7)
threshold_sig: ThresholdSig? // aggregated signature (set when threshold met)
finalized: bool
function create_checkpoint(fork: Fork, epoch: int64) -> Checkpoint:
root = compute_merkle_root(fork.state)
return Checkpoint {
fork_id: fork.id,
state_root: root,
epoch: epoch,
event_count: fork.state.event_count,
partial_sigs: [],
finalized: false,
}
function add_checkpoint_sig(checkpoint: Checkpoint, partial_sig: PartialSig) -> bool:
if partial_sig.signer not in eligible_arbiters(checkpoint.fork_id):
return false
checkpoint.partial_sigs.append(partial_sig)
if len(checkpoint.partial_sigs) >= CHECKPOINT_THRESHOLD:
checkpoint.threshold_sig = aggregate_threshold_sig(
checkpoint.partial_sigs[:CHECKPOINT_THRESHOLD]
)
checkpoint.finalized = true
return true
8. Merge Protocol Conditions
A fork may merge back into its parent only when all conditions are met:
function can_merge(fork: Fork, parent: Fork) -> (bool, string):
// 1. Fork must be ACTIVE (not abandoned or already merged)
if fork.status != ACTIVE:
return (false, "fork not active")
// 2. Must have at least one finalized checkpoint
if not any(c.finalized for c in fork.checkpoints):
return (false, "no finalized checkpoint")
// 3. No open disputes on the fork
if has_open_disputes(fork.id):
return (false, "open disputes on fork")
// 4. Merge proposal must have quorum from both fork and parent validators
if not has_merge_quorum(fork, parent):
return (false, "insufficient quorum")
// 5. State delta must not violate parent invariants
delta = compute_state_delta(fork.state, parent.state)
if violates_invariants(delta, parent):
return (false, "state delta violates parent invariants")
return (true, "")
function execute_merge(fork: Fork, parent: Fork) -> MergeResult:
assert can_merge(fork, parent)[0]
delta = compute_state_delta(fork.state, parent.state)
// Apply reputation discount for fork participants
FORK_REP_DISCOUNT = 5000 // 50% discount on fork-local rep gains
merged_rep = {}
for node_id, rep in delta.reputation_changes:
for domain, delta_value in rep:
if delta_value > 0:
merged_rep[node_id][domain] = (delta_value * (10000 - FORK_REP_DISCOUNT)) / 10000
else:
merged_rep[node_id][domain] = delta_value // penalties applied in full
// Apply merged state to parent
apply_state_delta(parent, delta, rep_override=merged_rep)
fork.status = MERGED
return MergeResult {
fork_id: fork.id,
parent_id: parent.id,
applied_at: current_epoch,
rep_discount: FORK_REP_DISCOUNT,
}
9. Fork Detection Integration
enum ForkDetectionResult:
ALREADY_FORKED // peer.fork_id != my_fork_id
IN_SYNC // peer.state_root == my_state_root
PEER_BEHIND // peer_root is ancestor of my_root
I_AM_BEHIND // my_root is ancestor of peer_root
UNPLANNED_FORK // divergence; trigger fork creation
function detect_fork(
peer_fork_id: bytes32, peer_root: bytes32,
my_fork_id: bytes32, my_root: bytes32,
) -> ForkDetectionResult:
if peer_fork_id != my_fork_id: return ALREADY_FORKED
if peer_root == my_root: return IN_SYNC
if is_ancestor(peer_root, my_root): return PEER_BEHIND
if is_ancestor(my_root, peer_root): return I_AM_BEHIND
return UNPLANNED_FORK // divergence detected
// On UNPLANNED_FORK:
// - Record divergence point
// - create_fork(reason=RULE_VERSION_CONFLICT or INVARIANT_VIOLATION)
// - Notify governance
10. Fork-Local State Properties
// Each fork carries its own copy of:
struct ForkState:
fork_id: bytes32
parent_id: bytes32 // null for genesis fork
state_root: bytes32 // Merkle root of this fork's state
epoch: int64
event_count: int64
reputation: Map<NodeId, Map<Domain, int64>>
tokens: Map<NodeId, TokenRecord[]>
rule_version: string // rule set hash active on this fork
isolation: ForkIsolation
// Events on a fork do NOT propagate to parent (unless BRIDGED mode)
// Rule version can diverge from parent
// Reputation accumulates independently
11. Dependencies
| Module | Interaction |
|---|---|
| θ Consensus | Consensus failure triggers fork creation |
| κ Rule Engine | Rule version conflict triggers fork; each fork uses own rule version |
| λ Reputation | Fork carries rep snapshot; merge applies discount |
| η Proof Store | Each fork maintains its own Merkle event log |
| π Governance | Governance rejection can trigger voluntary fork |
Links
| [[concepts/ι-state-fork | ι State Fork]] · [[spec/S07-fork-protocol | S07 Fork Protocol Spec]] · [[reference/extractions/theta-consensus-extraction | θ Extraction]] · [[reference/extractions/pi-governance-extraction | π Extraction]] |