Documentation
¶
Overview ¶
Package pinning is the deterministic single-writer assignment for the S-Chain storage VM. It maps each storage key-range to exactly ONE owning validator using weighted rendezvous (Highest-Random-Weight, HRW) hashing over the P-Chain validator set pinned to a block's epoch height.
This replaces raft leader election. Raft serializes EVERY mutation through one elected leader; HRW pinning gives a DIFFERENT single writer PER RANGE with NO election round-trip — two writes to different ranges proceed in parallel, two writes to the same range resolve to the same owner on every node. The function is PURE: the same (range, validator-set-at-epoch) inputs produce the identical owner on every validator, so it is safe to evaluate inside deterministic block Verify without any coordination.
HARD INVARIANT: the validator set MUST be the set at a fixed P-Chain epoch height (block.pChainHeight), never the live set. Every node verifying a block resolves the owner against the same frozen set, so ownership is a deterministic function of the block — not of wall-clock validator churn. Re-pinning happens only at epoch boundaries, when pChainHeight advances.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func EpochFingerprint ¶
EpochFingerprint is a deterministic digest of the (sorted) member set. Two nodes that resolved ownership against the same validator set produce the same fingerprint; a node can stamp it into its Allocate tx so peers VERIFY the owner was computed against the agreed epoch set — the divergence detector for the manifest state root (M1). A mismatch means the proposer pinned against a different validator set and the block must be rejected.
func IsOwner ¶
IsOwner reports whether self owns key under members. This is the exact check a node runs to decide "am I the pinned writer for this range?" — emit the Allocate/Put tx iff true; otherwise verify-and-vote only.
func Owner ¶
Owner returns the NodeID that owns key, and true, or EmptyNodeID and false when the set is empty. Ownership is weighted rendezvous: each member m draws a score from H(key || m.NodeID) scaled by m.Weight; the highest score wins.
Determinism: the score is a pure function of (key, NodeID); ties break on the lexicographically smaller NodeID. No map iteration order, no time, no float accumulation across members affects the winner. Every node computes the same owner for the same (key, members) — the property that lets the owner be resolved inside block Verify with zero coordination.
Weighting: a member with twice the stake is ~twice as likely to own any given range, so write load tracks stake — the same economic alignment raft never had (raft's single leader carried 100% regardless of stake).
Minimal disruption: when one member is added or removed, only the ranges whose winner WAS or NOW IS that member move; every other range keeps its owner. This is the defining HRW property and is what bounds re-pinning churn at an epoch boundary to O(ranges × Δvalidators / N) rather than a full reshuffle.
Types ¶
type Member ¶
Member is one validator eligible to own a range: its identity and its stake weight. It is the projection of validators.GetValidatorOutput this package needs — id + weight only, no keys — so the pure pinning logic carries no dependency on the validators package and is trivially testable. The caller (the VM, holding *runtime.Runtime.ValidatorState) builds []Member from GetValidatorSet(ctx, block.pChainHeight, netID).
func SortMembers ¶
SortMembers returns members in a canonical (NodeID-ascending) order. The caller does not need this for correctness — Owner is order-independent — but a canonical order makes the set hashable for an epoch-fingerprint and makes test output stable.