Runes hebben geen specificatie

De referentie-implementatie van Runes, ord, is de normatieve specificatie van het Runes-protocol.

Niets wat je hier of elders leest, behalve de code van ord, is een specificatie. Deze prozaïsche beschrijving van het runes-protocol wordt verstrekt als een gids voor het gedrag van ord, en de code van ord zelf moet altijd worden geraadpleegd om de juistheid van elke prozaïsche beschrijving te bevestigen.

Als door een bug in ord dit document afwijkt van het daadwerkelijke gedrag van ord en het onpraktisch verstorend is om het gedrag van ord te wijzigen, zal dit document worden aangepast om overeen te komen met het werkelijke gedrag van ord.

Gebruikers van alternatieve implementaties doen dit op eigen risico, en diensten die Runes willen integreren worden sterk aangemoedigd om ord zelf te gebruiken voor het uitvoeren van Runes-transacties en voor het bepalen van de status van runes, mints en saldi.

Runestones

Berichten van het rune-protocol worden "runestones" genoemd.

Het Runes-protocol wordt geactiveerd bij blok 840.000. Runestones in eerdere blokken worden genegeerd.

In abstracte termen bevatten runestones de volgende velden:

#![allow(unused)]
fn main() {
struct Runestone {
  edicts: Vec<Edict>,
  etching: Option<Etching>,
  mint: Option<RuneId>,
  pointer: Option<u32>,
}
}

Runes worden gecreëerd door etchings:

#![allow(unused)]
fn main() {
struct Etching {
  divisibility: Option<u8>,
  premine: Option<u128>,
  rune: Option<Rune>,
  spacers: Option<u32>,
  symbol: Option<char>,
  terms: Option<Terms>,
}
}

Die mint-voorwaarden kunnen bevatten:

#![allow(unused)]
fn main() {
struct Terms {
  amount: Option<u128>,
  cap: Option<u128>,
  height: (Option<u64>, Option<u64>),
  offset: (Option<u64>, Option<u64>),
}
}

Runes worden overgedragen door middel van een edict:

#![allow(unused)]
fn main() {
struct Edict {
  id: RuneId,
  amount: u128,
  output: u32,
}
}

Rune-ID's worden gecodeerd als de blokhoogte en de transactie-index van de transactie waarin de rune werd geëtched:

#![allow(unused)]
fn main() {
struct RuneId {
  block: u64,
  tx: u32,
}
}

Rune-ID's worden in tekst weergegeven als BLOCK:TX.

Rune-namen worden gecodeerd als gemodificeerde base-26 gehele getallen:

#![allow(unused)]
fn main() {
struct Rune(u128);
}

Ontcijferen

Runestones worden ontcijferd uit transacties met de volgende stappen:

  1. Vind de eerste transactie-output waarvan de script pubkey begint met OP_RETURN OP_13.

  2. Concateneer alle volgende data pushes in een payload-buffer.

  3. Decodeer een reeks van 128-bit LEB128 gehele getallen uit de payload-buffer.

  4. Parse de reeks van gehele getallen in een ongetypeerd bericht.

  5. Parse het ongetypeerde bericht naar een runestone.

Decoderen kan een onjuist gevormde runestone opleveren, genoemd een cenotaph.

Het vinden van de Runestone-output

Outputs worden doorzocht naar de eerste script pubkey die begint met OP_RETURN OP_13. Als het decoderen mislukt, worden latere overeenkomende outputs niet beschouwd.

Het payloadbuffer samenstellen

Het payloadbuffer wordt samengesteld door de datastukken na OP_13 in de overeenkomende script pubkey aan elkaar te koppelen.

De datastukken zijn opcodes 0 tot en met 78 inclusief. Als een niet-data push opcode wordt aangetroffen, dat wil zeggen een opcode gelijk aan of groter dan opcode 79, dan is de ontcijferde runestone een cenotaaf zonder etching, mint of edicts.

Decoderen van de gehele reeks van 128-bit LEB128-getallen uit de payloadbuffer

Een reeks van 128-bit gehele getallen wordt uit de payload gedecodeerd als LEB128 varints.

LEB128 varints worden gecodeerd als een reeks bytes, waarvan elke byte het meest significante bit ingesteld heeft, behalve de laatste.

Als een LEB128 varint meer dan 18 bytes bevat, een u128 zou overlopen, of wordt afgekapt, wat betekent dat het einde van de payloadbuffer is bereikt voordat een byte met het voortzettingsbit niet ingesteld is wordt aangetroffen, is de gedecodeerde runestone een cenotaph zonder etching, mint of edicts.

Het ontleden van de boodschap

De reeks gehele getallen wordt ontleed in een ongetypte boodschap:

#![allow(unused)]
fn main() {
struct Message {
  fields: Map<u128, Vec<u128>>,
  edicts: Vec<Edict>,
}
}

De gehele getallen worden geïnterpreteerd als een reeks tag/waarde-paren, waarbij dubbele tags hun waarde toevoegen aan de veldwaarde.

Als een tag met de waarde nul wordt aangetroffen, worden alle volgende gehele getallen geïnterpreteerd als een reeks van vier-integer edicts, elk bestaande uit een rune-ID blockhoogte, rune-ID transactienummer, hoeveelheid en uitvoer.

#![allow(unused)]
fn main() {
struct Edict {
  id: RuneId,
  amount: u128,
  output: u32,
}
}

De blockhoogtes en transactienummers van rune-ID's in edicts zijn delta-gecodeerd.

Decodering van edict rune-ID's begint met een basis blockhoogte en transactienummer van nul. Bij het decoderen van elke rune-ID wordt eerst de gecodeerde blockhoogte-delta bij de basis blockhoogte opgeteld. Als de blockhoogte-delta nul is, is het volgende geheel getal een transactienummer-delta. Als de blockhoogte-delta groter is dan nul, is het volgende geheel getal in plaats daarvan een absoluut transactienummer.

Dit houdt in dat edicts eerst gesorteerd moeten worden op rune-ID voordat ze worden gecodeerd in een runestone.

Bijvoorbeeld, om de volgende edicts te coderen:

blockTXaantaloutput
10551
501254
10718
105103

Ze worden eerst gesorteerd op blokhoogte en transactie-index:

blockTXaantaloutput
10551
105103
10718
501254

En daarna delta-gecodeerd als:

block deltaTX deltaaantaloutput
10551
00103
0218
401254

Als een edictoutput groter is dan het aantal outputs van de transactie, wordt een edict-rune-ID aangetroffen met block nul en een niet-nul transactieverwijzing, of een veld is afgebroken, wat betekent dat een tag zonder waarde wordt aangetroffen, dan is de gedecodeerde runestone een cenotaaf.

Houd er rekening mee dat als hier een cenotaaf wordt geproduceerd, de cenotaaf niet leeg is, wat betekent dat deze de velden en edicts bevat, die een etching en mint kunnen omvatten.

Het Ontcijferen van de Runestone

De runestone:

#![allow(unused)]
fn main() {
struct Runestone {
  edicts: Vec<Edict>,
  etching: Option<Etching>,
  mint: Option<RuneId>,
  pointer: Option<u32>,
}
}

Wordt ontcijferd uit het ongetekende bericht met behulp van de volgende tags:

#![allow(unused)]
fn main() {
enum Tag {
  Body = 0,
  Flags = 2,
  Rune = 4,
  Premine = 6,
  Cap = 8,
  Amount = 10,
  HeightStart = 12,
  HeightEnd = 14,
  OffsetStart = 16,
  OffsetEnd = 18,
  Mint = 20,
  Pointer = 22,
  Cenotaph = 126,

  Divisibility = 1,
  Spacers = 3,
  Symbol = 5,
  Nop = 127,
}
}

Let op dat tags worden gegroepeerd op pariteit, d.w.z. of ze even of oneven zijn. Onbekende oneven tags worden genegeerd. Onbekende even tags produceren een cenotaaf.

All unused tags are reserved for use by the protocol, may be assigned at any time, and should not be used.

Lichaam (Body)

The Body tag marks the end of the runestone's fields, causing all following integers to be interpreted as edicts.

Vlag (Flag)

Het Flag-veld bevat een bitmap van vlaggen, waarvan de positie 1 << FLAG_VALUE is:

#![allow(unused)]
fn main() {
enum Flag {
  Etching = 0,
  Terms = 1,
  Turbo = 2,
  Cenotaph = 127,
}
}

De Etching-vlag markeert deze transactie als een etching.

De Terms-vlag markeert de etching van deze transactie als het hebben van open mint-voorwaarden.

De Turbo-vlag markeert de etching van deze transactie als meewerkend aan toekomstige protocolwijzigingen. Deze protocolwijzigingen kunnen de validatiekosten voor lichte clients verhogen, of gewoon sterk afwijkend zijn.

De Cenotaph-vlag wordt niet herkend.

Als de waarde van het Flags-veld, na het verwijderen van erkende vlaggen, niet nul is, wordt de runestone beschouwd als een cenotaaf.

Rune

Het Rune-veld bevat de naam van de rune die wordt geëtst. Als de Etching-vlag is ingesteld maar het Rune-veld ontbreekt, wordt een gereserveerde rune-naam toegewezen.

Premine

Het Premine-veld bevat het aantal voorgemijnde runes.

Limiet

Het Cap-veld bevat het toegestane aantal mints.

Aantal

Het Amount-veld bevat het aantal runes dat elke mint-transactie ontvangt.

HeightStart en HeightEnd

De velden HeightStart en HeightEnd bevatten respectievelijk de absolute blokhoogtes waarop de mint begint en eindigt. De mint is open vanaf het blok met hoogte HeightStart en sluit in het blok met hoogte HeightEnd.

OffsetStart en OffsetEnd

De velden OffsetStart en OffsetEnd bevatten de relatieve start- en eindblokhoogtes van de mint, ten opzichte van het blok waarin de etching wordt gemined. De mint is open vanaf het blok met hoogte OffsetStart + ETCHING_HEIGHT, en sluit in het blok met hoogte OffsetEnd + ETCHING_HEIGHT.

Mint

Het veld Mint bevat de Rune ID van de rune die in deze transactie gemint moet worden.

Pointer

The Pointer field contains the index of the output to which runes unallocated by edicts should be transferred. If the Pointer field is absent, unallocated runes are transferred to the first non-OP_RETURN output. If the pointer is greater than the number of outputs, the runestone is a cenotaph.

Cenotaaf

Het veld Cenotaph is niet herkend.

Deelbaarheid

Het veld Divisibility, verheven tot de macht van tien, is het aantal subeenheden in een supereenheid van runes.

Bijvoorbeeld, het bedrag van 1234 runes met een divisibility van 0 tot 3 wordt als volgt weergegeven:

DeelbaarheidWeergave
01234
1123.4
212.34
31.234
Spaties

Het veld Spacers is een bitveld van spaties die moeten worden weergegeven tussen de letters van de naam van de rune.

Het N-de veld van het bitveld, beginnend bij de minst significante bit, bepaalt of er al dan niet een spatie moet worden weergegeven tussen de N-de en de N+1-de karakter, beginnend vanaf de linkerkant van de naam van de rune.

Bijvoorbeeld, de rune-naam AAAA weergegeven met verschillende spaties:

SpatiesWeergave
0b1A•AAA
0b11A•A•AA
0b10AA•AA
0b111A•A•A•A

Achteraf geplaatste spaties worden genegeerd.

Symbool

Het veld Symbol is de Unicode-codepunt van het valuta-symbool van de Rune, dat na de bedragen van die rune moet worden weergegeven. Als een rune geen valuta-symbool heeft, moet het algemene valutateken ¤ worden gebruikt.

Bijvoorbeeld, als het Symbol # is en de deelbaarheid 2 is, zou het bedrag van 1234 eenheden worden weergegeven als 12.34 #.

Nop

Het Nop-veld is niet herkend.

Cenotaaf

Cenotafen hebben de volgende effecten:

  • Alle runes die worden ingevoerd in een transactie die een cenotaph bevat, worden verbrand.

  • Als de runestone die de cenotaph heeft geproduceerd een etching bevatte, heeft de geëtste rune een aanbod van nul en kan deze niet worden gemint.

  • Als de runestone die de cenotaph heeft geproduceerd een mint is, telt de mint mee voor de mint cap en worden de geminte runes verbrand.

Cenotaphs kunnen worden gemaakt als een runestone een niet-herkenbaar even tag bevat, een niet-herkenbaar vlag, een edict met een outputnummer groter dan het aantal inputs, een rune ID met blok nul en een niet-nul transactienummer, een verkeerd geformatteerde varint, een niet-datapush-instructie in het runestone outputscript pubkey, een tag zonder een volgende waarde, of achterblijvende gehele getallen die geen deel uitmaken van een edict.

Uitvoeren van de Runestone

Runestones worden uitgevoerd in de volgorde waarin hun transacties in blokken zijn opgenomen.

Etchings

Een runestone kan een etching bevatten:

#![allow(unused)]
fn main() {
struct Etching {
  divisibility: Option<u8>,
  premine: Option<u128>,
  rune: Option<Rune>,
  spacers: Option<u32>,
  symbol: Option<char>,
  terms: Option<Terms>,
}
}

rune is de naam van de rune die geëtst moet worden, gecodeerd als een gemodificeerde base-26 integer.

Rune-namen bestaan uit de letters A tot Z, met de volgende codering:

NaamCodering
A0
B1
Y24
Z25
AA26
AB27
AY50
AZ51
BA52

Enzovoort, enzovoort.

Rune-namen AAAAAAAAAAAAAAAAAAAAAAAAAAA en hoger zijn gereserveerd.

Als rune wordt weggelaten, wordt een gereserveerde runenaam toegewezen als volgt:

#![allow(unused)]
fn main() {
fn reserve(block: u64, tx: u32) -> Rune {
  Rune(
    6402364363415443603228541259936211926
    + (u128::from(block) << 32 | u128::from(tx))
  )
}
}

6402364363415443603228541259936211926 reageert op de naam van de rune AAAAAAAAAAAAAAAAAAAAAAAAAAA.

Als rune aanwezig is, moet deze worden ontgrendeld vanaf de block waarin de etching verschijnt.

Aanvankelijk worden alle runenamen met een lengte van dertien tekens en langer, tot aan de eerste gereserveerde runenaam, ontgrendeld.

Runen beginnen te ontgrendelen in blok 840.000, het blok waarin het runes-protocol wordt geactiveerd.

Daarna wordt in elke periode van 17.500 blokken de volgende kortste lengte van runenamen continu ontgrendeld. Dus, tussen blok 840.000 en blok 857.500 worden de runenamen van twaalf tekens ontgrendeld, tussen blok 857.500 en blok 875.000 worden de runenamen van elf tekens ontgrendeld, enzovoort, totdat de runenamen van één teken worden ontgrendeld tussen blok 1.032.500 en blok 1.050.000. Zie de ord codebase voor het exacte ontgrendelingsschema.

Om frontrunning van een etching die is uitgezonden maar nog niet gemined is te voorkomen, moet de etching-transactie, indien een niet-gereserveerde runenaam wordt geëtst, een geldige toewijding aan de te etsen naam bevatten.

Een toewijding bestaat uit een datapush van de runenaam, gecodeerd als een little-endian geheel getal waarbij de achteraan geplaatste nullen zijn weggelaten, aanwezig in een input witness tapscript waarbij de output die wordt uitgegeven minstens zes bevestigingen heeft.

Als een geldige toewijding niet aanwezig is, wordt het etsen genegeerd.

Minting

Een runestone kan een rune slaan door de ID van de rune op te nemen in het Mint-veld.

Als de mint open is, wordt het mintbedrag toegevoegd aan de niet-toegewezen runes in de inputs van de transactie. Deze runes kunnen worden overgedragen met behulp van edicten en worden anders overgedragen naar de eerste niet-OP_RETURN output of naar de output die is aangewezen door het Pointer-veld.

Mints kunnen in elke transactie worden uitgevoerd na een etching, inclusief in hetzelfde blok.

Overdragen

Runes worden overgedragen door middel van een edict:

#![allow(unused)]
fn main() {
struct Edict {
  id: RuneId,
  amount: u128,
  output: u32,
}
}

Een runestone kan een onbeperkt aantal edicten bevatten, die in volgorde worden verwerkt.

Voordat edicten worden verwerkt, zijn de invoerrunes, evenals geminte of vooraf gemijnde runes, indien aanwezig, niet toegewezen.

Elke edict verlaagt de niet-toegewezen balans van rune id en verhoogt de balans die is toegewezen aan de transactievermeldingen van rune id.

Als een edict meer runes zou toewijzen dan er momenteel niet-toegewezen zijn, wordt het amount verlaagd tot het aantal momenteel niet-toegewezen runes. Met andere woorden, de edict wijst alle resterende niet-toegewezen eenheden van rune id toe.

Omdat de ID van een gegraveerde rune niet bekend is voordat deze in een blok is opgenomen, wordt ID 0:0 gebruikt om de rune aan te duiden die in deze transactie wordt gegraveerd, indien aanwezig.

Een edict met een amount van nul wijst alle resterende eenheden van rune id toe.

Een edict met output gelijk aan het aantal transactie-uitgangen wijst amount runes toe aan elke niet-OP_RETURN uitgang in volgorde.

Een edict met amount nul en output gelijk aan het aantal transactie-uitgangen verdeelt alle niet-toegewezen eenheden van rune id over elke niet-OP_RETURN uitgang. Als het aantal niet-toegewezen runes niet deelbaar is door het aantal niet-OP_RETURN uitgangen, wordt 1 extra rune toegewezen aan de eerste R niet-OP_RETURN uitgangen, waarbij R de rest is na deling van het saldo van niet-toegewezen eenheden van rune id door het aantal niet-OP_RETURN uitgangen.

Als een edict in een runestone een rune-ID heeft met block nul en tx groter dan nul, of output groter dan het aantal transactie-uitgangen, is de runestone een cenotaph.

Let op dat edicts in cenotaphs niet worden verwerkt en alle invoerrunes worden verbrand.