Het protocol

Dit moet een feeder, relay of client spreken om met de rest samen te werken. De referentie is de wire-crate in de Tally-repository, de enige code daar die het protocol codeert of decodeert, en elke binary gebruikt die. Gehele getallen zijn overal big-endian.

Transport

Elke hop is Noise_IK_25519_ChaChaPoly_BLAKE2s over TCP. Elk Noise-bericht wordt verstuurd achter een lengte van twee bytes, maximaal 65.535 bytes inclusief tag, en bevat alleen volledige records.

Identiteit is één Ed25519-sleutel. De X25519-sleutel die Noise authenticeert wordt daarvan afgeleid (sk_to_curve25519 van libsodium), en het eerste handshakebericht van de initiator bevat zijn publieke Ed25519-sleutel van 32 bytes, die de responder controleert tegen de sleutel die de handshake heeft bewezen. Eén sleutel benoemt een antenne overal.

De preamble

Vóór de handshake stuurt de initiator 16 bytes in platte tekst. Ze zijn ook de Noise-proloog, dus een gewijzigde byte laat de handshake mislukken. En ze maken het mogelijk om de handshake zelf later te veranderen, en een relay tijdens het roteren een oude en een nieuwe sleutel te laten houden.

BytesVeldBetekenis
0–3MagicDe ASCII-letters TALY.
4Preambleversie1.
5Handshake1: het Noise-patroon hierboven.
6–7GereserveerdNul.
8–15SleutelhintAan welke sleutel van de responder de verbinding is gericht: de eerste 8 bytes van BLAKE2s-256 over zijn X25519-sleutel.

Versies

Daarna stuurt de initiator Hello met de laagste en hoogste wire-versie die hij spreekt, en zijn rol. De responder antwoordt met Welcome en de versie die beide vanaf dan spreken, of met Goodbye, een reden en hoe lang er gewacht moet worden. Van de eerste byte tot Welcome duurt hoogstens 15 seconden, en elke verzending daarna heeft een deadline van 30. Wire-versie 1 is tot nu toe de enige.

Een relay beantwoordt elke wire-versie die ooit met een feeder is uitgeleverd, voor altijd. Geïnstalleerde feeders worden niet bijgewerkt, en de rest van het protocol rust op deze regel.

Records

Een record is een typebyte, een inhoudslengte van twee bytes, en de inhoud. Dit zijn de typen die wire-versie 1 kent:

TypeRecordInhoud
0x01HelloLaagste versie, hoogste versie (elk twee bytes), rol (één byte: 1 feeder, 2 abonnee, 3 relay, 4 MLAT, een relay die posities publiceert).
0x02WelcomeDe versie die beide vanaf nu spreken (twee bytes).
0x03BatchDe ondertekende batch van een ontvanger, zie hieronder. Relays sturen hem byte voor byte door.
0x04ReceiverInfoDe ondertekende beschrijving die een ontvanger van zichzelf geeft: locatie en de precisie daarvan, klokklasse, software en de relays die hij koos.
0x05HeartbeatLeeg. Teken van leven.
0x06RedirectSeconden wachttijd (vier bytes) en relays als hints. Het betekent alleen “ga bij me weg”; de feeder kiest nog steeds volgens zijn eigen regels.
0x07RelayListRelays die deze relay kent, aangeboden als hints.
0x08RateLimitBytes per seconde en burst (elk vier bytes): het maximum dat de relay wil. Een feeder mag lager gaan, maar nooit boven het plafond van zijn eigenaar.
0x09GoodbyeEen reden (één byte) en seconden wachttijd (vier bytes): de relay sluit.
0x0aSubscribeStreams (één byte met vlaggen: 1 ruw, 2 ontdubbeld, 4 posities), een aantal (twee bytes) en zoveel H3-cellen (elk acht bytes), maximaal 64. Vervangt de vorige Subscribe van de abonnee.
0x0bRelayBatchEen batch die de relay zelf heeft ondertekend: zijn ontdubbelde stream.
0x0cPositionsPosities die de MLAT van een relay heeft berekend, ondertekend door die relay.

Regels voor verandering

Feeders worden nooit bijgewerkt, dus dit zijn de regels waarmee het protocol zonder hen kan veranderen:

  • Een onbekend type wordt overgeslagen, tenzij de hoogste bit (0x80) het als kritiek markeert, wat de sessie netjes beëindigt. Nieuwe records zijn daarom niet kritiek, tenzij het fout zou zijn om ze te negeren.
  • Een inhoud mag na de velden die een lezer kent nog bytes bevatten, en die worden genegeerd. Velden worden toegevoegd door ze achteraan te plaatsen.
  • Een lezer bewaart een enumwaarde die hij niet kent als de waarde Other, nooit als fout.
  • Een ondertekende vorm houdt in elke formaatversie hetzelfde prefix en eindigt met zijn handtekening over alles daarvoor, zodat een relay een formaat dat hij verder niet leest kan verifiëren, routeren en ontdubbelen.
  • Het formaat van een observatie is voor 1090 MHz de eigen typebyte van BEAST. 978 MHz UAT krijgt nieuwe waarden en heeft geen nieuw record nodig, en relays sturen formaten die ze niet kennen gewoon door.

De ondertekende batch

Een batch is ongeveer een seconde aan ontvangsten van één ontvanger. Formaat 1 is zo opgebouwd:

BytesVeldBetekenis
1Formaat1.
32SleutelDe publieke Ed25519-sleutel van de ontvanger.
8Boot-idWillekeurig bij elke start van de feeder.
8Volgnummer0, 1, 2 enzovoort binnen één boot. Een gat verderop in de keten is data die een hop niet heeft afgeleverd.
4Teller-epochWordt verhoogd zodra de teller van de ontvanger opnieuw gestart kan zijn, zodat tellerstanden van ervoor en erna elkaar nooit raken.
8KloktijdDe klok van de feeder in Unix-milliseconden. Ter informatie: hij kan verkeerd staan.
4WeggegooidOntvangsten die het eigen plafond van de feeder sinds de vorige batch heeft weggegooid.
32VorigeDe hash van de vorige batch van deze boot, nullen voor de eerste, zodat een ontvanger geen twee geschiedenissen kan ondertekenen.
4AantalHoeveel observaties er volgen.
10 + n per stukObservatiesElk een formaat (één byte), de ruwe 48-bit teller van de ontvanger (zes), het signaalniveau (één), een lengte (twee) en zoveel bytes van het bericht zoals de decoder het uitgaf.
64Ed25519-handtekeningOver alles daarvoor.

Observatieformaten: 1 is Mode A/C (2 bytes), 2 Mode-S kort (7), 3 Mode-S lang (14), D een 978 MHz UAT-downlink, U een UAT-uplink vanaf de grond, elk geschreven als zijn ASCII-teken.

De handtekening dekt de ASCII-tekst tally batch, een nulbyte en elke byte van de batch vóór de handtekening. De eigen ontdubbelde batches van een relay ondertekenen in plaats daarvan tally relay batch, zodat de een nooit voor de ander kan doorgaan.

De identiteit van een batch is de BLAKE2s-256-hash van al zijn bytes, handtekening inbegrepen. Relays ontdubbelen daarop, en het veld Vorige van de volgende batch noemt hem.

De eerste 49 bytes (formaat, sleutel, boot-id en volgnummer) houden hun plaats in elk toekomstig formaat, en de handtekening komt altijd als laatste.

Tellers worden vóór de MLAT nooit gekalibreerd, door niemand: de MLAT van een relay heeft de ruwe teller nodig om te rekenen.