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:
-
Vind de eerste transactie-output waarvan de script pubkey begint met
OP_RETURN OP_13
. -
Concateneer alle volgende data pushes in een payload-buffer.
-
Decodeer een reeks van 128-bit LEB128 gehele getallen uit de payload-buffer.
-
Parse de reeks van gehele getallen in een ongetypeerd bericht.
-
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:
block | TX | aantal | output |
---|---|---|---|
10 | 5 | 5 | 1 |
50 | 1 | 25 | 4 |
10 | 7 | 1 | 8 |
10 | 5 | 10 | 3 |
Ze worden eerst gesorteerd op blokhoogte en transactie-index:
block | TX | aantal | output |
---|---|---|---|
10 | 5 | 5 | 1 |
10 | 5 | 10 | 3 |
10 | 7 | 1 | 8 |
50 | 1 | 25 | 4 |
En daarna delta-gecodeerd als:
block delta | TX delta | aantal | output |
---|---|---|---|
10 | 5 | 5 | 1 |
0 | 0 | 10 | 3 |
0 | 2 | 1 | 8 |
40 | 1 | 25 | 4 |
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:
Deelbaarheid | Weergave |
---|---|
0 | 1234 |
1 | 123.4 |
2 | 12.34 |
3 | 1.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:
Spaties | Weergave |
---|---|
0b1 | A•AAA |
0b11 | A•A•AA |
0b10 | AA•AA |
0b111 | A•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:
Naam | Codering |
---|---|
A | 0 |
B | 1 |
… | … |
Y | 24 |
Z | 25 |
AA | 26 |
AB | 27 |
… | … |
AY | 50 |
AZ | 51 |
BA | 52 |
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.