- Sashité for Developers
- Nostr
- NIPs
- Glicko-2 Rating Attestation
NIP-XX
Glicko-2 Rating Attestation
draft optional
Abstract
This NIP defines an event kind for a rating authority to publish a signed attestation of a Glicko-2 rating update for a single player following the outcome of a two-player duel. The event is self-contained: it carries the player’s pre-duel and post-duel Glicko-2 triplets (rating, rating deviation, volatility), the player’s score in the duel, and the system constant τ used in the computation. The event does not depend on any other NIP and may be used for any two-player game whose outcome can be expressed as a score in the interval [0, 1] (with 1, 0.5, and 0 as the classical win, draw, and loss).
Motivation
The Glicko-2 rating system, introduced by Mark Glickman as an evolution of the original Glicko system, addresses two key limitations of classical Elo: it tracks rating reliability (rating deviation) and rating volatility (how erratic a player’s recent performance has been). Glicko-2 produces rating updates that are responsive for new or returning players (high RD) while conservative for established players with stable performance histories (low RD).
Glicko-2 is widely used by online chess and abstract strategy game platforms (Lichess, the Free Internet Chess Server, and many others) and is a confidence-aware alternative to the simpler Elo Rating Attestation NIP.
A publicly signed, self-contained Glicko-2 rating attestation event serves three purposes:
- Auditability — anyone can verify the computation against the documented Glicko-2 algorithm, given the inputs carried by the event.
- Discoverability — clients can query a player’s rating history without recomputing it from raw duel outcomes.
- Pluralism — multiple rating authorities (online platforms, federations, application-specific operators) MAY publish independent attestations for the same duels; consumers choose which authorities to trust.
The event is minimalist by design. It carries one attestation for one player, plus references to the duel and the rating pool. Verification logic, prior-rating lookups, and consumer-side filtering are left to the consuming application.
Specification
Event kind
kind: 3427
Glicko-2 Rating Attestation events are regular events per NIP-01: immutable, persistent, and referenced by their event ID.
Signer — the rating authority
The event is signed by a rating authority — a pubkey that computes and certifies the rating update. The rating authority is conceptually independent of the duel’s participants, of any arbiter or other role in the consuming application, and of any timestamping service. Multiple rating authorities MAY publish independent attestations for the same duel; consumers choose which authorities to trust on out-of-band grounds (reputation, NIP-05 verification, federation membership, etc.).
Tags
Reference tags
| Tag | Cardinality | Value | Description |
|---|---|---|---|
e duel |
exactly one | event id, optional relay hint, marker duel |
reference to the duel event (kind and structure defined by the consuming application) |
p |
exactly one | player pubkey | the player whose rating is attested |
The duel referent is application-defined at the primitive level. In this suite, the duel e tag references the Game Session (kind 3422) event id — the immutable event whose adjudicated outcome the rating consumes; both attestations of a duel (one per player) carry the same reference, which is the deduplication key below.
Rating-pool tags
| Tag | Cardinality | Value | Description |
|---|---|---|---|
game |
exactly one | game identifier matching ^[a-z][a-z0-9]{0,31}$ |
the game in which this rating is computed |
variant |
0 to 2 | variant identifier matching ^[a-z][a-z0-9]{0,31}$ |
the variant(s) of the game; cardinality interpretation below |
The variant tag cardinality conveys the variant structure of the duel:
- 0 — the game has no formal variants, or the rating applies to the base game.
- 1 — both players played the same variant; the rating belongs to the (game, variant) pool.
- 2 — the players played different variants in a multi-variant duel. The two variants are listed without prescribed order; the rating authority’s published policy determines which pool, if any, the rating contributes to.
The 0–2 bound is intrinsic, not an arbitrary restriction: a rating attestation describes a duel, which is two-participant, so at most two distinct variants are present. It is the two-participant projection of the suite’s general 0–n variant convention — a kind states the general form its subject admits, and lets the subject’s own arity bound it: a kind describing a position with an unbounded number of participants would state the general form.
Rating computation tags
| Tag | Cardinality | Value | Description |
|---|---|---|---|
score |
exactly one | decimal in [0, 1] | the rated player’s score in the duel |
glicko2_pre |
exactly one | three additional values: R, RD, σ |
the player’s Glicko-2 triplet before this duel |
glicko2_post |
exactly one | three additional values: R, RD, σ |
the player’s Glicko-2 triplet after this duel |
glicko2_tau |
exactly one | positive decimal | the system constant τ used in the computation |
The Glicko-2 triplet values are ordered consistently across glicko2_pre and glicko2_post:
- R (rating) — non-negative decimal; the player’s skill estimate on the Glicko-2 display scale (typically anchored at 1500 for new players).
- RD (rating deviation) — positive decimal; the uncertainty in the rating (typically 350 for new players, decreasing as more duels are played).
- σ (volatility) — positive decimal; the expected fluctuation of the rating (typically 0.06 for new players).
The system constant glicko2_tau (τ) is the volatility constraint parameter, chosen by the rating authority (typical values lie between 0.3 and 1.2). Larger τ allows volatility to change more freely; smaller τ constrains volatility to be more stable.
Score values
The score tag’s value MUST be a decimal number in the closed interval [0, 1], representing the rated player’s outcome in the duel. The opponent’s score is 1 − score.
The three classical values are the common cases:
1— the rated player won the duel.0.5— the duel was drawn.0— the rated player lost the duel.
Values strictly between these represent partial or asymmetric outcomes — for example a rule system that awards a partial win (a result better than a draw but short of a full win) to the player who forces a particular terminal position. Game-specific result notations (chess "1-0" / "1/2-1/2" / "0-1", go "B+R" / "W+R" / "Jigo", etc.) MUST be normalized to a value in [0, 1] when constructing the event. The Glicko-2 algorithm below is defined for any such score, since the actual score enters only through the term (s − E).
Content
The content field MUST be the empty string (""). The semantics of the event are fully expressed by its tags.
Glicko-2 algorithm
For reference, the Glicko-2 computation (Glickman, Example of the Glicko-2 system, revised 2022; summarized for the per-duel case) proceeds as follows:
- Convert to internal scale for the player and the opponent:
- μ = (R − 1500) / 173.7178
- φ = RD / 173.7178
- σ unchanged
- Compute auxiliary quantities for the opponent:
- g(φ_opp) = 1 / √(1 + 3·φ_opp² / π²)
- E(μ, μ_opp, φ_opp) = 1 / (1 + exp(−g(φ_opp)·(μ − μ_opp)))
- Estimated variance: v = 1 / [g(φ_opp)² · E · (1 − E)]
- Estimated improvement: Δ = v · g(φ_opp) · (s − E)
- Update volatility σ’ via the Illinois iteration on the system constant τ (see Glickman §Step 5 for the full procedure).
- Update RD:
- φ* = √(φ² + σ’²)
- φ’ = 1 / √(1/(φ*)² + 1/v)
- Update rating: μ’ = μ + φ’² · g(φ_opp) · (s − E)
- Convert back to display scale:
- R’ = 173.7178 · μ’ + 1500
- RD’ = 173.7178 · φ’
- σ’ as computed in step 5.
The opponent’s pre-duel (R, RD) is obtained by the consumer from the rating authority’s prior Glicko-2 Rating Attestation for the opponent in the same pool (or the rating authority’s documented initial conventions if no prior attestation exists).
Semantic constraints
Throughout these constraints, a decimal number is a string matching ^(0|[1-9][0-9]*)(\.[0-9]+)?$ — no sign, no exponent, no leading zeros, . as the separator; non-negative admits any such string, and positive additionally excludes representations of zero (0, 0.0, …).
A conforming Glicko-2 Rating Attestation event MUST satisfy all of the following:
- Exactly one
etag with markerduel, whose second element is a valid event id. - Exactly one
ptag. - Exactly one
gametag whose second element matches^[a-z][a-z0-9]{0,31}$. - Zero, one, or two
varianttags, each whose second element matches^[a-z][a-z0-9]{0,31}$. - Exactly one
scoretag whose second element is a decimal number (grammar above) in the closed interval [0, 1]. - Exactly one
glicko2_pretag with exactly three additional elements: the first is a non-negative decimal number (grammar above) (R), the second a positive decimal number (RD), the third a positive decimal number (σ). - Exactly one
glicko2_posttag with the same structure asglicko2_pre. - Exactly one
glicko2_tautag whose second element is a positive decimal number (grammar above). - The
contentfield is the empty string ("").
All nine constraints are checkable from the event alone. Verifying that glicko2_post is the correct result of the Glicko-2 algorithm applied to glicko2_pre, the opponent’s pre-duel (R, RD), score, and glicko2_tau requires cross-event lookups and is the consumer’s responsibility.
Race resolution
A rating authority SHOULD publish at most one Glicko-2 Rating Attestation per (rating authority, player, duel) triple. If multiple events exist for the same triple, the canonical event is determined deterministically:
- Smallest
created_atfirst. - Smallest event ID as tiebreaker.
Non-canonical events MUST be ignored by consumers.
This rule uses the event’s own created_at — the rating authority’s self-declared timestamp. The NIP does not require external timestamping. Consumers requiring authoritative, third-party-verified timing (for example, to detect a rating authority backdating their attestations) SHOULD layer an external mechanism such as the Event Timestamp Attestation NIP on top of these events.
A rating authority who realizes they computed incorrectly cannot override their first Attestation by publishing a later one (the later event would have a larger created_at and thus be non-canonical). Their options are NIP-09 deletion (with the usual caveats about relay support and asynchronous propagation) or accepting the error as historical. Signed events are immutable.
Examples
Example 1 — Standard chess duel, decisive
Alice (Glicko-2 default state R=1500, RD=350, σ=0.06) defeats Bob (same default state) in a chess duel. The rating authority (using τ=0.5) publishes Alice’s attestation:
{
"kind": 3427,
"pubkey": "<rating_authority_pubkey>",
"created_at": 1700000000,
"tags": [
["e", "<duel_event_id>", "wss://relay.example.com", "duel"],
["p", "<alice_pubkey>"],
["game", "chess"],
["variant", "chess"],
["score", "1"],
["glicko2_pre", "1500", "350", "0.06"],
["glicko2_post", "1662.31", "290.32", "0.0599997"],
["glicko2_tau", "0.5"]
],
"content": "",
"id": "...",
"sig": "..."
}
A symmetric attestation is published for Bob with score = 0 and a post-state showing a comparable rating decrease. The large magnitude of the rating change reflects the high RD of new players; subsequent duels will produce smaller changes as RD decreases — this is the confidence-aware property that distinguishes Glicko-2 from classical Elo.
Example 2 — Go duel, draw
Alice (rated R=1842, RD=125, σ=0.058) draws Bob (R=1800, RD=140, σ=0.06) in a go duel. The rating authority publishes Alice’s attestation:
{
"kind": 3427,
"pubkey": "<rating_authority_pubkey>",
"created_at": 1700000000,
"tags": [
["e", "<duel_event_id>", "wss://relay.example.com", "duel"],
["p", "<alice_pubkey>"],
["game", "go"],
["score", "0.5"],
["glicko2_pre", "1842", "125", "0.058"],
["glicko2_post", "1837.89", "119.16", "0.0579968"],
["glicko2_tau", "0.6"]
],
"content": "",
"id": "...",
"sig": "..."
}
The variant tag is absent: the rating pool is the base go game.
Example 3 — Multi-variant duel
Alice plays one variant (<variant1>), Bob another (<variant2>), on a shared board (a multi-variant duel in a hybrid platform). The rating authority publishes Alice’s attestation, listing both variants present in the duel:
{
"kind": 3427,
"pubkey": "<rating_authority_pubkey>",
"created_at": 1700000000,
"tags": [
["e", "<duel_event_id>", "wss://relay.example.com", "duel"],
["p", "<alice_pubkey>"],
["game", "<game>"],
["variant", "<variant1>"],
["variant", "<variant2>"],
["score", "0"],
["glicko2_pre", "1700", "180", "0.061"],
["glicko2_post", "1683.91", "175.42", "0.060991"],
["glicko2_tau", "0.5"]
],
"content": "",
"id": "...",
"sig": "..."
}
Two variant tags signal the multi-variant nature of the duel. The pool the attestation contributes to follows the rating authority’s own pool computation (§Rating pool tags): an authority computing pergame pools credits the duel to the single game pool, the variant tags being descriptive only; a pervariant authority would exclude the duel from its pools and publish no attestation for it.
Example 4 — Partial-win outcome
Some rule systems award a partial result that is neither a full win nor a draw. (This is a generic capability of the attestation; the reference sanki arbiter never emits one — per the reference authority’s supporting document, Rating Specification — Glicko-2.) Here a hypothetical rule system scores Alice’s terminal position (Glicko-2 default state R=1500, RD=350, σ=0.06) as a partial win (0.75), against an opponent in the same default state, with τ=0.5. Both players played the same (game, variant), so the rating belongs to that single pool:
{
"kind": 3427,
"pubkey": "<rating_authority_pubkey>",
"created_at": 1700000000,
"tags": [
["e", "<duel_event_id>", "wss://relay.example.com", "duel"],
["p", "<alice_pubkey>"],
["game", "<game>"],
["variant", "<variant>"],
["score", "0.75"],
["glicko2_pre", "1500", "350", "0.06"],
["glicko2_post", "1581.16", "290.32", "0.0599991"],
["glicko2_tau", "0.5"]
],
"content": "",
"id": "...",
"sig": "..."
}
The partial score 0.75 enters the Glicko-2 update through the (s − E) term exactly as a win or a draw would; the rating rises by less than a full win against an equal opponent would yield (a full win from this state produces R ≈ 1662.31). Alice’s opponent receives a symmetric attestation with score = 0.25 (post-state R ≈ 1418.84).
Client guidelines
Clients implementing kind: 3427 SHOULD:
- Subscribe to
kind: 3427with appropriate#pfilters to track displayed players’ ratings, or withauthorsfilters when tracking specific rating authorities. - Validate received events against the semantic constraints (§Semantic constraints) before treating them as authoritative.
- Decide which rating authorities to trust based on user preferences or application policy; ratings from different authorities SHOULD NOT be averaged or combined silently.
- To determine a player’s current rating in a pool from a trusted rating authority, select the most recent Glicko-2 Rating Attestation matching the player and the pool scope in effect (where the consumer is evaluating a
ratingfilter, the scope the filter declares — kind3418§Match-terms tags): under a pervariant scope, attestations whosegameand singlevarianttag identify the (game, variant) pool; under a pergame scope, all attestations carrying thatgame, regardless of theirvarianttags (zero, one, or two). “Most recent” is determined by the event’screated_at(largest first), with the smallest event ID as tiebreaker. Apply §Race resolution first — deduplicate to the canonical attestation per(authority, player, duel)triple — and select among the survivors, so a republished duplicate never masquerades as a newer rating. Thiscreated_at-based selection is sound only for an authority that publishes in duel order and never back-fills older duels (the reference authority is forward-only — Rating Specification — Glicko-2 §Signed-snapshot production) — under a back-filling authority, an attestation for an older duel published later would wrongly become “current”, and consumers of such an authority need a duel-timing-based selection instead. - When verifying a rating computation, fetch the opponent’s contemporaneous pre-duel (R, RD) from the same rating authority’s prior Attestation and apply the Glicko-2 algorithm.
- For a player with no Attestation from a trusted authority, treat the player as unrated. Initial-rating conventions (commonly R=1500, RD=350, σ=0.06) are at the authority’s discretion.
- When displaying a Glicko-2 rating to end users, consider showing the confidence interval (approximately R ± 2·RD covers ~95% of the player’s actual skill range), since the raw R alone discards the confidence information that Glicko-2 explicitly tracks.
Security considerations
- Signatures — events are signed by the rating authority. Consumers MUST verify signatures per NIP-01 before treating an Attestation as authoritative.
- Rating authority trust — the rating authority’s correctness, neutrality, and accountability are out of band for this NIP. A malicious or buggy rating authority MAY publish events inconsistent with the Glicko-2 algorithm. Consumers SHOULD independently verify computations where integrity is critical.
- Multi-authority divergence — different rating authorities MAY publish different attestations for the same duel. This is by design. Each authority’s perspective SHOULD be presented separately.
- Self-declared timing — the event’s
created_atis the rating authority’s self-declared timestamp; there is no in-protocol mechanism to verify that the authority did not backdate or forward-date their attestations. Race resolution (§Race resolution) and current-rating lookup (§Client guidelines, item 4) both rely on this self-declared timestamp. Consumers requiring authoritative, third-party-verified timing SHOULD layer an external mechanism such as the Event Timestamp Attestation NIP on top of these events. - Implementation precision — the Glicko-2 algorithm includes an iterative root-finding step (the Illinois method) with a convergence tolerance (typically ε ≈ 10⁻⁶). Different implementations may converge to microscopically different values. This NIP does not constrain ε; consumers SHOULD tolerate small numerical differences when verifying computations.
- Immutability — an Attestation once signed cannot be retracted other than via NIP-09 deletion requests, with the usual caveats about relay support and asynchronous propagation.
References
- Mark E. Glickman, Example of the Glicko-2 system (revised March 22, 2022) — the canonical algorithmic description
- Mark E. Glickman, Parameter estimation in large dynamic paired comparison experiments (Applied Statistics, 1999) — theoretical foundation
- NIP-01 — Basic protocol flow
- NIP-09 — Event deletion
- The Event Timestamp Attestation NIP — generic primitive for authoritative timing, layerable on top of these events
