period/period.go
76 lines
1// Package period is the calendar of the protocol: four-week periods of2// 40 320 one-minute slots counted from genesis, split into four weekly3// phases, and the hour of the monthly event.4//5// period = slot / SlotsPerPeriod6// phase = (slot % SlotsPerPeriod) / SlotsPerPhase7//8// Phases are numbered 0–3 here; the specification calls them 1–4:9//10// Phase 0 (spec "phase 1") the event; Verify signed here11// Phases 0–1 Verified, Register, Mix, Vote, Commit12// Phase 2 (spec "phase 3") Reveal, and with it the UBI13// Phase 3 (spec "phase 4") pause; the seed and the next pairs are known14//15// Genesis is 07:00 UTC on a Saturday, and since a period is exactly four16// weeks every period begins there. The event is held at the period start17// plus the period's hour, SHA256(uint32(period)) mod 24, for fifteen18// minutes. That is a convention about when to show up, not a ledger rule:19// the ledger only maps slots to phases. Wall-clock time comes from the20// headers themselves (state.State.TimeOf), never from a remembered genesis21// constant.22package period2324import (25"crypto/sha256"26"encoding/binary"2728"peoplecoin/params"29"peoplecoin/rng"30)3132// Phase indices.33const (34PhaseEvent uint64 = 035PhaseCollect uint64 = 136PhaseReveal uint64 = 237PhasePause uint64 = 338)3940// Of returns the period a slot belongs to.41func Of(slot uint64) uint64 { return slot / params.SlotsPerPeriod }4243// Phase returns the phase (0–3) of a slot within its period.44func Phase(slot uint64) uint64 { return (slot % params.SlotsPerPeriod) / params.SlotsPerPhase }4546// Start returns the first slot of a period.47func Start(period uint64) uint64 { return period * params.SlotsPerPeriod }4849// End returns the first slot of the following period.50func End(period uint64) uint64 { return (period + 1) * params.SlotsPerPeriod }5152// IsBoundary reports whether slot is the first of a period.53func IsBoundary(slot uint64) bool { return slot%params.SlotsPerPeriod == 0 }5455// Number is the period as the uint32 that is hashed and signed.56func Number(slot uint64) uint32 { return uint32(Of(slot)) }5758// EventOffset is the event's hour, 0–23, counted from the period start:59// SHA256(uint32(period)) as a big-endian integer, mod 24. It depends on the60// period number alone, so it is known from genesis and cannot be moved by61// anyone.62func EventOffset(period uint32) uint64 {63var b [4]byte64binary.BigEndian.PutUint32(b[:], period)65return rng.HashMod(sha256.Sum256(b[:]), 24)66}6768// EventSlots is the length of the event in slots.69const EventSlots uint64 = 157071// EventSlot returns the slot at which the period's event begins. It is72// always in the first day of phase 0.73func EventSlot(period uint64) uint64 {74return Start(period) + EventOffset(uint32(period))*6075}