qub protokollspecifikáció
A qub egy kriptográfiai időbeli kötelezettségvállalási protokoll: szavakat zár egy jövőbeli dátumhoz, majd ellenőrizhetővé teszi, hogy pontosan mit pecsételtek le, melyik drand-kör kapuzta a felszabadítását, továbbá — ha tárolási tranzakció vagy átláthatósági napló bizonyítéka rendelkezésre áll — azt a függetlenül időbélyegzett felső korlátot, ameddig a titkosított szöveget már rögzítették.
Három alapelem teszi mindezt lehetővé. A drand decentralizált véletlenszerűségi jeladó — a felfedési dátumot kriptográfia érvényesíti, nem a qub jóindulata. A tartós tárolás és egy csak hozzáfűzhető átláthatósági napló megőrzi a lepecsételt bájtokat, és a kötegelt kötelezettségvállalásokat állandó nyilvános tárolóhoz horgonyozza; a fizetős T3 útvonal emellett egyedi állandó-tárolási tranzakciót is ír. Az ML-DSA-65 posztkvantum digitális aláírás — amikor a szerzőség engedélyezett, a qub egy olyan kulcspárhoz kötődik, amelynek titka sosem hagyja el a szerző eszközét.
Együttesen ezek az alapelemek időzárolt és hamisítás-érzékeny, opcionálisan tulajdonítható és függetlenül időbélyegezhető kijelentést hoznak létre — egy nyugtát, amelynek értéke azzal nő, ahogy a világ képessége a múlt meghamisítására fejlődik.
A dokumentum hátralévő része az interoperábilis megvalósításokhoz szükséges normatív specifikáció.
qub protokoll-specifikáció
| Mező | Érték |
|---|---|
| Dokumentumkiadás | 1.0.0 (protocol-v1.0.0) |
| Wire-protokoll | 0x01 |
| Külső burkoló | 0x01 |
| Hatálybalépés dátuma | 2026-09-23 |
| Állapot | Aktuális |
| Átnézve eddig | 2026-09-23 |
Ez a dokumentum a qub időzített kötelezettségvállalási rendszer normatív protokoll-specifikációja. Meghatározza az interoperábilis megvalósításokhoz szükséges adatstruktúrákat, szerializációs szabályokat, levezetési képleteket és ellenőrzési eljárásokat.
Hatókör: a protokollréteg szándékosan nyelvfüggetlen — a qub törzse átlátszatlan egyszerű szöveg / markdown / paktum-bájtok, és a területi beállításnak megfelelő megjelenítés a megjelenítő felelőssége (qub.social webalkalmazás, <qub-embed> iframe, MCP-kliensek stb.).
1. Jelölés és konvenciók
| Jelölés | Jelentés |
|---|---|
u8, u64, i64 |
Megadott bitszélességű előjel nélküli/előjeles egészek |
[u8; N] |
N bájt fix hosszúságú bájttömb |
Vec<u8> |
Változó hosszúságú bájttömb |
Option<T> |
T típusú érték, vagy hiányzó |
String |
UTF-8 szöveges karakterlánc, NFC-normalizált |
| ` | |
SHA3-256(x) |
Az x bájtsorozat NIST SHA3-256 kivonata (FIPS 202) |
ceil(x) |
Felső egészrész függvény: a legkisebb egész ≥ x |
| CBOR | Concise Binary Object Representation (RFC 8949) |
| big-endian | A legjelentősebb bájt elöl |
A bemeneti képek (preimage) konstrukcióiban minden egész szám big-endian fix szélességű bájttömbként van kódolva (i64 → 8 bájt, u8 → 1 bájt), hacsak másként nincs megadva.
Minden időbélyeg Unix másodperc UTC-ben.
2. Adatstruktúrák
2.1 ComposeQub (alkotó memóriában lévő állapota)
Nem szerializálódik CBOR-ba. Nem íródik állandó tárhelyre. Az alkotó alkalmazásához helyi.
ComposeQub {
draft_id: [u8; 16], // Random, generated locally
created_at: i64, // Unix seconds UTC
unlock_at: Option<i64>, // Unix seconds UTC; None while composing
visibility: u8, // 0x00 = private; 0x01 = public
content_type: u8, // 0x01 text; 0x03 pact; 0x04 verdict
plaintext: Vec<u8>, // Raw body bytes (UTF-8 for text)
sender_label: Option<String>, // Display name; V2-signed when authorship is enabled
title: Option<String>, // Plaintext countdown title; bound via title_hash
reply_to: Option<[u8; 32]>,// Parent qub_id; V2-signed when authorship is enabled
outcome_at: Option<i64>, // Optional future judgment time; bound to qub_id
status: DraftStatus, // Composing | Sealed | Uploaded | Failed
}
2.2 QubEnvelope (visszafejtett hasznos adat)
Kanonikus CBOR-ral szerializálva (§3). A SealedQub belsejében titkosítva. Ez a struktúra bizonyítja a tartalom integritását a visszafejtés után.
QubEnvelope {
version: u8, // Protocol major version (0x01 for v1)
qub_id: [u8; 32], // Derived (see §4.1)
content_type: u8, // Content type registry (see §6)
created_at: i64, // Unix seconds UTC
unlock_at: i64, // Unix seconds UTC
outcome_at: Option<i64>, // When reality renders judgment; bound to qub_id
sender_label: Option<String>, // Not in qub_id; V2-signed when authorship is enabled
reply_to: Option<[u8; 32]>,// Parent qub_id; not in qub_id; V2-signed when present
body: Vec<u8>, // UTF-8 text or canonical CBOR pact/verdict body
body_hash: [u8; 32], // SHA3-256(body) (see §4.2)
sig_alg: u8, // Signature algorithm (see §9.2)
author_signature: Option<Vec<u8>>, // Set when sig_alg != 0x00
author_pubkey: Option<Vec<u8>>, // Set when sig_alg != 0x00
cosigner_pubkey: Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
cosigner_signature: Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
}
Alapeset (aláíratlan szöveges qub): version = 0x01, content_type = 0x01, sig_alg = 0x00; az aláírási és társaláíró mezők hiányoznak. Más opcionális metaadatmezők jelen lehetnek.
Egyéb v1 konfigurációk: content_type = 0x03 (paktum-törzs, lásd §6.1); sig_alg = 0x01 (ML-DSA-65) jelen lévő author_signature és author_pubkey mezőkkel (lásd §9.3); cosigner_pubkey és cosigner_signature együttesen jelen van a társaláírt paktumoknál (lásd §9.7); reply_to a szülő qub qub_id értékére állítva a válaszlánc-qubokhoz (az aláírás-hatókör következményeiért lásd §9.3).
2.3 SealedQub (kanonikus wire-formátum)
Kanonikus CBOR-ral szerializálva (§3). Ez a belső wire-műtermék: nyilvános kézbesítéskor ezek a bájtok csupaszon kerülnek tárolásra, míg privát kézbesítéskor tárolás előtt OuterWrapper burkolatba kerülnek (§13).
SealedQub {
version: u8, // Protocol major version (0x01 for v1)
qub_id: [u8; 32], // Same as QubEnvelope.qub_id
visibility: u8, // 0x00 = private/wrapped; 0x01 = public/bare
unlock_at: i64, // Unix seconds UTC
outcome_at: Option<i64>, // Surfaced on the verdict-watch CTA
// before reveal; mirrors QubEnvelope.outcome_at;
// bound to qub_id via the §4.1 preimage.
drand_chain_id: String, // drand chain hash (hex string)
drand_round: u64, // Target drand round number
drand_chain_version: Option<u8>, // W3 — chain-migration version. Absent / 0 = quicknet
// (the only chain today). Lets a future chain swap
// be expressed on the wire without a breaking format
// change. NOT part of the §4.1 qub_id preimage, so its
// addition never alters an existing qub's identity.
tlock_ciphertext: Vec<u8>, // tlock-encrypted QubEnvelope CBOR bytes
recipient_pubkey: Option<[u8; 32]>,// Reserved field; accepted by canonical CBOR
// but not interpreted by the v1 reference viewer
title: Option<String>, // Plaintext title surfaced on the viewer
// countdown before reveal. Bound to qub_id
// via title_hash (§4.1). 1..=100 NFC code
// points, no hostile/control code points.
}
2.4 RevealedQub (megjelenítő alkalmazás állapota)
Nem szerializálódik CBOR-ba. A megjelenítő alkalmazáshoz helyi. Sikeres visszafejtés és ellenőrzés után épül fel.
RevealedQub {
qub_id: [u8; 32],
arweave_tx_id: String,
visibility: u8,
content_type: u8,
created_at: i64,
unlock_at: i64,
outcome_at: Option<i64>, // Carried from both wire layers; drives the verdict-watch block
drand_chain_id: String,
drand_round: u64,
sender_label: Option<String>,
title: Option<String>, // Carried forward from SealedQub.title
reply_to: Option<[u8; 32]>,
body: Vec<u8>,
body_hash: [u8; 32],
body_hash_verified: bool,
author_signature: Option<Vec<u8>>,
author_pubkey: Option<Vec<u8>>,
signature_verified: Option<bool>,
cosigner_pubkey: Option<Vec<u8>>,
cosigner_signature: Option<Vec<u8>>,
cosigner_verified: Option<bool>,
}
3. Kanonikus CBOR-profil
Minden SealedQub és QubEnvelope szerializációnak meg KELL felelnie ennek a profilnak. Két megvalósításnak ugyanazon logikai struktúra esetén azonos bájtokat KELL előállítania.
3.1 Kódolási szabályok
| Szabály | Specifikáció |
|---|---|
| Szabvány | RFC 8949 §4.2.1 (Core Deterministic Encoding Requirements) |
| Kulcsrendezés a térképben | Először a kódolt bájthossz szerint rendezve (rövidebb a hosszabb előtt), majd lexikografikusan (bájtonként az azonos hosszúságú kódolásoknál) |
| Egész szám kódolása | Legrövidebb forma: 0–23 a kezdeti bájtban; 24–255 2 bájtban; 256–65535 3 bájtban; stb. |
| Hosszkódolás | Csak határozott hosszúságok. Nincsenek határozatlan hosszúságú tömbök, térképek, bájtsorozatok vagy szöveges karakterláncok (a kiegészítő info = 31 tilos). |
| Címkék | Nincsenek CBOR-címkék (a 6-os főtípus tilos). |
| Lebegőpontos | Nincsenek lebegőpontos számok (a 7-es főtípus 0xF9–0xFB értékei tiltottak). |
| Szöveges karakterláncok | UTF-8 kódolt, NFC-normalizált (Unicode Normalization Form C). |
| Bájtsorozatok | Nyers bájtok. Nincs base64 kódolás a CBOR-rétegen. |
| Duplikált kulcsok | Hibával elutasítva. Az elemzők NEM fogadhatják el csendben a duplikált térképkulcsokat. |
| Ismeretlen kulcsok | Hibával elutasítva. Az elemzők NEM tolerálhatják a típus kanonikus kulcskészletén kívüli térképkulcsokat — két különböző kanonikus bájtsorozat soha nem dekódolódhat ugyanarra az értékre (encode(decode(x)) == x), aláírt törzsek esetében pedig egy extra kulcs olyan rejtett tartalom lenne, amelyhez mindkét aláírás kötelezi magát. A séma fejlődése a version mezőn keresztül történik, soha nem extra kulcsokkal. |
| Egyszerű értékek | Csak a true (0xF5), false (0xF4) és null (0xF6) megengedett. |
| Opcionális mezők | A hiányzó opcionális mezők teljesen kihagyásra kerülnek a CBOR-térképből (nem null-ként kódolva). A jelen lévő opcionális mezők rendezett kulcssorrendben szerepelnek. |
3.2 Ellenőrzött kanonikus kulcssorrendek
Ezek a kulcssorrendek normatívak. A megvalósításoknak pontosan ebben a sorrendben KELL kibocsátaniuk a kulcsokat. A hibakeresési ellenőrzéseknek (debug assertions) ELLENŐRIZNIÜK KELLENE a sorrendet a nem kiadási buildekben.
QubEnvelope (0x01-es verzió, aláíratlan, minden opcionális mező hiányzik):
"body" (5 encoded bytes)
"qub_id" (7 encoded bytes)
"sig_alg" (8 encoded bytes)
"version" (8 encoded bytes)
"reply_to" (9 encoded bytes) ← only if present (reply chains)
"body_hash" (10 encoded bytes)
"unlock_at" (10 encoded bytes)
"created_at" (11 encoded bytes)
"outcome_at" (11 encoded bytes) ← only if present (verdict mechanic)
"content_type" (13 encoded bytes)
"sender_label" (13 encoded bytes) ← only if present
"author_pubkey" (14 encoded bytes) ← only if present
"cosigner_pubkey" (16 encoded bytes) ← only if present (pact cosign)
"author_signature" (17 encoded bytes) ← only if present
"cosigner_signature" (19 encoded bytes) ← only if present (pact cosign)
QubEnvelope kulcssorrend levezetése: minden kulcs egy CBOR szöveges karakterlánc. Kódolt hossz = 1 bájt fejléc + a karakterlánc hossza (24 bájtnál rövidebb karakterláncoknál). Először a teljes kódolt hossz szerint rendezve, majd lexikografikusan az azonos hosszúságú kulcsoknál.
SealedQub (0x01-es verzió, nyilvános, címzett nélkül):
"title" (6 encoded bytes) ← only if present
"qub_id" (7 encoded bytes)
"version" (8 encoded bytes)
"unlock_at" (10 encoded bytes)
"outcome_at" (11 encoded bytes) ← only if present (verdict mechanic)
"visibility" (11 encoded bytes)
"drand_round" (12 encoded bytes)
"drand_chain_id" (15 encoded bytes)
"recipient_pubkey" (17 encoded bytes) ← only if present
"tlock_ciphertext" (17 encoded bytes)
"drand_chain_version" (20 encoded bytes) ← only if present (W3; absent = quicknet)
PactTerms (paktum-törzs, content_type 0x03):
"notes" (6 encoded bytes) ← only if present
"terms" (6 encoded bytes)
"title" (6 encoded bytes)
"party_a" (8 encoded bytes)
"party_b" (8 encoded bytes)
"pact_version" (13 encoded bytes)
PactTerm (a terms tömb egy sora):
"key" (4 encoded bytes)
"value" (6 encoded bytes)
PartyIdentifier (party_a / party_b térkép):
"label" (6 encoded bytes)
"contact" (8 encoded bytes) ← only if present
3.3 Bájtkódolási referencia
| Típus | CBOR-kódolás | Példa |
|---|---|---|
| SHA3-256 kivonat (32 bájt) | 0x58 0x20 + 32 bájt |
body_hash, qub_id |
| Időbélyegek (i64) | 0-s főtípus (pozitív) vagy 1-es (negatív), legrövidebb kódolás | Unix másodperc |
| Verzió (u8, 1-es érték) | 0x01 (egyetlen bájt) |
|
| Tartalomtípus (u8, 1-es érték) | 0x01 (egyetlen bájt) |
|
| sig_alg (u8, 0-s érték) | 0x00 (egyetlen bájt) |
|
| ML-DSA-65 aláírás (3 309 bájt) | 0x59 0x0C 0xED + 3 309 bájt |
author_signature, cosigner_signature |
| ML-DSA-65 nyilvános kulcs (1 952 bájt) | 0x59 0x07 0xA0 + 1 952 bájt |
author_pubkey, cosigner_pubkey |
4. Normatív levezetések
4.1 qub_id
A qub_id egyedileg azonosít egy qubot, és összeköti a QubEnvelope-ot a SealedQub-bal. Determinisztikusan vezetődik le a boríték tartalmából.
qub_id = SHA3-256(
"QUB_ID_V2" || // domain separator: ASCII bytes [0x51 0x55 0x42 0x5F 0x49 0x44 0x5F 0x56 0x32] (9 bytes) + 0x00 padding (1 byte) = 10 bytes
version || // u8 (1 byte)
content_type || // u8 (1 byte)
created_at || // i64 big-endian (8 bytes)
unlock_at || // i64 big-endian (8 bytes)
outcome_at_or_zero || // i64 big-endian (8 bytes; 0 when outcome_at is absent)
drand_round || // u64 big-endian (8 bytes)
body_hash || // [u8; 32] (32 bytes)
title_hash // [u8; 32] (32 bytes; absent-sentinel = [0u8; 32])
)
// Total preimage: 108 bytes → 32-byte output
Tartománymegkülönböztető kódolása: a "QUB_ID_V2" karakterlánc 9 ASCII-bájt. Egyetlen 0x00 kitöltőbájt fűződik hozzá, hogy elérje a 10 bájtot az igazításhoz. A megvalósításoknak pontosan ezt a 10 bájtot KELL használniuk: [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00].
outcome_at kódolása: egy kiadás előtti megvalósítási változat 92 bájtról 100 bájtra bővítette a bemeneti képet, hogy az opcionális outcome_at mezőt a kötésbe fonja. A hiányzó outcome_at 8 nulla bájtként kódolódik; a protokoll-validátorok mindenhol elutasítják az outcome_at <= 0 értékeket, így ez az őrérték nem ütközhet egy érvényes értékkel. Lásd a §3.2-t (wire-formátum) és a fán belüli tasks/verdict-uplift-plan.md fájlt a mezőt motiváló ítélet-mechanikáért.
drand_round kódolása: egy későbbi kiadás előtti megvalósítási változat 100 bájtról 108 bájtra bővítette a bemeneti képet, hogy a drand_round mezőt (a cél drand-kör, §4.3) is bekösse a kötésbe, és a tartományelválasztót QUB_ID_V2-re emelte. Ez beköti az időzáras kört a qub identitásába: egy átjáró nem kötheti át a titkosított szöveget egy másik (pl. már elmúlt) körhöz, mint amit a megjelenített unlock_at sugall. A feloldási eljárás (§8) ezen felül igazolja, hogy a tlock titkosított szöveg szakaszába (stanza) sütött kör megegyezik az unlock_round(unlock_at) értékével, így a megjelenített feloldási idő bizonyíthatóan az a kör, amely a visszafejtést kapuzza.
Tulajdonságok:
- A bemeneti képhez kötött bármely mező —
version,content_type,created_at,unlock_at,outcome_at,drand_round, a nyersbodybájtjai (abody_hash-en keresztül) vagy atitle(atitle_hash-en keresztül) — megváltoztatása eltérőqub_id-t eredményez. - A qub_id a titkosítás előtt számítódik ki. Mind a QubEnvelope, mind a SealedQub ugyanazt a qub_id-t hordozza. A megjelenítő ellenőrzi, hogy egyeznek-e a visszafejtés után.
- A
qub_idnem függ asender_label,reply_to, az aláírásbájtok vagy az aláíró nyilvános kulcsok mezőktől. A jelenlegi V2 aláírási konstrukcióban azonban az aláírások jelenlétekor asender_labelés areply_toközvetlenül hitelesített asender_label_hash, illetve areply_to_or_zerorévén (§9.3). - A SealedQub
titlemezőjének megváltoztatása (minden más rögzítve) megváltoztatja aqub_id-t atitle_hash-en keresztül. Egy átjáró tehát nem cserélheti ki a visszaszámláláson megjelenített egyszerű szöveges címet a qub-identitás érvénytelenné tétele nélkül. - A SealedQub
outcome_atmezőjének megváltoztatása (minden más rögzítve) megváltoztatja aqub_id-t a bemeneti képen keresztül. Egy átjáró nem cserélheti ki a visszaszámláláson a felfedés előtt megjelenített ítéletnap-dátumot a qub-identitás érvénytelenné tétele nélkül. - A
drand_roundmegváltoztatása (minden mást fixen hagyva) a preimage-en keresztül megváltoztatja aqub_idértékét. Egy átjáró nem kötheti át az időzáras titkosított szöveget egy másik körhöz a qub identitásának érvénytelenítése nélkül; a §8 feloldáskori szakasz-kör-ellenőrzéssel együtt a megjelenítettunlock_ataz a kör, amely ténylegesen kapuzza a visszafejtést.
4.2 body_hash
body_hash = SHA3-256(body)
Ahol a body a nyers Vec<u8> tartalom-hasznosadat. Szöveges qubok esetén ez az UTF-8 kódolt qub-törzs.
4.2.1 title_hash
title_hash = SHA3-256(NFC(title).utf8_bytes) if title is present
title_hash = [0u8; 32] if title is absent
Ahol a title az opcionális egyszerű szöveges cím, amely a megjelenítő visszaszámlálásán jelenik meg a felfedés előtt (lásd §3.2). Az NFC-normalizálás a kivonatképzés idején fut, így a kivonat stabil a vizuálisan egyenértékű kódpont-sorozatok között. A csupa nulla őrérték a hiányzó esetre van fenntartva; az üres karakterlánc a kanonikus CBOR-határon a „hiányzó” nem kanonikus kódolásaként kerül elutasításra (a kanonikus kódolás teljesen kihagyja a mezőt).
4.3 Feloldási kör leképezése
drand_round = floor((unlock_at - chain_genesis_time) / chain_period_seconds) + 1
| Paraméter | Forrás | Példa |
|---|---|---|
unlock_at |
Felhasználó által választott Unix másodperc UTC | 1735689600 (2025-01-01 00:00:00 UTC) |
chain_genesis_time |
drand-lánc info (genesis_time) |
1595431050 |
chain_period_seconds |
drand-lánc info (period) |
30 |
Ez a drand referencia-CurrentRound leképezése. A drand az r kör aláírását a chain_genesis_time + (r - 1) * chain_period_seconds időpontban teszi közzé.
Igazítási tulajdonság (a gyakorlatban fontos eset): ha az (unlock_at - chain_genesis_time) pontosan osztható a chain_period_seconds értékkel, a kiválasztott kör aláírása pontosan az unlock_at időpontban, sosem előbb jelenik meg. A referencia-telepítésben ez mindig teljesül: a quicknet genezisideje (1692803367) osztható a 3 másodperces periódusával, a referenciaalkalmazások pedig egész percekre rögzítik a feloldási időt. Nem igazított unlock_at esetén a kiválasztott kör aláírása szigorúan egy periódusnál kevesebbel az unlock_at előtt jelenik meg — a kötelezettségvállalás időbeli pontossága egy beacon-periódus.
Régi, kiadás előtti leképezés és feloldásoldali tolerancia: az eredeti leképezés ceil((unlock_at - chain_genesis_time) / chain_period_seconds) volt, amely a fenti periódushoz igazított esetben a unlock_at előtt pontosan egy teljes periódussal közzétett kört választotta ki. A két leképezés pontosan +1-gyel tér el, amikor a különbség osztható a periódussal, máskülönben megegyezik. Mivel a drand_round az állandó qub_id bemeneti képébe van kötve (§4.1), a régi leképezéssel lepecsételt műtárgyak nem vezethetők át újra; ezért a §8 6a. lépésének kör-keresztellenőrzését végző ellenőrzőknek el KELL fogadniuk, ha a tárolt drand_round vagy a levezetett kör, vagy a levezetett kör mínusz egy (és meg KELL követelniük, hogy a tlock szakaszköre pontosan a tárolt kör legyen). A tolerancia legfeljebb egy periódussal hozza előre a kapuzó aláírást. A paktum-előkészítő szolgáltatás ugyanezt a toleranciát alkalmazza a színrevitt paktum qub_id-jának újralevezetésekor, és ahhoz a körhöz pecsételi a végleges paktumot, amelyhez a qub_id ténylegesen kötődik.
Validáció: az unlock_at értéknek a lezárás idején a jövőben KELL lennie. Az unlock_at NEM lehet több mint 10 évvel a created_at után (a hosszú távú drand-függőség kockázatának korlátozása érdekében; a felhasználói felületnek FIGYELMEZTETNIE KELLENE a 2 éven túli feloldási dátumoknál).
5. Wire-formátum newtype-ok
A wire-formátum newtype-ok fordítási idejű biztonságot nyújtanak a CBOR-bájtok JSON-nal, nyers egyszerű szöveggel vagy más bájtkódolásokkal való összetévesztése ellen.
| Típus | Tartalmazza | Előállítja | Felhasználja |
|---|---|---|---|
SealedQubCbor |
A SealedQub kanonikus CBOR-ja | serialize_sealed_qub() |
Belső vezetékes műtárgy; nyilvános kézbesítésnél csupaszon, privát kézbesítésnél burkolva tárolódik, majd a megjelenítő állítja helyre |
QubEnvelopeCbor |
A QubEnvelope kanonikus CBOR-ja | serialize_qub_envelope() |
tlock-titkosítás bemenete, tlock-visszafejtés kimenete |
5.1 Konstrukciós szabályok
// Production code — only through CBOR serialisers:
let sealed = SealedQubCbor::from_encoded(cbor_bytes);
// There is deliberately NO From<Vec<u8>> implementation.
// You cannot accidentally wrap arbitrary bytes in a wire format type.
// Accessing raw bytes:
let bytes: &[u8] = sealed.as_bytes();
let bytes: Vec<u8> = sealed.into_bytes();
5.2 Validáció a konstrukciónál
A from_encoded()-nak ELLENŐRIZNIE KELLENE, hogy a bemenet érvényes CBOR-térképfejléccel kezdődik. A teljes szerkezeti validáció az elemzés idején történik, nem a konstrukció idején, hogy elkerülje a dupla elemzést.
6. Tartalomtípus-nyilvántartás
| Érték | Típus | Max. törzsméret | Megjegyzések |
|---|---|---|---|
0x00 |
Fenntartott (érvénytelen) | — | NEM HASZNÁLHATÓ |
0x01 |
Egyszerű szöveg (UTF-8, korlátozott Markdown) | 50 KB fizetős / 10 KB ingyenes | A megjelenítési szabályokért lásd §10. Az ingyenes / fizetős felosztást a feltöltési szolgáltatás érvényesíti; a protokollréteg kemény felső határa 50 KB. |
0x02 |
Fenntartott (jövőbeli) | — | Jövőbeli tartalomtípus számára lefoglalva; v1-ben nem érvényes. A megjelenítőknek el KELL utasítaniuk az alábbi szabály szerint. |
0x03 |
Paktum (kétoldalú megállapodás, CBOR-törzs) | 100 KB | A törzs kanonikus CBOR PactTerms (§6.1). Társaláírás a §9.7 szerint. |
0x04 |
Ítélet (alkotói önértékelés, CBOR-törzs) | 8 KB | A törzs kanonikus CBOR VerdictBody (§6.2). Csak a rendszeroldali verdict szándék bocsátja ki. A szülőkapcsolat a Parent-Tx-Id Arweave-címkén van, nem a törzsben. Lásd verdict-uplift-plan §3.4. |
A megjelenítőknek el KELL utasítaniuk az ismeretlen tartalomtípusokat egyértelmű, felhasználó számára látható hibával. A megjelenítők NEM kísérelhetik meg az ismeretlen típusok szövegként való megjelenítését.
6.1 Paktum-törzs (content_type = 0x03)
A paktum-törzs egy PactTerms érték kanonikus CBOR-kódolása:
PactTerms {
pact_version: u8, // 0x01 for structured/v1
title: String, // ≤ 200 bytes, NFC
terms: Vec<PactTerm>, // ≤ 20 rows
party_a: PartyIdentifier, // initiator
party_b: PartyIdentifier, // counter-signer
notes: Option<String>, // ≤ 5,000 bytes, NFC; absent key if none
}
PactTerm { key: String (≤ 100 bytes), value: String (≤ 2,000 bytes) } // NFC
PartyIdentifier{ label: String (≤ 100 bytes), contact: Option<String (≤ 320 bytes)> }
A három térkép kanonikus CBOR-kulcssorrendjeit a §3.2 adja meg. A teljes szerializált paktum-CBOR NEM haladhatja meg a 100 KB-ot (megegyezik a §6-tal).
Sémamegkülönböztető. A structured/v1 paktum terms tömbjének első sorának { key: "pact_schema", value: "structured/v1" }-nek KELL lennie. Az ezen jelölés nélküli sorok „egyedi” paktumok, és nem kapnak strukturált validációt vagy sématudatos megjelenítést.
Fagyasztott visszaigazolási helyek. A structured/v1 paktumok pontosan négy visszaigazolási sort hordoznak ezeken a kulcsokon:
"initiator_standard_terms"
"initiator_capacity_terms"
"counterparty_standard_terms"
"counterparty_capacity_terms"
Mindegyik value mezője nyolc fagyasztott angol karakterlánc egyike, amelyet a (role, kind) pár választ ki, ahol role ∈ { seller, buyer, provider, client } és kind ∈ { standard, capacity }. Maguk a karakterláncok normatív protokolladatok — mindkét fél ML-DSA-65 aláírása a body_hash-en keresztül a pontos bájtokra kötelez. NEM lokalizáltak; az aláírt törzs nyelvfüggetlen. Bármely szövegezési változtatás új sémaverziót igényel (structured/v2).
A nyolc karakterláncot, keresésüket (acknowledgement_for(role, kind)) és mindegyik indoklását a referencia-megvalósítás rögzíti. A megfelelő megvalósításoknak bájtazonos visszaigazolási értékeket KELL kibocsátaniuk; mind a négy szerepkombinációt lefedő arany-fixture SHA3-256 body-hash tesztek elkapnak bármely eltérést.
Megjelenítő-megjelenítési sorrend. A visszaigazolási karakterláncok olyan kifejezéseket tartalmaznak, mint a „described above” (fent leírt), amely feltételezi, hogy a leírás / hatókör sorok a visszaigazolások előtt jelennek meg. A megjelenítőknek a terms tömböt CBOR-sorrendben KELL megjeleníteniük; az átrendezés megtöri a prózai szemantikát.
Ellenérdekelt fél kapcsolata. Amikor a B fél contact mezője érvényes e-mail-cím, a qub feltöltési szolgáltatás automatikusan elküld egy áttekintési / társaláírási meghívó e-mailt a színrevitel idején, és az esetleges társaláírást ugyanazon cím ellenőrzéséhez köti (§9.7). Azok a paktumok, amelyek B felének kapcsolata hiányzik, továbbra is társaláírhatók, de csak sávon kívüli csatornán keresztül — a szolgáltatás visszautasítja azokat a társaláírási kéréseket, amelyek nem tudnak megfelelő 15 perces e-mail-ellenőrzési jelölőt előállítani.
6.2 Ítélet-törzs (content_type = 0x04)
Az ítélet-törzs egy VerdictBody érték kanonikus CBOR-kódolása:
VerdictBody {
verdict_version: u8, // 0x01 for structured/v1
outcome: u8, // 1=Right · 2=Partial · 3=Wrong · 4=Unfalsifiable
reflection: Option<String>, // ≤ 2,000 bytes NFC; "what changed, what did you learn"
evidence_url: Option<String>, // ≤ 2,048 bytes; HTTPS only; absent key when omitted
}
Kanonikus CBOR-kulcssorrend:
"outcome" (8 encoded bytes)
"reflection" (11 encoded bytes) ← only if present
"evidence_url" (13 encoded bytes) ← only if present
"verdict_version" (16 encoded bytes)
A teljes szerializált ítélet-CBOR NEM haladhatja meg a 8 KB-ot (megegyezik a fenti regisztrációs sorral).
Eredmény-enumeráció. A wire-bájt szándéktól független; a négy kategória — Right / Partial / Wrong / Unfalsifiable — lefedi minden ítéletet hordozó szándék eredményterét. A szándékfüggő címkék („Megmondtam” / „Megtartottam” / „Terv szerint szállítottuk” / „Az események igazolták” a Right esetében stb.) a megjelenítő oldali renderelés kérdése, a szülő qub szándéka alapján — a wire nyelv- és szándék-független marad. Az 1..=4 tartományon kívüli értékeket dekódoláskor el KELL utasítani.
Szülő-kapcsolat. Egy ítélet-qub NEM hordozza a szülő-hivatkozást a törzsében. A szülő qub Arweave-tranzakcióazonosítója a Parent-Tx-Id tárolási címkeként kerül kibocsátásra feltöltéskor (§7 tárolási címkeréteg). Ez a törzset önálló, aláírt önértékelési nyilatkozatként tartja meg; az audit-lánc („mire vonatkozóan volt igaza?”) az Arweave-címke keresése révén jön létre.
Bizonyíték-URL biztonsága (normatív). Amikor az evidence_url jelen van, a validátoroknak (összeállítás-oldal, wire-oldal, Worker él) érvényesíteniük KELL:
- Csak HTTPS. A karakterláncnak a
https://bájtsorozattal KELL kezdődnie. Bármely más séma —http,ftp,javascript,data,filestb. — elutasításra kerül. - Hosszkorlát. ≤ 2 048 bájt (gyakorlati böngésző-URL-korlát).
- NFC + ellenséges-kódpont-ellenőrzés. Ugyanaz a szabály, mint a
titleésreflectionesetén — bidi-felülírás / nulla szélességű / tag-blokk / BOM / C0 / C1 kódpontok elutasításra kerülnek. A definíció megegyezik a Rustcrate::handle::contains_hostile_text_codepointés a TSworkers/api/src/utils/unicode.ts::isHostileCodepointfüggvényekkel (tartsd őket szinkronban). - Nincs szóköz, nincsenek ASCII-vezérlők. A szóközök / DEL /
0x20alatti bájtok az URL bármely pontján elutasításra kerülnek — ez zárja le a\n/\tinjekciós vektort, amelyet a bidi-szabály nem fed le. - Nem üres gazdagép-szegmens. A
https://és az első/,?vagy#közötti tartománynak nem üresnek KELL lennie.
Nincs szerveroldali lekérés. A Worker NEM proxyzhatja, kérheti le vagy nézheti meg előnézetben az URL-t. A protokoll egy karakterláncot tárol; a megjelenítés megjelenítő-oldalon történik rel="nofollow noopener noreferrer" target="_blank" attribútumokkal és a linkszöveg mellett láthatóan megjelenített gazdagéppel.
Reflexió. Opcionális alkotó által írt reflexiós szöveg („mi változott, mit tanultál”). Ugyanaz az NFC + ellenséges-kódpont-validáció, mint a title esetében. Az üres / csak szóközből álló bemenet az építéskor hiányzóra esik vissza.
Sémaverzió. A v1 csak verdict_version = 0x01 értéket támogat. A jövőbeli sémaverziók megemelik ezt a bájtot, és új protokollverzióval együtt érkeznek a §12 szerint.
7. Lezárási protokoll
A teljes lezárási sorozat. Minden lépés normatív.
1. User composes plaintext and metadata in ComposeQub.
2. Validate:
a. body is non-empty.
b. body size ≤ max for content_type and user tier (see §6).
c. unlock_at is in the future.
d. unlock_at ≤ created_at + 10 years.
e. content_type is a known, supported value.
f. visibility is 0x00 (private) or 0x01 (public).
3. Compute body_hash = SHA3-256(body).
4. Set created_at = current Unix seconds UTC.
5. Select drand chain. Load chain_genesis_time and chain_period_seconds, and
compute drand_round = floor((unlock_at - chain_genesis_time) / chain_period_seconds) + 1
(§4.3). (Computed here, before qub_id, because drand_round is bound into the
qub_id preimage—§4.1.)
6. Compute qub_id (see §4.1), folding in drand_round from step 5.
7. Construct QubEnvelope with all fields.
8. Serialise QubEnvelope using canonical CBOR → bytes B.
Assert: serialised output matches canonical profile (§3).
9. Compute C = tlock_encrypt(B, drand_round, drand_chain_public_key).
10. Construct SealedQub with tlock_ciphertext = C and matching qub_id, version,
visibility, unlock_at, drand_chain_id, and drand_round.
11. Serialise SealedQub using canonical CBOR → SealedQubCbor.
12. Select the delivery shape from visibility:
a. Private (0x00): generate K = 32 random bytes and N = 12 random bytes
using a CSPRNG. Compute W = wrap_sealed_qub(SealedQubCbor,
qub_id=qub_id, key=K, nonce=N) per §13. Upload payload = W.
b. Public (0x01): upload payload = bare SealedQubCbor; do not generate K.
13. Display seal-time disclosure. User confirms.
14. Validate upload eligibility via the qub upload service (bot-detection, entitlement, rate limits).
15. Submit the selected upload payload to the qub upload service. For a private
browser seal, the service is byte-blind to the inner SealedQubCbor and never
receives K. The Builder `/api/v1/seal` route is an explicit exception: it
receives plaintext and caller-supplied K in memory, then persists neither.
16. Receive arweave_tx_id from the service. For private delivery, construct
`<origin>/c/<arweave_tx_id>#<base64url(K)>` (or the equivalent short-code
path). For public delivery, omit the fragment. Browsers do not transmit URL
fragments to servers, so K from the browser-seal path is not observed by
qub.social or any storage gateway.
Tárolási címkeréteg (sávon kívül). A qub feltöltési szolgáltatás szándékosan kis halmaz tárolási tranzakciós címkét csatol a kiválasztott feltöltési hasznos adat mellé. A Content-Type=application/octet-stream normatívan kötelező. A referencia-szolgáltatás emellett három opcionális címkét csatol, amikor az alkotó úgy dönt, hogy megjeleníti őket: Intent (engedélylistával ellenőrzött összeállítási szándék — announcement, thesis, prediction, letter, secret, commitment, proof vagy a rendszer által kibocsátott verdict), Author (az alkotó §9.3 nyilvános kulcsának ujjlenyomata 64 karakteres kisbetűs hexként) és Parent-Tx-Id (a szülő qub tárolási tranzakciós azonosítója válaszláncokhoz, 43 karakteres base64url).
Az Author címke qubonként választható: a referencia-alkotóalkalmazás csak akkor csatolja, ha a felhasználó kifejezetten engedélyezi a nyilvános tulajdonítást a lezárás idején. Amikor a kapcsoló ki van kapcsolva — ez az alapértelmezett —, nem íródik Author címke, és a qub a láncon tulajdonítatlan: semmi az állandó tárhelyen nem köti össze a feltöltést egy alkotó kezelőjével, e-mail-címével vagy más qubjaival. Amikor a kapcsoló be van kapcsolva, az Author ujjlenyomat az alkotó által választott @kezelő-re oldódik fel a §9.5 attesztációs láncon keresztül. A válaszlánc-kapcsolatok és az Intent nem azonosítóak. Privát kézbesítésnél a külső burkoló (§13) titkosítja a felismerhető belső SealedQub-artefaktumot, ezért a tárolt burkolók begyűjtése és a nyilvános drand-aláírások megszerzése K nélkül továbbra sem elegendő a törzs visszanyeréséhez; a tárolási címkék szándékosan nyilvános metaadatok maradnak.
A referencia-szolgáltatás szándékosan NEM csatol App-Name, App-Version vagy Type címkéket: bármely ilyen egyértékű szűrő egy GraphQL-lekérdezésnek a teljes qub-korpuszt visszaadná, ami nincs összhangban a burkoló csak-törzs bizalmassági hatókörével.
A megfelelő ellenőrzőnek NEM szabad semmilyen tárolási címkétől függenie a §11 harmadik fél általi ellenőrzéshez; a body hash / qub_id / aláírás csak a belső CBOR-ra kötelez, soha nem a címkehalmazra.
8. Feloldási protokoll
A teljes feloldási sorozat. Minden lépés normatív.
1. Viewer opens delivery URL. Extract arweave_tx_id from the path and retain
the optional URL fragment. Do not assume a missing fragment is an error:
public/bare delivery intentionally has no K.
2. Check denylist. If tx_id is denylisted → display block message. Stop.
3. Fetch the stored bytes (with multi-gateway fallback).
3a. Resolve the delivery shape structurally:
a. If the bytes parse as OuterWrapper, require a well-formed 32-byte K in
the URL fragment, require wrapper version 0x01, and unwrap per §13.
Any missing/malformed K or AEAD failure is a terminal error.
b. Otherwise require the bytes to parse as bare SealedQubCbor; no K is
required. If neither shape parses, report an integrity error.
4. Parse SealedQubCbor → SealedQub.
5. Validate: SealedQub.version is known (0x01), visibility is known, and the
delivery shape matches it (wrapped = 0x00 private; bare = 0x01 public).
Reject any mismatch or unknown value.
6. If current time < SealedQub.unlock_at → display countdown. Poll or wait.
6a. Round-binding check. Recompute expected_round from
SealedQub.unlock_at per §4.3. Reject unless SealedQub.drand_round ==
expected_round OR SealedQub.drand_round == expected_round - 1 (the
legacy pre-release mapping—see §4.3), AND the round baked into the tlock
ciphertext stanza (read via the age/tlock header, no signature required)
== SealedQub.drand_round exactly. The stanza round is the one that
actually gates decryption; without this check a malicious creator could
bind the ciphertext to an already-past round while displaying a future
countdown, so anyone reading the stored bytes could decrypt before
unlock_at. Implementations with no chain identity (test mocks) skip this
check.
7. Once current time ≥ SealedQub.unlock_at:
a. Fetch drand round signature for SealedQub.drand_round from drand network.
b. Compute B = tlock_decrypt(SealedQub.tlock_ciphertext, round_signature).
8. Parse B → QubEnvelope.
9. Validate QubEnvelope.version is known.
10. Verify: SHA3-256(QubEnvelope.body) == QubEnvelope.body_hash.
Fail → integrity error.
11. Verify: QubEnvelope.qub_id == SealedQub.qub_id.
Fail → integrity error.
12. Verify: QubEnvelope.unlock_at == SealedQub.unlock_at.
Fail → integrity error.
12a. Verify: QubEnvelope.outcome_at == SealedQub.outcome_at (both absent, or
both present and equal). Fail → integrity error.
12b. Content re-derivation. Recompute qub_id per §4.1 from the decrypted
fields — (QubEnvelope.version, content_type, created_at, unlock_at,
outcome_at, SealedQub.drand_round, QubEnvelope.body_hash,
title_hash(SealedQub.title)) — and verify it equals SealedQub.qub_id.
Fail → integrity error. The pairwise checks in steps 10-12a only prove
the two layers agree with EACH OTHER; a forger who rewrites a bound
field consistently on both surfaces (a pre-reveal title swap, or a
post-round body swap with a recomputed body_hash re-encrypted to the
same round under the same qub_id) passes them all. Only re-deriving
the identity from content closes this.
13. Verify: QubEnvelope.content_type is known and renderable.
Known values: 0x01 (text), 0x03 (pact), 0x04 (verdict).
Unknown → display error.
14. If QubEnvelope.sig_alg != 0x00 → verify author signature (see §9.4).
15. If cosigner_pubkey or cosigner_signature present → verify cosigner (see §9.7).
16. Render content using the appropriate renderer (see §10 for text and §6 for pact/verdict).
17. Construct RevealedQub for display.
9. Szerzőség aláírása
9.1 Indoklás
A qubok állandó tárhelyen tárolódnak. A szerzőségi aláírásoknak határozatlan ideig hamisíthatatlannak kell maradniuk, ezért a v1.0 a posztkvantum ML-DSA-65 sémát (FIPS 204) használja, nem pedig egy klasszikus sémát, amelynek biztonsága a qub állandó élettartamán belül romolhat.
9.2 Algoritmus-nyilvántartás
sig_alg |
Séma | Kulcsméret | Aláírásméret | Állapot |
|---|---|---|---|---|
0x00 |
Nincs aláírás (aláíratlan) | — | — | Aktív |
0x01 |
ML-DSA-65 (FIPS 204) | 1 952 bájt | 3 309 bájt | Aktív |
0x02 |
Ed25519 | 32 bájt | 64 bájt | Fenntartott konstans; a v1 protokollban nem támogatott |
A v1 protokoll megjelenítőinek a {0x00, 0x01} halmazon kívüli minden értéket el KELL utasítaniuk, beleértve a fenntartott 0x02 értéket is. A fenntartás megakadályozza a véletlen újrafelhasználást; nem jelenti az aktiválást. Az aktiválás a §15-ben leírt szabályozott változtatást igényli.
9.3 Aláírt bemeneti kép konstrukciója
Két bemeneti kép-verzió létezett. Minden aláírásnak V2-t KELL használnia, és az ellenőrzőknek KIZÁRÓLAG a V2-t KELL elfogadniuk. A régi V1 bemeneti kép (alább, történeti hivatkozásként dokumentálva) csak ellenőrzési tartalékként volt elfogadott a V2-re való átállás idején; ez a tartalék azóta kivezetésre került, és a kizárólag V1 ellen érvényes aláírást mostantól elutasítjuk.
V2 (jelenlegi — minden új szerzői aláírás, valamint a paktum-színrevitel / társaláírási folyamat mindkét aláírása ezt állítja elő):
sig_input = SHA3-256(
"QUB_AUTHOR_SIG_V2" || // domain separator (17 bytes)
version || // u8 (1 byte)
qub_id || // [u8; 32] (32 bytes)
body_hash || // [u8; 32] (32 bytes)
unlock_at || // i64 big-endian (8 bytes)
0x00 || // u8 (1 byte): MUST be 0x00 in v1.x
sender_label_hash || // [u8; 32]: SHA3-256(NFC(sender_label)),
// or 32 zero bytes when absent
reply_to_or_zero // [u8; 32]: parent qub_id, or 32 zero
// bytes when absent
)
// Total preimage: 155 bytes → 32-byte hash
signature = Sign(author_secret_key, sig_input)
A sender_label_hash ugyanazt a hiányt jelző (absent-sentinel) konvenciót követi, mint a title_hash (§4.2.1): a 32 nullbájt nem érvényes SHA3-256 kimenet, így a „hiányzó” soha nem ütközhet egy jelen lévő címkével. Minden mező fix szélességű, így a bemeneti kép hosszelőtagok nélkül is egyértelmű.
V1 (régi — KIVEZETVE; többé nem állítjuk elő, és ellenőrzéskor sem fogadjuk el):
sig_input = SHA3-256(
"QUB_AUTHOR_SIG_V1" || // domain separator (17 bytes)
version || // u8 (1 byte)
qub_id || // [u8; 32] (32 bytes)
body_hash || // [u8; 32] (32 bytes)
unlock_at || // i64 big-endian (8 bytes)
0x00 // u8 (1 byte): MUST be 0x00 in v1.0
)
// Total preimage: 91 bytes → 32-byte hash
A V1 bemeneti kép kihagyta a sender_label és reply_to mezőket. Csak ellenőrzési tartalékként volt elfogadott a V2-re való átállás idején; ez a tartalék azóta kivezetésre került — az ellenőrzőknek KIZÁRÓLAG a V2 bemeneti képet KELL elfogadniuk. A definíciót itt történeti hivatkozásként, valamint az alábbi tartománymegkülönböztető magyarázata céljából őrizzük meg. Az olyan aláírást, amely csak a V1 ellen érvényes, ellenőrzési hibaként KELL kezelni.
Tartománymegkülönböztetők: a "QUB_AUTHOR_SIG_V1" / "QUB_AUTHOR_SIG_V2" egyenként 17 ASCII-bájt ([0x51, 0x55, 0x42, 0x5F, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x5F, 0x53, 0x49, 0x47, 0x5F, 0x56, 0x31/0x32]). Nincs kitöltés. Az eltérő megkülönböztető tartományilag elválasztja a két konstrukciót, így az egyik bemeneti kép fölötti aláírás soha nem ellenőrizhető a másikként.
org_id_present bájt: az unlock_at-ot követő bájtnak 0x00-nak KELL lennie. A referencia-megvalósítás ezt ORG_ID_PRESENT_INDIVIDUAL = 0x00 konstansként teszi elérhetővé a crates/qub-core/src/signing.rs fájlban; az ellenőrzéshez sig_input-ot újraépítő megjelenítőknek ugyanazt a bájtot KELL kibocsátaniuk.
Aláírás-hatókör — mi van és mi nincs lefedve. A V2 sig_input közvetlenül a version, qub_id, body_hash, unlock_at, sender_label és reply_to mezőkre kötelez (plusz a rögzített tartománymegkülönböztető és az org_id_present bájt). A qub_id maga is a version, content_type, created_at, unlock_at, outcome_at, drand_round és body_hash mezőkből vezetődik le a §4.1 bemeneti képen keresztül, így e mezők bármely változtatása eltérő qub_id-t eredményez, és tranzitíven érvényteleníti az aláírást. A közvetlenül hitelesített felület tehát:
| Mező | Aláírás által hitelesített | Hogyan |
|---|---|---|
version |
✓ | Közvetlen bemenet a sig_input-hoz |
qub_id |
✓ | Közvetlen bemenet |
body_hash |
✓ | Közvetlen bemenet |
unlock_at |
✓ | Közvetlen bemenet |
content_type |
✓ | Tranzitíven, a qub_id bemeneti képen keresztül |
created_at |
✓ | Tranzitíven, a qub_id bemeneti képen keresztül |
outcome_at |
✓ | Tranzitíven, a qub_id bemeneti képen keresztül |
drand_round |
✓ | Tranzitíven, a qub_id bemeneti képen keresztül |
body |
✓ | Tranzitíven, a body_hash = SHA3-256(body)-on keresztül |
author_pubkey |
— (implicit) | Az aláírást ellenőrző kulcs definíció szerint a szerző |
sender_label |
✓ | Közvetlen bemenet a sender_label_hash-en keresztül (V2 bemeneti kép — az egyetlen elfogadott forma) |
reply_to |
✓ | Közvetlen bemenet a reply_to_or_zero-n keresztül (V2 bemeneti kép — az egyetlen elfogadott forma) |
cosigner_pubkey / cosigner_signature |
— | Függetlenül aláírva ugyanazon sig_input-ra (lásd §9.7) |
drand_chain_id, tlock_ciphertext, visibility |
— | Külső SealedQub mezők, nem a borítékon belül — saját szerkezeti invariánsaik (kör- / lánckonzisztencia) fedik le őket, de nem a szerzői aláírás (A drand_round mostantól tranzitívan kötve van a qub_id preimage-en keresztül — lásd fent.) |
Miért a V2 az egyetlen elfogadott bemeneti kép.
- A kivezetett V1 bemeneti kép alatt a tárolt bájtokhoz írási hozzáféréssel rendelkező fél kicserélhette a
sender_label-t („Alice” → „Mallory”) vagy átszülőzhette areply_to-t — és a kör után újratitkosíthatott — a szerzői aláírás érvénytelenné tétele nélkül, mivel egyik mező sem szerepelt az aláírt bemeneti képben. A V2 mindkettőt lefedi, így bármelyik mező bármilyen változtatása „sikertelenre” billenti az ellenőrzést. Mivel az ellenőrzők mostantól kizárólag a V2-t fogadják el, ez a csere minden aláírásra le van zárva: azt az aláírást, amely egyik mezőt sem köti (azaz csak a V1 ellen érvényes), egyenesen elutasítjuk, nem pedig visszafokozunk hozzá. - A borítékon belüli
author_pubkeymarad a valódi identitáshorgony — a megjelenítőknek a megjelenítési identitást azauthor_pubkey-ből KELL levezetniük (a §9.5 attesztációs rétegen keresztül), nem pedig asender_label-ben bízva.
Azoknak a megvalósításoknak, amelyek sender_label-t vagy reply_to-t jelenítenek meg a végfelhasználóknak, a hitelesített identitást (nyilvános kulcs ujjlenyomata, attesztáció) KELL elsődleges identitásjelzésként megjeleníteniük, nem a címkét.
9.4 Ellenőrzési eljárás
1. Read sig_alg from QubEnvelope.
2. If sig_alg == 0x00 → unsigned. No verification. Display "unsigned qub."
3. If sig_alg is unknown → reject. Display "unrecognised signature scheme."
4. Extract author_signature and author_pubkey. If either is absent → integrity error.
5. Reconstruct sig_input using fields from QubEnvelope (V2 formula, §9.3).
6. Verify(author_pubkey, sig_input, author_signature). The V2 preimage is the
only accepted form — the legacy V1 fallback is retired (§9.3), so a
signature that does not verify against V2 fails, full stop.
7. If verification succeeds → display "signed by [key fingerprint]."
8. If verification fails → display "signature verification failed."
Az aláírás-ellenőrzés a legdrágább művelet (különösen az ML-DSA-65). Az összes olcsóbb ellenőrzés (kivonat, qub_id, unlock_at) sikeres áthaladása UTÁN KELLENE elvégezni.
9.5 Identitás-attesztációk
Az identitás-attesztációk — az author_pubkey leképezése ember számára felismerhető identitási állításokra, mint például egy qub-kezelő, e-mail-cím, közösségi kezelő vagy passkey hitelesítő adat — megjelenítő-oldali progresszív fejlesztés, és nem szükségesek az aláírás-ellenőrzéshez. Azoknak a megjelenítőknek, amelyek megjelenítési identitásra oldják fel az attesztációkat, az alábbi elsőbbséget KELL alkalmazniuk:
handle > email > social > fingerprint
Az ujjlenyomat-tartalékérték a SHA3-256(author_pubkey) kisbetűs hexa formája; mindig elérhető bármely aláírt qubhoz. A megjelenítők megjelenítés céljából RÖVIDÍTHETIK — a referencia-megjelenítő a qub: előtagot, majd az első és utolsó négy bájtot jeleníti meg (qub:<8 hex>…<8 hex>).
A megfelelő ellenőrző a §9.4 minden ellenőrzését el tudja végezni anélkül, hogy a qub API-val kapcsolatba lépne, az állandó tárhelyen és a drandon túli bármilyen hálózat nélkül, és bármilyen szerveroldali keresés nélkül. Az attesztáció feloldása külön, legjobb erőfeszítésű lépés, amelyet csak az aláírás-ellenőrzés sikeres befejezése után végeznek el.
9.6 Méretre gyakorolt hatás
| Ed25519 | ML-DSA-65 | |
|---|---|---|
| Aláírás | 64 bájt | 3 309 bájt |
| Nyilvános kulcs | 32 bájt | 1 952 bájt |
| Összesen qubonként | 96 bájt | 5 261 bájt |
| Tárolási költségkülönbség (~$5/MB-nál) | ~$0,0005 | ~$0,026 |
Egy 500–2 000 bájtos szöveges qub esetén az ML-DSA-65 nagyjából megháromszorozza a tárolt méretet. Az abszolút költség elhanyagolható.
9.7 Társaláíró-ellenőrzés (paktum kétoldalú megállapodások)
Kétoldalú megállapodásoknál (content_type = 0x03) egy második aláírási réteg bizonyítja, hogy mindkét fél hozzájárult ugyanazokhoz a feltételekhez.
Borítékmezők:
cosigner_pubkey: az ellenérdekelt aláíró (B fél) ML-DSA-65 nyilvános kulcsa.cosigner_signature: aláírás ugyanazonsig_input-ra, mint a szerzőé (§9.3).
Mindkét mezőnek együtt KELL jelen lennie, vagy mindkettőnek hiányoznia. Ha pontosan az egyik van jelen, a megjelenítőknek integritáshibát KELL jelenteniük.
Ellenőrzési eljárás:
1. If cosigner_pubkey absent and cosigner_signature absent → no cosigner. Done.
2. If exactly one is present → integrity error.
3. Verify cosigner_pubkey != author_pubkey (prevent self-cosigning).
Fail → display "cosigner pubkey must differ from author."
4. Reconstruct sig_input using the same formula as §9.3 (V2 only — the
legacy V1 fallback is retired; all pact clients produce V2 signatures).
5. Verify(cosigner_pubkey, sig_input, cosigner_signature).
6. Success → display "co-signed by [cosigner fingerprint]."
7. Failure → display "co-signature verification failed."
Tulajdonságok:
- A társaláíró ugyanazt a
sig_input-ot írja alá, mint a szerző — mindkét fél ugyanarra aqub_id-ra,body_hash-re ésunlock_at-ra kötelez (és V2 alatt ugyanarra asender_label_hash-re ésreply_to_or_zero-ra). - Hogy az ellenérdekelt aláíró a nyers borítékbájtokhoz való hozzáférés nélkül is újra tudja építeni a V2 bemeneti képet, a színrevitel-szolgáltatás a színrevitel idején kikényszeríti, hogy a paktum-boríték
sender_labelmezője megegyezzen apact_terms.party_a.labelértékkel, és hogy areply_tohiányozzon. Mindkettő teljesül minden referencia-kliens paktumára; a feltételt sértő borítékokat a színrevitelkor elutasítjuk. - A
qub_idlevezetése (§4.1) NEM tartalmazza a társaláíró-mezőket. Társaláíró hozzáadása egy meglévő borítékhoz nem változtatja meg aqub_id-t. - Egy paktum lehet csak szerző által aláírt (egyoldalú kötelezettségvállalás), csak társaláírt (szokatlan) vagy mindkettő (teljes kétoldalú bizonyíték).
E-mail-kötési kapu (működési). Amikor egy színrevitt paktum B fél e-mail-kapcsolatot hordoz (§6.1), a qub feltöltési szolgáltatásnak el KELL utasítania a társaláírási kérést, hacsak nem létezik rövid élettartamú e-mail-ellenőrzési jelölő, amely megegyezik mind a színrevitel azonosítójával, mind az adott kapcsolat normalizált e-mail-kivonatával. A jelölőt a /api/v1/auth/verify írja, amikor a magic-link token staging_id-t hordoz, és az ellenőrzött cím megegyezik a SHA-256(normalise_email(party_b.contact))-tal — ahol a normalise_email(addr) megőrzi a helyi rész kis-/nagybetűjét, és csak a tartományrészt kisbetűsíti (az RFC 5321 §2.3.11 szerint), és a SHA-256 itt a NIST FIPS 180-4 kivonat (eltérő a §4 levezetésekben használt SHA3-256-tól) —, és 900 másodperccel (15 perccel) a kibocsátás után lejár. Ez működési megszemélyesítés-elleni kapu, NEM a láncon lévő qub-bizonyíték része — egy harmadik fél ellenőrzőnek, amely a §11-et lejátssza, csak állandó tárhelyre és drandra van szüksége, bármilyen szerveroldali keresés nélkül. A jelölő csak szerveroldalon létezik, és soha nem része az aláírt törzsnek.
Méretre gyakorolt hatás (ML-DSA-65 szerző + társaláíró):
| Komponens | Méret |
|---|---|
| Szerzői aláírás | 3 309 bájt |
| Szerzői nyilvános kulcs | 1 952 bájt |
| Társaláírói aláírás | 3 309 bájt |
| Társaláírói nyilvános kulcs | 1 952 bájt |
| Teljes kriptográfiai többletteher | 10 522 bájt |
| Tárolási költségkülönbség | ~$0,05 |
10. Markdown-megjelenítés és -tisztítás
Ez a szakasz biztonságkritikus. A megjelenítő a szöveges qubokat (content_type = 0x01) korlátozott Markdown-részhalmazzal jeleníti meg.
10.1 Engedélyezett elemek
- Címsorok:
#-tól####-ig (nincs#####vagy######) - Kiemelés: félkövér (
**), dőlt (*), áthúzott (~~) - Listák: rendezett (
1.) és rendezetlen (-,*) - Idézetblokkok (
>) - Kód: soron belüli szakaszok (```) és bekerített blokkok (`````)
- Vízszintes vonalak (
---) - Sortörések (két záró szóköz vagy üres sor)
- Bekezdések
10.2 Tiltott elemek
| Elem | Kezelés |
|---|---|
Nyers HTML (<div>, <script> stb.) |
Teljesen eltávolítva. Semmilyen HTML nem jut át. |
Képek () |
Eltávolítva. A kép-szintaxis eltávolításra kerül a kimenetből. |
Hivatkozások ([text](url)) |
Az URL látható egyszerű szövegként jelenik meg. Nincs automatikus hivatkozás. Kifejezett felhasználói művelet nélkül nem kattintható. |
| Veszélyes URL-sémák | javascript:, data:, vbscript:, file: — eltávolítva. |
| Iframe-ek, beágyazások, objektumok | Eltávolítva. |
| HTML-entitások | Megjelenítési karakterekké dekódolva, csak ha biztonságosak. |
10.3 Megvalósítás
A megvalósításoknak szigorú engedélylista-elemzőt KELL használniuk, nem tiltólistát. Az ajánlott megközelítés:
- A Markdown elemzése
pulldown-cmark(vagy egyenértékű) használatával. - Az AST bejárása, és bármely olyan csomópont elvetése, amely nincs az engedélylistán (§10.1).
- Hivatkozási csomópontoknál: az URL kibocsátása látható szövegként, nem kattintható
<a>elemként. - A szűrt AST átalakítása típusos köztes ábrázolássá (pl. egy
MarkdownNodeenum csak biztonságos variánsokkal). A nyers HTML szerkezetileg nem ábrázolható ebben a köztes ábrázolásban. - Megjelenítés a típusos köztes ábrázolásból a cél megjelenítési rétegbe (pl. reaktív megjelenítési komponensek, DOM-csomópontok). Semmilyen ponton nincs HTML-karakterlánc-összefűzés vagy
innerHTML.
A tiltólista-megközelítések törékenyek, mert az új Markdown-bővítmények vagy elemző-furcsaságok szűretlen elemeket vezethetnek be. A típusos-AST megközelítés szerkezetileg lehetetlenné teszi az XSS-t — nincs olyan variáns, amely tetszőleges HTML-t hordozhatna.
10.4 Méret- és szerkezeti korlátok
- Maximális megjelenített címsormélység:
####(H4). A#####és mélyebbek félkövér szövegként jelennek meg. - Nincs korlát a bekezdések számára (a §6-ban lévő törzsméret-korlátok a megszorítás).
- Bekerített kódblokkok: nincs szintaxiskiemelés az MVP-ben. Monospace előformázott szövegként jelennek meg.
11. Harmadik fél általi ellenőrzés
Bármely harmadik fél, aki birtokolja a tárolt bájtokat (privát/burkolt qub esetén K-t is), a qub együttműködése nélkül ellenőrizheti a kriptográfiai műtárgyat. A függetlenül időbélyegzett létezési állításhoz emellett vagy qubonként ellenőrzött állandó-tárolási befoglalás, vagy ellenőrzött §16 átláthatósági napló bizonyíték szükséges.
1. Obtain the stored bytes. For a private delivery, also obtain K from the
delivery-link fragment.
2. Resolve the delivery shape (§8 step 3a): unwrap OuterWrapper with K, or
accept bare SealedQubCbor. Require shape/visibility agreement.
3. Parse SealedQubCbor → SealedQub; validate protocol version, visibility,
content type, chain identity, and structural bounds.
4. Recompute expected_round from unlock_at (§4.3); require the stored round
(allowing the documented legacy minus-one case) and ciphertext-stanza round
to agree exactly as §8 step 6a specifies.
5. Obtain the drand signature for SealedQub.drand_round and verify its BLS
signature against the pinned chain public key.
6. tlock_decrypt(tlock_ciphertext, round_signature) → QubEnvelope CBOR bytes.
7. Parse → QubEnvelope.
8. Verify SHA3-256(body) == body_hash.
9. Verify envelope/sealed equality for qub_id, unlock_at, and outcome_at.
10. Recompute qub_id from the decrypted fields, sealed drand_round, and title;
require it to equal the carried qub_id (§4.1).
11. If sig_alg != 0x00, verify the V2 author signature (§9.4). If cosigner
fields are present, verify their pairing, key separation, and signature
(§9.7).
12. For an existence-time claim, independently verify either:
a. the permanent-storage transaction's data-to-id binding, owner, block
inclusion, and block timestamp; or
b. a §16 inclusion proof through its pinned anchor and anchor block time.
13. Report each verified claim separately; do not collapse an absent storage
or anchor proof into a successful timing verdict.
Mit bizonyít az ellenőrzés:
| Bizonyítási bemenet | Mit állapít meg |
|---|---|
| Érvényes csomag / lepecsételt műtárgy + drand-aláírás | A visszanyert törzs megfelel a body_hash értékének; a qub_id-ba kötött metaadatok sértetlenek; a titkosított szöveg a kijelölt drand-körhöz kötött; és a kör eltelt. Ez nem állapítja meg, mikor hozták létre a titkosított szöveget. |
| Érvényes V2 szerzői/társaláírói aláírás | A megfelelő titkos kulcs(ok) birtokosa(i) hitelesítették a §9.3 aláírt felületét. |
| Függetlenül ellenőrzött qubonkénti tárolási tranzakció | A pontosan tárolt titkosított szöveg legkésőbb a blokk időbélyegének idején létezett. |
| Érvényes lehorgonyzott átláthatósági napló bizonyíték | A §16.11 levéltípus-specifikus állítása, beleértve a kötelezettségvállalási idő felső korlátját a horgonyblokkból. |
Mit NEM bizonyít az ellenőrzés:
| Nem-bizonyíték | Miért |
|---|---|
| Szerzőség | A sender_label dekoratív. sig_alg ≥ 0x01 nélkül bárki lezárhatta volna ezt a tartalmat. |
| Szándék | A műtárgy bájtokat és kriptográfiai kapcsolatokat bizonyít, nem azt, amit az alkotó szubjektíven gondolt. |
Előzetes kötelezettségvállalás csak a .qub csomagból |
Egy alkotó a kötött kör eltelte után is összeállíthat érvényes csomagot. A beágyazott drand-aláírás a kör elteltét, nem a titkosított szöveg korábbi létezését bizonyítja. |
| A pecsételőgomb pontos ideje | A tárolási vagy horgonyblokk időbélyege függetlenül ellenőrizhető felső korlát, és késhet a felhasználó helyi műveletéhez képest. A sealed_at / received_at állítások nem bizonyító erejűek. |
A megvalósított átláthatósági napló (§16) qubokon átívelően hamisítás-érzékeny sorrendet és megbízható harmadik fél nélküli felső korlátú kötelezettségvállalási időt (a horgonyblokk idejét) ad hozzá, a levél típusa szerint hatókörözve (§16.11). Nem ad hozzá szerzőséget vagy szándékot; az alapértelmezett bájtvak feltöltési útvonalon önmagában nem bizonyítja a body_hash vagy drand_round értékét, amelyek továbbra is a műtárgy ellenőrzéseiből származnak.
12. Verziókezelés és kiadásvezérlés
A dokumentumkiadások, a belső wire-protokoll és a külső burkoló külön verziótér. Így egy csak dokumentációs pontosítás nem változtatja meg észrevétlenül a bájtokat, egy jövőbeli wire-migráció pedig nem álcázhatja magát szerkesztési változtatásnak.
12.1 Dokumentumkiadás verziója
Ez a specifikáció szemantikus dokumentumkiadásokat (MAJOR.MINOR.PATCH) és protocol-v<release> nevű megváltoztathatatlan Git-címkét használ.
- PATCH: pontossági vagy szerkesztési javítás, amely nem változtatja meg a megfelelő bájtokat vagy az előírt viselkedést.
- MINOR: visszafelé kompatibilis normatív kiegészítés, új nyilvántartási bejegyzés vagy új, függetlenül verziózott kísérőformátum.
- MAJOR: inkompatibilis normatív változtatás, beleértve egy új kötelező wire-értelmezést.
A kiadási állapot Tervezet (még nem normatív), Aktuális (az egyetlen ajánlott megvalósítási cél) vagy Felváltott (történeti ellenőrzés céljából megőrzött). A verzió nélküli /protokoll útvonal az Aktuális kiadást jeleníti meg; a kiadási címke megőrzi annak pontos forrását és minden vele kiadott területi változatot. Az állapot vagy a kiadási szám módosításához ugyanabban a felülvizsgált változtatásban frissíteni kell ezt a táblázatot és a kiadástörténetet.
| Dokumentumkiadás | Hatálybalépés dátuma | Állapot | Wire-protokoll | Burkoló | Forrás |
|---|---|---|---|---|---|
| 1.0.0 | 2026-09-23 | Aktuális | 0x01 |
0x01 |
protocol-v1.0.0 |
12.2 Protokollverzió
A version mező (u8) mind a SealedQub-ban, mind a QubEnvelope-ban a fő protokollverziót azonosítja.
- A megjelenítőknek el KELL utasítaniuk az ismeretlen fő verziókat egyértelmű hibával.
- Egy ismert fő verzión belül a dekódolóknak el KELL utasítaniuk az ismeretlen térképkulcsokat (§3.1) — a séma fejlődése új
versionbevezetésével történik, nem olyan kulcsok hozzáadásával, amelyeket a meglévő dekódolók átugranának. (A specifikáció korábbi változatai megengedték az ismeretlen opcionális mezők tolerálását; ez a kikötés visszavonásra került — megszüntette azencode(decode(x))injektivitását, és megnyitotta a rejtett aláírt tartalom támadási vektorát a paktumtörzseken.) - A tartalomtípusok (
content_type) és aláírási sémák (sig_alg) verzió-vezéreltek: új értékek csak új protokollverzió vagy kifejezett nyilvántartás-frissítés mellett vezethetők be.
12.3 Protokollverzió-történet
| Verzió | Érték | Leírás |
|---|---|---|
| v1 | 0x01 |
Privát/burkolt és nyilvános/csupasz kézbesítés; szöveges (0x01), paktum- (0x03) és ítélet- (0x04) törzsek; ML-DSA-65 V2 szerzői/társaláírói aláírás; drand quicknet tlock; SHA3-256. |
12.4 Előrekompatibilitás
Egy v1-megjelenítőnek, amely ismeretlen CBOR-térképkulcsokat (a §3.2 kanonikus sorrendjében nem szereplő kulcsokat) tartalmazó QubEnvelope-ba ütközik, dekódolási hibával el KELL utasítania azt (§3.1). Az előrekompatibilitás a version mezőn nyugszik, nem a kulcsok tolerálásán: a jövőbeli kiegészítések — még a kisebb metaadatok is — új version érték alatt jelennek meg, amelyet egy v1-megjelenítő egyértelmű „újabb protokoll” hibával utasít el, ahelyett hogy csendben eldobná azt a tartalmat, amelyhez az aláírások kötelezik magukat.
Egy v1-megjelenítőnek, amely sig_alg = 0x01 (ML-DSA-65) értékbe ütközik, de hiányzik az ML-DSA-65 ellenőrzési támogatása, a qub-tartalmat „aláírás jelen van, de nem ellenőrizhető” megjegyzéssel KELLENE megjelenítenie, nem pedig a qubot teljesen elutasítania. A referencia-megvalósítás ma minden sig_alg értéket elutasít a 0x00 és 0x01 kivételével, mert a v1 nyilvántartás nem tartalmaz más érvényes algoritmust — a szigorú elutasítás és a lágy hiba megfigyelhetően azonosak, amíg egy harmadik algoritmus regisztrálásra nem kerül. A fenti lágy-hiba viselkedés akkor válik teherviselővé, amikor a §9.2 új bejegyzést fogad be, és a referencia-megjelenítő ezen a ponton frissül lágy-hibára.
12.5 Külső burkoló verziója
A §13-ban leírt OuterWrapper saját version bájtot hordoz, függetlenül a SealedQub.version és QubEnvelope.version mezőktől. A két verziótér külön fejlődik: egy jövőbeli posztkvantum-biztonságos szimmetrikus csere megemeli a burkoló bájtját anélkül, hogy a belső protokollverziót érintené, és egy jövőbeli protokollréteg-kiegészítés (pl. egy új borítékmező) megemeli a belső verziót anélkül, hogy a burkoló bájtját érintené.
OUTER_WRAPPER_VERSION_* |
Érték | Algoritmus | Állapot |
|---|---|---|---|
OUTER_WRAPPER_VERSION_1 |
0x01 |
AES-256-GCM 12 bájtos nonce-szal, 16 bájtos hitelesítési címkével, a qub_id-hoz kötött AAD-vel |
Aktív privát kézbesítéshez |
| — | 0x02–0xFF |
Fenntartott | Jövőbeli |
A megjelenítőknek el KELL utasítaniuk az ismeretlen burkoló-verziókat egyértelmű hibával. A protokoll szándékosan szűken tartja a burkoló-verzióteret, amíg egy konkrét migrációs hajtóerő meg nem jelenik (pl. egy másik AEAD-et előnyben részesítő NIST-irányelv); egy 0x02 hely ugyanabban a felülvizsgálatban kerül kiosztásra, amely bevezeti az algoritmust.
13. Külső titkosító burkoló
13.1 Indoklás
A protokollrétegek (QubEnvelope → tlock → SealedQub) időzárolttá teszik a lezárt qubot: a törzs olvashatatlan az unlock_at-ig, és amíg a drand-kör aláírása közzétételre nem kerül. A feloldás után azonban a kör aláírása nyilvános, és a SealedQub kanonikus CBOR-alakja felismerhető, így egy gyűjtő, aki indexelte az állandó tárhelyű tranzakciókat, tömegesen visszafejthetné az egész qub-korpuszt.
Privát kézbesítésnél a külső titkosító burkoló egy további szimmetrikus AEAD-réteget iktat a kanonikus SealedQubCbor és a tárolt bájtok közé. A böngészős pecsételési útvonalon a 256 bites K kulcs kizárólag a kézbesítési URL töredékében és a felhasználói eszközökön él; a böngészők nem továbbítják az URL-töredékeket a szervereknek, így a qub.social, minden tárolási átjáró és minden CDN bármelyikük előtt nem látja K-t. Egy privát qub tárolt alakja ezért átlátszatlan titkosított szöveg, amelynek nyílt szövege az alkotó által megosztott URL nélkül nem nyerhető vissza. A nyilvános kézbesítés szándékosan elhagyja ezt a réteget (§13.8).
Nettó hatás:
- Felsorolás-ellenállás privát kézbesítésnél. Az
OuterWrapperfelismerhető strukturált CBOR marad — nem szó szerint megkülönböztethetetlen a véletlen bájtoktól —, de a titkosított szöveg mezője elrejti a felismerhető belsőSealedQub-alakot. A dokumentált „GraphQL-lekérdezés csupasz, qub alakú feltöltésekre, majd tömeges visszafejtés nyilvános drand-aláírásokkal” gyűjtőstratégia K nélkül nem jut nyílt szöveghez. - Kriptográfiai megsemmisítési adatvédelmi tartás az alapértelmezett privát böngészős folyamatban. A qub.social az alapértelmezett szerveroldali adataiból nem tudja visszafejteni ezeket a tárolt artefaktumokat. A kifejezett helyreállítás, a nyilvános kézbesítés és a megbízható szerveroldali pecsételés eltérő, közzétett bizalmi határokkal rendelkezik.
- Kétszintű bizalmassági létra. Alapértelmezett = hivatkozás-vezérelt hozzáférés (ez a szakasz). A címzettnek titkosított privát qubok (fenntartott 2. fázisú funkció, még nincs specifikálva) a tetejére rétegződnek második szintként.
13.2 Rétegezés
plaintext body ← QubEnvelope.body (§2.2)
↓ canonical CBOR (§3)
envelope CBOR
↓ tlock encrypt to drand round (§7 step 10)
tlock_ciphertext (inside SealedQub) (§2.3)
↓ canonical CBOR (§3)
SealedQubCbor bytes ← inner wire artifact
├─ public (visibility=0x01) ───────────────▶ stored directly (§13.8)
└─ private (visibility=0x00)
↓ AES-256-GCM(K, nonce, AAD=qub_id) (§7 step 12, this section)
OuterWrapper CBOR bytes ← stored private payload
A lezárás és feloldás a protokollrétegen (§7, §8) változatlan a burkoló-határ alatt; a burkoló a seal() hívási helyén csatlakozik, és az unlock() hívási helyén válik le.
13.3 OuterWrapper adatstruktúra
struct OuterWrapper {
version: u8, // 0x01, see §12.5
qub_id: [u8; 32], // copied from inner SealedQub; AEAD AAD
nonce: [u8; 12], // 96-bit AEAD nonce
ciphertext: Vec<u8>, // AES-256-GCM(K, nonce, SealedQubCbor, AAD=qub_id) || 16-byte tag
}
Mező-invariánsok.
- A
versionmezőnek0x01-nek KELL lennie a v1.0 burkoló-bájtoknál. - A
qub_idmezőnek meg KELL egyeznie a kicsomagolás után visszanyert SealedQubqub_idmezőjével. A referenciawrap_sealed_qubésunwrap_sealed_qubegyaránt elemzi a belső CBOR-t, és közvetlenül kikényszeríti ezt az egyezést; az AAD-kötés külön biztosítja, hogy a külsőqub_idbecsomagolás utáni módosítása meghiúsítsa a hitelesítést. - A
noncemezőnek 96 bitnek (12 bájtnak) KELL lennie, frissen generálva egy CSPRNG által minden becsomagolási műveletnél. Egy nonce újrahasználata ugyanazon kulcs alatt lehetővé teszi az AEAD nonce-újrahasználati támadásokat, amelyek visszanyerik az egyszerű szöveget; az előállítóknak a (key,nonce) párokat egyszer használatosként KELL kezelniük. - A
ciphertextaz AES-256-GCM kimenete: a rejtjelezett szöveg bájtjai összefűzve a 16 bájtos hitelesítési címkével. Aciphertext.len() == SealedQubCbor.len() + 16pontosan.
CBOR-kódolás. Kanonikus CBOR a §3 szerint, ugyanazzal a kulcsrendezési szabállyal (kódolt bájthossz szerint növekvően rendezve, majd lexikografikusan). A négy kulcs:
| Kulcs | Kódolt bájtok | Sorrend |
|---|---|---|
nonce |
6 | 1 |
qub_id |
7 | 2 |
version |
8 | 3 |
ciphertext |
11 | 4 |
Az OuterWrapper CBOR első bájtja tehát egy 4 bejegyzéses térkép határozott hosszúságú térképfejléce (0xA4).
13.4 AAD-kötés a qub_id-hoz
A burkoló a qub_id-t AEAD kiegészítő hitelesített adatként köti. Ez a teherviselő szerkezeti védelem három támadásosztály ellen:
| Támadás | Védelem |
|---|---|
A rejtjelezett szöveg áthelyezése egy másik qub_id mező alá a burkolóban |
AAD-eltérés → az AEAD-hitelesítés meghiúsul |
| Az A qub URL-fragmentjének keverése a B qub tárolt bájtjaival | Hibás kulcs (és ettől függetlenül kötött AAD) → az AEAD-hitelesítés meghiúsul |
A burkoló qub_id mezőjének meghamisítása a feltöltés után |
AAD-eltérés → az AEAD-hitelesítés meghiúsul |
A qub_id burkoló egyszerű szövegében való hordozása nem gyengíti érdemben a felsorolás-immunitást — a qub_id maga is a §4.1 bemeneti kép SHA3-256 kivonata, a kivonatból nem visszanyerhető bemeneti képpel, és egy felsoroló, aki már begyűjtötte a burkoló bájtjait, semmi olyat nem tanul a látható qub_id-ból, amit ne tudna kikövetkeztetni magának a feltöltésnek a létezéséből.
13.5 Becsomagolási és kicsomagolási algoritmusok
wrap_sealed_qub(SealedQubCbor S, qub_id Q, key K, nonce N):
require K.len() == 32 and N.len() == 12 and Q.len() == 32
I := canonical_cbor_decode(S) as SealedQub
require I.qub_id == Q // reject mismatched caller AAD
C := AES_256_GCM_encrypt(key=K, nonce=N, msg=S, aad=Q)
// C includes the 16-byte authentication tag at the end
return canonical_cbor_encode(OuterWrapper{
version: 0x01,
qub_id: Q,
nonce: N,
ciphertext: C,
})
unwrap_sealed_qub(OuterWrapper bytes W, key K):
require K.len() == 32
O := canonical_cbor_decode(W) as OuterWrapper
require O.version == 0x01 // §12.5
P := AES_256_GCM_decrypt(
key=K, nonce=O.nonce, ciphertext=O.ciphertext, aad=O.qub_id
)
// any AEAD failure → DECRYPT_FAILED, indistinguishable to caller
S := canonical_cbor_decode(P) as SealedQub
require S.qub_id == O.qub_id // explicit inner/outer cross-check
return P // P is the validated SealedQubCbor
Hibamód-összeomlás. A rossz K, a rossz nonce, az AAD-eltérés és a meghamisított rejtjelezett szöveg mind ugyanazt a DECRYPT_FAILED hibát eredményezi. Ez szándékos AEAD-tulajdonság: a hibamód megkülönböztetése oldalcsatornát hozna létre, amelyet egy távoli támadó hibás formátumú burkolók küldésével és a válasz időzítésével vizsgálhatna. A referencia-megvalósításoknak minden AEAD-hibát egyetlen hibaalakra KELL összeomlasztaniuk.
13.6 Kulcsanyag és terjesztés
A becsomagoló K kulcs egy 256 bites egyenletes véletlen érték, amelyet qubonként generál egy CSPRNG. A referencia-megvalósítások az alábbiakból nyerik:
- WASM alkotó:
getrandom(WebCrypto awasm_jsháttér alatt). - A szerveroldali lezárási API hívója: a saját helyi CSPRNG-je; a hívó adja meg és tartja meg a
Kértéketwrapper_key_b64url-ként. A Worker aKkulcsot a memóriában használja a burkolóhoz, de NEM szabad megőriznie. Ez lehetővé teszi, hogy egy idempotens újrapróbálkozás a hívó megtartott képességét felhasználva állítson helyre egy szerkesztett választ, ahelyett hogy egy egyszer használatos, szerver által generált titokra támaszkodna.
Terjesztés: a K mezőt URL-biztonságos base64-ként KELL kódolni (RFC 4648 §5, kitöltés nélkül), és a kézbesítési URL-hez fragmentkomponensként hozzáfűzni:
delivery_url = <origin>/c/<arweave_tx_id>#<base64url(K)>
A fragmentet egy megfelelő böngésző soha nem továbbítja egyetlen szervernek sem. Azok a helyreállítási csatornák (szerveroldali előzményindex, választható e-mailes automatikus küldés), amelyek a teljes kézbesítési URL-t — beleértve a fragmentet — a felhasználó eszközén túl megőrzik, kifejezett kompromisszum az alapértelmezett kripto-aprítási tartással szemben, és kifejezett felhasználói beleegyezéshez KELL kötni őket.
Fragmentvesztés. Ha egy felhasználó elveszíti az URL-fragmentet, és nincs helyreállítási csatornája, a qub olvashatatlan. Ez a tervezés teherviselő kompromisszuma, és a lezárás idején KÖZÖLNI KELL a felhasználóval. Az MVP megerősíti a lezárás-idejű közlést kifejezett „mentse el ezt az URL-t” szöveggel és egy ellenőrzött e-mailes helyreállítási csatornával azoknak a felhasználóknak, akik ezt választják.
13.7 A szakasz hatókörén kívül
- A szerzőség aláírása (§9) változatlan: az aláírások a belső
QubEnvelope-on belül számítódnak ki, és a kicsomagolás → tlock-visszafejtés → CBOR-elemzés után kerülnek visszanyerésre. - A címzett nyilvános kulcsával történő titkosítás (a fenntartott
recipient_pubkeymező) a mai privát, linkképességgel kapuzott burkolómódtól különálló jövőbeli funkció. - A jelenlegi kiszolgálóoldali paktum-ellenjegyzési folyamat nyilvános/csupasz,
0x01láthatóságúSealedQubCbor-t bocsát ki; nem tud megfelelni a csak böngészőben tartott K titkossági modelljének, mert a végső pecsételés a kiszolgáló által közvetített ellenjegyzés után történik. Egy jövőbeli privát paktum-előállító használhatja ugyanezt a burkolót, amely nem lát bele a belső tartalomtípusba.
13.8 Nyilvános qubok (a burkoló elhagyása)
A külső burkoló a kézbesítési rétegen választható. Egy alkotó nyilvánosként is lepecsételhet egy qubot, amely esetben a kanonikus SealedQubCbor közvetlenül lép be a tárolási folyamatba, OuterWrapper réteg és K kulcs nélkül:
SealedQubCbor bytes ──(public)──▶ stored as-is
SealedQubCbor bytes ──(private)─▶ AES-256-GCM(K, …) ▶ OuterWrapper ▶ stored
Egy nyilvános qub időzárolt, de nincs hivatkozással kapuzva: olvashatatlan marad, amíg a drand-köre közzétételre nem kerül (a tlock-réteg változatlan), de a feloldás után bárki vissza tudja fejteni, akinek megvan a tárolási tranzakció azonosítója — nincs szükség URL-fragmentre, mert nincs K. Ez a szándékos kompromisszum azokhoz a felületekhez, amelyeket a szervernek kell működtetnie: a felfedés-értesítő e-mailekhez, a fragment nélküli oEmbed/automatikus beágyazási hivatkozásokhoz és a gazdagabb felfedés utáni SEO-hoz olyan hivatkozás kell, amely a szerver által soha nem birtokolt titok nélkül működik (§13.6). Egy privát qub továbbra is használhatja a kifejezett <qub-embed src="full_delivery_url"> alakot, ha a közzétevő megadja a fragmentet tartalmazó teljes képességét.
Következmények, amelyekkel egy előállítónak SZÁMOLNIA KELL:
- Nincs felsorolás-immunitás. A nyilvános qubok konstrukciójukból adódóan lemondanak a §13.1 felsorolás-immunitási tulajdonságról. A referencia-feltöltési szolgáltatás
Visibility: publicállandó-tárhely címkével látja el őket (és csak őket), így szándékosan felfedezhetők; a privát qubok nem hordoznak ilyen címkét, és megőrzik a bájtszintű megkülönböztethetetlenségüket. - Egyszerű szöveges cím feltárva a lezárás idején. A §3.2
titlemező egyszerű szöveg aSealedQubCbor-on belül. A burkoló alatt rejtve marad, amíg egy megjelenítő nem szolgáltatja aK-t; a burkoló nélkül a feltöltés pillanatától, a feloldás előtt, az állandó tárhelyen mindenki számára olvasható. A megfelelő alkotó-alkalmazásoknak ezt a lezárás idején KÖZÖLNIÜK KELL. - A felismerés szerkezeti és keresztellenőrzött. Egy megfelelő megjelenítő/beágyazás elemzéssel különbözteti meg a két tárolt alakot: az
OuterWrapper-ként elemezhető bájtok aK-val-kicsomagolás útvonalát követik; a csupaszSealedQubCbor-ként elemezhető bájtok közvetlenül elfogadásra kerülnek. A visszanyert belső értéknek egyeznie KELL (0x00a burkolt/privát,0x01a csupasz/nyilvános alakhoz). Aqub_idnem köti a láthatóságot, de a kanonikusSealedQubbájtjai hordozzák, ezért a nyilvános és privát belső kódolások nem bájtazonosak.
A privát (becsomagolt) marad az alapértelmezett; a nyilvános kifejezett, qubonkénti alkotói választás.
14. Tesztvektorok
14.1 qub_id levezetése
Input:
version = 0x01
content_type = 0x01
created_at = 1735689600 (2025-01-01 00:00:00 UTC)
unlock_at = 1736294400 (2025-01-08 00:00:00 UTC)
outcome_at = absent
drand_round = 4695446 (= floor((1736294400 - 1595431050) / 30) + 1, §4.3 mapping, drand mainnet params §14.2)
body = "Hello, future." (UTF-8, 14 bytes)
title = absent
Intermediate:
body_hash = SHA3-256("Hello, future.")
= 76ab8b3f843c6ed4f2d0fd75b9f457b4
ad49dd4450f9c22723ae430e3af3211d
title_hash = [0u8; 32] (title absent — §4.2.1 sentinel)
Domain separator (10 bytes):
[0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00]
Preimage (108 bytes—current protocol v1):
domain_separator || // 10 bytes
0x01 || // version
0x01 || // content_type
0x0000000067748580 || // created_at as i64 big-endian (1735689600)
0x00000000677DC000 || // unlock_at as i64 big-endian (1736294400)
0x0000000000000000 || // outcome_at_or_zero (outcome_at absent)
0x000000000047A596 || // drand_round as u64 big-endian (4695446)
body_hash || // 32 bytes
title_hash // 32 bytes (all-zeros sentinel; title absent)
Expected output:
qub_id = SHA3-256(preimage)
= 4a84e3dfaec32954949c30073f8e6506
fd3204c1bb97f9162b81c7587afe412e
Az implementációknak ehhez a bemenethez azonos body_hash és qub_id értékeket KELL előállítaniuk. Ezt a tesztvektort érdemes első egységtesztként megírni. A fenti kanonikus értékeket a referencia-megvalósítás számította ki, és bitről bitre egyezniük KELL. A történeti, kiadás előtti prototípus-elrendezések (az első kettőtől egyetlen élő qub sem függött) 92 bájtot használtak az outcome_at előtt (3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0), majd 100 bájtot az outcome_at_or_zero hozzáadása után (b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed). A jelenlegi 108 bájtos elrendezés ezután hozzáadta a drand_round mezőt és a QUB_ID_V2 tartományelválasztót. Egy korai 108 bájtos vektor a régi ceil körleképezést (drand_round = 4695445) használta, és 3a9fcb31b750d985c262fada6d4f777fd6a28be831d941d85c131f5a4bbaf8a4 értéket adott — ez továbbra is érvényes qub_id ahhoz a körbemenethez, míg a fenti példa a §4.3 jelenlegi körleképezését követi.
14.2 Feloldási kör leképezése
Input:
unlock_at = 1735689600
chain_genesis_time = 1595431050
chain_period_seconds = 30
Calculation:
(1735689600 - 1595431050) / 30 = 4675285.0
floor(4675285.0) + 1 = 4675286
drand_round = 4675286
A 4675286. kör a 1595431050 + (4675286 - 1) * 30 = 1735689600 időpontban jelenik meg — pontosan az unlock_at időpontban, sosem előtte. (A régi, kiadás előtti ceil leképezés 4675285-öt adott, amely 1735689570 időpontban, 30 másodperccel korábban jelent meg; az ellenőrzők a §4.3 szerint elfogadják ezt a régi kört.)
14.3 Kanonikus CBOR oda-vissza
A megvalósításoknak ellenőrizniük KELL, hogy a serialize(parse(serialize(qub))) == serialize(qub) minden érvényes bemenetre. Ez tulajdonságteszt, nem egyetlen vektor.
14.4 PactTerms CBOR (content_type 0x03)
Input:
pact_version = 1
title = "Scooter deposit"
terms = [
{ key: "Item", value: "Honda Metropolitan scooter" },
{ key: "Price", value: "$100" },
{ key: "Deposit", value: "$10" }
]
party_a = { label: "Alice" }
party_b = { label: "Bob", contact: "bob@example.com" }
notes = absent
Canonical CBOR key order (PactTerms):
"notes"(6) < "terms"(6) < "title"(6) < "party_a"(8) < "party_b"(8) < "pact_version"(13)
Canonical CBOR key order (PactTerm):
"key"(4) < "value"(6)
Canonical CBOR key order (PartyIdentifier):
"label"(6) < "contact"(8)
A kanonikus CBOR-bájtokat és a SHA3-256 body_hash-t a referencia-megvalósítás számítja ki. A megvalósításoknak bájtazonos CBOR-t KELL előállítaniuk erre a bemenetre.
A megvalósításoknak emellett ellenőrizniük KELL, hogy a serialize(parse(serialize(pact))) == serialize(pact) minden érvényes PactTerms bemenetre (tulajdonságteszt).
14.5 Külső burkoló nyelvközi vektorok
A külső burkolónak (§13) külön kanonikus fixture-je van itt: crates/qub-core/tests/vectors/wrapper_v1.json. Minden eset egy (key, nonce, qub_id, sealed_cbor) rendezett ötöst rögzít átlátszatlan hexa-bemenetekként, és egy konkrét expected_wrapper_hex kimenetet állít. Mindkét referencia-megvalósítás ugyanazt a JSON-fájlt használja:
- Rust:
crates/qub-core/tests/wrapper_vectors.rs(cargo test -p qub-core --test wrapper_vectors). - TypeScript:
workers/api/src/crypto/__tests__/wrapper.test.ts(npm test).
A fixture jelenleg három alacsony szintű burkolóesetet rögzít. Ezek a determinisztikus OuterWrapper-kódolást és az AEAD-interoperabilitást a §13.8 szerinti kézbesítési alakra vonatkozó invariánstól függetlenül tesztelik; különösen a történeti basic-text-public név és belső visibility = 0x01 értéke nem teszi az így kapott burkolt bájtokat megfelelő nyilvános kézbesítéssé. Az előállítónak továbbra is csupaszon KELL tárolnia a nyilvános belső bájtokat, és csak a privát (0x00) belső bájtokat szabad becsomagolnia.
| Eset | Lefedettség |
|---|---|
basic-text-public |
Történeti alacsony szintű fixture-név. A legkisebb realisztikus SealedQub-alak, opcionális mezők nélkül; kizárólag a burkolóbájtokat teszteli, és nem megfelelő §13.8 szerinti tárolt kézbesítés. |
with-recipient-pubkey |
SealedQub beállított recipient_pubkey-vel (fenntartott jövőbeli útvonal). Eltérő belső CBOR-kulcskészletet gyakorol; a fixture eltérő tartalma ettől függetlenül eltérő qub_id-t eredményez (maga a recipient_pubkey nem része a §4.1 szerinti preimage-nek). |
longer-body |
~4 KiB-os törzs — gyakorolja a többbájtos CBOR-hosszelőtagokat mind a belső borítékon, mind a külső rejtjelezett szövegen belül. |
A megvalósításoknak bájtazonos expected_wrapper_hex-et KELL előállítaniuk a rögzített bemenetekre. A fixture újragenerálása QUB_REGEN_VECTORS=1 cargo test -p qub-core --test wrapper_vectors parancsot igényel, és szándékos formátumváltoztatásokra van fenntartva.
15. Kriptográfiai profil kormányzása (jövőbeli)
Ez a szakasz informatív a v1-re, és normatívvá válik, amikor először lép be egy második algoritmus a qub kriptográfiai alapelemeinek bármelyikébe.
15.1 Jelenlegi tartás
A v1 protokoll alapelemenként pontosan egy algoritmust köt:
- Aláírás: ML-DSA-65 (
sig_alg = 0x01; 1952 bájtos nyilvános kulcs, 3309 bájtos aláírás) és aláíratlan (sig_alg = 0x00). A kódbázis a0x02értéket fenntartja az Ed25519 számára, de a v1 protokoll nem aktiválja; egy v1-ellenőrzőnek el KELL utasítania minden{0x00, 0x01}halmazon kívülisig_algértéket. - Időzár: csak drand quicknet — a lánckivonat, a nyilvános kulcs, a genesis-idő és a periódus rögzített hálózati paraméterek, amelyeket a referencia
DrandTimelockProvider::quicknet()(crates/qub-core/src/tlock.rs) és aconfig/drand-endpoints.jsonhordoz. - Külső burkoló: csak AES-256-GCM v1 (§13).
Az ellenőrzők jelenleg keményen kódolják az aktív primitívek kulcs- és aláíráshosszait. A sig_alg és a burkolóverzió bájtjai kifejezett választók, de a v1 nem végez sávon belüli egyeztetést, és csak a fenti aktív értékeket fogadja el.
15.2 Tervezett alak
Amikor egy második algoritmus belép a protokollba, az ellenőrző egy elnevezett CryptoProfile-hoz (pl. ExqubV1) lesz konfigurálva, amely felsorolja az alapelemenként engedélyezett értékek pontos halmazát — sig_alg-ek, drand-láncok, burkoló-verziók, tartalomtípusok. A profil az ellenőrzés idején rögzül, soha nincs sávon belül egyeztetve. Az aktív profilon kívüli bármely érték elutasításra kerül.
Ez garantálja, hogy az ML-DSA-87 hozzáadása vagy az Ed25519 aktiválása nem gyengítheti visszamenőlegesen a meglévő ellenőrző-konfigurációkat: egy v1-ellenőrző v1-ellenőrző marad még egy v2-profil közzététele után is.
15.3 Kiváltó feltételek
Léptesse elő a §15-öt normatív státuszra, amikor az alábbiak bármelyike javaslatra kerül:
- Egy második
sig_algbájt (Ed25519 aktiválás, ML-DSA-87 vagy bármely új bejegyzés a §9 nyilvántartásban). - Egy második drand-lánc éles használatban.
- Egy második külső-burkoló verzió.
- Az átláthatósági napló bizalmi gyökerének rotációja — a
LogProfile.anchor_ownercím vagy a rögzített nyugtakulcs nyilvános kulcsa (§16.6). ALogProfilea §15.2 profilfelületéhez szabályozott primitívként csatlakozik: a rotáció egy ellenőrzőfrissítésben kiadott aláírtLogProfile-emelés.
Addig a §15 helykitöltő, amely rögzíti a migrációs alakot, hogy a jövőbeli PR-ek ismert célpontra érkezzenek, ahelyett, hogy a tárgyalási felületet a nulláról újratárgyalnák.
16. Átláthatósági napló és tartóssági szintek (Megvalósítva — értékelés befejezve)
Állapot. Ez a szakasz implementált (W5/UP-B1, 1–8. szakasz), itt van megadva a producer és a trust root hatótávolsága. A vezeték formátumok, a hashing és az ellenőrjáratok élő: a mag Merkle + kanonikus-CBOR típusok (
qub-core), a TypeScript tükör + ANS-104 bundler (workers/api/src/crypto/), az egyíróLogDO+ koordináta kulcsú R2 csomópont tároló, az/uploadlog-append kísérlet, a napi horgony + bundler-drain cronok, aGET /api/v1/qub/:tx_id/proof(inkluzió) ésGET /api/v1/log/consistency(RFC 9162) bizonyítási végpontok, a.qubcsomagban hordozott típusos befogadási bizonyítás (§17.5), a natív ANS-104 anchor verifiert (tools/qub-verify), valamint a dupla önkiadott-fejes hookot (§16.6). Egy sikeres/uploadmindig R2-tartós, de csak akkor van log-lefedett, haLOG_DObe van állítva, és az inline append sikeres lesz; csak ekkor viszi a válaszalog_seq,receiptésanchor_status. HaRECEIPT_SKhiányzik vagy érvénytelen, az a visszaigazolássig_b64urlüres, és nem ad visszautasítást. A jelenlegi/sealés pakt közzétételi útvonalak az egyes Arweave tranzakciókat ütemezik, de nem csatolnak naplólevelet. Jelenleg egyetlen kód hajtja végre a/uploadkommentár által javasolt későbbi egyeztetést egy kiegészítő hiba után. A W5 külső felülvizsgálata befejeződött: a §16.15 rögzíti a tervezési döntéseket és a indítási korlátozásokat, de ezek a korlátozások nem bővítik a gyártó lefedettségét. Három bizalmi/telepítési elem zárt marad: (a) a dedikált anchor wallet (ANCHOR_JWK;LogProfile.anchor_ownertovábbra is a[0xAB; 32]helykitöltő; (b) a visszaigazolási kulcs és a hozzá tartozó nyilvános kulcs pin (RECEIPT_SKopcionális,LogProfile.receipt_pubkeyjelenleg üres); és (c) az önkiadott fejű GitHub tároló + token (§16.6). Amíg a anchor/profile pineket nem biztosítják, egy önálló ellenőrző őszintén jelenti a bizonyítási státuszt, ahelyett, hogy teljesen rögzített, rögzített ellenőrzést igényelne. A kialakítás szigorúan additív, és nincs változás aSealedQub/QubEnvelopevezeték formátumban.
16.1 Indoklás és tartóssági szintek
A jelenlegi közzétételi útvonalak elválasztják az elismerést az Arweave megerősítéstől: egyedi tranzakciót vezetnek és írnak alá, megőrzik az artefaktut és pontos beküldési állapotot az R2-ben, majd aszinkron módon posztolnak. Az átláthatósági napló egy önállóan rögzített sorrendi réteget ad hozzá az általános /upload kérések részhalmazához, amelynek LogDO kiegészítése sikeres:
| Szint | Név | Garancia | Mikor |
|---|---|---|---|
| T1 | R2-első szinkron visszaigazolás | Tartóssági minimum — a lezárt bájtokat és a pontos közzétételi állapotot tartós tárolóba írják, mielőtt a siker visszaigazolást visszaadják. | Megvalósítva a jelenlegi közzétételi útvonalakon. |
| T2 | Csomagolt átláthatósági naplóba való felvétel | Csak hozzáfűzhető, manipulációt jelző kötelezettségvállalás + teljes rendezés egyszer, amikor beillesztik és horgonyozzák. | Jelenlegi előállító: sikeres LogDO hozzáfűzések a /upload; a válasz a nyugtázó tuple-t hordozza. Nem univerzális. |
| T3 | Qubonkénti Arweave állandóság | Egyéni Arweave tranzakció a qub számára. | Jelenleg minden elfogadott közzétételhez előkészítve és aszinkron módon közzétéve; a pontos aláírt tranzakció a kiüríthető kimenő postaládában marad, amíg kézbesítésre nem kerül. |
A szintek különböző bizonyíték- és tartóssági tulajdonságokat írnak le, nem a jelenlegi kereskedelmi tervet. A jelenlegi kód továbbra is minden elfogadott közzétételhez ütemez egy egyéni Arweave tranzakciót; nem teszi elérhetővé a T3-at csupán fizetős kiegészítésként. Az API-kulcs/fiók kvóta plafonjai továbbra is külön alkalmazásvezérlők.
Tartóssági becsület. A T1 írás szinkron, így a sikeres válasz az alkalmazásszintű tartósságot garantálja anélkül, hogy várni kellene az Arweave átjáróra. Önmagában nem állít fel független időbélyeget. Egy megerősített egyéni tranzakció biztosítja a blokkidő felső határát. Egy teljes T2 nyugtázó tuple-t hordozó válasz esetén a következő megerősített horgony biztosíthatja az alább leírt napló bizonyítékot. Ha a tuple hiányzik, semmi sem sugallhatja, hogy ez a qub már az átláthatósági naplóban van. A horgony- és közzétételi késleltetésnek nincs protokoll szintű numerikus SLA-ja.
16.2 LogLeaf struktúra (két kötelezett forma)
Egy naplóbejegyzés egy LogLeaf, amely kézzel írott kanonikus CBOR-ként van kódolva a §3.1 profil szerint (határozott hosszúság, nincs címke, nincs lebegőpontos szám, rövid formátumú egész számok, NFC szöveg, az opcionális mezők hiány esetén elhagyva, a kulcsok kódolt bájthossz szerinti növekvő sorrendben, majd bájtonként rendezve). A §3.1 parse → re-encode → compare kanonikus őr alkalmazásra kerül a kódolás során, a hash-elés előtt (nem csak a dekódálásnál), így két implementáció nem térhet el a levélbájtoknál egész szám szélesség vagy kulcsrendi különbség miatt. Minden egész szám u8 / u64 / i64; minden digest 32 bájtos bájt-sorozat (bstr[32]). Egy tárolt Arweave tranzakció azonosító nyers 32 bájtos SHA-256 digestként jelenik meg bstr[32]-ként, soha nem base64url szövegként (a §3.3-mal összhangban).
A levélnek két formája van, amelyet egy kind bájt választ ki, mert az általános feltöltési útvonal bájtfüggetlen: POST /api/v1/upload szándékosan mindkét elfogadott adatforma opaque-ként kezeli, és qub_id-t és unlock_at-t csak nem megbízható kliensi állításokként fogad el. Az alapértelmezett privát útvonalon, body_hash, drand_round, created_at és drand_chain_version továbbiakban a §13 külső burkolaton belül vannak elrejtve, amelynek kulcsát a Worker soha nem birtokolja. A típus rendszer meghatározza továbbá az attesztált formát egy előállítóra, aki maga származtat body_hash / drand_round-t. A jelenlegi /seal útvonal ezeket az értékeket tartalmazza, de nem hívja meg LogDO-t, így a gyártás jelenleg csak állított (0x02) leveleket bocsát ki a sikeres általános feltöltési kiterjesztésekből. A szétválasztás minden rögzített értéket őszintén tart anélkül, hogy az attesztált előállítót bekapcsoltnak tételezné.
| kulcs | enc. len | típus | jelenlét | jelentés |
|---|---|---|---|---|
seq |
4 | u64 |
szükséges | globális 0-alapú levélindex; az a pozíció, amelyhez az inklektív bizonyítás elköteleződik. |
kind |
5 | u8 |
0x01 igazolt (defintál, jelenleg nem kibocsátott) vagy 0x02 állítás (kliens-pecsét/bájtvak feltöltés) szükséges. |
|
ref |
4. | bstr[32] |
szükséges | Leaf referenciaazonosító. Bizonyítva → nyers qub_id. A vakított azonosító → SHA3-256(qub_id ‖ log_blind_secret) (§16.2.1) állították. |
chash |
6 | bstr[32] |
Tartalom címe SHA3-256(stored_bytes) — az egyetlen tartalomkötés, amit a Munkás mindig őszintén ki tud számolni, mindkét úton. |
|
unlock_at |
10 | i64 |
szükséges | Másolt (igazolt) vagy állított (állítva); > 0 igazolva, mielőtt belép a levélbe. |
received_at |
12 | i64 |
szükséges | Worker falóra-óra R2-ack-nél. Nem bizonyíték (operátor által állított; §16.6). Önleíráshoz való jelenlét, soha nem bizonyíték. Hitelesített > 0. |
body_hash |
10 | bstr[32] |
kind=0x01 csak |
hagyta ki 0x02 — a Munkás nem rendelkezik a 13. § alapján. |
drand_round |
12 | u64 |
kind=0x01 csak |
hagyták ki a 0x02-n. |
Egy kind=0x02 levél szándékosan nem követi el sem body_hash, sem drand_round: igazolja egy átlátszatlan titkosított szöveg elköteleződését és rendezését a chash tartalomcímen, állítása qub_id és unlock_at — nem a tiszta szöveg vagy a kör. Az állított qub tiszta szöveg/kör lábai a meglévő §11 .qub-csomagos ellenőrzésből származnak, nem a naplóból (§16.11). drand_chain_version nincs a levélben (az alapértelmezett úton a csomagolásban van); a lánc granularitása a horgonyonyon él (§16.7). Kódoló fegyelem: elutasítsd az all-zero ref vagy chash-et, és elutasítsd a nem pozitív unlock_at / received_at-et, ami tükrözi a outcome_at > 0 sentinel guardot cbor.rs-ben.
16.2.1 Magán-qub vakítás
A napló nem válhat azzá az enumerációs orákulumba, amelyet a §13 külső csomagolás megakadályozni akar (§13.1). Egy privát (becsomagolt) qub esetén a asserted levél megköti a vakított azonosítót SHA3-256(qub_id ‖ log_blind_secret), ahol log_blind_secret szerver által őrzött titkos, és kihagyja a body_hash. Egy harmadik fél nem kötheti az ilyen levelet egy adott qub_id-hez; a qub tulajdonosa, akinek a szállítási URL-je van, így qub_id, újraszámolhatja a vakot, hogy megerősítse saját bevonását. Egy nyilvános qub (már felsorolható, már a §13.8 szerinti Visibility: public Arweave címkét viseli) elvégzi a nyers qub_id. Ez az egyetlen hely, ahol az önálló ellenőrizhetőség szándékosan enged egy terhvivő adatvédelmi invariánsnak; a magán qub-ok önálló köteléke chash (§16.9).
log_blind_secret őrzetesség (megoldva — §16.15 Q4). A vak védi levél összekapcsolhatóságát, nem a tiszta szöveges titoktartást (a §13 csomagolás ezt függetlenül tartja). Egy log_blind_secret kompromisszum esetén, bármely qub_id esetén az ellenfél már birtokolja vagy képes rekonstruálni (minden qub, amelynek csomagja/URL-je van, plusz bármilyen alacsony entrópiás vagy nyilvános qub_id), újraszámolja a ref levelet egy hash** formátumban és összekapcsolja — ez egy ismert populáció közvetlen összekapcsolása, nem egy ismeretlen tér feletti erőszak. Osztályozzuk log_blind_secret korrelációs/Sybil-szintű titkosnak ugyanabban a felügyeleti szintben, mint más szerver titkok, és csak előre forgatni (a rotáció újravakítja a jövőbeli leveleket; nem tudja utólag lekapcsolni a már rögzített leveleket).
16.3 Levél- és csomópont-hashing
RFC 6962 §2.1 tartomány-szétválasztott hashelés, SHA-256 helyett SHA3-256-tal helyettesítve:
leaf_hash = SHA3-256(0x00 || canonical_cbor(LogLeaf))
node_hash(l,r) = SHA3-256(0x01 || l || r)
empty tree = SHA3-256("") // defined but never anchored
A 0x02 (entry chain, §16.4) és 0x03 (STH hash, §16.6) tartomány előtagok ezekből külön és különállóak. Egyetlen bájt, így nem ütközhetnek a meglévő 10 bájtos ASCII tartományelválasztókkal (QUB_ID_V2 stb.). A fa az RFC 6962 left-full, kiegyensúlyozatlan fa (minden belső oldal két legnagyobb, szigorúan kevesebb, mint az alfa levélszám), amely lehetővé teszi, hogy a befogadás és konzisztencia bizonyításai egy audit-út algoritmusban használják. A referenciaspecifikáció explicit bal/jobb levezetési pszeudokódot hordoz, és egy nem két-ható (5 leveles) tesztvektort rögzít, így a jobb szélű előléptetési esetet — amelyet egy 4leveles vektor elrejt — alkalmazzák.
16.4 Hash láncolás (internal)
A LogDO belső bejegyzési láncot tart fenn kizárólag a crash-konzisztens érdekében. Ez soha nem jelenik meg, és soha nem is ellenőrzőhöz:
entry_chain[seq] = SHA3-256(0x02 || entry_chain[seq-1] || leaf_hash[seq])
entry_chain[-1] = SHA3-256("QUB_TLOG_GENESIS_V1")
A közzétett csak kiegészítő hatóság a kumulatív Merkle gyökér + annak horgonya (§16.5–16.6), soha nem az a nyers sorrend, amelyben az operátor a leveleket szolgálja: a lánc bármely szolgált sorrendre újraszámol, így csak a rögzített gyökér rögzíti a kanonikus pozíciót.
16.5 Összesített Merklefa és köteges
Van egy folyamatosan növekvő RFC 6962 fa az összes levél felett seq sorrendben — nem külön tételenkénti fák. (A carry-leaf-chained per batch konstrukciót elutasították: nem valódi előtag reláció, így a "konzisztencia bizonyításai" nem megbízható.) Az összesebb fa valódi RFC 9162 konzisztencia bizonyításokat ad, és lehetővé teszi, hogy egyetlen friss horgony bizonyítsa a befogadást bármely régebbi qub esetén.
A LogDO Tartós Objektum az egyetlen író (blockConcurrencyWhile, QuotaDO / EntitlementDO tükrözi) — a megosztott naplóhoz hozzáadva olvasás-módosítás-írás közös állapotban történik, ezért KELL DO-n keresztülmenni, soha KV-n. Gyorsítótárban tárolja a fa jobb szélének határát (O(log n) hash-eket), így a kötet lezárása O(batch). A batch a levelek összefüggő halmaza; a megvalósított triggerei legalább tree_size előrelépés LOG_BATCH_MAX_LEAVES-vel (alapértelmezett 4096), az életkor elérése a horgonyritmushoz, vagy egy explicit adminisztratív / cron kényszerítő lezárás. root_i a Merkle fa hasa a 0 .. tree_size_i levelek felett összegző összesített hasa.
16.6 Aláírt Tree Head az Arweave Anchoron keresztül
Az Arweave anchor tranzakció az az Aláírt Fafej, és helyettesíti egy operátor aláírást magának a fafejnek: a napi horgonynak nincs szüksége qub kulcsra, mert az Arweave tx owner az aláírás. A vizesárok tézis igaz — a megváltoztathatatlan alap, nem egy qub-által őrzött titk, terhelő a rögzített gyökér számára.
A naplótervezés egy meleg, sikeres csatolású fogadó kulcs (§16.10) igényli, amelyet LogProfile-ben rögzítettek és anchor_owner keresztaláír. A jelenlegi megvalósítás nem fejezte be ezt a bizalmi gyökér kijelölést: RECEIPT_SK opcionális, hiányzó/érvénytelen kulcs sig_b64url: "" ad, és a lefordított LogProfile.receipt_pubkey üres. Egy ilyen visszaigazolás leírhatja az csatolt levelet, de nem nem megérdőjelezhető aláírt blokk. Az erősebb tervezési igény csak akkor érvényes, ha egy ellenőrségi kiadás kitűzi a megfelelő nyilvános kulcsot, és a horgony tulajdonosa keresztaláírja. Egy teljes fogadó tuple nélküli publikációs válasz nem tesz napló-elfogadási állítást; egy üres aláírással rendelkező válasz csatolás-pozíció igényt tesz, de nincs aláírás-ellenőrzési igény.
A SignedTreeHead kanonikus CBOR (kulcsok kódolt hossz szerint): size:u64, root:bstr[32], batch:u64, prev:bstr[32] (sth_hash előtt; genesis = 32 nulla bájt), log_id:bstr[32], first_seq:u64, anchored_at:i64. Hashje sth_hash = SHA3-256(0x03 || canonical_cbor(SignedTreeHead)).
Rögzített megbízhatósági gyökér. log_id = SHA3-256("QUB_TLOG_V1" || anchor_owner_address). Egy megfelelő ellenőrzőnek KÖTELEZŐ igényelnie a anchor_tx.owner == LogProfile.anchor_owner-et, ahol a anchor_owner (és a nyugtakulcs nyilvános kulcsa) be van égetve a qub_core-be LogProfile-ként — a gyorshálózati állandók mellett, amelyek már benne vannak a DrandTimelockProvider::quicknet()-ben — és distribúcióra kerül az ellenőrző binárisával. Az ellenőrző KÖTELEZŐEN ellenőriznie kell az Arweave tranzakció adat → tx_id kötést helyben, a HTTP gateway /raw/ válaszában való megbízás helyett. Ez zárja a kártevő tárcákkal való kettős mérce hézagát: az „Arweave-ra horgonyozva” jelentés nélküli, amíg az ellenőrző nem tűzi ki, melyik tárca.
A forgatás a §15 irányítási kiterjesztés, nem újrahasználat (megoldva — §16.15 Q3). A §15.2 profilfelület jelenleg csak sig_algs / drand láncok / wrapper verziók / tartalomtípusok felsorolását tartalmazza, és a §15.3 kiváltólistája egyiket sem — a LogProfile / anchor_owner még nincs a §15 felületén. A forgatás irányítása ezért ki kell építeni: a §15.3 kiterjesztésre kerül (lent) a LogProfile kiváltó hozzáadásával, és a forgatás egy aláírt LogProfile emelés, amelyet az ellenőrző frissítése tartalmaz. Egy tervezett forgatás tartalmaz egy kilépő → belépő keresztaláírást; egy meghibásodásból eredő forgatás nem tudja (a kilépő kulcs ekkor megbízhatatlan/ nem elérhető), és visszatér a §15 által irányított emeléshez, a korábbi horgony elágazás-ellenőrzéssel (lent), amely ideiglenesen korlátozza a kárt.
Kettős mérce ablak (elsőrendű megbízhatósági paraméter). Egy levél csak akkor ellenáll a kettős mércézésnek, ha a lefedő horgonya Arweave-megerősített. Az ablak received_at → anchor confirmation (ritmus + Arweave véglegesség, protokoll-latencia garancia nélkül). A megbízhatósági gyökér biztosítása előtt a jelenlegi implementáció az üzemeltetési integritást (qub) nyújtja, plusz az összes aláíratlan hozzáfűzött metaadatot; nem nyújtja a tervezett tagadhatatlansági garanciát. Három elszámoltathatósági tárgy definiálja a kifejlesztett tervet (a tanú modell a §16.15 Q2 megoldása):
- Pecsét-fogadó (provisioning-függő) — az SCT analóg visszatér, amikor a feltöltés napló kiegészítése sikeres lesz (§16.10). Csak akkor válik visszautasításhatatlanná, ha
sig_b64urlnem üres és a megfelelő nyilvános kulcs/horgony-tulajdonos kapcsolat a hitelesítésben van rögzítve. A jelenleg üres gyártási profil tű nem támasztja alá ezt az ítéletet. Ez a kontroll nem vonatkozik kihagyott visszaigazolási tupléra vagy aláíratlan nyugtakra. - Publikált monitor módszertan + előzetes lánc sétá — a lánc
prevhorgonyja a "walked head→genesis"; a vila (két horgony egysizekülönbözőrootvagy egy töröttprev) publikálható bizonyíték a visszaélésre. Az kétértelműség felismerése egy kifejezett operatív elkötelezettség, nem egy néma feltételezés. - Kettős önkiadott fej — minden új fej
{sth_hash, tree_size}egy dediktált, qub tulajdonában lévő nyilvános, csak csatolható GitHub repozióriumba (a terhelő, manipuláló önkiadási rész) közzétételére kerül ki, a közösségi bejegyzés pedig csak a legjobb megerősítés érdekében. Egy sikertelen közzététel KÖTELEZŐ oldal (nem fail silent). *Megvalósítva (8. szakasz) apublishHeadhorogként a horgony a cronon (workers/api/src/utils/heads-publish.ts): a tartalom API-jánakPUTshanélkül csak kiegészítésre alkalmas (a422azt jelenti, hogy a fej már közzé van adva, soha nem felülírás); opt-in / deploy-kapusPUBLISH_HEAD_GITHUB_{TOKEN,OWNER,REPO}-en és inert addig, amíg a tároló kialakítódik. Egy kemény GitHub hiba ahealth_alertcsatornán keresztül oldalaz, és egy tartós hiba metrikát (m:tlog_publish_head_fail) érint; maga az Arweave anchor soha nem görgeti vissza a közzétételi hibát. A "nem hibás hangtalanság" garantált az a tartós metrika — amelyen az operátoroknak KÖTELEZŐ dashboard-riasztást kell adniuk — még akkor is, ha a legjobb erőfeszítésű e-mail oldal nem érkezik meg. Két őszinte korlát van a "anchor-on-advance" (a cron csak a méret növekedése után jelenik meg): egy átmeneti GitHub-hiba *rést hagy a publikált fejek sorozatában ebben a méretben — korlátozott, nem néma (oldala), és mivel minden fej egy szuperset fát köt, egy §16.9 konzisztencia bizonyítás hidalja át a szakadékot; lényeges, hogy ez a konzisztencia bizonyítása a tekintélyes Arweave-által rögzített fából számítanak, nem a GitHub felületéről, így a GitHub rés sosem gyengíti az ellenőrizhetőséget. Egy felzárkózó visszatöltés, amely kitölti a publikált fejek hiányosságait, egy halasztott fejlesztés.
**Őszinteséghez kötött (kötelező korlátozás). ** Mivel a qub mindkét tervezett közzétételi felületet ellenőrzi, ez önkiadás, nem önállóan tanús. Egyetlen termék, marketing vagy jogi felület sem állíthatja, hogy a napló "önállóan tanús". Miután a belépő/profil/fejkapuk kibiztosították, az engedélyezett állítás, hogy kétértelműség észlelhető, és egy sikeresen aláírt csatolás nem visszavonható blokkát hagy hátra. Addig ez a igény nem elérhető. Egy valódi független harmadik fél tanút egy jövőbeli §15 kormányzati átállásra kerül.
received_at operátor által állított, és semmilyen igény nem támaszkodhat rá — soha nem jelenik meg bizonyítékként vagy vita megerősítésként semmilyen terméken, jogi / API-n / bizonyítási felületen. Az Arweave anchor block time T az egyetlen bizalmatlan időbélyeg (egy felső határ a "loged" alatt). Bármely monitor józan ész ellenőrzése received_at-on KELL összehasonlítania T-vel, nem az operátor által irányított anchored_at STH mezővel; ilyen ellenőrzés csak egy tisztességes operátor óra-hibája ellen véd, nem egy rosszindulatú operátor elleni elszámoltathatósági vezérlés (§16.15 Q5).
16.7 Anchor tranzakció formátuma és ritmusa
A AnchorBundle a kanonikus-CBOR Arweave tranzakció teste, amelyet a §16.8 bundlerrel írnak: ver:u8, sth:bstr (kanonikus SignedTreeHead bájt), prev_anchor:bstr (korábbi anchor tx id nyers bájt; a genesisnél kihagyva), chain_hash:tstr (a drand lánc érvényben — quicknet), és a batch levél-CBOR áramlata seq sorrendben, így a horgony önálló: egy monitor újra levezeti root a nulla qub-függőségű testből. (Ha a levélfolyam nagy volumenben nagyra válik, egy jövőbeli változat csak egy levéltartományt alkalmazhat referencia alapján; megjegyezve, nem alkalmazták az 1. v1-ben.)
Az Arweave címkék szándékosan megszámlálhatók — a napló megtalálható eredetű, ellentétben a privát qubokkal: App-Name: qub-tlog, Anchor-Format: 1, Log-Id: <hex>, Batch: <n>, Tree-Size: <n>, Root: <hex>, Prev-Anchor: <tx>, Content-Type: application/cbor. A címkék megbízhatatlan tippek; a CBOR test az egyetlen hatóság.
Cadence: alapértelmezett naponta, újra megnézve a volumengel (a méret trigger automatikusan rövidíti az effektív ritmust terhelés alatt). A jelenlegi gyártó nem vezet be fizetett zárás-erőhorgonyhorgot. A horgonytárca dedikált és alacsony sebességű, különálló a feltöltési pénztárcától — KÖTELEZŐEN saját JWK-nak kell lennie (egy különálló kulcs, nem logikus szerep a feltöltési tárcán), így a feltöltés-tárca kompromisszum nem tud hamisítani horgongot — kemény napi horgony-tranzakciós költségvetéssel. A lekezelő pozíció egyértelműen megfogalmazódik: egy szűk hatótávolságú gyorsbillentyű szoros megszakítóval és alacsony egyenleggel, nem "hideg" — egy olyan tárca, amely naponta automatikusan aláír, nem lehet hideg, és a specifikáció nem állít mást.
16.8 ANS-104 Bundler
Egy házon belüli ANS-104 DataItem kódoló és mély-hash aláíró, körülbelül 300 sor, Csak Web Crypto, nulla npm függőség (mindkét Turbo SDK nem teljesíti a npm ci --ignore-scripts ellátási lánc kapuját). DataItem bájt elrendezés:
signatureType (2, LE) || raw_signature || owner || target(flag+0|32) || anchor(flag+0|32) || num_tags(8, LE) || tags_len(8, LE) || avro_tags || data
Az aláírás Arweave deepHash — egy rekurzív SHA-384 digest (Arweave vezeték követelménye, crypto.subtle.digest("SHA-384")) ["dataitem", "1", sig_type, owner, target, anchor, encoded_tags, data] felett — majd RSA-PSS a mély hash-en keresztül a JWK tárcával crypto.subtle-n keresztül; id = base64url(SHA-256(signature)). A SHA-384 itt Arweave-wire primitívként karanténban van, soha nem qub trust primitív (§15 rögzíti a kerítést; qub trust hashing SHA3-256 végig).
Az ANS-104 kódút a halasztott tartalék/leszívó gépezetet szolgálja, és AnchorBundle DataItems gépet ír. A hagyományos közzétételi útvonal először egy pontos aláírt Arweave tranzakciót hoz létre, és a JSON-ját tartós kimenődobozban tartja; a közvetlen közzététel késleltetésoptimalizálás, és a drain path ugyanazt a tranzakciót próbálja újra, mielőtt alkalmazná a bundler tartalékot. Aláírási séma (megoldott — §16.15 Q8): v1 RSA-PSS-szel (aláírás típus 1) a meglévő Arweave pénztárca JWK mechanizmus újrahasznosítása (nulla új, hosszú életű kulcsőrző, a "egy kevesebb titok" tézist szolgálva); Az Ed25519 a §15 PQ-migrációs útra van áthelyezve.
A kézzel tekert deep hash a W5 legmagasabb kockázatú, legalacsonyabb természetes lefedettségi kódja, így a gating nem tárgyalható (§16.15 Q8):
- A nyelvközi
tlog_v1.jsonrögzítés (Rust + TS, a §14.5wrapper_v1.jsonminta) lefedi a mély hash-t, a DataItem bájtjait + azonosítóját, a levél hash-eket, egy 5 leveles gyökeret + audit útvonalat, egy STH hash-t, egy befogadási igazolást és egy konzisztencia igazolást — mind a aláírási, mind az ellenőrzési irányban (az ellenőrzési irány fontos, mert §16.6 helyi tx → tx_id ellenőrzés a mély hash-t minden önálló ellenőrzőbe beemeli, nem csak az íróba). - Egy egyszeri interoperabilitási oda-vissza út egy referencia ANS-104 csomagolóval, csak statikus tesztadatként felhasználva — soha nem npm futási függőségként (a kizárólag Web-Crypto / nincs telepítési szkriptek hozzáállás érvényben marad).
- A mély hash + RSA-PSS útvonalnak végig kell mennie a ugyanazon
crypto.subtleprimitíveken a termelésben, így a házon belüli kódoló bájtközi kompatibilis. - A folyamatban lévő post-csomag elfogadási monitor megerősíti, hogy minden anchor / fallback DataItem valójában eléri az Arweave elfogadást, riasztással + áramkör-kikapcsolóval — mert a mély hash az Arweave-hiányosságok pótló sorát is szolgálja, így egy néma visszaesés a hálózattól elutasított elemekkel töltené fel azt a sorozatot a pontos kimaradás idején, amit le kell fednie.
16.9 Befogadási és Konzisztencia Igazolások
Mindkettő RFC 9162, SHA3-256, kanonikus CBOR formátumban szolgáltatva.
InclusionProof — GET /api/v1/qub/:tx_id/proof: ver:u8, leaf:bstr (a pontos levél CBOR — az ellenőrző magától számítja újra a leaf_hash-t, és soha nem bízik egy megadott hash-ben), index:u64, size:u64, audit:[bstr[32]], root:bstr[32], anchor:{ txid:bstr[32], batch:u64, sth:bstr[32], log_id:bstr[32], block_height?:u64, anchored_at?:i64 }.
ConsistencyProof — GET /api/v1/log/consistency?first=<size_a>&second=<size_b>: ver:u8, first_size:u64, second_size:u64, first_root:bstr[32], second_root:bstr[32], nodes:[bstr[32]], first_anchor, second_anchor. Egyetlen egyértelmű kulcslista, tesztvektorral rögzítve.
Önálló ellenőrzés (qub szerver nélkül, kiterjeszti a §11-et):
1. Parse .qub bundle → SealedQub; recompute qub_id (§4.1).
2. Read leaf.kind.
3a. kind=0x01 (attested):
assert leaf.ref == qub_id
assert leaf.body_hash == SHA3-256(body)
assert leaf.drand_round == unlock_round(unlock_at)
3b. kind=0x02 (asserted):
assert leaf.ref == SHA3-256(qub_id || blind) // holder supplies blind
OR treat ref as opaque and bind via leaf.chash == SHA3-256(stored_bytes)
4. Recompute leaf_hash = SHA3-256(0x00 || leaf); fold `audit` per RFC 6962
using index/size; require derived root == proof.root.
5. Fetch anchor.txid from any gateway; verify the tx data → tx_id binding
(do not trust a gateway /raw/ response); REQUIRE anchor_tx.owner ==
LogProfile.anchor_owner.
6. Parse AnchorBundle; require committed root == proof.root and size ==
proof.size; read the Arweave block time T.
7. Emit the claim scoped by leaf.kind (§16.11).
A proof-service tárolónak KELL koordináta kulcsolással (megoldott — §16.15 Q7, előfeltétel blokkolása). A hideg levél bizonyítás generálása helyesség-semleges csak akkor, aki** az R2 audit anyag egy tartós Merkle-csomópont tároló, amelyet abszolút fa koordináta (level, index) kulcsolt — nem batch csomópontonkénti delta. Koordináta kulcsos tárolóval bármely (leaf i, size N) audit útvonal O(log N) közvetlen R2 GET halmaza, amelyekben nincs újraszámítás a batch határain át; egy batch-key tárolónál nem, ami az a tároló-elrendezési rés, amelyet ez a felbontás bezár. A levéltestek is seq által tartalmi címezhetőek is. Egy W5 tesztvektornak bizonyítania kell egy genesis korszakbeli hideg levelet egy sokkal későbbi gyökérrel szemben, csak R2 + Arweave-vel, a LogDO tároló törlésével, így a §16.13-ban szereplő reclamation-safety állítás inkább alátámasztható, mint kiállított. A O(log N) szekvenciális R2 GET csak aszinkron bizonyítási végponton találhatók — soha nem a seal hot path-on (§16.10) vagy egy tick-en-tick cron-on.
16.10 R2-első Ack sorrend
A megvalósított POST /api/v1/upload sorozat a következő:
- Első félkapuk (auth, validáció, idempotencia szilánkulcs) — változatlan.
- Hozd létre, címkézze és írja alá pontosan az egyes Arweave tranzakciót. Ez helyben vezeti
tx_id, bár a tranzakció létrehozása letöltheti a jutalma/horgonymetaadatokat egy átjáróból. Egy előkészítő hiba még mindig meghiúsítja a kérést a visszaigazolás előtt. - Szinkron írja le a kiválasztott artefaktumot
qub-cache/<tx_id>-nél, és persistente a stabil létrehozási/kimeneti rekordokat. Ezek a tartósság és újrapróbálkozás szintje; kudarcok a 503-as elszámolás előtt. - Amikor
LOG_DObe van állítva, szinkron próbálkozásaLogDO.append(leaf). Az egyetlen íróseqrendeli hozzá, meghosszabbítja a bejegyzési láncot, és frissíti a határt. Az append RPC csak ezt teszi; a batch close lefut a riasztáson. Az append transport/application hiba jelenleg fail-soft: a válasz még mindig sikeres lehetlog_seq,receiptvagyanchor_statusnélkül. A megvalósítási megjegyzés ellenére ma nincs automatikus későbbi naplóegyeztetés. - Visszaküldje a visszaigazolást. Csak akkor tüntesse fel
{ log_seq, anchor_status: "pending", receipt }, amikor a kiegészített teljes sikeres tuple-t küldte vissza.receipt.sig_b64urlüres, amikor a fogadó aláíró nem elérhető; az ügyfelek NEM nevezhetik ezt az értéket aláírtnak vagy nem visszavonhatónak. A tuple hiánya csak tartós közzétételt jelent, nem pedig átlátszósági napló elfogadást. - Használj egy halasztott feladatot a pontos aláírt tranzakció közzétételére. Siker eltávolítja a kimenetet; a kudarc a korlátolt leszívó cronra kerül, és nem változtathatja meg a már elismert
tx_id. Az ideiglenes metaadatok és más legjobb oldalkartok is halasztottak.
Késleltetési határ. A kérés útvonala tartalmazza az első felében történő hatósági/kvóta munkát, tranzakció előkészítést/aláírást, tartós R2 írásokat, és (ha konfigurált) a LogDO próbálkozást. A < 300 ms a tervezési felülvizsgálatban operatív célnak jelenik meg, nem pedig protokollgaranciának; a jelenlegi tranzakció-előkészítési lépés végezhet átjáró metaadat-kérést. A késleltetési riasztások és indítási kapuk operatív ellenőrzések, nem pedig a hitelesítő számára rendelkezésre álló bizonyítékok.
16.11 Bizalmi modell — a pontos állítás, levél típus által korlátozva
A kind=0x01 (tanúsított) esetén: „Ez a tartalom — test megegyezve a body_hash-szel, azonosítva a qub_id által — rögzítésre került a qub hozzáfűző logjában a seq pozíciónál, és legkésőbb az Arweave blokk időpontjáig T létezett; kriptográfiailag olvashatatlan volt a drand kör előtt R = unlock_round(unlock_at).” Ez a teljes {tlock round binding + Merkle inclusion + anchored root} hármas.
A kind=0x02 (állított, alapértelmezett) esetén: „Egy átlátszatlan titkosított szöveg a chash tartalom-címmel, igényelve qub_id és unlock_at, rögzítésre került a hozzáfűző logban a seq pozíciónál, és legkésőbb az Arweave blokk időpontjáig T létezett.” A kör- és test részeket a meglévő §11 .qub-csomag ellenőrzés (qub_core::unlock) szolgáltatja, nem a log; amit a log hozzáad egy puszta qub-tranzakcióhoz, az a beavatkozás-észlelhető sorrendiség, a bizalom nélküli felső határ elkötelezés ideje, és az ellentmondás-ellenállás.
Mindkét állítás kizárja a §11 alapján: szerzőség sig_alg ≥ 0x01 nélkül, szándék, és rész-anker granuláris időzítés. Egyik sem engedi, hogy bármely állítás a received_at-ra támaszkodjon.
Állítási plafon (kötő indítási korlátozás — megoldva §16.15 Q1). Egy állított (kind=0x02) levél esetén a fenti korlátozott állítás a plafon arra vonatkozóan, amit bármely termék, marketing, feltételek, vagy bizonyítási felület állíthat. Egyetlen felület sem állíthatja vagy sugallhatja, hogy a log bizonyítja a tartalmat vagy egy bájt-süket feltöltés feloldási körét — a log bizonyítja a sorrendet + egy bizalom nélküli felső határ elkötelezés idejét egy átlátszatlan titkosított szövegnél. A tartalom- és kör bizonyítás kizárólag a meglévő §11 .qub-csomag ellenőrzésből származik, ami független a logtól. Egy publikáció, amely sikertelen hozzáfűzéssel/átvétellel rendelkezik, egyáltalán nem rendelkezik log-állítással.
16.12 Verziózás és W3 koordináció
Nincs SealedQub vezeték-bump, így nincs protokoll-verzió bump (§12.2): a napló egy sidecar, amely a meglévő mezők és bájtok mellett köteleződik, így nem lép be a §12.3 protokollverzió történetébe. W3 opcionális drand_chain_version érintetlen, és továbbra is az egyetlen opcionális SealedQub mező. A napló ehelyett saját független verziótereket vezet be — LOG_VERSION_1, ANCHOR_FORMAT_1, InclusionProof.ver —, amelyek tükrözik a §12.5 wrapper-verzió függetlenségét (a burkoló verzió bájtját hordozza a protokoll verziójától, és a napló verziók ugyanazt a szétválasztást követik).
A bizonyítás átadása alapértelmezettben előhívható, opcionális egy kísérőúttal. Bizonyítás nem létezhet pecsétidőpontban (a horgonyt még nem írták meg), így a pecsét-idő .qub csomag bizonyítékmentes marad. W7 ellenőrzője egyszer hívja GET …/proof-ot, vagy teljesen offline módban rekonstruálja a bizonyítást a nyilvános AnchorBundle Arweave lekérdezéssel az Log-Id-n. A .qub csomag (W7) egy **opcionális inclusion_proof tagot tart fenn — amely a pecsétnél hiányzik, és egy horgonyutáni újraexporttal töltve fel hideg archív céljából — ugyanazt a "opcionális, alapértelmezetten kihagyott, additív" mintát követve, mint a W3 drand_chain_version-je.
16.13 Megtartás
A LogDO nyitott farok, az R2 bizonyító aljzat, a horgony megszakító számlálói és a bundler tartalék sorának megtartási ablakai docs/DATA-RETENTION.md-ben vannak megadva. Elv: a napló forró bejegyzésenkénti tárolása (LogDO) visszafoglalható a rögzítés után; az audit anyaga — a koordinátakulcsos (level, index) Merkle-csomópont tároló + az seq-címzett levéltest (§16.9) + az Arweave horgonyok — végleges. Ha egy hideg levél visszaszerzi a DO-tól, soha nem érvényteleníti a kiadott bizonyítást, mert a bizonyítás ellen oldódik az állandó R2 csomópont tárolóval és az Arweave angonyával, nem a DO-val (és ezt bizonyítja a §16.9 törölt DO tesztvektor).
16.14 Tesztvektorok
A W5 tartalmazza a keresztnyelvi fixtúrát tlog_v1.json (§16.8) plusz a munkás vektorokat: egy kind=0x01 és egy kind=0x02 levél → leaf_hash; az 5 leveles kumulatív gyökeret; egy bevonási bizonyítást; egy konzisztencia bizonyítást; egy AnchorBundle; és egy DataItem azonosítót. Ezek a §14.5 külső csomagolási vektorokkal együtt működnek, és mind a Rust (qub-core), mind a TypeScript (Worker) implementációk alkalmazzák őket.
16.15 Felülvizsgálati döntések (W5 — elzárva)
A W5 külső felülvizsgálata (ellenséges tervezési engedély + tulajdonosi jóváhagyás) befejeződött. Minden alábbi döntés elzáródott és tükröződik a fenti §16 szövegben; a kötelező indítási korlátokat a végén újra megfogalmazzuk. A megvalósítás ezek alapján folytatódhat.
Alapértelmezett út (
kind=0x02) levél őszinteség — MEGOLDVA. Küldjük a kétleveles felosztást a megadott módon:kind=0x02sembody_hash, semdrand_roundnem követ el. Nincs*_body_hashmező a bájtvak úton (ez lenne a legolvashatóbb hamis "ellenőrizett" jel az integrátorok számára, és a §11 már biztosít kényelmet a csomagból). Ne ne kell szerverpecsétet naplóval igazolt qub-okhoz (ami a tiszta szöveget kényszerítené a Munkáson, és megsemmisítené a kripto-szétszóró árkot). Bármilyen önmagát leíró rövidzárlat a.qubcsomag / proof borítékba tartozik, mint egy ellenőriző által újrakiszámított mező, soha nem levélmező. Tulajdonos által megerősített igény plafonja: §16.11.Kétértelműség / elhagyás felelősségvállalása — TERVEZÉS MEGOLDVA, PROVISIONING HIÁNYOS. A tervezéshez a pecsét-visszaigazolási kulcsot
LogProfile-ben kell rögzíteni, ésanchor_ownerkeresztaláírja, valamint monitorozó módszertant, korábbi lánc sétát és kettős önkiadott fejet. A lefordított profil és telepítési hookok továbbra is helykitöltők/opcionálisak, ahogy azt a §16.6 részletezte, így a erősebb észlelhető + megvett állítás nem érvényes, amíg ezek a kapuk be nem záródnak. Sosem szabad függetlenül tanúként reklámozni. Egy valódi harmadik fél tanút egy §15-ös irányítási bumpra utal.Rögzített horgony-tulajdonosi bizalmi root + rotáció — MEGOLDVA. Fogadd be a
LogProfilepint (§16.6); az ellenőrző ellenőrzianchor_tx.owner == anchor_ownerés ellenőrizi a tx adatokat → tx_id helyben kötést. A rotációs irányítás egy §15 kiterjesztés a buildhez (§15.3 trigger hozzáadva), nem újrahasználat; a tervezett rotációk keresztjelet mutatnak, kompromisszum-alapú rotációk visszaesnek a §15-ös bumphoz, ahol a fork check határolja a kárt.Privát-qub levélvakítás — MEGOLDVA. Fenntartsd a vakozást privát qub-oknál (
ref = SHA3-256(qub_id ‖ log_blind_secret)), a nyersqub_ida nyilvános qub-oknál (már §16.2.1),chashönálló kötelékként.log_blind_secretkorreláció/Sybil-fokozatú titkos, csak forgatás előre (§16.2.1).received_at— ELDÖNTVE. Tartsd a levélben, elkötelezett, de kifejezetten nem bizonyítékként; soha nem jelent meg bizonyítékként vagy vitató megerősítésként egyetlen felületen. Bármely monitor józan ész ellenőrzése összehasonlítja az Arweave blokkidőT-vel, nem a kezelő által vezéreltanchored_at(§16.6).Fokozatos bizonyítható időzítés — TERVEZÉSI FELBONTÁS, NEM AKTUÁLIS ÚTVONAL. Az átvizsgált terv a kötött szinthez a horgonyblokk időzítést rendeli, a fizetett T3-hoz pedig pontos óra-bizonyítást, az előbbihez pedig nincs numerikus SLA. A jelenlegi útvonalak nem rögzítették ezt a kereskedelmi megkülönböztetést: minden elfogadott kiadványhoz egyéni tranzakciót ütemeznek, és a napló lefedettsége feltételes marad, ahogy azt a §16.1/§16.10 is előírja. A termékmásolat a megvalósítást kell leírnia, nem ezt a jövőbeli szintfelosztást.
Kumulatív fa a Munkásokon — MEGOLDVA. Egyetlen kumulatív RFC 9162 fa + határmentesen gyorsítótárazott egy-író LogDO (kényelmes tartalék a ~1k írás/sec DO plafonhoz képest; a shard-gyökerek Merkle-elosztását halasszuk a határhoz közel). A koordináta-kulcsos
(level, index)R2 csomópont-tár + törölt-DO hideg-levél tesztvektor megvalósítva (§16.9).< 300 mstovábbra is tervezési/működési cél, nem protokoll ígéret (§16.10).ANS-104 aláírási séma + mély-hash — MEGOLDVA. RSA-PSS (aláírás típus 1, a dedikált anchor-wallet JWK újrahasználatával); Ed25519 későbbre halasztva a §15 PQ úton. A kézzel készített SHA-384 mély hash a kétirányú cross-impl rögzítőre, egy statikus-only referencia-bundler interoperabilitási ellenőrzésre, a shared-
crypto.subtleoda-vissza útra, és a csomag utáni Arweave-elfogadási monitorra van kötve (§16.8).
Kötődik indítási korlátokhoz (végrehajtásba és termék/jogi felülvizsgálatba átvinni):
- Követelés felső határa (Q1/Q6). Egyetlen felület sem állíthatja, hogy a napló bizonyítja egy kijelentett levél tartalmát vagy a feloldási kört; a sikeresen rögzített
kind=0x02levél esetén megengedett követelés: rendezett, visszaélésre utaló jelekkel, bizalmatlan felső határ elkötelezési idő mellett. A nyugtató tuple nélkül küldött válasznak nincs naplókövetelése. Egyetlen időbélyeg-másolat sem tartalmaz numerikus késleltetési garanciát. - Tanú becsületessége (Q2). Piaci kétértelműség mint észlelhető + nyugtázott, soha mint függetlenül tanúsított.
- Nyugta- és horgonyzási kulcsok (Q2/Q8). A tagadhatatlansági/horgonyzott ellenőrzési követelés szállítása előtt, biztosítani és összerakni kell a nyugta nyilvános kulcsát, kereszt-aláírni a biztosított horgony tulajdonossal, és a horgony pénztárcát saját JWK-ként kell kezelni, külön a feltöltési pénztárcától.
- Mély-hash kapu (Q8). Egyetlen horgony vagy T3 tx sem szállítható, amíg a kétirányú rögzítés + interoperabilitási ellenőrzés nem sikerül; a fogadási monitor hívást indít hibánál.
- Tárhely előfeltétel (Q7). A koordinált kulccsal ellátott node-tároló + törölt-DO hideg-levél vektor előfeltételei a „visszakövetelés soha nem érvénytelenít egy bizonyítékot” garanciának.
17. Hordozható ellenőrzési csomag (.qub)
Állapot. Ez a szakasz megvalósítva (W7 / UP-C2): a
qub_core::exportelőállítja és elemzi a csomagot, atools/qub-verifypedig nyilvános, önálló CLI, amely offline ellenőrzi. A §11 és §16.9 már „.qubcsomagként” hivatkozik arra az egységre, amelyet egy önálló ellenőrző felhasznál; ez a szakasz meghatározza a bájtjait és az ellenőrzési menetet. Szigorúan kiegészítő — a csomag a meglévő §11 bemeneteket foglalja össze, és nem változtat semmilyen láncon lévő wire-formátumon.
17.1 Cél
A §11 megállapítja, hogy bármely harmadik fél a qub együttműködése nélkül ellenőrizheti egy qub kriptográfiai műtárgyát. A .qub csomag ezt az ellenőrzést hordozhatóvá és offline-ná teszi: a lepecsételt CBOR-t és az azt feloldó drand-kör aláírását egyetlen önálló műtárgyba csomagolja, így a címzett a tartalom integritását, a körhöz kötést és az esetleges szerzőségi aláírásokat minden hálózati hívás nélkül ellenőrizheti (nincs tárolási lekérés, élő drand-kérés vagy qub API). A csomag önmagában nem bizonyítja, mikor hozták létre a titkosított szöveget; ezt a külön létezésiidő-állítást függetlenül ellenőrzött tárolási tranzakció vagy lehorgonyzott naplóbizonyíték szolgáltatja (§11, §17.5).
17.2 Csomagformátum
A QubBundle kézzel írt kanonikus CBOR a §3.1 profil szerint (határozott hosszúságok, címkék és lebegőpontos számok nélkül, legrövidebb egészalakok, NFC-szöveg, a hiányzó opcionális mezők kihagyva, a kulcsok növekvő kódoltbájt-hossz, majd bájtsorrend szerint rendezve). A három 15 karakteres kulcs sorrendje d < i < s. Egy nyers .qub fájl pontosan ezekből a bájtokból áll; URL-es vagy másolás-beillesztéses szállításnál ugyanezek a bájtok base64url(no-pad) alakúak.
| Kulcs | Kód. hossz | Típus | Jelenlét | Jelentés |
|---|---|---|---|---|
version |
8 | u8 |
kötelező | Csomagformátum verziója (0x01). |
sealed_at |
10 | i64 |
opcionális | Az alkotó által állított pecsételési idő (Unix-másodperc); önleíró, nem bizonyító erejű. |
drand_round |
12 | u64 |
kötelező | A kör, amelyhez a qub zárolva van. A beágyazott lepecsételt qub vetülete. |
arweave_tx_id |
14 | tstr |
kötelező | Annak a tranzakciónak az azonosítója, amely alatt a lepecsételt bájtokat tárolták (eredetmutató). |
drand_chain_id |
15 | tstr |
kötelező | A drand-lánc (hex). A beágyazott lepecsételt qub vetülete. |
drand_signature |
16 | bstr |
kötelező | A drand_round drand-beacon aláírása — a titkosított szöveget feloldó érték. |
inclusion_proof |
16 | bstr |
opcionális | A §16 átláthatósági napló Merkle-befoglalási bizonyítéka (§17.5). |
sealed_qub_cbor |
16 | bstr |
kötelező | A belső SealedQubCbor bájtjai (a §13 kicsomagolása után), vagyis a §11 ellenőrzési bemenete. |
A drand_round és drand_chain_id a sealed_qub_cbor kényelmi vetületei, hogy az eszközök a belső CBOR elemzése nélkül olvashassák őket. Előállításkor levezetjük, dekódoláskor pedig újra ellenőrizzük őket az elemzett lepecsételt qubhoz képest; a felső szintű mező és a hasznos adat eltérése esetén a csomag elutasítandó. A kódolói fegyelem a wire-formátum többi részét tükrözi: az üres drand_signature vagy arweave_tx_id elutasítandó, és minden változó hosszúságú mező korlátozandó.
17.3 Mit bizonyít a beágyazott drand-aláírás
A csomag a drand-aláírást hordozza, nem követeli meg az ellenőrzőtől annak lekérését. Az időzáras visszafejtés (tlock a drand-láncon, §8) csak a kötött kör valódi beacon-aláírásával sikerülhet — ezzel az értékkel, amelyet a lánc csak a kör eltelte után tesz közzé, és amely érvényes BLS-aláírás a lánc nyilvános kulcsa alatt. A hamis vagy téves aláírás megbukik a BLS-ellenőrzésen vagy az IBE/AEAD-visszafejtésen. A sikeresen visszafejtett csomag ezért ezt bizonyítja: a titkosított szöveg az R körhöz kötött, és az R kör eltelt. Az ellenőrző rögzíti a láncot (DrandTimelockProvider::quicknet()), és alkalmazza a §11 körkötési ellenőrzését, így a csomag nem állíthat olyan kört, amelyhez a titkosított szöveg nincs kötve.
Ez felszabadításifeltétel-bizonyíték, nem létrehozási időbélyeg. Az R kör eltelte után bárki létrehozhat új titkosított szöveget R-hez, és becsomagolhatja a már nyilvános aláírást. Ezért a csomagot önmagában NEM SZABAD annak bizonyítékaként leírni, hogy a titkosított szöveg vagy tartalom R, az unlock_at vagy bármely esemény előtt létezett.
17.4 Offline ellenőrzési menet
A qub-verify <file.qub> a szabványos §11 eljárást teljesen a csomagból futtatja, a qub_core::unlock::unlock függvényt rögzített DrandTimelockProvider-rel hajtva:
1. Parse the .qub bytes → QubBundle (canonical-CBOR guard; bound every field;
re-check drand_round / drand_chain_id against the embedded sealed qub).
2. BLS-verify bundle.drand_signature for the pinned chain and round, then
tlock_decrypt(sealed.tlock_ciphertext, bundle.drand_signature) → QubEnvelope.
3. Verify SHA3-256(body) == body_hash (§11 step 8).
4. Verify QubEnvelope.qub_id == SealedQub.qub_id (§11 step 9).
5. Verify QubEnvelope.unlock_at == SealedQub.unlock_at (§11 step 10).
6. Verify ciphertext round == unlock_round(unlock_at) and the chain binding.
7. If sig_alg != 0x00: verify author_signature (and any cosigner; §9.4).
8. Report integrity, round-elapsed/round-binding, authorship, and cosigner
verdicts separately, plus the recovered body. Do not report a commitment
timestamp unless step 9 succeeds.
9. Optional existence-time leg: verify an included §16 proof through its pinned
anchor, or independently verify the referenced storage transaction. Report
its block time as an upper bound on ciphertext existence.
A CLI 0 kóddal lép ki (ellenőrzött), 1 kóddal, ha az ellenőrzés meghiúsult — még zárolt, eltérő törzskivonat, hibás kör-/lánckötés vagy sikertelen aláírás-ellenőrzés —, illetve 2 kóddal használati hiba vagy rosszul formázott csomag esetén. A --json jelentés ugyanezeket az ítéleteket hordozza automatizáláshoz. Mivel a csomag önálló, egy harmadik félnek csak az ellenőrző crate-re (qub-core) és a CLI-re (qub-verify) van szüksége; mindkettő nyilvános és a protokoll meglévő ellenőrzési útvonalát használja — nincs egyedi kriptográfia.
17.5 Kapcsolat az átláthatósági naplóval
Az inclusion_proof opcionális hely a §16 Merkle-befoglalási bizonyítékának. A csak csomagos ellenőrzés (§17.4) teljes az integritás, a körhöz kötés / kör eltelte és az opcionális szerzőség tekintetében, de szándékosan nincs függetlenül időbélyegzett létezési állítása. Egy jelen lévő, horgonyig teljesen ellenőrzött inclusion_proof a csomagformátum verziójának módosítása nélkül hozzáadja a §16.11 levéltípus-specifikus kötelezettségvállalását és felső korlátú idejét. A hiányzó bizonyíték csak azt jelenti, hogy „nincs bizonyíték mellékelve” — nem azt, hogy „érvénytelen”, és nem feltétlenül azt, hogy „nincs lehorgonyozva”.
A referencia-megvalósításban a hely már típusos: a qub_core::export::QubBundle::inclusion_proof_typed() egy Option<InclusionProof> értéket ad vissza, amely a teljes §16.9 struktúrát (levél, auditút, lehorgonyzott gyökér és AnchorRef) ugyanazon átlátszatlan CBOR-mezőn keresztül hordozza — csomagformátum-verzió emelése nélkül. Az önálló qub-verify CLI a --anchor ágon fogyasztja; amíg a horgonypénztárca nincs kiépítve (§16, Állapot), a jelen lévő, de helykitöltő tulajdonosú bizonyítékot csak befoglalásiként, nem teljesen horgonyellenőrzöttként jelenti.