qub protokollspecifikáció
A qub egy protokoll kriptográfiai időbeli kötelezettségvállalásokhoz: olyan rendszer, amely szavakat zár le egy jövőbeli dátumhoz, és amikor ez a dátum elérkezik, bizonyítja, hogy pontosan mit mondtak és mikor.
Három alapelem teszi mindezt lehetővé. A drand egy decentralizált véletlenszerűségi jeladó — a felfedési dátumot a fizika érvényesíti, nem pedig bármely fél jóindulata. Az állandó nyilvános tárhely egy hamisíthatatlan nyilvános tár — egyetlen fél sem tudja szerkeszteni vagy törölni a qubot, miután lezárták. Az ML-DSA-65 egy posztkvantum digitális aláírás — minden qub egy kulcspárhoz kötődik, amelynek titkos kulcsa soha nem hagyja el a szerző eszközét.
Együttesen ezek az alapelemek olyan kijelentést hoznak létre, amely időzárolt, hamisítás-érzékeny és tulajdonítható — egy nyugta, 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 |
|---|---|
| Verzió | 1.0 (protokollverzió 0x01, külső burkoló verziója 0x01) |
| Dátum | 2026-05-01 |
| Állapot | Tervezet |
| Átnézve eddig | 2026-05-01 |
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, // 0x01 = public (only value in MVP)
content_type: u8, // 0x01 = text (only value in MVP)
plaintext: Vec<u8>, // UTF-8 qub body
sender_label: Option<String>, // Decorative display name; not authenticated
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>, // V1.1 — when reality renders judgment (verdict-uplift-plan §3.1)
sender_label: Option<String>, // Decorative; not authenticated in MVP
reply_to: Option<[u8; 32]>,// Parent qub_id for reply chains; not in qub_id preimage; not signed (see §9.3)
body: Vec<u8>, // Content payload (UTF-8 for text, CBOR for pact)
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, minden Option mező hiányzik.
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). Állandó tárhelyre írva. Ez a láncon lévő műtermék.
SealedQub {
version: u8, // Protocol major version (0x01 for v1)
qub_id: [u8; 32], // Same as QubEnvelope.qub_id
visibility: u8, // 0x01 = public; v1 viewers reject other values
unlock_at: i64, // Unix seconds UTC
outcome_at: Option<i64>, // V1.1 — 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
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 control characters.
}
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,
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 (V1.1 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 (V1.1 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)
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: a V1.1 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: A V1.2 a preimage-et 100 bájtról 108 bájtra bővítette, 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 QubEnvelope bármely mezőjének (törzs, időbélyegek, tartalomtípus, verzió) 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_id nem függ a
sender_label,author_signaturevagyauthor_pubkeymezőktől. Ez azt jelenti, hogy ugyanaz a tartalom ugyanabban az időpontban lezárva ugyanazt a qub_id-t eredményezi, függetlenül attól, ki írja alá. - 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 = ceil((unlock_at - chain_genesis_time) / chain_period_seconds)
| 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 |
A ceil() művelet az első olyan drand-kört választja ki, amelynek felfedési ideje ≥ unlock_at. Ez biztosítja, hogy a qub ne váljon visszafejthetővé a választott feloldási idő előtt.
Szélső eset: ha az (unlock_at - chain_genesis_time) pontosan osztható a chain_period_seconds értékkel, az eredmény pontosan az a kör — a qub pontosan az adott kör felfedési idejében oldódik fel.
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() |
Állandó tárhelyre feltöltés, megjelenítő lekérés |
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. |
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), value: String (≤ 2,000) } // NFC on both sides
PartyIdentifier{ label: String (≤ 100), contact: Option<String (≤ 320)> }
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.
3. Compute body_hash = SHA3-256(body).
4. Set created_at = current Unix seconds UTC.
5. Válaszd ki a drand láncot. Töltsd be a chain_genesis_time és chain_period_seconds
értékeket, és számítsd ki: drand_round = ceil((unlock_at - chain_genesis_time) / chain_period_seconds).
(Itt számoljuk ki, a qub_id előtt, mert a drand_round be van kötve a qub_id
preimage-be — §4.1, V1.2.)
6. Számítsd ki a qub_id-t (lásd §4.1), bekötve az 5. lépés drand_round értékét.
7. Hozd létre a QubEnvelope-ot minden mezővel.
8. Szerializáld a QubEnvelope-ot kanonikus CBOR-ral → B bájtok.
Ellenőrzés: a szerializált kimenet megfelel a kanonikus profilnak (§3).
9. Számítsd ki: C = tlock_encrypt(B, drand_round, drand_chain_public_key).
10. Hozd létre a SealedQub-ot tlock_ciphertext = C értékkel, és egyező qub_id, version,
unlock_at, drand_chain_id, drand_round mezőkkel.
12. Serialise SealedQub using canonical CBOR → SealedQubCbor.
12a. Generate K = 32 random bytes (CSPRNG) and N = 12 random bytes (CSPRNG).
Compute W = wrap_sealed_qub(SealedQubCbor, qub_id=qub_id, key=K, nonce=N)
per §13. The bytes uploaded to permanent storage are the OuterWrapper CBOR W,
never the bare SealedQubCbor. K leaves the device only as the URL
fragment in step 16.
13. Display seal-time disclosure. User confirms.
14. Validate upload eligibility via the qub upload service (bot-detection, entitlement, rate limits).
15. Submit W (the OuterWrapper bytes) to the qub upload service; the service
signs and uploads to permanent storage. The service is byte-blind to the inner
SealedQubCbor and never receives K.
16. Receive arweave_tx_id from the service. Construct delivery URL as
`<origin>/c/<arweave_tx_id>#<base64url(K)>` (or `<origin>/s/<short_code>#<base64url(K)>`
when a short code is allocated). Browsers do not transmit URL fragments
to servers, so K is never 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 becsomagolt 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 validált összeállítási szándék — pl. quote, reply, commitment), 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. A külső burkoló (§13) védi a belső törzset a rejtjelezett szöveg korrelációjától — megakadályozva, hogy egy gyűjtő felismerje és tömegesen visszafejtse a qub formájú feltöltéseket, miután a drand-körük közzétételre kerül.
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 path AND
K = base64url_decode(fragment) from the URL fragment. If the fragment
is absent or malformed → display "this URL is missing its decryption
key" and stop; the viewer MUST NOT contact the storage gateway
without K, since fetching wrapped bytes the viewer cannot decrypt
serves no purpose and only leaks the access attempt.
2. Check denylist. If tx_id is denylisted → display block message. Stop.
3. Fetch OuterWrapper bytes from permanent storage (with multi-gateway fallback).
3a. Unwrap: parse the bytes as OuterWrapper (§13), verify the wrapper
`version` byte is `0x01`, and compute SealedQubCbor =
unwrap_sealed_qub(OuterWrapper, key=K). Any AEAD authentication
failure (wrong K, tampered ciphertext, swapped qub_id-as-AAD,
swapped nonce) → display "this URL's decryption key does not match
the stored qub" and stop. Authentication failures are
indistinguishable to the viewer per §13.5.
4. Parse SealedQubCbor → SealedQub.
5. Validate: SealedQub.version is known (0x01). Reject unknown versions.
6. If current time < SealedQub.unlock_at → display countdown. Poll or wait.
6a. Körkötés-ellenőrzés (V1.2). Számold újra az expected_round =
ceil((SealedQub.unlock_at - chain_genesis_time) / chain_period_seconds) értéket.
Utasítsd el, kivéve ha SealedQub.drand_round == expected_round ÉS a tlock titkosított
szöveg szakaszába (stanza) sütött kör (az age/tlock fejlécből beolvasva, aláírás nélkül)
== expected_round. A szakasz köre az, amely ténylegesen kapuzza a visszafejtést; ezen
ellenőrzés nélkül egy rosszindulatú szerző egy már elmúlt körhöz köthetné a titkosított
szöveget, miközben jövőbeli visszaszámlálást jelenít meg, így bárki, aki beolvassa a
tárolt bájtokat, az unlock_at előtt visszafejthetné. A láncidentitás nélküli
implementációk (tesztmockok) kihagyják ezt az ellenőrzést.
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.
13. Verify: QubEnvelope.content_type is known and renderable.
Known values: 0x01 (text), 0x03 (pact). 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 appropriate renderer (see §10 for text, §6 for pact).
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 |
|---|---|---|---|
0x00 |
Nincs aláírás (aláíratlan) | — | — |
0x01 |
ML-DSA-65 (FIPS 204) | 1 952 bájt | 3 309 bájt |
A megjelenítőknek el KELL utasítaniuk az ismeretlen sig_alg értékeket.
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 |
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 ellenőrizhet egy nyilvános qubot a qub együttműködése nélkül. Az ellenőrzési eljárás:
1. Obtain arweave_tx_id (from delivery URL or direct knowledge).
2. Fetch SealedQubCbor from any storage gateway.
3. Confirm storage block inclusion (block height, block timestamp).
4. Parse SealedQubCbor → SealedQub.
5. Fetch drand round signature for SealedQub.drand_round.
6. tlock_decrypt(tlock_ciphertext, round_signature) → QubEnvelope CBOR bytes.
7. Parse → QubEnvelope.
8. Verify SHA3-256(body) == body_hash.
9. Verify QubEnvelope.qub_id == SealedQub.qub_id.
10. Verify QubEnvelope.unlock_at == SealedQub.unlock_at.
11. If sig_alg != 0x00: verify author_signature (see §9.4).
12. All checks pass → qub is verified.
Mit bizonyít az ellenőrzés:
| Bizonyíték | Mit állapít meg |
|---|---|
| Kötelezettségvállalás | A rejtjelezett szöveg létezett a tárolási blokk időbélyege idején. |
| Integritás | Az egyszerű szöveges törzs megegyezik a vállalt kivonattal, és nem módosították. |
| Időzítés | A tartalom olvashatatlan volt a drand-körig, amely megfelel a választott feloldási időnek (a tlock és a drand biztonsági feltételezéseitől függően). |
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 qub a tartalmat és az időzítést bizonyítja, nem azt, amit az alkotó szubjektíven gondolt. |
| Esemény előtti időzítés | A tárolási blokkba kerülés perceket késhet a tényleges feltöltéshez képest. A kötelezettségvállalás időbélyege a blokk ideje, nem az a pillanat, amikor a felhasználó megnyomta a „lezárás”-t. |
12. Verziókezelés
12.1 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.2 Verziótörténet
| Verzió | Érték | Leírás |
|---|---|---|
| v1 | 0x01 |
Nyilvános szöveges qubok (content_type 0x01), paktum kétoldalú megállapodások (0x03, structured/v1 séma, ML-DSA-65 szerző + társaláíró), tlock, SHA3-256 |
12.3 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.4 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 |
v1 alapértelmezett |
| — | 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.
A külső titkosító burkoló bezárja ezt a csatornát azáltal, hogy egy további szimmetrikus AEAD-réteget iktat be a kanonikus SealedQubCbor és az állandó tárhelyre írt bájtok közé. A 256 bites K kulcs kizárólag a kézbesítési URL fragmentjében és a felhasználói eszközökön él; a böngészők nem továbbítják az URL-fragmenteket a szervereknek, így a qub.social, minden tárolási átjáró és minden CDN bármelyikük előtt megfigyelhetően vak a K-ra. Az állandó tárhelyen lévő minden qub tehát átlátszatlan rejtjelezett szöveg, amelynek egyszerű szövege visszanyerhetetlen az alkotó által megosztani választott URL nélkül.
Nettó hatás:
- Felsorolás-immunitás alapértelmezetten. Az állandó tárhelyen lévő becsomagolt bájtok bájtszinten megkülönböztethetetlenek a tetszőleges rejtjelezett szövegtől. Egy „GraphQL-lekérdezés qub formájú feltöltésekre, tömeges visszafejtés nyilvános drand-aláírásokkal” gyűjtőstratégia nem végződik egyszerű szöveggel.
- Kripto-aprítási adatvédelmi tartás. A qub.social szó szerint nem tudja visszafejteni a saját korpuszát. Az idézések rejtjelezett szöveget érnek el, nem egyszerű szöveget.
- 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
↓ AES-256-GCM(K, nonce, AAD=qub_id) (§7 step 12a, this section)
OuterWrapper CBOR bytes ← uploaded to permanent storage (§7 step 15)
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.4
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 kicsomagolási lépés ezt nem érvényesíti közvetlenül (az AEAD AAD-kötés lehetetlenné teszi a bájtszintű hamisítást), de a feloldási réteg tranzitíven ellenőrzi a kapcsolatot: ha egy alkotó olyanSealedQubCbor-t csomagol be, amelynek belsőqub_id-ja nem egyezik a burkolóqub_id-jával, a §8 11. lépése meghiúsul. - 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 állandó tárhelyű bájtjaival | AAD-eltérés → 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
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.4
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
return P // P is the inner 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ímzettnek titkosított privát qubok (fenntartott 2. fázisú funkció, még nincs specifikálva) e burkoló tetejére komponálódnak második bizalmassági szintként; mindkét szint egyidejűleg aktív lehet.
- A paktumok (§6, content_type
0x03) pontosan úgy csomagolódnak be, mint a szöveges qubok; a burkoló bájtvak a belső tartalomtípusra.
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 kerül az állandó tárhelyre, OuterWrapper réteg és K kulcs nélkül:
SealedQubCbor bytes ──(public)──▶ uploaded to permanent storage as-is
SealedQubCbor bytes ──(private)─▶ AES-256-GCM(K, …) ▶ OuterWrapper ▶ uploaded
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, akinek megvan az arweave_tx_id, vissza tudja fejteni — nincs szükség URL-fragmentre, mert nincs K. Ez a szándékos kompromisszum azokhoz a felületekhez, amelyeket a szervernek kell mozgatnia: a felfedés-értesítő e-mailek, a harmadik féltől származó beágyazások és a gazdagabb felfedés-utáni SEO mind olyan hivatkozást igényel, amely olyan titok nélkül működik, amelyet a szerver soha nem tart a kezében (§13.6).
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. Egy megfelelő megjelenítő/beágyazás elemzéssel különbözteti meg a két 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. Nincs szükség wire-jelzőre, és aqub_idnem köti a láthatóságot — ugyanaz a tartalom aSealedQubrétegen bájtazonos, akár nyilvánosan, akár privátként lett lepecsételve.
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 = 4695445 (= (1736294400 - 1595431050) / 30, 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 — V1.2):
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)
0x000000000047A595 || // drand_round as u64 big-endian (4695445)
body_hash || // 32 bytes
title_hash // 32 bytes (all-zeros sentinel; title absent)
Expected output:
qub_id = SHA3-256(preimage)
= 3a9fcb31b750d985c262fada6d4f777f
d6a28be831d941d85c131f5a4bbaf8a4
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-implementáció számította ki, és bitről bitre egyezniük KELL. Korábbi preimage-elrendezések (indulás előtt — egyetlen élő qub sem függött ezektől): a 92 bájtos V1.0 qub_id 3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0 volt; a 100 bájtos V1.1 qub_id (az outcome_at_or_zero bekötése után) b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed volt. A V1.2 bevonja a drand_round mezőt, és a tartományelválasztót QUB_ID_V2-re emeli.
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
ceil(4675285.0) = 4675285
drand_round = 4675285
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 esetet rögzít:
| Eset | Lefedettség |
|---|---|
basic-text-public |
A legkisebb realisztikus SealedQub alak; opcionális mezők nélkül. Megállapítja a kanonikus burkoló-alakot egy v1.0-tipikus qubhoz. |
with-recipient-pubkey |
SealedQub beállított recipient_pubkey-vel (2. fázis útvonal). Eltérő belső CBOR-kulcskészlet, eltérő qub_id. |
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 §9.2 nyilvántartás nem határoz meg más értékeket; egy v1-ellenőrzőnek el KELL utasítania minden{0x00, 0x01}halmazon kívülisig_algértéket. Egy jövőbeli Ed25519 bejegyzés várható (§15.3), de v1-ben nincs lefoglalva. - 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 a kulcs- és aláíráshosszakat alapelemenként. A wire-formátum nem tár fel agilitási felületet.
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ó.
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 (tervezet — a felülvizsgálat lezárult)
Állapot. Ez a szakasz tervezési specifikáció. Az alábbi wire-formátumok, kivonatolás és bizalmi modell normatívak a megvalósításra nézve, de még semmilyen átláthatósági-napló kód nem került élesítésre. A W5 külső felülvizsgálat lezárult: a §16.15 rögzíti a feloldott döntéseket és az ezekből származó kötelező indítási korlátokat. A megvalósítás megkezdődhet ezen korlátok mellett. A §16 ugyanabban az értelemben marad előretekintő, mint a §15 — rögzíti a célt, hogy a megvalósítás egy letisztult tervhez illeszkedjen, ahelyett, hogy a bizalmi modellt a kódfelülvizsgálat során újra levezetné. Szigorúan kiegészítő jellegű — minden meglévő qub megtartja egyéni állandó tárhelyű tranzakcióját, és nincs változás a
SealedQub/QubEnvelopewire-formátumban.
16.1 Indoklás és tartóssági szintek
Ma egy qub tartóssága és időbeli kötelezettségvállalása egyaránt egyetlen qubonkénti állandó tárhelyű tranzakción nyugszik (§11). Ez a lezárás késleltetését az állandó tárhely véglegességéhez köti, a qubonkénti feltöltést termékköltség-felső korláttá teszi (ARWEAVE_DAILY_CEILING), és nem ad módosításfelismerő sorrendezést a qubok között. Az átláthatósági napló két réteget ad e mögé és e köré az egyetlen szint köré:
| Szint | Név | Garancia | Mikor |
|---|---|---|---|
| T1 | R2-elsődleges szinkron nyugta | Tartóssági alsó határ — a lezárt bájtok tartós tárolóba kerülnek, mielőtt a lezárás visszatér (< 300 ms p95). |
Minden qub, szinkron módon (§16.10). |
| T2 | Kötegelt átláthatósági-napló befoglalás | Univerzális, csak hozzáfűzhető, módosításfelismerő kötelezettségvállalás + teljes sorrendezés, állandó tárhelyhez horgonyozva. | Minden qub, késleltetve + kötegelve (§16.5–16.7). |
| T3 | Qubonkénti állandó tárhelyű maradandóság | Egy egyéni állandó tárhelyű tranzakció a qubhoz. | Fizetős kiegészítés, és az állandó tárhely elérhetetlenségére adott tartalék (§16.8). |
A T2 a qubonkénti állandó tárhelyet választássá (T3) teszi, nem az egyetlen tartóssági úttá. Az ARWEAVE_DAILY_CEILING mint termék-felső korlát kivezetésre kerül, és kizárólag a dedikált horgony-tárcán működő áramkör-megszakítóvá fokozódik le (§16.7); a felhasználói lezárások soha nem kerülnek elutasításra annak túllépése miatt.
Tartóssági őszinteség (feloldva — §16.15 Q6). A tartósság nem romlik: a T1 R2-írás szinkron és egyszer-írható, így egy ingyenes szintű qub, amely nem vásárolt T3-at, teljesen tartós abban a pillanatban, amikor a lezárás visszatér. Ami durvábbá válik, az a bizonyítható felső korlátú kötelezettségvállalási idő: egy ingyenes qub esetében ez a horgony blokkidejévé válik, nem egy qubonkénti tranzakció blokkidejévé. Alacsony forgalom mellett — a realisztikus korai indítási és csúcson kívüli állapot — a teljes napi ütem a tipikus alsó határ, nem ritka szélső eset. A termék-keretezés ezért egy felső korlát vállalt számszerű késleltetés nélkül — „most lepecsételve és tartós; egy független nyilvános időbélyeg a következő naplóhorgonynál kerül hozzáadásra (tipikusan naponta)” — és a pontos órányi kötelezettségvállalás-bizonyíték fizetős T3 tulajdonság, amely a szint-összehasonlító felületen és a feltételekben kerül feltárásra (§16.11, §16.15 Q6). Bármely időkorlát kizárólag belső SLO, soha nem marketingelt SLA.
16.2 LogLeaf-struktúra (két vállalt alak)
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ú, címkék nélkül, lebegőpontos számok nélkül, legrövidebb alakú egészek, NFC-szöveg, a hiányzó opcionális mezők kihagyva, a kulcsok a kódolt bájthossz szerint növekvő, majd bájtonkénti sorrendben). A §3.1 parse → re-encode → compare kanonikus őr a kódolási úton, a kivonatolás előtt kerül alkalmazásra (nem csak dekódoláskor), így két megvalósítás nem térhet el a levél bájtjaiban egy egészszélesség- vagy kulcssorrend-különbség révén. Minden egész u8 / u64 / i64; minden kivonat 32 bájtos bájtfüzér (bstr[32]). Egy tárolt állandó tárhelyű tranzakció-azonosító egy nyers 32 bájtos SHA-256 kivonat, amelyet bstr[32]-ként hordoz, soha nem base64url szöveges füzérként (megfelel a §3.3-nak).
A levélnek két alakja van, amelyet egy kind bájt választ ki, mert az alapértelmezett feltöltési úton a Worker bájtvak: a POST /api/v1/upload csak a qub_id-t és az unlock_at-ot kapja meg nem megbízható kliensállításokként — a body_hash, drand_round, created_at és drand_chain_version mind a §13 külső burkolóba van lezárva, amelynek kulcsát a Worker soha nem tartja. Csak a szerver-lezárási út (POST /api/v1/seal) vezeti le a body_hash / drand_round értékeket az egyszerű szövegből. Egyetlen, body_hash + drand_round hordozó levélalak ezért olyan értékeket vállalna, amelyeket az üzemeltető a valódi qubok többségénél soha nem ellenőrzött. A felosztás minden vállalt értéket őszintén tart:
| Kulcs | Kód. hossz | Típus | Jelenlét | Jelentés |
|---|---|---|---|---|
seq |
4 | u64 |
kötelező | Globális, 0-alapú levélindex; az a pozíció, amelyhez a befoglalási bizonyíték kötelezi magát. |
kind |
5 | u8 |
kötelező | 0x01 tanúsított (szerver-lezárás) vagy 0x02 állított (kliens-lezárás / bájtvak feltöltés). |
ref |
4 | bstr[32] |
kötelező | Levélhivatkozási azonosító. Tanúsított → nyers qub_id. Állított → a vakított azonosító SHA3-256(qub_id ‖ log_blind_secret) (§16.2.1). |
chash |
6 | bstr[32] |
kötelező | Tartalomcím SHA3-256(stored_bytes) — az egyetlen tartalmi kötés, amelyet a Worker mindig őszintén ki tud számolni, mindkét úton. |
unlock_at |
10 | i64 |
kötelező | Másolva (tanúsított) vagy állítva (állított); > 0 ellenőrzéssel, mielőtt belép a levélbe. |
received_at |
12 | i64 |
kötelező | A Worker faliórája az R2-nyugtánál. Nem bizonyítóerejű (üzemeltető által állított; §16.6). Önleírásként jelen van, soha nem bizonyíték. > 0 ellenőrzéssel. |
body_hash |
10 | bstr[32] |
csak kind=0x01 |
A 0x02-n kihagyva — a Worker nem rendelkezik vele a §13 szerint. |
drand_round |
12 | u64 |
csak kind=0x01 |
A 0x02-n kihagyva. |
Egy kind=0x02 levél szándékosan sem body_hash-t, sem drand_round-ot nem vállal: egy átlátszatlan rejtjelezett szöveg kötelezettségvállalását és sorrendezését tanúsítja a chash tartalomcímen, qub_id-t és unlock_at-ot állítva — nem az egyszerű szövegét vagy körét. Egy állított qub egyszerűszöveg/kör lábai a meglévő §11 .qub-csomag ellenőrzéséből származnak, nem a naplóból (§16.11). A drand_chain_version nincs a levélben (az alapértelmezett úton a burkolóban van); a lánc-granularitás a horgonyon él (§16.7). Kódolói fegyelem: utasíts el egy csupa nulla ref-et vagy chash-t, és utasítsd el a nem pozitív unlock_at / received_at értéket, tükrözve a cbor.rs-ben lévő outcome_at > 0 őrjelet.
16.2.1 Privát-qub vakítás
A napló nem válhat azzá a felsorolási orákulummá, amelynek megelőzésére a §13 külső burkoló létezik (§13.1). Egy privát (becsomagolt) qub esetében az állított levél a vakított azonosítót SHA3-256(qub_id ‖ log_blind_secret) vállalja, ahol a log_blind_secret egy szerver által tartott titok, és kihagyja a body_hash-t. Egy harmadik fél nem tud ilyen levelet egy konkrét qub_id-hoz kötni; a qub birtokosa, akinek megvan a kézbesítési URL-je és így a qub_id-ja, újra ki tudja számolni a vakítást saját befoglalásának megerősítésére. Egy nyilvános qub (amely már felsorolható, és már hordozza a Visibility: public állandó tárhely-címkét a §13.8 szerint) a nyers qub_id-t vállalja. Ez az egyetlen hely, ahol az önálló ellenőrizhetőség szándékosan enged egy teherviselő adatvédelmi invariánsnak; a privát qubok önálló kötése a chash (§16.9).
A log_blind_secret őrzése (feloldva — §16.15 Q4). A vakítás a levél-összekapcsolhatatlanságot védi, nem az egyszerűszöveg-bizalmasságot (azt a §13 burkoló önállóan tartja). Egy log_blind_secret kompromittálódásakor minden olyan qub_id-ra, amelyet a támadó már birtokol vagy rekonstruálni tud (minden qub, amelynek csomagjával/URL-jével rendelkezik, plusz bármely alacsony entrópiájú vagy nyilvános qub_id), egyetlen kivonatban újraszámítja a levél ref-jét és összekapcsolja — ez egy ismert populáció közvetlen összekapcsolása, nem egy ismeretlen téren végzett nyers erő. Sorold a log_blind_secret-et korreláció/Sybil-szintű titokká, ugyanabba az őrzési szintbe, mint a többi szervertitkot, és csak előrefelé forgasd (egy forgatás újravakítja a jövőbeli leveleket; nem tudja visszamenőlegesen szétkapcsolni a már lehorgonyzottakat).
16.3 Levél- és csomópont-kivonatolás
RFC 6962 §2.1 tartomány-elválasztott kivonatolás, az SHA-256-ot SHA3-256-ra cserélve:
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 (bejegyzéslánc, §16.4) és a 0x03 (STH-kivonat, §16.6) tartomány-előtagbájtok fenntartottak és diszjunktak ezektől. Egyetlen bájtok, így nem ütközhetnek a meglévő 10 bájtos ASCII tartomány-elválasztókkal (QUB_ID_V2 stb.). A fa az RFC 6962 balra-teli kiegyensúlyozatlan fája (minden belső felosztás a részfa levélszámánál szigorúan kisebb legnagyobb kettőhatványnál történik), ami lehetővé teszi, hogy a befoglalási és a konzisztencia-bizonyítékok egyetlen audit-út algoritmuson osztozzanak. A referenciaspecifikáció explicit bal/jobb levezetési pszeudokódot hordoz, és rögzít egy nem kettőhatvány (5 levelű) tesztvektort, így a jobboldali-él előléptetési eset — amelyet egy 4 levelű vektor elrejt — gyakorlásra kerül.
16.4 Kivonatláncolás (belső)
A LogDO egy belső bejegyzésláncot tart fenn kizárólag összeomlás-konzisztencia céljából. Ez soha nem kerül közzétételre, és soha nem ellenőrző-felé fordul:
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 hozzáfűzhető tekintély a kumulatív Merkle-gyökér + horgonya (§16.5–16.6), soha nem az a nyers sorrend, amelyben az üzemeltető éppen kiszolgálja a leveleket: a lánc bármely kiszolgált sorrendre újraszámítható, így csak a lehorgonyzott gyökér rögzíti a kanonikus pozíciót.
16.5 Kumulatív Merkle-fa és kötegelés
Egyetlen, folyamatosan növekvő RFC 6962 fa van az összes levél felett seq sorrendben — nem elszigetelt kötegenkénti fák. (Egy átviteli-levél-láncolt kötegenkénti konstrukció elutasításra került: ez nem valódi prefix-reláció, így „konzisztencia-bizonyítékai” megalapozatlanok.) A kumulatív fa valódi RFC 9162 konzisztencia-bizonyítékokat ad, és lehetővé teszi, hogy egyetlen friss horgony bizonyítsa bármely régebbi qub befoglalását.
A LogDO Durable Object az egyetlen író (blockConcurrencyWhile, a QuotaDO / EntitlementDO mintáját tükrözve) — egy megosztott naplóhoz való hozzáfűzés olvasás-módosítás-írás megosztott állapoton, így DO-n KELL áthaladnia, soha nem KV-n. Gyorsítótárazza a fa jobboldali-éli határvonalát (O(log n) kivonat), így egy köteg lezárása O(batch). Egy köteg az együtt lehorgonyzott levelek halmaza; kiváltói konfigurálhatók, nem protokoll-rögzítettek: legalább LOG_BATCH_MAX_LEAVES (alapértelmezetten 4096) tree_size-előrelépés, vagy a horgonyütemet elérő életkor, vagy egy kényszerített kiürítés, amikor egy fizetős T3-lezárás megérkezik. A root_i a kumulatív Merkle-fa-kivonat a 0 .. tree_size_i levelek felett.
16.6 Aláírt fafej állandó tárhelyű horgonyon keresztül
Az állandó tárhelyű horgony-tranzakció az aláírt fafej, és felváltja az üzemeltetői aláírást magára a fafejre nézve: a napi horgonynak nincs szüksége qub-kulcsra, mert az állandó tárhely tranzakciójának owner-je az aláírás. A védőárok-tézis tartja magát — az állandó hordozó, nem egy qub által tartott titok teherviselő a lehorgonyzott gyökérhez.
A tervben pontosan egy meleg qub-aláírókulcs van, és ez rögzített: a lezárásonkénti nyugtakulcs (§16.10). Nyilvános kulcsa a LogProfile-ban van vállalva (az ellenőrzővel együtt terjesztve) és az anchor_owner által keresztaláírva, így egy ellenőrző egy nyugtát ugyanahhoz a rögzített gyökérhez validál, mint a horgonyt. Ez a §16.15 Q2 feloldása — egy nem rögzített, üzemeltető által forgatható nyugtakulcs letagadható lenne (az üzemeltető tagadhatná, hogy a kulcs az övé volt), ami semmissé tenné a nyugta elszámoltathatósági értékét azzal az üzemeltető-szintű ellenféllel szemben, akinek elrettentésére a nyugta létezik. Tehát: a qub nem tart nem rögzített napló-aláírókulcsot; a nyugtakulcs rögzített és anchor_owner-keresztaláírt.
A SignedTreeHead kanonikus CBOR (a kulcsok kódolt hossz szerint): size:u64, root:bstr[32], batch:u64, prev:bstr[32] (korábbi sth_hash; genesis = 32 nullabájt), log_id:bstr[32], first_seq:u64, anchored_at:i64. Kivonata sth_hash = SHA3-256(0x03 || canonical_cbor(SignedTreeHead)).
Rögzített bizalmi gyökér. log_id = SHA3-256("QUB_TLOG_V1" || anchor_owner_address). Egy megfelelő ellenőrzőnek meg KELL követelnie, hogy anchor_tx.owner == LogProfile.anchor_owner, ahol az anchor_owner (és a nyugtakulcs nyilvános kulcsa) a qub_core-ba van beépítve LogProfile-ként — a DrandTimelockProvider::quicknet()-ben már szereplő quicknet-konstansok mellett — és az ellenőrző bináris fájllal együtt terjesztve. Az ellenőrzőnek helyileg is ellenőriznie KELL az állandó tárhely tranzakciójának adat → tx_id kötését, ahelyett, hogy megbízna egy átjáró /raw/ válaszában. Ez bezárja a gazember-tárca egyenlőtlenségi rését: az „állandó tárhelyhez horgonyozva” értelmetlen, amíg az ellenőrző nem rögzíti, melyik tárca.
A forgatás egy §15 kormányzási kiterjesztés, nem újrafelhasználás (feloldva — §16.15 Q3). A §15.2 profilfelülete jelenleg csak sig_alg-eket / drand-láncokat / burkoló-verziókat / tartalomtípusokat sorol fel, és a §15.3 kiváltói ezekből egyet sem listáznak — a LogProfile / anchor_owner még nincs a §15 felületén. A forgatási kormányzást ezért fel kell építeni: a §15.3 kiterjesztésre kerül (lent) a LogProfile kiváltóval, és egy forgatás egy aláírt LogProfile-emelés, amely egy ellenőrző-frissítésben szállítódik. Egy tervezett forgatás kimenő → bejövő keresztaláírást hordoz; egy kompromittálódás-vezérelt forgatás nem tud (a kimenő kulcs pontosan akkor nem megbízható/elérhetetlen), és a §15-kormányzott emelésre esik vissza, ahol a korábbi-horgony elágazás-ellenőrzés (lent) korlátozza a kárt a közbenső időszakban.
Egyenlőtlenségi ablak (elsőosztályú bizalmi paraméter). Egy levél csak akkor egyenlőtlenség-ellenálló, ha a lefedő horgonya állandó tárhelyen megerősített. Az ablak received_at → horgony-megerősítés (≤ ütem + állandó tárhely véglegessége). Ezen belül az egyetlen garancia a rögzített lezárási nyugta (§16.10) és a qub működési integritása. Három elszámoltathatósági műtermék teszi ezt őszintévé, nem pedig elsuhanttá (a tanúmodell a §16.15 Q2 feloldása):
- Rögzített, aláírt lezárási nyugta — az SCT-analóg, amely a feltöltési válaszban (§16.10) kerül visszaadásra, a rögzített,
anchor_owner-keresztaláírt nyugtakulccsal aláírva. Egy a horgonya előtt eldobott levél nem letagadható nyugtát hagy az áldozatnak a közzétételhez, bezárva a néma-kihagyási rést. - Közzétett megfigyelési módszertan + korábbi-lánc bejárás — a horgony
prevlánca fej→genesis bejárásra kerül; egy elágazás (két horgony egysize-nál különbözőroot-tal, vagy egy töröttprev) közzétehető bizonyíték a helytelen viselkedésre. Az egyenlőtlenség-felismerés kimondott működési kötelezettségvállalás, nem néma feltételezés. - Kettős önközzétett fejek — minden új fej
{sth_hash, tree_size}egy dedikált, qub-tulajdonú nyilvános, csak hozzáfűzhető GitHub-tárházba kerül kiküldésre (a teherviselő, módosításfelismerő önközzétételi láb), egy közösségi bejegyzéssel mint csak legjobb-szándékú megerősítés. Egy sikertelen kiküldésnek riasztania KELL (nem némán meghiúsulnia).
Őszinteségi korlát (kötelező korlát). Mivel a qub mindkét kiküldési felületet vezérli, ez önközzétett, nem függetlenül tanúsított. Semmilyen termék-, marketing- vagy jogi felület nem állíthatja, hogy a napló „függetlenül tanúsított”; a megengedett állítás az, hogy az egyenlőtlenség felismerhető és nem letagadható nyugtát hagy. Egy valódi, független, harmadik fél általi tanú egy jövőbeli §15 kormányzási emelésre van halasztva.
A received_at üzemeltető által állított, és semmilyen állítás nem támaszkodhat rá — soha nem jelenik meg bizonyítékként vagy vita-megerősítésként semmilyen termék- / jogi- / API- / bizonyíték-megjelenítési felületen. Az állandó tárhely horgony-blokkidő T az egyetlen megbízhatóságmentes időbélyeg (egy felső korlát arra, hogy „mikor naplózva”). Bármely megfigyelői épelméjűségi ellenőrzésnek a received_at-on T-vel KELL összevetnie, nem az üzemeltető által vezérelt anchored_at STH-mezővel; egy ilyen ellenőrzés kizárólag egy őszinte üzemeltető órahibája elleni őr, nem elszámoltathatósági kontroll egy rosszhiszemű üzemeltetővel szemben (§16.15 Q5).
16.7 Horgony-tranzakció formátuma és üteme
Az AnchorBundle a kanonikus-CBOR állandó tárhely tranzakció-törzse, amely a §16.8 kötegelőn keresztül íródik: ver:u8, sth:bstr (kanonikus SignedTreeHead-bájtok), prev_anchor:bstr (korábbi horgony-tranzakció azonosítójának nyers bájtjai; a genesisnél kihagyva), chain_hash:tstr (az érvényben lévő drand-lánc — quicknet), és a köteg levél-CBOR-folyama seq sorrendben, így a horgony önálló: egy megfigyelő nulla qub-függőséggel újra levezeti a root-ot a törzsből. (Ha a levélfolyam nagyra nő nagy forgalom mellett, egy jövőbeli revízió hivatkozással csak egy levéltartományt vállalhat; megjegyezve, nem elfogadva v1-ben.)
Az állandó tárhely címkéi szándékosan felsorolhatók — a naplót meg kell találni, a privát qubokkal ellentétben: 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 nem megbízható tippek; a CBOR-törzs az egyetlen tekintély.
Ütem: alapértelmezetten napi, a forgalommal újragondolva (a méret-kiváltó terhelés alatt automatikusan lerövidíti a tényleges ütemet); egy fizetős T3-lezárás kikényszerít egy horgonyt, így a fizető ügyfelek soha nem várnak egy napot. A horgony-tárca dedikált és kis sebességű, elkülönülve a feltöltési tárcától — saját JWK-jának KELL lennie (egy különálló kulcs, nem egy logikai szerepkör a feltöltési tárcán), így egy feltöltési-tárca kompromittálódása nem tud horgonyokat hamisítani — egy kemény, napi horgony-tranzakció költségkerettel (a lefokozott ARWEAVE_DAILY_CEILING). Az őrzési hozzáállás kerek perec ki van mondva: egy szűk hatókörű meleg kulcs szoros áramkör-megszakítóval és alacsony egyenleggel, nem „hideg” — egy tárca, amely naponta automatikusan aláír, nem lehet hideg, és a specifikáció nem is tesz úgy, mintha az lenne.
16.8 ANS-104 kötegelő
Egy házon belüli ANS-104 DataItem-kódoló és deep-hash-aláíró, nagyjából 300 sor, csak Web Crypto, nulla npm-függőség (mindkét Turbo SDK megbukik az npm ci --ignore-scripts ellátási-lánc kapun). A DataItem bájtelrendezése:
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 az állandó tárhely deepHash-e — egy rekurzív SHA-384 kivonat (az állandó tárhely wire-követelménye, crypto.subtle.digest("SHA-384")) a ["dataitem", "1", sig_type, owner, target, anchor, encoded_tags, data] felett — majd RSA-PSS a deep hash felett a tárca JWK-jával a crypto.subtle-n keresztül; id = base64url(SHA-256(signature)). Az itteni SHA-384 karanténba van zárva mint kizárólag állandó-tárhely-wire alapelem, soha nem qub-bizalmi alapelem (a §15 rögzíti a kerítést; a qub bizalmi kivonatolása végig SHA3-256).
Egyetlen kódút három fogyasztót szolgál ki: a fizetős T3 qubonkénti maradandóságot, az állandó tárhely elérhetetlenségére adott tartalékot (sorold be a DataItemet, add vissza az R2-elsődleges nyugtát mindenképp — ez bezárja a jelenlegi ARWEAVE_UNAVAILABLE 503 zsákutcát), és az AnchorBundle írását. Aláírási séma (feloldva — §16.15 Q8): a v1 RSA-PSS-szel ír alá (1-es aláírástípus), újrafelhasználva a meglévő állandó tárhely tárca-JWK mechanizmusát (nulla új, hosszú életű kulcs-őrzés, az „eggyel kevesebb titok” tézist szolgálva); az Ed25519 a §15 PQ-migrációs útra van halasztva.
A kézzel készített deep hash a W5 legmagasabb kockázatú, legalacsonyabb természetes lefedettségű kódja, így annak kapuzása nem alkudható meg (§16.15 Q8):
- A
tlog_v1.jsontöbbnyelvű fixture (Rust + TS, a §14.5wrapper_v1.jsonminta) lefedi a deep-hasht, a DataItem-bájtokat + azonosítót, a levélkivonatokat, egy 5 levelű gyökeret + audit-utat, egy STH-kivonatot, egy befoglalási bizonyítékot és egy konzisztencia-bizonyítékot — mind az aláírási, mind az ellenőrzési irányban (az ellenőrzési irány azért számít, mert a §16.6 helyi tx → tx_id ellenőrzése a deep hasht minden önálló ellenőrzőbe behúzza, nem csak az íróba). - Egy egyszeri interop-körutazás egy referencia ANS-104 kötegelőn keresztül, amelyet kizárólag statikus tesztadatként fogyasztunk — soha nem npm futásidejű függőségként (a csak-Web-Crypto / telepítési-szkript-nélküli hozzáállás áll).
- A deep-hash + RSA-PSS útnak ugyanazokon a
crypto.subtlealapelemeken kell körbejárnia, amelyeket az éles használ, így a házon belüli kódoló bájtkompatibilis. - Egy folyamatos köteg-utáni elfogadási megfigyelő megerősíti, hogy minden horgony / tartalék DataItem ténylegesen eléri az állandó tárhely elfogadását, riasztással + áramkör-megszakítóval — mert a deep hash kiszolgálja az állandó tárhely elérhetetlenségére adott tartaléksort is, így egy néma visszalépés hálózat által elutasított elemekkel töltené fel azt a sort pontosan azon kimaradás alatt, amelyet lefedni hivatott.
16.9 Befoglalási és konzisztencia-bizonyítékok
Mindkettő RFC 9162, SHA3-256, kanonikus CBOR-ként kiszolgálva.
InclusionProof — GET /api/v1/qub/:tx_id/proof: ver:u8, leaf:bstr (a pontos levél-CBOR — az ellenőrző maga számolja újra a leaf_hash-t, és soha nem bízik egy átadott kivonatban), 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 (nincs qub-szerver, 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 bizonyítékkiszolgáló tárolásnak koordináta-kulcsoltnak KELL lennie (feloldva — §16.15 Q7, blokkoló előfeltétel). A hideg-levél bizonyítékgenerálás csak akkor korrektség-semleges, ha az R2 audit-anyag egy abszolút fa-koordinátával (level, index) kulcsolt tartós Merkle-csomópont-tár — nem kötegenkénti (batch) csomópont-delták. Egy koordináta-kulcsolt tárral bármely (leaf i, size N) audit-út O(log N) közvetlen R2 GET halmaza kötegmélységeken átívelő újraszámítás nélkül; egy köteg-kulcsolt tárral nem az, és ez a tárolás-elrendezési rés az, amelyet ez a feloldás bezár. A levéltörzsek hasonlóképpen tartalomcímezhetők seq szerint. Egy W5 tesztvektornak bizonyítania KELL egy genesis-korú hideg levelet egy jóval későbbi gyökérrel szemben, kizárólag R2 + állandó tárhely használatával, törölt LogDO-tárolóval, így a §16.13 visszanyerés-biztonsági állítása alátámasztott, nem állított. Az O(log N) szekvenciális R2 GET-ek kizárólag az aszinkron bizonyíték-végpontra valók — soha nem a lezárás forró útjára (§16.10) vagy egy tickenkénti cronra.
16.10 R2-elsődleges nyugta-sorrendezés
A POST /api/v1/upload szekvencia ezzé válik:
- Elülső-fél kapuk (hitelesítés, ellenőrzés, idempotencia-szilánkkulcs) — változatlan.
- Szinkron módon
await QUB_CACHE.put(qub-cache/<tx_id>, wrappedBytes)— a tartóssági alsó határ; bezárja a W1 előgyorsítótár-versengést is (korábban egyctx.waitUntilaz állandó tárhely beküldése után). - Szinkron módon
await LogDO.append(leaf)— egy colón belüli DO RPC; az egyetlen író hozzárendeli aseq-et, kiterjeszti a bejegyzésláncot és frissíti a határvonalat. (RMW megosztott állapoton → DO, soha nem KV.) AzappendRPC kizárólag ezt teszi — azO(batch)Merkle-köteglezárási munka ezen az RPC-n kívül fut a LogDO riasztásán, különben az append p95-je mindenLOG_BATCH_MAX_LEAVES-edik lezárásnál megugrik. - Add vissza a nyugtát most — a lezárási nyugtával (a rögzített nyugtakulccsal aláírva, §16.6) és
{ tx_id, log_seq, anchor_status: "pending" }-vel. A több másodperces állandó tárhely kiterjesztés eltávolításra kerül a kritikus útról. - Egyetlen
ctx.waitUntilvárólistára teszi a késleltetett munkát: a qubonkénti állandó tárhely beküldést (most legjobb-szándékú / fizetős; meghiúsulás esetén a kötegelő tartaléksorára irányít ahelyett, hogy 503-mal felelne a felhasználónak), plusz a meglévő ideiglenes-meta írásokat. A köteglezárás és a horgonyzás a LogDO riasztásától és a napi horgony-crontól függetlenül fut. Nincsctx.waitUntilcikluson belül; a meglévő idempotencia-szilánkkulcs megőrzött.
Késleltetési költségkeret (feloldva — §16.15 Q7). A < 300 ms p95 cél egy mért indítási kapu, nem feltételezés. Az őszinte kritikus út az elülső-fél KV-olvasások + egy R2 PUT + két sorba kötött Durable Object — a meglévő QuotaDO lezárási-kvóta terhelés és az új LogDO append — így a költségkeretnek két colón belüli DO-körutazással kell számolnia, nem eggyel. Szállíts egy LogDO késleltetési riasztást, amely a QuotaDO-ét tükrözi, és kezelj egy p95-visszalépést kiadásblokkolóként.
16.11 Bizalmi modell — a pontos állítás, a levél típusa szerint hatókörözve
A kind=0x01 (tanúsított) esetében: „Ez a tartalom — a body_hash-nek megfelelő törzs, a qub_id-vel azonosítva — a qub csak hozzáfűzhető naplójához lett kötelezve a seq pozícióban, és legkésőbb az állandó tárhely T blokkidejekor létezett; kriptográfiailag olvashatatlan volt a R = unlock_round(unlock_at) drand-körig.” Ez a teljes {tlock kör-kötés + Merkle-befoglalás + lehorgonyzott gyökér} hármas.
A kind=0x02 (állított, az alapértelmezett) esetében: „Egy átlátszatlan, chash tartalomcímű rejtjelezett szöveg, amely qub_id-t és unlock_at-ot állít, a csak hozzáfűzhető naplóhoz lett kötelezve a seq pozícióban, és legkésőbb az állandó tárhely T blokkidejekor létezett.” A kör- és törzslábakat a meglévő §11 .qub-csomag ellenőrzése (qub_core::unlock) szolgáltatja, nem a napló; amit a napló egy puszta qubonkénti tranzakcióhoz képest hozzáad, az a módosításfelismerő sorrendezés, egy megbízhatóságmentes felső korlátú kötelezettségvállalási idő, és az egyenlőtlenség-ellenállás.
Mindkét állítás kizárja, a §11 szerint: a szerzőséget sig_alg ≥ 0x01 nélkül, a szándékot, és a horgony-alatti granularitású időzítést. Egyik sem engedi, hogy bármely állítás a received_at-ra támaszkodjon.
Állítási mennyezet (kötelező indítási korlát — feloldva §16.15 Q1). Az ingyenes / alapértelmezett (kind=0x02) qubok esetében a fenti hatókörözött kind=0x02 állítás a mennyezet arra nézve, amit bármely termék-, marketing-, feltétel- vagy bizonyíték-megjelenítési felület állíthat. Semmilyen felület nem mondhatja vagy sugallhatja, hogy a napló bizonyítja egy alapértelmezett qub tartalmát vagy feloldási körét — a napló egy átlátszatlan rejtjelezett szöveg sorrendezését + egy megbízhatóságmentes felső korlátú kötelezettségvállalási idejét bizonyítja. A tartalom- és kör-bizonyíték kizárólag a meglévő §11 .qub-csomag ellenőrzéséből származik, amely naplófüggetlen. Ez kemény indítási blokkoló a szövegre, nem stilisztikai preferencia; ez az a feloldás, amely a bájtvak alapértelmezett utat őszintén tartja.
16.12 Verziókezelés és W3-koordináció
Nincs SealedQub wire-emelés, és ezért nincs protokollverzió-emelés (§12.1): a napló egy oldalkocsi, amely meglévő mezőkhöz és bájtokhoz kötelezi magát, így nem lép be a §12.2 protokollverzió-történetbe. A W3 opcionális drand_chain_version-je érintetlen, és továbbra is az egyetlen opcionális SealedQub-mező. A napló ehelyett saját, független verzióterületeket vezet be — LOG_VERSION_1, ANCHOR_FORMAT_1, InclusionProof.ver —, tükrözve a §12.4 burkoló-verzió függetlenségét (a burkoló a protokollverziótól független verzióbájtot hordoz, és a napló-verziók ugyanazt az elválasztást követik).
A bizonyíték-kézbesítés alapértelmezetten lekérdezett, egy opcionális együtt-utazóval. Egy bizonyíték nem létezhet lezárási időben (a horgony még nincs megírva), így a lezárási idejű .qub-csomag bizonyíték-mentes marad. A W7 ellenőrzője egyszer lekéri a GET …/proof-ot, vagy teljesen offline módban rekonstruálja a bizonyítékot a nyilvános AnchorBundle-ből egy Log-Id-en végzett állandó tárhely-lekérdezés révén. A .qub-csomag (W7) fenntart egy opcionális inclusion_proof tagot — a lezárásnál hiányzik, egy horgony-utáni újraexportálás tölti fel hideg archiváláshoz —, ugyanazt az „opcionális, alapértelmezetten kihagyott, kiegészítő” mintát követve, mint a W3 drand_chain_version-je.
16.13 Megőrzés
A LogDO nyitott farkának, az R2 bizonyítékkiszolgáló alaprétegnek, a horgony áramkör-megszakító számlálóknak és a kötegelő tartaléksornak a megőrzési ablakait a docs/DATA-RETENTION.md specifikálja. Elv: a napló forró, bejegyzésenkénti tárolása (LogDO) horgony után visszanyerhető; audit-anyaga — a koordináta-kulcsolt (level, index) Merkle-csomópont-tár + a seq-címzett levéltörzsek (§16.9) + az állandó tárhely horgonyai — állandó. Egy hideg levél visszanyerése a DO-ból soha nem érvénytelenít egy kiadott bizonyítékot, mert egy bizonyíték azzal az állandó R2 csomópont-tárral és az állandó tárhely horgonyával szemben oldódik fel, nem a DO-val (és a §16.9 törölt-DO tesztvektor bizonyítja ezt).
16.14 Tesztvektorok
A W5 szállítja a tlog_v1.json többnyelvű fixture-t (§16.8) plusz kidolgozott vektorokat: egy kind=0x01 és egy kind=0x02 levél → leaf_hash; az 5 levelű kumulatív gyökér; egy befoglalási bizonyíték; egy konzisztencia-bizonyíték; egy AnchorBundle; és egy DataItem-azonosító. Ezek a §14.5 külső-burkoló vektorai mellett élnek, és mind a Rust (qub-core), mind a TypeScript (Worker) megvalósítás gyakorolja őket.
16.15 Felülvizsgálati döntések (W5 — feloldva)
A W5 külső felülvizsgálat (egy ellenséges tervezési áttekintés + tulajdonosi jóváhagyás) lezárult. Az alábbi minden döntés letisztult, és a fenti §16 szövegben tükröződik; a kötelező indítási korlátok a végén újra megfogalmazásra kerülnek. A megvalósítás megkezdődhet ezek mellett.
- Alapértelmezett-úti (
kind=0x02) levél-őszinteség — FELOLDVA. Szállítsd a kétlevéltípusú felosztást a specifikáció szerint: akind=0x02sembody_hash-t, semdrand_round-ot nem vállal. Nincs*_body_hashmező a bájtvak úton (ez lenne a leginkább olvasható hamis „ellenőrzött” jelzés az integrátoroknak, és olyan kényelem, amit a §11 már biztosít a csomagból). Ne követelj szerver-lezárást a napló-tanúsított qubokhoz (ez egyszerű szöveget kényszerítene a Workeren át, és lerombolná a kripto-aprítási védőárkot). Bármely önleíró rövidzár a.qub-csomagba / bizonyíték-borítékba tartozik mint ellenőrző által újraszámolt mező, soha nem levélmező. Tulajdonos által megerősített állítási mennyezet: §16.11. - Egyenlőtlenség / kihagyás elszámoltathatósága — FELOLDVA. A lezárási-nyugta kulcs a
LogProfile-ban rögzített +anchor_owner-keresztaláírt (bezárva a korábbi „nincs aláírókulcs” ellentmondást; §16.6). Indítási tanúmodell: rögzített nyugta + megfigyelési módszertan + korábbi-lánc bejárás + kettős önközzétett fejek (qub-tulajdonú nyilvános GitHub-tárház, közösségi legjobb-szándékú), felismerhetőként + nyugtázottként marketingelve, soha függetlenül tanúsítottként. Egy valódi, harmadik fél általi tanú egy §15 kormányzási emelésre van halasztva. - Rögzített horgony-tulajdonos bizalmi gyökér + forgatás — FELOLDVA. Vedd át a
LogProfile-rögzítést (§16.6); az ellenőrző ellenőrzi azanchor_tx.owner == anchor_owner-t, és helyileg ellenőrzi a tx adat → tx_id kötést. A forgatási kormányzás egy §15 megépítendő kiterjesztés (§15.3 kiváltó hozzáadva), nem újrafelhasználás; a tervezett forgatások keresztaláírnak, a kompromittálódás-vezérelt forgatások a §15-emelésre esnek vissza, ahol az elágazás-ellenőrzés korlátozza a kárt. - Privát-qub levélvakítás — FELOLDVA. Tartsd meg a vakítást a privát qubokhoz (
ref = SHA3-256(qub_id ‖ log_blind_secret)), nyersqub_id-t a nyilvános qubokhoz (már §16.2.1), achash-t mint önálló kötést. Alog_blind_secretegy korreláció/Sybil-szintű titok, csak előrefelé forgatva (§16.2.1). received_at— FELOLDVA. Tartsd meg a levélben, vállalva, de explicit módon nem bizonyítóerejűként; soha nem jelenítve meg bizonyítékként vagy vita-megerősítésként semmilyen felületen. Bármely megfigyelői épelméjűségi ellenőrzés az állandó tárhelyTblokkidejével vet össze, nem az üzemeltető által vezéreltanchored_at-tal (§16.6).- Ingyenes szintű bizonyítható időzítés — FELOLDVA (tulajdonosi jóváhagyás). A tartósság nem romlik; csak a bizonyítható felső korlátú kötelezettségvállalási idő durvul a horgony blokkidejéhez. Az ingyenes szintű szöveg nem használ számszerű SLA-t („…a következő naplóhorgonynál hozzáadva, tipikusan naponta”); a pontos órányi bizonyíték egy fizetős T3 tulajdonság, a szint-összehasonlító felületen + a feltételekben feltárva (§16.1).
- Kumulatív fa a Workerseken — FELOLDVA. Egyetlen kumulatív RFC 9162 fa + határvonal-gyorsítótárazott egyetlen-író LogDO (kényelmes mozgástér a ~1k írás/mp DO-mennyezethez képest; halaszd a Merkle-szilánk-gyökerek szilánkolását, amíg közel nem kerülsz hozzá). Blokkoló előfeltétel: koordináta-kulcsolt
(level, index)R2 csomópont-tár + a törölt-DO hideg-levél tesztvektor (§16.9); a< 300 msegy mért indítási kapu két sorba kötött DO felett (§16.10). - ANS-104 aláírási séma + deep-hash — FELOLDVA. RSA-PSS (1-es aláírástípus, a dedikált horgony-tárca JWK-ját újrafelhasználva); az Ed25519 a §15 PQ-útra halasztva. A kézzel készített SHA-384 deep hash a mindkét-irányú, megvalósítások közötti fixture-ön, egy kizárólag statikus referencia-kötegelő interop-ellenőrzésen, a megosztott
crypto.subtlekörutazáson és a köteg-utáni állandó tárhely-elfogadási megfigyelőn kapuzott (§16.8).
Kötelező indítási korlátok (vidd át a megvalósításba + termék/jogi felülvizsgálatba):
- Állítási mennyezet (Q1/Q6). Semmilyen felület nem mondhatja, hogy a napló bizonyítja egy alapértelmezett qub tartalmát vagy feloldási körét; a megengedett állítás az, hogy sorrendezett, módosításfelismerő módon, egy megbízhatóságmentes felső korlátú kötelezettségvállalási idővel. Az ingyenes szintű időbélyeg-szöveg nem hordoz számszerű késleltetést; a pontos órányi bizonyíték kizárólag fizetős T3.
- Tanú-őszinteség (Q2). Az egyenlőtlenséget felismerhetőként + nyugtázottként marketingeld, soha függetlenül tanúsítottként.
- Nyugta- + horgony-kulcsok (Q2/Q8). A nyugtakulcs rögzített + keresztaláírt; a horgony-tárca a saját JWK-ja, elkülönülve a feltöltési tárcától.
- Deep-hash kapu (Q8). Semmilyen horgony vagy T3-tranzakció nem szállítódik, amíg a mindkét-irányú fixture + interop-ellenőrzés át nem megy; az elfogadási megfigyelő riaszt meghiúsuláskor.
- Tárolási előfeltétel (Q7). A koordináta-kulcsolt csomópont-tár + a törölt-DO hideg-levél vektor előfeltételei a „a visszanyerés soha nem érvénytelenít egy bizonyítékot” garanciának.