qub Protocol Specification
Ang qub ay isang protocol para sa mga kriptograpikong panandaliang pangako: isang sistema para sa pagselyo ng mga salita para sa isang hinaharap na petsa at kalaunan ay beripikahin nang eksakto kung ano ang naiselyo, kung saan ang drand ay nagtulak ng pagkakawala nito, at—kapag mayroong transaksyon sa imbakan o patunay mula sa transparency-log—isang independiyenteng may timestamp na pinakamataas na hangganan kung kailan naipahayag ang ciphertext.
Tatlong primitibo ang nagpapatakbo nito. drand ay isang desentralisadong beacon ng randomness—ang petsa ng pagsisiwalat ay pinipilit sa pamamagitan ng kriptograpiya sa halip na sa kagandahang-loob ng qub. Matibay na imbakan pinapanatili ang kinikilalang selyadong mga byte habang ang kasalukuyang mga landas ng publikasyon ay nagsasaayos ng indibidwal na mga transaksyon para sa permanenteng imbakan; ang matagumpay na pagdagdag sa log ng pangkalahatang pag-upload ay maaari ring sumali sa pinagsamang, naka-angkla na mga pangako. ML-DSA-65 ay isang post-quantum digital signature—kapag pinagana ang pag-aakda, ang qub ay naka-ugnay sa isang key pair na ang lihim ay hindi kailanman umaalis sa aparato ng may-akda.
Sama-sama, ang mga pangunahing elementong ito ay bumubuo ng isang pahayag na naka-lock sa oras at madaling makita kung na-tamper, maaaring italaga kung nais, at independiyenteng maaaring lagyan ng timestamp—isang resibo na lumalaki ang halaga habang umuunlad ang kakayahan ng mundo na likhain ang nakaraan.
Ang natitirang bahagi ng dokumentong ito ay ang pamantayang pagtutukoy na kinakailangan para sa magkakasamang pagpapatupad.
qub Protocol Specification
| Luparan | Halaga |
|---|---|
| Pagpapalabas ng dokumento | 1.0.0 (protocol-v1.0.0) |
| Protocol ng kawad | 0x01 |
| Panlabas na pambalot | 0x01 |
| Epektibong petsa | 2026-09-23 |
| Katayuan | Kasalukuyan |
| Sinuri sa pamamagitan ng | 2026-09-23 |
Ang dokumentong ito ay ang normatibong tukoy ng protokol para sa sistema ng nakatakdang-oras na pangako ng qub. Tinutukoy nito ang mga istruktura ng datos, mga panuntunan sa serialisation, mga pormula ng derivation, at mga pamamaraan ng pagberipika na kinakailangan para sa magkakaugnay na implementasyon.
Saklaw: ang protocol layer ay sadyang neutral sa wika — ang katawan ng qub ay opaque plaintext / markdown / pact bytes, at ang locale-aware na pag-render ay responsibilidad ng mambabasa (qub.social web app, <qub-embed> iframe, MCP clients, atbp.).
1. Notasyon at mga Kumbensiyon
| Notation | Meaning |
|---|---|
u8, u64, i64 |
Unsigned/signed integers of specified bit width |
[u8; N] |
Fixed-length byte array of N bytes |
Vec<u8> |
Variable-length byte array |
Option<T> |
Value of type T, or absent |
String |
UTF-8 text string, NFC normalised |
| ` | |
SHA3-256(x) |
NIST SHA3-256 hash of byte string x (FIPS 202) |
ceil(x) |
Ceiling function: smallest integer ≥ x |
| CBOR | Concise Binary Object Representation (RFC 8949) |
| big-endian | Most significant byte first |
Lahat ng integer sa preimage constructions ay naka-encode bilang big-endian fixed-width byte arrays (i64 → 8 bytes, u8 → 1 byte) maliban kung iba ang itinakda.
Lahat ng timestamp ay Unix seconds sa UTC.
2. Mga Istruktura ng Datos
2.1 ComposeQub (Estado ng Tagalikha sa Memorya)
Hindi ini-serialize sa CBOR. Hindi isinusulat sa permanenteng storage. Lokal lamang sa app ng tagalikha.
ComposeQub {
draft_id: [u8; 16], // Random, generated locally
created_at: i64, // Unix seconds UTC
unlock_at: Option<i64>, // Unix seconds UTC; None while composing
visibility: u8, // 0x00 = private; 0x01 = public
content_type: u8, // 0x01 text; 0x03 pact; 0x04 verdict
plaintext: Vec<u8>, // Raw body bytes (UTF-8 for text)
sender_label: Option<String>, // Display name; V2-signed when authorship is enabled
title: Option<String>, // Plaintext countdown title; bound via title_hash
reply_to: Option<[u8; 32]>,// Parent qub_id; V2-signed when authorship is enabled
outcome_at: Option<i64>, // Optional future judgment time; bound to qub_id
status: DraftStatus, // Composing | Sealed | Uploaded | Failed
}
2.2 QubEnvelope (Na-decrypt na Payload)
Naka-serialize gamit ang canonical CBOR (§3). Naka-encrypt sa loob ng SealedQub. Ito ang istrukturang nagpapatunay ng integridad ng nilalaman pagkatapos ng pag-decrypt.
QubEnvelope {
version: u8, // Protocol major version (0x01 for v1)
qub_id: [u8; 32], // Derived (see §4.1)
content_type: u8, // Content type registry (see §6)
created_at: i64, // Unix seconds UTC
unlock_at: i64, // Unix seconds UTC
outcome_at: Option<i64>, // When reality renders judgment; bound to qub_id
sender_label: Option<String>, // Not in qub_id; V2-signed when authorship is enabled
reply_to: Option<[u8; 32]>,// Parent qub_id; not in qub_id; V2-signed when present
body: Vec<u8>, // UTF-8 text or canonical CBOR pact/verdict body
body_hash: [u8; 32], // SHA3-256(body) (see §4.2)
sig_alg: u8, // Signature algorithm (see §9.2)
author_signature: Option<Vec<u8>>, // Set when sig_alg != 0x00
author_pubkey: Option<Vec<u8>>, // Set when sig_alg != 0x00
cosigner_pubkey: Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
cosigner_signature: Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
}
Baseline (hindi pinirmahang text qub): version = 0x01, content_type = 0x01, sig_alg = 0x00; wala ang mga patlang para sa pirma at kasamang pumipirma. Maaaring naroroon ang iba pang opsyonal na patlang ng metadata.
Iba pang v1 configurations: content_type = 0x03 (pact body, tingnan §6.1); sig_alg = 0x01 (ML-DSA-65) na may author_signature at author_pubkey (tingnan §9.3); cosigner_pubkey at cosigner_signature ay magkasama para sa mga kasunduang may kasamang lagda (tingnan §9.7); reply_to itinakda sa qub_id ng magulang na qub para sa mga reply-chain qubs (tingnan §9.3 para sa mga implikasyon sa saklaw ng lagda).
2.3 SealedQub (Canonical Wire Format)
Isinalin gamit ang canonical CBOR (§3). Ito ang panloob na wire artifact: inilalagay ng pampublikong paghahatid ang mga byte na ito nang diretso, habang ang pribadong paghahatid ay binalot ang mga ito sa OuterWrapper bago mag-imbak (§13).
SealedQub {
version: u8, // Protocol major version (0x01 for v1)
qub_id: [u8; 32], // Same as QubEnvelope.qub_id
visibility: u8, // 0x00 = private/wrapped; 0x01 = public/bare
unlock_at: i64, // Unix seconds UTC
outcome_at: Option<i64>, // Surfaced on the verdict-watch CTA
// before reveal; mirrors QubEnvelope.outcome_at;
// bound to qub_id via the §4.1 preimage.
drand_chain_id: String, // drand chain hash (hex string)
drand_round: u64, // Target drand round number
drand_chain_version: Option<u8>, // W3 — chain-migration version. Absent / 0 = quicknet
// (the only chain today). Lets a future chain swap
// be expressed on the wire without a breaking format
// change. NOT part of the §4.1 qub_id preimage, so its
// addition never alters an existing qub's identity.
tlock_ciphertext: Vec<u8>, // tlock-encrypted QubEnvelope CBOR bytes
recipient_pubkey: Option<[u8; 32]>,// Reserved field; accepted by canonical CBOR
// but not interpreted by the v1 reference viewer
title: Option<String>, // Plaintext title surfaced on the viewer
// countdown before reveal. Bound to qub_id
// via title_hash (§4.1). 1..=100 NFC code
// points, no hostile/control code points.
}
2.4 RevealedQub (Estado ng Aplikasyon ng Mambabasa)
Hindi ini-serialize sa CBOR. Lokal lamang sa app ng mambabasa. Binubuo pagkatapos ng matagumpay na pag-decrypt at pagberipika.
RevealedQub {
qub_id: [u8; 32],
arweave_tx_id: String,
visibility: u8,
content_type: u8,
created_at: i64,
unlock_at: i64,
outcome_at: Option<i64>, // Carried from both wire layers; drives the verdict-watch block
drand_chain_id: String,
drand_round: u64,
sender_label: Option<String>,
title: Option<String>, // Carried forward from SealedQub.title
reply_to: Option<[u8; 32]>,
body: Vec<u8>,
body_hash: [u8; 32],
body_hash_verified: bool,
author_signature: Option<Vec<u8>>,
author_pubkey: Option<Vec<u8>>,
signature_verified: Option<bool>,
cosigner_pubkey: Option<Vec<u8>>,
cosigner_signature: Option<Vec<u8>>,
cosigner_verified: Option<bool>,
}
3. Canonical CBOR Profile
Lahat ng SealedQub at QubEnvelope serialisation ay MUST sumunod sa profile na ito. Dalawang implementasyon na binigyan ng parehong lohikal na istruktura ay MUST gumawa ng magkaparehong bytes.
3.1 Mga Panuntunan sa Pag-encode
| Rule | Specification |
|---|---|
| Standard | RFC 8949 §4.2.1 (Core Deterministic Encoding Requirements) |
| Map key ordering | Sorted by encoded byte length first (shorter before longer), then lexicographically (byte-by-byte for same-length encodings) |
| Integer encoding | Shortest form: 0–23 in initial byte; 24–255 in 2 bytes; 256–65535 in 3 bytes; etc. |
| Length encoding | Definite lengths only. No indefinite-length arrays, maps, byte strings, or text strings (additional info = 31 is forbidden). |
| Tags | No CBOR tags (major type 6 is forbidden). |
| Floating-point | No floats (major types 7 values 0xF9–0xFB are forbidden). |
| Text strings | UTF-8 encoded, NFC normalised (Unicode Normalization Form C). |
| Byte strings | Raw bytes. No base64 encoding at the CBOR layer. |
| Duplicate keys | Reject with error. Parsers MUST NOT silently accept duplicate map keys. |
| Unknown keys | Reject with error. Parsers MUST NOT tolerate map keys outside the type's canonical key set — two distinct canonical byte strings must never decode to the same value (encode(decode(x)) == x), and for signed payloads an extra key would be hidden content both signatures commit to. Schema evolution goes through version, never extra keys. |
| Simple values | Only true (0xF5), false (0xF4), and null (0xF6) are permitted. |
| Optional fields | Absent optional fields are omitted from the CBOR map entirely (not encoded as null). Present optional fields are included in sorted key order. |
3.2 Verified Canonical Key Orders
Ang mga key order na ito ay normatibo. Ang mga implementasyon ay MUST mag-emit ng mga key sa eksaktong pagkakasunod na ito. Ang mga debug assertion ay SHOULD magberipika ng pagkakasunod sa mga non-release build.
QubEnvelope (version 0x01, unsigned, all optional fields absent):
"body" (5 encoded bytes)
"qub_id" (7 encoded bytes)
"sig_alg" (8 encoded bytes)
"version" (8 encoded bytes)
"reply_to" (9 encoded bytes) ← only if present (reply chains)
"body_hash" (10 encoded bytes)
"unlock_at" (10 encoded bytes)
"created_at" (11 encoded bytes)
"outcome_at" (11 encoded bytes) ← only if present (verdict mechanic)
"content_type" (13 encoded bytes)
"sender_label" (13 encoded bytes) ← only if present
"author_pubkey" (14 encoded bytes) ← only if present
"cosigner_pubkey" (16 encoded bytes) ← only if present (pact cosign)
"author_signature" (17 encoded bytes) ← only if present
"cosigner_signature" (19 encoded bytes) ← only if present (pact cosign)
Derivation ng key order ng QubEnvelope: bawat key ay isang CBOR text string. Encoded length = 1 byte header + string length (para sa mga string na mas mababa sa 24 bytes). Pagsunod-sunurin ayon sa kabuuang encoded length muna, pagkatapos ay lexicographically para sa mga key na may parehong haba.
SealedQub (version 0x01, public, no recipient):
"title" (6 encoded bytes) ← only if present
"qub_id" (7 encoded bytes)
"version" (8 encoded bytes)
"unlock_at" (10 encoded bytes)
"outcome_at" (11 encoded bytes) ← only if present (verdict mechanic)
"visibility" (11 encoded bytes)
"drand_round" (12 encoded bytes)
"drand_chain_id" (15 encoded bytes)
"recipient_pubkey" (17 encoded bytes) ← only if present
"tlock_ciphertext" (17 encoded bytes)
"drand_chain_version" (20 encoded bytes) ← only if present (W3; absent = quicknet)
PactTerms (pact body, 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 (row of the terms array):
"key" (4 encoded bytes)
"value" (6 encoded bytes)
PartyIdentifier (party_a / party_b map):
"label" (6 encoded bytes)
"contact" (8 encoded bytes) ← only if present
3.3 Sanggunian ng Byte Encoding
| Type | CBOR encoding | Example |
|---|---|---|
| SHA3-256 hash (32 bytes) | 0x58 0x20 + 32 bytes |
body_hash, qub_id |
| Timestamps (i64) | Major type 0 (positive) or 1 (negative), shortest encoding | Unix seconds |
| Version (u8, value 1) | 0x01 (single byte) |
|
| Content type (u8, value 1) | 0x01 (single byte) |
|
| sig_alg (u8, value 0) | 0x00 (single byte) |
|
| ML-DSA-65 signature (3,309 bytes) | 0x59 0x0C 0xED + 3,309 bytes |
author_signature, cosigner_signature |
| ML-DSA-65 public key (1,952 bytes) | 0x59 0x07 0xA0 + 1,952 bytes |
author_pubkey, cosigner_pubkey |
4. Mga Normatibong Derivation
4.1 qub_id
Ang qub_id ay natatanging tumutukoy sa isang qub at nagbubuklod sa QubEnvelope sa SealedQub. Ito ay deterministikong nakuha mula sa nilalaman ng envelope.
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
Encoding ng domain separator: Ang string na "QUB_ID_V2" ay 9 ASCII bytes. Isang 0x00 padding byte ang idinaragdag upang maabot ang 10 bytes para sa pagkakahanay. Ang mga implementasyon ay MUST gumamit ng eksaktong 10 bytes na ito: [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00].
outcome_at pag-eencode: Isang pre-release na rebisyon ng pagpapatupad ang pinalawig ang preimage mula 92 hanggang 100 bytes upang ipaloob ang opsyonal outcome_at patlang sa pagtali. Wala outcome_at ay naka-encode bilang 8 zero byte; tinatanggihan ng mga validator ng protocol outcome_at <= 0 saanman upang ang batayang bantay na ito ay hindi masasagupa ang isang lehitimong halaga. Tingnan ang §3.2 (wire format) at ang in-tree tasks/verdict-uplift-plan.md para sa mekaniko ng hatol na nag-uudyok sa larangang ito.
drand_round pag-eencode: Isang mas huling pre-release na rebisyon ng implementasyon ang pinalawig ang preimage mula 100 hanggang 108 na bytes upang i-fold drand_round (ang target drand round, §4.3) sa binding, at itinaas ang domain separator sa QUB_ID_V2. Ito ay nagbubuklod sa timelock na round sa qub identity: ang isang gateway ay hindi maaaring muling ibuklod ang ciphertext sa ibang round (halimbawa, na lampas na) kaysa sa ipinapakita unlock_at nangangahulugan. Karagdagan, sinusuri ng proseso ng pag-unlock (§8) na ang round na nakabuo sa tlock ciphertext stanza ay tugma unlock_round(unlock_at), kaya ang ipinakitang oras ng pag-unlock ay patunay na ang round na iyon ang nagbubukas ng decryption.
Mga katangian:
- Pagbabago ng anumang larangan na nakatali sa preimage—
version,content_type,created_at,unlock_at,outcome_at,drand_round, ang hilawbodybytes (sa pamamagitan ngbody_hash), otitle(sa pamamagitan ngtitle_hash)—nagbubunga ng ibaqub_id. - Ang qub_id ay kinakalkula bago ang encryption. Pareho ang QubEnvelope at SealedQub na may parehong qub_id. Tinitiyak ng viewer na magkapareho ang mga ito pagkatapos ng decryption.
qub_idhindi nakadepende sasender_label,reply_to, mga signature byte, o mga pampublikong key ng pagpirma. Sa ilalim ng kasalukuyang V2 na konstruksiyon ng pagpirma, gayunpaman,sender_labelatreply_toay direktang pinatutunayan ngsender_label_hashatreply_to_or_zero(§9.3) tuwing mayroong mga pirma.- Pagpapalit ng SealedQub
title(na ayusin na ang lahat ng iba pa) mga pagbabagoqub_idsa pamamagitan ngtitle_hash. Samakatuwid, ang isang gateway ay hindi maaaring palitan ang plaintext na pamagat na ipinapakita sa countdown nang hindi pinapawalang-bisa ang qub identity. - Pagpapalit ng SealedQub
outcome_at(sa lahat ng iba pang ayusin) pagbabagoqub_idsa pamamagitan ng preimage. Ang isang gateway ay hindi maaaring palitan ang petsa ng pre-reveal verdict-on na ipinapakita sa countdown nang hindi pinapawalang-bisa ang qub identity. - Nagbabago
drand_round(sa lahat ng iba pang ayusin) pagbabagoqub_idsa pamamagitan ng preimage. Hindi maaaring ibalik ng isang gateway ang timelock ciphertext sa ibang round nang hindi pinapawalang-bisa ang qub identity; kapag pinagsama sa §8 unlock-time stanza-round check, ang ipinapakitaunlock_atay ang round na talagang nagga-gate sa decryption.
4.2 body_hash
body_hash = SHA3-256(body)
Kung saan ang body ay ang raw Vec<u8> content payload. Para sa mga text qub, ito ang UTF-8 encoded na katawan ng qub.
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
Kung saan ang title ay ang opsyonal na plaintext title na ipinapakita sa countdown ng mambabasa bago ang paghahayag (tingnan §3.2). Ang NFC normalisation ay tumatakbo sa oras ng pag-hash upang ang digest ay stable sa mga visually-equivalent code-point sequence. Ang all-zeros sentinel ay nakalaan para sa kasong wala; ang isang walang lamang string ay tinatanggihan sa canonical CBOR boundary bilang non-canonical encoding ng "wala" (ang canonical encoding ay tinatanggal ang field nang buo).
4.3 Pag-unlock-Paglaban ng Mapa
drand_round = floor((unlock_at - chain_genesis_time) / chain_period_seconds) + 1
| Parametro | Pinagmulan | Halimbawa |
|---|---|---|
unlock_at |
Mga segundo ng Unix na pinili ng gumagamit UTC | 1735689600 (2025-01-01 00:00:00 UTC) |
chain_genesis_time |
impormasyon ng drand chain (genesis_time) |
1595431050 |
chain_period_seconds |
impormasyon ng drand chain (period) |
30 |
Ito ang sanggunian ng tlock mapping (drand's) CurrentRound). naglalathala ang drand ng round N at chain_genesis_time + (N - 1) * chain_period_seconds, kaya pinipili ng formula ang paikot na kasalukuyan sa unlock_at — ang ikot na ang pirma ang unang makikita ng isang manonood pagdating unlock_at maaaring gamitin.
Ari-arian ng pagkakahanay (ang kaso na mahalaga sa praktika): kailan (unlock_at - chain_genesis_time) ay eksaktong nahahati sa chain_period_seconds, ang pirma ng napiling round ay inilathala eksakto sa unlock_at, kailanman bago ito. Ito ay palaging totoo para sa reference deployment: ang oras ng genesis ng quicknet (1692803367) ay nahahati sa 3-segundong period nito, at ang mga reference na app ay nagtatakda ng oras ng pag-unlock ng PIN sa buong minuto. Para sa hindi naka-align unlock_at, ang napiling lagda ng round ay nailalathala nang mas mababa sa isang panahon bago unlock_at — ang pansamantalang katumpakan ng pangako ay isang yugto ng parola.
Pamamantayang pre-release ng legacy at toleransiya sa unlock-side: ang orihinal na mapa ay ceil((unlock_at - chain_genesis_time) / chain_period_seconds), na—para sa kaso na naka-aligned sa panahon sa itaas—pinili ang bilog na nailathalang isang buong panahon bago unlock_at, na ginagawa ang ciphertext na ma-decrypt nang maaga ng eksaktong isang period. Ang dalawang mapping ay naiiba ng eksaktong +1 kapag hinahati ng delta ang panahon, at sumasang-ayon sa iba. Dahil drand_round ay nakatiklop sa di-nabawas qub_id preimage (§4.1), ang mga artipakto na naka-seal sa ilalim ng legacy na mapping ay hindi maaaring muling makuha; samakatuwid ang mga tagasuri na gumagawa ng §8 hakbang 6a na pag-ikot na pagsusuri ay DAPAT tanggapin ang naka-imbak drand_round katumbas ng alinman ang nakuha na bilog o ang nakuha na round minus isa (at DAPAT na kailangan ang tlock stanza round upang eksaktong tumugma sa nakaimbak na round). Ang pagtitiis ay nagpapalawak sa pinakamaagang gating signature ng hindi hihigit sa isang panahon. Ang pact staging service ay ipinapataw ang parehong pagtitiis kapag muling kinukuha nito ang isang staged pact's qub_id (at stage at co-sign): kung ang kasalukuyang mapping na round ay hindi nireproduce ang naipangako qub_id at hinahati ng delta ang panahon, sinusubukan ulit nito sa paligid minus isa, at sinisira nito ang tapos na kasunduan sa alinmang round ang qub_id talagang nag-uugnay—hindi kailanman bulag sa muling kinompyut na bilog, na magpapagawa sa artifact na hindi na mapapatunayan nang permanente.
Pagpapatunay: unlock_at Dapat ay sa hinaharap sa oras ng selyo. unlock_at HINDI dapat lumampas sa 10 taon mula sa created_at (upang limitahan ang panganib sa dependency ng long-horizon drand; DAPAT magbigay ng babala ang UI para sa mga petsa ng pag-unlock na lampas sa 2 taon).
5. Mga Newtype ng Wire Format
Ang mga newtype ng wire format ay nagbibigay ng compile-time na kaligtasan laban sa paglilito ng CBOR bytes sa JSON, raw plaintext, o iba pang byte encodings.
| Uri | Naglalaman | Ginawa Ni | Kinain ng |
|---|---|---|---|
SealedQubCbor |
Kanonikal na CBOR ng SealedQub | serialize_sealed_qub() |
Inner wire artifact; iniimbak nang walang takip para sa pampublikong paghahatid o binalot para sa pribadong paghahatid, pagkatapos ay kinabawi ng manonood |
QubEnvelopeCbor |
Canonical CBOR ng QubEnvelope | serialize_qub_envelope() |
tlock i-encrypt ang input, tlock i-decrypt ang output |
5.1 Mga Panuntunan sa Construction
// 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 Pagberipika sa Construction
Ang from_encoded() ay SHOULD magberipika na ang input ay nagsisimula sa isang valid na CBOR map header. Ang buong structural validation ay nangyayari sa parse time, hindi construction time, upang maiwasan ang double-parsing.
6. Rehistro ng Content Type
| Value | Type | Max Body Size | Notes |
|---|---|---|---|
0x00 |
Reserved (invalid) | — | MUST NOT be used |
0x01 |
Plain text (UTF-8, restricted Markdown) | 50 KB paid / 10 KB free | See §10 for rendering rules. The free / paid split is enforced by the upload service; the protocol-layer hard ceiling is 50 KB. |
0x02 |
Reserved (future) | — | Allocated for a future content type; not valid in v1. Viewers MUST reject per the rule below. |
0x03 |
Pact (bilateral agreement, CBOR body) | 100 KB | Body is canonical CBOR PactTerms (§6.1). Cosigner signing per §9.7. |
0x04 |
Verdict (self-grading ng tagalikha, CBOR body) | 8 KB | Ang body ay canonical CBOR VerdictBody (§6.2). Inilalabas lamang ng system-side na verdict intent. Ang relasyong magulang ay nasa Arweave tag na Parent-Tx-Id, hindi sa body. Tingnan ang verdict-uplift-plan §3.4. |
Ang mga mambabasa ay MUST tanggihan ang mga hindi kilalang content type na may malinaw na error na nakikita ng gumagamit. Ang mga mambabasa ay MUST NOT subukang i-render ang mga hindi kilalang uri bilang text.
6.1 Katawan ng Kasunduan (content_type = 0x03)
Ang katawan ng kasunduan ay ang canonical CBOR encoding ng isang PactTerms na halaga:
PactTerms {
pact_version: u8, // 0x01 for structured/v1
title: String, // ≤ 200 bytes, NFC
terms: Vec<PactTerm>, // ≤ 20 rows
party_a: PartyIdentifier, // initiator
party_b: PartyIdentifier, // counter-signer
notes: Option<String>, // ≤ 5,000 bytes, NFC; absent key if none
}
PactTerm { key: String (≤ 100 bytes), value: String (≤ 2,000 bytes) } // NFC
PartyIdentifier{ label: String (≤ 100 bytes), contact: Option<String (≤ 320 bytes)> }
Ang mga canonical CBOR key order para sa lahat ng tatlong map ay nasa §3.2. Ang kabuuang naka-serialize na pact CBOR ay MUST NOT lumampas sa 100 KB (tumutugma sa §6).
Tagapag-iba ng schema. Ang unang row sa terms para sa isang structured/v1 na kasunduan ay MUST { key: "pact_schema", value: "structured/v1" }. Ang mga row na walang ganitong marker ay "custom" na kasunduan at hindi tumatanggap ng structured validation o schema-aware rendering.
Frozen acknowledgement slots. Ang structured/v1 na kasunduan ay nagdadala ng eksaktong apat na acknowledgement row sa ilalim ng mga key na ito:
"initiator_standard_terms"
"initiator_capacity_terms"
"counterparty_standard_terms"
"counterparty_capacity_terms"
Ang value para sa bawat isa ay isa sa walong frozen English string na pinili ng (role, kind) pair, kung saan role ∈ { seller, buyer, provider, client } at kind ∈ { standard, capacity }. Ang mga string mismo ay normatibong datos ng protokol — parehong ML-DSA-65 signatures ng dalawang panig ay nangangako sa eksaktong bytes sa pamamagitan ng body_hash. HINDI sila isinasalin; ang naka-lagdang katawan ay neutral sa wika. Ang anumang pagbabago sa pananalita ay nangangailangan ng bagong bersyon ng schema (structured/v2).
Ang walong string, ang kanilang lookup (acknowledgement_for(role, kind)), at ang katwiran para sa bawat isa ay nakatakda ng reference implementation. Ang mga sumusunod na implementasyon ay MUST mag-emit ng byte-identical na acknowledgement values; ang golden-fixture SHA3-256 body-hash tests na sumasaklaw sa lahat ng apat na kombinasyon ng role ay nakahuli ng anumang pag-anod.
Pagkakasunod-sunod ng pagpapakita sa mambabasa. Ang mga acknowledgement string ay naglalaman ng mga parirala tulad ng "described above", na ipinagpapalagay na ang mga description / scope row ay nag-render nang nauna sa mga acknowledgement. Ang mga mambabasa ay MUST mag-render ng terms array sa pagkakasunod ng CBOR; ang pag-aayos muli ay sumisira sa semantiko ng prosa.
Pakikipag-ugnayan sa kabilang panig. Kapag ang contact ni Party B ay isang valid na email address, ang qub upload service ay awtomatikong nagpapadala ng review / co-sign invite email sa stage time at nagbubuklod sa magiging co-sign sa pagberipika ng parehong address na iyon (§9.7). Ang mga kasunduang ang Party B contact ay wala ay maaari pa ring magkaroon ng kasamang lagda, ngunit sa pamamagitan lamang ng out-of-band channel — tinatanggihan ng serbisyo ang mga co-sign request na hindi makakagawa ng tumutugmang 15-minutong email-verification marker.
6.2 Katawan ng Hatol (content_type = 0x04)
Ang katawan ng hatol ay ang canonical CBOR encoding ng isang VerdictBody na halaga:
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
}
Canonical CBOR key order:
"outcome" (8 encoded bytes)
"reflection" (11 encoded bytes) ← only if present
"evidence_url" (13 encoded bytes) ← only if present
"verdict_version" (16 encoded bytes)
Ang kabuuang naka-serialize na verdict CBOR ay MUST NOT lumampas sa 8 KB (tumutugma sa registry row sa itaas).
Outcome enum. Ang wire byte ay neutral sa intent; ang apat na bucket na Right / Partial / Wrong / Unfalsifiable ay sumasaklaw sa buong outcome space ng bawat verdict-bearing intent. Ang mga per-intent label ("Tama ang hula" / "Tinupad ko" / "Naipadala" / "Pinatunayan" para sa Right, atbp.) ay isang viewer-side rendering concern na sinasagot laban sa intent ng magulang na qub — ang wire ay nananatiling neutral sa wika at intent. Ang mga value na nasa labas ng 1..=4 ay MUST tanggihan sa decode.
Pag-uugnay sa magulang. Ang isang verdict qub ay HINDI nagdadala ng reference sa magulang sa loob ng kanyang body. Ang Arweave transaction id ng magulang na qub ay inilalabas bilang Parent-Tx-Id storage tag sa upload time (§7 storage-tag layer). Pinapanatili nito ang body bilang isang self-contained na nakalagdang pahayag ng self-assessment; ang audit chain ("tama tungkol saan?") ay itinatatag sa pamamagitan ng Arweave-tag lookup.
Kaligtasan ng evidence URL (normatibo). Kapag mayroong evidence_url, ang mga validator (compose-side, wire-side, Worker edge) ay MUST ipatupad ang sumusunod:
- HTTPS lamang. Ang string ay MUST magsimula sa byte sequence na
https://. Anumang ibang scheme —http,ftp,javascript,data,file, atbp. — ay tinatanggihan. - Limitasyon ng haba. ≤ 2,048 bytes (praktikal na limitasyon ng browser URL).
- NFC + hostile-codepoint check. Parehong tuntunin sa
titleatreflection— ang mga bidi-override / zero-width / tag-block / BOM / C0 / C1 codepoint ay tinatanggihan. Ang depinisyon ay tumutugma sa Rustcrate::handle::contains_hostile_text_codepointat sa TSworkers/api/src/utils/unicode.ts::isHostileCodepoint(panatilihing magkasabay). - Walang whitespace, walang ASCII controls. Ang whitespace / DEL / sub-
0x20bytes saanman sa URL ay tinatanggihan — pinipigilan ang\n/\tinjection vector na hindi sakop ng tuntunin ng bidi. - Hindi walang-laman ang host segment. Lahat sa pagitan ng
https://at ng unang/,?, o#ay MUST hindi walang laman.
Walang server-side fetching. Ang Worker ay MUST NOT mag-proxy, mag-fetch, o mag-preview ng URL. Ang protocol ay nag-iimbak ng isang string; ang rendering ay nangyayari viewer-side gamit ang rel="nofollow noopener noreferrer" target="_blank" at isang nakikitang host na ipinapakita kasama ng link text.
Repleksyon. Opsyonal na repleksyon na isinulat ng tagalikha ("ano ang nagbago, ano ang natutunan mo"). Parehong NFC + hostile-codepoint validation tulad ng title. Ang walang laman / whitespace-only input ay isasara sa absent sa construction time.
Bersyon ng schema. Ang v1 ay sumusuporta sa verdict_version = 0x01 lamang. Ang mga panghinaharap na schema revision ay magtataas ng byte na ito at darating kasabay ng bagong protocol version ayon sa §12.
7. Protokol ng Pag-selyo
Ang kumpletong sequence ng pag-selyo. Bawat hakbang ay normatibo.
1. User composes plaintext and metadata in ComposeQub.
2. Validate:
a. body is non-empty.
b. body size ≤ max for content_type and user tier (see §6).
c. unlock_at is in the future.
d. unlock_at ≤ created_at + 10 years.
e. content_type is a known, supported value.
f. visibility is 0x00 (private) or 0x01 (public).
3. Compute body_hash = SHA3-256(body).
4. Set created_at = current Unix seconds UTC.
5. Select drand chain. Load chain_genesis_time and chain_period_seconds, and
compute drand_round = floor((unlock_at - chain_genesis_time) / chain_period_seconds) + 1
(§4.3). (Computed here, before qub_id, because drand_round is bound into the
qub_id preimage—§4.1.)
6. Compute qub_id (see §4.1), folding in drand_round from step 5.
7. Construct QubEnvelope with all fields.
8. Serialise QubEnvelope using canonical CBOR → bytes B.
Assert: serialised output matches canonical profile (§3).
9. Compute C = tlock_encrypt(B, drand_round, drand_chain_public_key).
10. Construct SealedQub with tlock_ciphertext = C and matching qub_id, version,
visibility, unlock_at, drand_chain_id, and drand_round.
11. Serialise SealedQub using canonical CBOR → SealedQubCbor.
12. Select the delivery shape from visibility:
a. Private (0x00): generate K = 32 random bytes and N = 12 random bytes
using a CSPRNG. Compute W = wrap_sealed_qub(SealedQubCbor,
qub_id=qub_id, key=K, nonce=N) per §13. Upload payload = W.
b. Public (0x01): upload payload = bare SealedQubCbor; do not generate K.
13. Display seal-time disclosure. User confirms.
14. Validate upload eligibility via the qub upload service (bot-detection, entitlement, rate limits).
15. Submit the selected upload payload to the qub upload service. For a private
browser seal, the service is byte-blind to the inner SealedQubCbor and never
receives K. The Builder `/api/v1/seal` route is an explicit exception: it
receives plaintext and caller-supplied K in memory, then persists neither.
16. Receive arweave_tx_id from the service. For private delivery, construct
`<origin>/c/<arweave_tx_id>#<base64url(K)>` (or the equivalent short-code
path). For public delivery, omit the fragment. Browsers do not transmit URL
fragments to servers, so K from the browser-seal path is not observed by
qub.social or any storage gateway.
Antas ng tag ng imbakan (labas-sa-band). Ang serbisyo ng qub upload ay naglalakip ng sinadya na maliit na set ng mga tag ng transaksyon sa imbakan kasama ng piniling payload ng upload. Content-Type=application/octet-stream ay kinakailangang normatibo. Dagdag pa, ang serbisyo ng sanggunian ay naglalakip ng tatlong opsyonal na tag kapag pinili ng gumawa na ipakita ang mga ito: Intent (pinahintulutang listahang-bisa na layunin sa paggawa—announcement, thesis, prediction, letter, secret, commitment, proof, o inilabas ng sistema verdict), Author (fingerprint ng pubkey ng creator §9.3 bilang 64-character na maliit na hex), at Parent-Tx-Id (id ng storage transaction ng parent qub para sa mga reply chain, 43-character na base64url).
Ang Author tatak ay sumali per qub: ikinakabit lang ito ng reference creator app kapag tahasang pinapagana ng user ang pampublikong atribusyon sa oras ng selyo. Kapag nakapatay ang toggle — ang default — wala Author nakasulat ang tag at ang qub ay walang pagkakakilanlan sa chain: walang anumang nasa permanenteng imbakan na nag-uugnay ng upload sa handle ng tagalikha, email, o iba pang qubs. Kapag naka-on ang toggle, ang Author ang fingerprint ay tumutukoy sa pinili ng gumawa @handle sa pamamagitan ng §9.5 na kadena ng pagpapatunay. Mga relasyon sa kadena ng tugon at Intent ay hindi nakikilala. Para sa pribadong paghahatid, ang panlabas na balot (§13) ay nag-e-encrypt sa makikilalang panloob SealedQub artepakto kaya ang pag-aani ng mga naka-imbak na balot at pagkuha ng mga pampublikong lagda ng drand ay hindi pa rin sapat upang mabawi ang katawan nang wala ang K; ang mga tag ng imbakan ay nananatiling sadyang pampublikong metadata.
Ang reference service ay sinasadyang HINDI nag-aattach ng App-Name, App-Version, o Type tags: ang anumang ganitong single-value filter ay magbabalik ng buong qub corpus sa isang GraphQL query, na hindi tugma sa body-only confidentiality scope ng wrapper.
Ang isang sumusunod na verifier ay MUST NOT umaasa sa anumang storage tag para sa §11 third-party verification; ang body hash / qub_id / signature ay nangangako lamang sa panloob na CBOR, hindi sa tag set.
8. Protokol ng Paghahayag
Ang kumpletong sequence ng paghahayag. Bawat hakbang ay normatibo.
1. Viewer opens delivery URL. Extract arweave_tx_id from the path and retain
the optional URL fragment. Do not assume a missing fragment is an error:
public/bare delivery intentionally has no K.
2. Check denylist. If tx_id is denylisted → display block message. Stop.
3. Fetch the stored bytes (with multi-gateway fallback).
3a. Resolve the delivery shape structurally:
a. If the bytes parse as OuterWrapper, require a well-formed 32-byte K in
the URL fragment, require wrapper version 0x01, and unwrap per §13.
Any missing/malformed K or AEAD failure is a terminal error.
b. Otherwise require the bytes to parse as bare SealedQubCbor; no K is
required. If neither shape parses, report an integrity error.
4. Parse SealedQubCbor → SealedQub.
5. Validate: SealedQub.version is known (0x01), visibility is known, and the
delivery shape matches it (wrapped = 0x00 private; bare = 0x01 public).
Reject any mismatch or unknown value.
6. If current time < SealedQub.unlock_at → display countdown. Poll or wait.
6a. Round-binding check. Recompute expected_round from
SealedQub.unlock_at per §4.3. Reject unless SealedQub.drand_round ==
expected_round OR SealedQub.drand_round == expected_round - 1 (the
legacy pre-release mapping—see §4.3), AND the round baked into the tlock
ciphertext stanza (read via the age/tlock header, no signature required)
== SealedQub.drand_round exactly. The stanza round is the one that
actually gates decryption; without this check a malicious creator could
bind the ciphertext to an already-past round while displaying a future
countdown, so anyone reading the stored bytes could decrypt before
unlock_at. Implementations with no chain identity (test mocks) skip this
check.
7. Once current time ≥ SealedQub.unlock_at:
a. Fetch drand round signature for SealedQub.drand_round from drand network.
b. Compute B = tlock_decrypt(SealedQub.tlock_ciphertext, round_signature).
8. Parse B → QubEnvelope.
9. Validate QubEnvelope.version is known.
10. Verify: SHA3-256(QubEnvelope.body) == QubEnvelope.body_hash.
Fail → integrity error.
11. Verify: QubEnvelope.qub_id == SealedQub.qub_id.
Fail → integrity error.
12. Verify: QubEnvelope.unlock_at == SealedQub.unlock_at.
Fail → integrity error.
12a. Verify: QubEnvelope.outcome_at == SealedQub.outcome_at (both absent, or
both present and equal). Fail → integrity error.
12b. Content re-derivation. Recompute qub_id per §4.1 from the decrypted
fields — (QubEnvelope.version, content_type, created_at, unlock_at,
outcome_at, SealedQub.drand_round, QubEnvelope.body_hash,
title_hash(SealedQub.title)) — and verify it equals SealedQub.qub_id.
Fail → integrity error. The pairwise checks in steps 10-12a only prove
the two layers agree with EACH OTHER; a forger who rewrites a bound
field consistently on both surfaces (a pre-reveal title swap, or a
post-round body swap with a recomputed body_hash re-encrypted to the
same round under the same qub_id) passes them all. Only re-deriving
the identity from content closes this.
13. Verify: QubEnvelope.content_type is known and renderable.
Known values: 0x01 (text), 0x03 (pact), 0x04 (verdict).
Unknown → display error.
14. If QubEnvelope.sig_alg != 0x00 → verify author signature (see §9.4).
15. If cosigner_pubkey or cosigner_signature present → verify cosigner (see §9.7).
16. Render content using the appropriate renderer (see §10 for text and §6 for pact/verdict).
17. Construct RevealedQub for display.
9. Paglagda ng Pagiging May-akda
9.1 Katwiran
Ang mga qub ay permanenteng naka-imbak sa permanenteng storage. Ang mga lagda ng pagiging may-akda ay dapat manatiling hindi maaaring pekein nang walang hangganan, kaya naman ang v1.0 ay gumagamit ng post-quantum ML-DSA-65 scheme (FIPS 204) sa halip na isang klasikal na scheme na ang seguridad ay maaaring humina sa loob ng permanenteng buhay ng qub.
9.2 Rehistro ng Algorithm
sig_alg |
Eskema | Laki ng Susi | Laki ng Pirma | Katayuan |
|---|---|---|---|---|
0x00 |
Walang pirma (hindi pinirmahan) | — | — | Aktibo |
0x01 |
ML-DSA-65 (FIPS 204) | 1,952 bait | 3,309 na byte | Aktibo |
0x02 |
Ed25519 | 32 bytes | 64 na bytes | Nakalaan na constant; hindi suportado sa protocol v1 |
DAPAT tanggihan ng mga manonood ng Protocol-v1 ang bawat halaga sa labas {0x00, 0x01}, kasama na
ang masinop 0x02 halaga. Ang pagreserba ay pumipigil sa aksidenteng muling paggamit; ito ay hindi
aktibasyon. Ang pag-aktiba nito ay nangangailangan ng pinamamahalang pagbabago na inilarawan sa §15.
9.3 Konstruksiyon ng Naka-lagdang Preimage
Dalawang bersyon ng preimage ang umiral. Ang lahat ng lagda ay MUST gumamit ng V2, at ang mga verifier ay MUST tumanggap lamang ng V2. Ang legacy na V1 preimage (dinodokumento sa ibaba para sa makasaysayang sanggunian) ay tinanggap bilang verification-only na fallback noong migration patungong V2; ang fallback na iyon ay inalis na at ang isang V1-only na lagda ay tinatanggihan na ngayon.
V2 (kasalukuyan — ginagawa ng lahat ng bagong paglagda ng may-akda, at ng parehong lagda ng pact staging / cosign flow):
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)
Ang sender_label_hash ay sumusunod sa parehong absent-sentinel na kombensiyon tulad ng title_hash (§4.2.1): ang 32 zero bytes ay hindi wastong SHA3-256 output, kaya ang "absent" ay hindi kailanman maaaring mag-collide sa isang naroroong label. Ang lahat ng field ay fixed-width, kaya ang preimage ay hindi malabo kahit walang length prefix.
V1 (legacy — INALIS NA; hindi na ginagawa at hindi na tinatanggap sa pagberipika):
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
Ang V1 preimage ay nag-omit ng sender_label at reply_to. Ito ay tinanggap bilang verification-only na fallback noong migration patungong V2; ang fallback na iyon ay inalis na — ang mga verifier ay MUST tumanggap lamang ng V2 preimage. Ang depinisyon ay pinananatili dito para sa makasaysayang sanggunian at upang ipaliwanag ang domain separator sa ibaba. Ang isang lagda na nagve-verify lamang laban sa V1 ay MUST ituring bilang verification failure.
Mga domain separator: ang "QUB_AUTHOR_SIG_V1" / "QUB_AUTHOR_SIG_V2" ay tig-17 ASCII bytes ([0x51, 0x55, 0x42, 0x5F, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x5F, 0x53, 0x49, 0x47, 0x5F, 0x56, 0x31/0x32]). Walang padding. Ang naiibang separator ay nagbibigay ng domain separation sa dalawang konstruksiyon, kaya ang isang lagda sa isang preimage ay hindi kailanman maaaring mag-verify bilang ang isa pa.
org_id_present byte: ang byte na kasunod ng unlock_at ay MUST 0x00. Ang reference implementation ay naglalantad nito bilang ang constant na ORG_ID_PRESENT_INDIVIDUAL = 0x00 sa crates/qub-core/src/signing.rs; ang mga mambabasang nagbubuo muli ng sig_input para sa pagberipika ay MUST mag-emit ng parehong byte.
Saklaw ng lagda — kung ano ang sakop at hindi. Ang V2 na sig_input ay direktang nangangako sa version, qub_id, body_hash, unlock_at, sender_label, at reply_to (kasama ang nakapirming domain separator at org_id_present byte). Ang qub_id mismo ay nakuha mula sa version, content_type, created_at, unlock_at, outcome_at, drand_round, at body_hash sa pamamagitan ng §4.1 preimage, kaya ang anumang pagbabago sa mga field na iyon ay gumagawa ng ibang qub_id at transitively na nagpapawalang-bisa sa lagda. Ang pinapatotohanang ibabaw ay samakatuwid:
| Luparan | Pinagtibay ng pirma | Paano |
|---|---|---|
version |
✓ | Tuwirang input sa sig_input |
qub_id |
✓ | Direktang input |
body_hash |
✓ | Direktang input |
unlock_at |
✓ | Direktang input |
sender_label |
✓ | Tuwirang input sa pamamagitan ng sender_label_hash (V2 preimage — ang tanging tinatanggap na anyo) |
reply_to |
✓ | Tuwirang input sa pamamagitan ng reply_to_or_zero (V2 preimage — ang tanging tinatanggap na anyo) |
content_type |
✓ | Transitively, sa pamamagitan ng qub_id preimage |
created_at |
✓ | Sa pamamagitan ng transitibo qub_id paunang-larawan |
outcome_at |
✓ | Transitibo, sa pamamagitan ng qub_id paunang-larawan |
drand_round |
✓ | Transitively, sa pamamagitan ng qub_id paunang-larawan |
body |
✓ | Transitively, sa pamamagitan ng body_hash = SHA3-256(body) |
author_pubkey |
— (palihim) | Ang susi na nagpapatunay na ang lagda ay mula sa may-akda, ayon sa kahulugan |
cosigner_pubkey / cosigner_signature |
— | Malaya na pinirmahan sa parehong sig_input (tingnan §9.7) |
drand_chain_id, tlock_ciphertext, visibility |
— | Panlabas SealedQub mga patlang, hindi sa loob ng sobre — sakop ng kanilang sariling mga estruktural na invariant (pagkakapareho ng bilog / kadena) ngunit hindi ng pirma ng may-akda. (drand_round ay ngayon ay konektado sa pamamagitan ng qub_id preimage — tingnan sa itaas.) |
Bakit ang V2 lamang ang tinatanggap na preimage.
- Sa ilalim ng inalis nang V1 preimage, ang isang panig na may write access sa mga naka-imbak na bytes ay maaaring magpalit ng
sender_label("Alice" → "Mallory") o mag-re-parent ngreply_to— at muling mag-encrypt pagkatapos ng round — nang hindi pinawawalang-bisa ang lagda ng may-akda, dahil wala sa alinmang field sa naka-lagdang preimage. Sinasaklaw ng V2 ang dalawa, kaya ang anumang pagbabago sa alinmang field ay nagbabago ng pagberipika patungong "nabigo". Dahil ang mga verifier ngayon ay tumatanggap lamang ng V2, ang palitan na ito ay sarado na para sa bawat lagda: ang isang lagda na hindi nagbubuklod sa alinmang field (i.e. nagve-verify lamang laban sa V1) ay tinatanggihan nang tuluyan sa halip na i-downgrade dito. - Ang
author_pubkeysa loob ng envelope ay nananatiling tunay na anchor ng pagkakakilanlan — ang mga mambabasa ay MUST kumuha ng display identity mula saauthor_pubkey(sa pamamagitan ng §9.5 attestation layer) sa halip na magtiwala sasender_label.
Ang mga implementasyon na nagpapakita ng sender_label o reply_to sa mga end user ay MUST ilantad ang authenticated identity (pubkey fingerprint, attestation) bilang pangunahing signal ng pagkakakilanlan, hindi ang label.
9.4 Pamamaraan ng Pagberipika
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."
Ang pagberipika ng lagda ay ang pinakamamahal na operasyon (lalo na ang ML-DSA-65). Ito ay SHOULD isagawa pagkatapos pumasa ang lahat ng mas murang pagsusuri (hash, qub_id, unlock_at).
9.5 Mga Attestation ng Pagkakakilanlan
Ang mga attestation ng pagkakakilanlan — ang pagmamapa ng author_pubkey sa mga claim ng pagkakakilanlan na nakikilala ng tao tulad ng qub handle, email address, social handle, o passkey credential — ay isang viewer-side progressive enhancement at hindi kinakailangan para sa pagberipika ng lagda. Ang mga mambabasang nagrereresolba ng attestation sa display identity ay MUST gamitin ang precedence:
handle > email > social > fingerprint
Ang fingerprint fallback ay ang lowercase hex ng SHA3-256(author_pubkey); palagi itong available para sa anumang naka-lagdang qub. Ang mga viewer ay MAY paikliin ito para sa pagpapakita — ang reference viewer ay nagre-render ng qub: na sinusundan ng unang at huling apat na bytes (qub:<8 hex>…<8 hex>).
Ang isang sumusunod na verifier ay maaaring makumpleto ang bawat tseke sa §9.4 nang hindi nakikipag-ugnay sa qub API, nang walang network maliban sa permanenteng storage at drand, at walang anumang server-side lookup. Ang attestation resolution ay isang hiwalay na best-effort step na isinasagawa lamang pagkatapos ng matagumpay na pagberipika ng lagda.
9.6 Epekto sa Laki
| Ed25519 | ML-DSA-65 | |
|---|---|---|
| Signature | 64 bytes | 3,309 bytes |
| Public key | 32 bytes | 1,952 bytes |
| Total per qub | 96 bytes | 5,261 bytes |
| Storage cost delta (at ~$5/MB) | ~$0.0005 | ~$0.026 |
Para sa isang text qub na 500–2,000 bytes, ang ML-DSA-65 ay halos triple ang naka-imbak na laki. Ang absolute cost ay napakaliit.
9.7 Pagberipika ng Kasamang Lagda (mga Bilateral na Kasunduan)
Para sa mga bilateral na kasunduan (content_type = 0x03), isang pangalawang signature layer ang nagpapatunay na pinagsang-ayunan ng dalawang panig ang parehong mga termino.
Mga envelope field:
cosigner_pubkey: ML-DSA-65 public key ng counter-signer (Party B).cosigner_signature: Lagda sa parehongsig_inputtulad ng sa may-akda (§9.3).
Parehong field ay MUST naroroon nang sama-sama o parehong wala. Kung eksaktong isa lamang ang naroroon, ang mga mambabasa ay MUST mag-ulat ng integrity error.
Pamamaraan ng pagberipika:
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."
Mga katangian:
- Ang kasamang lumagda ay pumipirma ng magkaparehong
sig_inputtulad ng may-akda — parehong panig ay nangangako sa parehongqub_id,body_hash, atunlock_at(at, sa ilalim ng V2, ang parehongsender_label_hashatreply_to_or_zero). - Upang mabuo muli ng counter-signer ang V2 preimage nang walang access sa raw envelope bytes, ang staging service ay nagpapatupad sa stage time na ang
sender_labelng isang pact envelope ay katumbas ngpact_terms.party_a.labelat na angreply_toay wala. Parehong totoo para sa bawat reference-client na pact; ang mga lumalabag na envelope ay tinatanggihan sa staging. - Ang derivation ng
qub_id(§4.1) ay HINDI kasama ang mga field ng kasamang lumagda. Ang pagdaragdag ng kasamang lumagda sa umiiral na envelope ay hindi nagpapabago ngqub_id. - Ang isang kasunduan ay maaaring author-signed lamang (one-sided commitment), cosigner-only (hindi karaniwan), o pareho (full bilateral proof).
Email-binding gate (operasyonal). Kapag ang isang staged na kasunduan ay nagdadala ng Party B email contact (§6.1), ang qub upload service ay MUST tanggihan ang co-sign request maliban kung mayroong panandaliang email-verification marker na tumutugma sa staging id at sa normalised-email hash ng contact na iyon. Ang marker ay isinusulat ng /api/v1/auth/verify kapag ang magic-link token ay nagdadala ng staging_id at ang naverify na address ay tumutugma sa SHA-256(normalise_email(party_b.contact)) — kung saan ang normalise_email(addr) ay nagpapanatili ng case ng local-part at nagpapababa lamang ng case ng domain part (ayon sa RFC 5321 §2.3.11), at ang SHA-256 dito ay ang NIST FIPS 180-4 hash (naiibang mula sa SHA3-256 na ginagamit sa §4 derivations) — at nag-eexpire 900 segundo (15 minuto) pagkatapos ng pag-issue. Ito ay operasyonal na anti-impersonation gate, HINDI bahagi ng on-chain qub proof — ang isang third-party verifier na nagre-replay ng §11 ay nangangailangan lamang ng permanenteng storage at drand, walang anumang server-side lookup. Ang marker ay umiiral sa server-side lamang at hindi kailanman bahagi ng naka-lagdang katawan.
Epekto sa laki (ML-DSA-65 may-akda + kasamang lumagda):
| Component | Size |
|---|---|
| Author signature | 3,309 bytes |
| Author public key | 1,952 bytes |
| Cosigner signature | 3,309 bytes |
| Cosigner public key | 1,952 bytes |
| Total crypto overhead | 10,522 bytes |
| Storage cost delta | ~$0.05 |
10. Pag-render at Pag-sanitise ng Markdown
Ang seksyong ito ay kritikal sa seguridad. Ang mambabasa ay nagre-render ng mga text qub (content_type = 0x01) gamit ang isang pinaghihigpitang subset ng Markdown.
10.1 Mga Pinapayagang Elemento
- Mga heading:
#hanggang####(walang#####o######) - Emphasis: bold (
**), italic (*), strikethrough (~~) - Mga listahan: ordered (
1.) at unordered (-,*) - Blockquotes (
>) - Code: inline spans (```) at fenced blocks (`````)
- Mga horizontal rule (
---) - Mga line break (dalawang trailing space o blangkong linya)
- Mga talata
10.2 Mga Ipinagbabawal na Elemento
| Element | Handling |
|---|---|
Raw HTML (<div>, <script>, etc.) |
Stripped entirely. No HTML passes through. |
Images () |
Stripped. Image syntax is removed from output. |
Links ([text](url)) |
URL rendered as visible plain text. Not auto-linked. Not clickable without explicit user action. |
| Dangerous URL schemes | javascript:, data:, vbscript:, file: — stripped. |
| Iframes, embeds, objects | Stripped. |
| HTML entities | Decoded to display characters only if safe. |
10.3 Implementasyon
Ang mga implementasyon ay MUST gumamit ng strict allowlist parser, hindi blocklist. Ang inirerekomendang approach:
- I-parse ang Markdown gamit ang
pulldown-cmark(o katumbas). - Lakaran ang AST at i-drop ang anumang node na wala sa allowlist (§10.1).
- Para sa mga link node: i-emit ang URL bilang nakikitang text, hindi bilang isang clickable na
<a>element. - I-convert ang filtered AST sa isang typed intermediate representation (hal., isang
MarkdownNodeenum na may mga safe variant lamang). Ang raw HTML ay structurally unrepresentable sa IR na ito. - Mag-render mula sa typed IR papunta sa target view layer (hal., reactive view components, DOM nodes). Walang HTML string concatenation o
innerHTMLsa anumang punto.
Ang mga blocklist approach ay marupok dahil ang mga bagong Markdown extension o parser quirk ay maaaring magpasok ng mga hindi nasala na elemento. Ang typed-AST approach ay ginagawang structurally imposible ang XSS — walang variant na maaaring magdala ng arbitrary HTML.
10.4 Mga Limitasyon sa Laki at Istruktura
- Pinakamataas na rendered heading depth:
####(H4). Ang#####at mas malalim ay nire-render bilang bold text. - Walang limitasyon sa bilang ng talata (ang mga limitasyon sa laki ng katawan sa §6 ang nagdidikta).
- Mga fenced code block: walang syntax highlighting sa MVP. Naka-render bilang monospace preformatted text.
11. Pagpapatunay ng Ikatlong Panig
Anumang ikatlong partido na humahawak sa naka-imbak na bytes (at K para sa isang pribado/naka-balot na qub) ay maaaring beripikahin ang kriptograpikong artipakto nang walang kooperasyon ng qub. Isang malaya may petsa at oras pag-iral ang pag-angkin ay kinakailangan din ng alinman sa na-verify per-qub na permanent-storage na pagsasama o isang beripikadong §16 na katibayan mula sa transparency-log.
1. Obtain the stored bytes. For a private delivery, also obtain K from the
delivery-link fragment.
2. Resolve the delivery shape (§8 step 3a): unwrap OuterWrapper with K, or
accept bare SealedQubCbor. Require shape/visibility agreement.
3. Parse SealedQubCbor → SealedQub; validate protocol version, visibility,
content type, chain identity, and structural bounds.
4. Recompute expected_round from unlock_at (§4.3); require the stored round
(allowing the documented legacy minus-one case) and ciphertext-stanza round
to agree exactly as §8 step 6a specifies.
5. Obtain the drand signature for SealedQub.drand_round and verify its BLS
signature against the pinned chain public key.
6. tlock_decrypt(tlock_ciphertext, round_signature) → QubEnvelope CBOR bytes.
7. Parse → QubEnvelope.
8. Verify SHA3-256(body) == body_hash.
9. Verify envelope/sealed equality for qub_id, unlock_at, and outcome_at.
10. Recompute qub_id from the decrypted fields, sealed drand_round, and title;
require it to equal the carried qub_id (§4.1).
11. If sig_alg != 0x00, verify the V2 author signature (§9.4). If cosigner
fields are present, verify their pairing, key separation, and signature
(§9.7).
12. For an existence-time claim, independently verify either:
a. the permanent-storage transaction's data-to-id binding, owner, block
inclusion, and block timestamp; or
b. a §16 inclusion proof through its pinned anchor and anchor block time.
13. Report each verified claim separately; do not collapse an absent storage
or anchor proof into a successful timing verdict.
Ano ang pinatutunayan ng beripikasyon:
| Patunayan ang input | Kung ano ang itinataguyod nito |
|---|---|
| Bale-walang bisa / selyadong artipakto + pirma ng drand | Ang natagpuang katawan ay tumutugma body_hash; ang metadata na nakatali sa qub_id ay buo; ang ciphertext ay nakatali sa idineklarang drand round; at ang round na iyon ay lumipas na. Ito ay hindi tataguyod kung kailan nilikha ang ciphertext. |
| Balidong lagda ng may-akda/kasamang lumagda ng V2 | Ang may hawak ng kaukulang lihim na susi ay nagpapatunay sa pinirmahang ibabaw sa §9.3. |
| Independiyenteng beripikadong bawat transaksyon sa imbakan ng qub | Ang eksaktong nakaimbak na ciphertext ay umiiral hindi hihigit sa oras ng kanyang block timestamp. |
| Balidong nakatali na katibayan ng talaan ng transparency | Ang claim na tiyak sa uri ng dahon sa §16.11, kasama ang isang oras ng pangako na nasa itaas na hanggan mula sa anchor block. |
Ano ang hindi pinatutunayan ng beripikasyon:
| Hindi patunay | Bakit |
|---|---|
| Pagkakakilanlan ng may-akda | Ang sender_label ay pampalamuti. Nang wala sig_alg ≥ 0x01, kahit sino ay maaaring nakapirma ng nilalamang ito. |
| Layon | Pinapatunayan ng artifact ang bytes at mga ugnayang kriptograpiko, hindi ang kung ano ang pakahulugan ng lumikha nang panandalian. |
Naunang pangako mula sa .qub mag-isa |
Maaaring buuin ng isang tagalikha ang isang wastong bundle pagkatapos lumipas ang itinakdang round. Ipinapakita ng naka-embed na drand signature na lumipas ang round, hindi na ang ciphertext ay umiiral bago ito. |
| Eksaktong oras ng pindutan ng selyo | Ang timestamp ng isang storage o anchor block ay isang malaya na maaaring patunayan na pinakamataas na hangganan, at maaaring mahuli sa lokal na aksyon ng gumagamit. sealed_at / received_at ang mga pahayag ay walang ebidensya. |
Ang ipinatupad na transparency log (§16) ay nagpapalawak ng beripikasyon sa lahat ng qubs kasama ang
halatang pinakialaman pag-oorder at isang walang tiwala oras ng pinakamataas na hangganan ng pangako (ang
oras ng anchor block), isinasaalang-alang batay sa uri ng dahon (§16.11). Hindi ito nagdadagdag ng pagiging may-akda o
layunin; para sa default na byte-blind na path ng pag-upload, hindi nito napatutunayan mismo
body_hash o drand_round, na patuloy na nagmumula sa mga tseke ng artepakto.
12. Pag-versiyon at Kontrol ng Pagpapalabas
Ang pagpapalabas ng dokumento, ang panloob na wire protocol, at ang panlabas na pambalot ay hiwalay mga puwang ng bersyon. Ang paglilinaw na nakatuon lamang sa dokumento ay samakatuwid ay hindi tahimik palitan ang mga byte, at ang isang hinaharap na paglipat ng wire ay hindi maaaring magpanggap bilang isang editoryal rebisyon.
12.1 Bersyon ng Pagpapalaya ng Dokumento
Ang espesipikasyong ito ay gumagamit ng mga semantic na paglabas ng dokumento (MAJOR.MINOR.PATCH) at
isang hindi nababagong Git tag na pinangalanan protocol-v<release>.
- PLASTA: kawastuhan o pagwawasto ng editoryal na hindi binabago ang mga sumusunod na byte o kinakailangang pag-uugali.
- BATANGE: pabalik na katugmang normatibong karagdagan, bagong tala sa rehistro, o bagong independiyenteng bersyon na format ng sidecar.
- MAJOR: hindi tugmang pagbabago sa pamantayan, kabilang ang bagong kinakailangang interpretasyon ng kawad.
Ang status ng pagpapalabas ay isa sa Burador (hindi pa pamantayan), Kasalukuyan (ang nag-iisa
inirerekomendang target na pagpapatupad), o Napalitan (napanatili para sa historikal)
beripikasyon). Ang hindi na-version /protocol ipinapakita ng ruta ang Kasalukuyang bersyon;
Ang release tag ay pinapanatili ang eksaktong pinagmulan nito at bawat locale na nai-publish kasama nito.
Ang pagbabago ng status o numero ng release ay nangangailangan ng pag-update sa talahanayan at sa release
kasaysayan sa parehong nirepasong pagbabago.
| Pagpapalabas ng dokumento | Epektibong petsa | Katayuan | Protokol ng kawad | Balot | Pinagmulan |
|---|---|---|---|---|---|
| 1.0.0 | 2026-09-23 | Kasalukuyan | 0x01 |
0x01 |
protocol-v1.0.0 |
12.2 Bersyon ng Protokol
Ang version field (u8) sa parehong SealedQub at QubEnvelope tinutukoy ang pangunahing bersyon ng protocol.
- Dapat tanggihan ng mga manonood ang mga hindi kilalang pangunahing bersyon na may malinaw na error.
- Sa loob ng isang kilalang pangunahing bersyon, DAPAT tanggihan ng mga decoder ang hindi kilalang mga susi ng mapa (§3.1) — nangyayari ang ebolusyon ng iskema sa pamamagitan ng pagpapakilala ng bago
version, hindi sa pamamagitan ng pagdagdag ng mga susi na laktawan ng umiiral na mga decoder. (Ang mga naunang rebisyon ng espesipikasyong ito ay pinahihintulutang tanggapin ang mga hindi kilalang opsiyonal na patlang; ang talatang iyon ay inalis — ginawa nitoencode(decode(x))hindi-injeksyonal at nagbukas ng nakatagong-lagda-na-laman na vector sa mga pact payloads.) - Mga uri ng nilalaman (
content_type) at mga scheme ng pirma (sig_alg) ay version-gated: ang mga bagong halaga ay maaari lamang ipakilala kasabay ng bagong bersyon ng protocol o tahasang pag-update ng talaan.
12.3 Kasaysayan ng Bersyon ng Protokol
| Bersyon | Halaga | Paglalarawan |
|---|---|---|
| v1 | 0x01 |
Pribado/naka-balot at pampubliko/kalat na paghahatid; teksto (0x01), kasunduan (0x03), at hatol (0x04) mga katawan; ML-DSA-65 V2 may-akda/kasamang lumagda; drand quicknet tlock; SHA3-256. |
12.4 Pasulong na Kakayahang Tumbasan
Ang isang v1 viewer na nakatagpo ng QubEnvelope na may hindi kilalang CBOR map na mga susi (mga susi na hindi nasa §3.2 canonical na pagkakasunud-sunod) DAPAT itong tanggihan na may decode error (§3.1). Nakadepende ang forward compatibility sa version larangan, hindi sa pagtitiis ng susi: mga darating na karagdagan — kahit na maliit na metadata — ipinapadala sa ilalim ng bago version halaga, na tinatanggihan ng isang v1 viewer na may malinaw na error na "mas bagong protocol" sa halip na tahimik na i-drop ang content na pinagtibay ng mga lagda.
Isang manonood ng v1 na nakakasalubong sig_alg = 0x01 (ML-DSA-65) ngunit kung walang suporta sa beripikasyon ng ML-DSA-65 AY DAPAT ipakita ang nilalaman ng qub na may paunawang “may lagda ngunit hindi maverify”, hindi tuluyang tanggihan ang qub. Ang sangguniang implementasyon ngayon ay tinatanggihan ang bawat sig_alg halaga maliban sa 0x00 at 0x01 dahil ang v1 registry ay wala nang ibang wastong algorithm — ang mahigpit na pagtanggi at malambot na pagkabigo ay obserbasyonal na magkatulad hanggang sa mairehistro ang isang ikatlong algorithm. Ang pamamaraang malambot na pagkabigo sa itaas ay nagiging mahalaga kapag pinayagan ng §9.2 ang isang bagong entry, at ang reference viewer ay ia-update sa malambot na pagkabigo sa puntong iyon.
12.5 Bersyon ng Panlabas na Balot
Ang OuterWrapper na inilarawan sa §13 ay may dala nito version baits malaya ng SealedQub.version at QubEnvelope.version. Ang dalawang version space ay umuunlad nang hiwalay: ang isang hinaharap na post-quantum-safe na symmetric replacement ay nagtataas ng wrapper byte nang hindi hinahawakan ang inner protocol version, at isang hinaharap na protocol-layer addition (hal., isang bagong envelope field) ay nagtataas ng inner version nang hindi hinahawakan ang wrapper byte.
OUTER_WRAPPER_VERSION_* |
Halaga | Algoritmo | Katayuan |
|---|---|---|---|
OUTER_WRAPPER_VERSION_1 |
0x01 |
AES-256-GCM na may 12-byte nonce, 16-byte authentication tag, AAD na nakakabit sa qub_id |
Aktibo para sa pribadong paghahatid |
| — | 0x02–0xFF |
Nakalaan | Kinabukasan |
Dapat tanggihan ng mga manonood ang mga hindi kilalang bersyon ng wrapper na may malinaw na error. Sinasadyang pinananatiling makitid ng protocol ang espasyo ng bersyon ng wrapper hanggang sa lumitaw ang isang konkretong driver ng migrasyon (hal., patnubay ng NIST na pabor sa ibang AEAD); a 0x02 Ang slot ay ilalaan sa parehong rebisyon na nagpakilala ng algorithm.
13. Outer Encryption Wrapper
13.1 Katwiran
Ang mga protocol layer (QubEnvelope → tlock → SealedQub) ay gumagawang time-locked ng isang naselyong qub: ang katawan ay hindi mababasa hanggang sa unlock_at at na-publish ang drand round signature. Pagkatapos ng paghahayag, gayunpaman, ang round signature ay pampubliko at ang canonical CBOR shape ng SealedQub ay nakikilala, kaya ang isang harvester na nag-index ng mga permanenteng-storage transaction ay maaaring bulk-decrypt ang buong qub corpus.
Para sa pribadong paghahatid, ang panlabas na encryption na pambalot ay isinasara ang kanal na iyon sa pamamagitan ng paglalagay ng karagdagang symmetric AEAD na layer sa pagitan ng canonical SealedQubCbor at ang nakaimbak na bytes. Sa path ng browser-seal, ang 256-bit na susi K mga buhay lamang sa bahagi ng URL ng delivery URL at sa mga device ng gumagamit; ang mga browser ay hindi nagpapadala ng mga bahagi ng URL sa mga server, kaya ang qub.social, bawat storage gateway, at bawat CDN sa harap ng alinman sa dalawa ay obserbasyonal na bulag sa K. Ang nakaimbak na representasyon ng isang pribadong qub ay samakatuwid na opaque na ciphertext na ang plaintext ay hindi na mababawi nang wala ang URL na pinili ng tagalikha na ibahagi. Ang pampublikong paghahatid ay sinadyang tinatanggal ang layer na ito (§13.8).
Net effect:
- Pagtutol sa pagbibilang para sa pribadong paghahatid.
OuterWrappernananatiling makikilala ang nakaayos na CBOR—hindi ito literal na hindi mahahambing sa mga random na byte—ngunit tinatago ng kanyang ciphertext field ang makikilalang loobSealedQubhugis. Ang naitalang estratehiya ng tag-aani na "GraphQL-query para sa mga bare qub-shaped na upload, bulk-decrypt gamit ang mga pampublikong drand na pirma" ay hindi nagtatapos sa plain text kung walang K. - Crypto-shredding na postura sa privacy para sa default na pribadong daloy ng browser. Hindi ma-decrypt ng qub.social ang mga nakaimbak na artipakto mula sa default nitong server-side na data. Magkaiba ang ipinapakitang mga hangganan ng tiwala ng tahasang pagbawi, pampublikong paghahatid, at pinagkakatiwalaang server-side na sealing.
- Doble antas na hagdan ng pagiging kompidensiyal. Default = link-controlled access (itong seksyon). Recipient-encrypted private qubs (isang nakalaang Phase-2 na tampok, hindi pa tinutukoy) ay inilalagay sa itaas bilang ikalawang antas.
13.2 Layering
plaintext body ← QubEnvelope.body (§2.2)
↓ canonical CBOR (§3)
envelope CBOR
↓ tlock encrypt to drand round (§7 step 10)
tlock_ciphertext (inside SealedQub) (§2.3)
↓ canonical CBOR (§3)
SealedQubCbor bytes ← inner wire artifact
├─ public (visibility=0x01) ───────────────▶ stored directly (§13.8)
└─ private (visibility=0x00)
↓ AES-256-GCM(K, nonce, AAD=qub_id) (§7 step 12, this section)
OuterWrapper CBOR bytes ← stored private payload
Ang pag-selyo at paghahayag sa protocol layer (§7, §8) ay hindi nagbabago sa ilalim ng wrapper boundary; ang wrapper ay nakakabit sa call site ng seal() at nahihiwalay sa call site ng unlock().
13.3 Istruktura ng Datos ng OuterWrapper
struct OuterWrapper {
version: u8, // 0x01, see §12.5
qub_id: [u8; 32], // copied from inner SealedQub; AEAD AAD
nonce: [u8; 12], // 96-bit AEAD nonce
ciphertext: Vec<u8>, // AES-256-GCM(K, nonce, SealedQubCbor, AAD=qub_id) || 16-byte tag
}
Mga invariant ng field.
versionDAPAT pantay0x01para sa v1.0 wrapper bytes.qub_idDAPAT magkapantay saqub_idlarangan ng SealedQub na nakuha matapos buksan. Parehong sanggunianwrap_sealed_qubatunwrap_sealed_qubi-parse ang panloob na CBOR at ipatupad ang pagkakapantay na ito nang direkta; ang hiwalay na AAD binding ay nagiging sanhi ng pag-alter pagkatapos i-wrap ang panlabasqub_idnabigo sa pagpapatunay.nonceDAPAT ay 96 na bits (12 bytes), na sariwang ginawa ng CSPRNG para sa bawat wrap na operasyon. Ang muling paggamit ng nonce sa parehong susi ay nagpapahintulot sa AEAD nonce-reuse na mga atake na nakakabawi ng plaintext; ang mga tagagawa DAPAT tratuhin (key,nonce) na pares bilang one-shot.ciphertextang output ng AES-256-GCM: mga byte ng ciphertext na pinagsama sa 16-byte na authentication tag.ciphertext.len() == SealedQubCbor.len() + 16eksakto.
Encoding ng CBOR. Canonical CBOR ayon sa §3, na may parehong key-ordering rule (na-sort ayon sa encoded byte length na pataas, pagkatapos ay lexicographically). Ang apat na key ay:
| Key | Encoded bytes | Order |
|---|---|---|
nonce |
6 | 1 |
qub_id |
7 | 2 |
version |
8 | 3 |
ciphertext |
11 | 4 |
Ang unang byte ng OuterWrapper CBOR ay samakatuwid ang definite-length map header para sa 4-entry map (0xA4).
13.4 AAD Binding sa qub_id
Iniuugnay ng wrapper ang qub_id bilang AEAD additional authenticated data. Ito ay ang load-bearing structural defence laban sa tatlong klase ng atake:
| Atake | Depensa |
|---|---|
Ilipat ang ciphertext sa ilalim ng iba qub_id larangan sa pambalot |
Hindi tugma ang AAD → Nabigong AEAD authentication |
| Haluin ang fragment ng URL ng qub A sa naka-imbak na bytes ng qub B | Maling susi (at independiyenteng nakatali na AAD) → Nabibigo ang AEAD authentication |
Manoklo sa qub_id larangan ng pambalot pagkatapos ng pag-upload |
Hindi tugma ang AAD → Nabigong AEAD authentication |
Ang pagdadala ng qub_id sa wrapper plaintext ay hindi nagpapahina sa enumeration immunity nang makabuluhan — ang qub_id mismo ay isang SHA3-256 hash ng §4.1 preimage na walang mababawing preimage mula sa digest, at ang isang enumerator na nag-harvest na ng wrapper bytes ay walang natututunan mula sa nakikitang qub_id na hindi nila mahihinuha mula sa pag-iral mismo ng upload.
13.5 Mga Wrap at Unwrap Algorithm
wrap_sealed_qub(SealedQubCbor S, qub_id Q, key K, nonce N):
require K.len() == 32 and N.len() == 12 and Q.len() == 32
I := canonical_cbor_decode(S) as SealedQub
require I.qub_id == Q // reject mismatched caller AAD
C := AES_256_GCM_encrypt(key=K, nonce=N, msg=S, aad=Q)
// C includes the 16-byte authentication tag at the end
return canonical_cbor_encode(OuterWrapper{
version: 0x01,
qub_id: Q,
nonce: N,
ciphertext: C,
})
unwrap_sealed_qub(OuterWrapper bytes W, key K):
require K.len() == 32
O := canonical_cbor_decode(W) as OuterWrapper
require O.version == 0x01 // §12.5
P := AES_256_GCM_decrypt(
key=K, nonce=O.nonce, ciphertext=O.ciphertext, aad=O.qub_id
)
// any AEAD failure → DECRYPT_FAILED, indistinguishable to caller
S := canonical_cbor_decode(P) as SealedQub
require S.qub_id == O.qub_id // explicit inner/outer cross-check
return P // P is the validated SealedQubCbor
Pagbagsak ng failure-mode. Ang maling K, maling nonce, AAD mismatch, at tampered ciphertext ay lahat gumagawa ng parehong DECRYPT_FAILED error. Ito ay sadyang AEAD property: ang pagkilala sa failure mode ay magbubuo ng side channel na maaaring sundutin ng isang malayong umaatake sa pamamagitan ng pagpapadala ng malformed wrapper at pag-time ng tugon. Ang mga reference implementation ay MUST i-collapse ang lahat ng AEAD failure sa iisang error shape.
13.6 Susing Materyal at Pamamahagi
Ang wrapping key na K ay isang 256-bit uniform random value na nabuo bawat qub ng isang CSPRNG. Ang mga reference implementation ay kumukuha nito mula sa:
- WASM creator:
getrandom(WebCrypto sa ilalim ngwasm_jsbackend). - Caller ng server-side seal API: ang lokal nitong CSPRNG; ang caller ang naglalaan at nagpapanatili ng
Kbilangwrapper_key_b64url. Ginagamit ng Worker angKsa memorya para sa wrapper ngunit MUST NOT itong panatilihin. Nagbibigay-daan ito sa isang idempotent na retry na mabawi ang isang redacted na response gamit ang napanatiling capability ng caller sa halip na umasa sa isang one-shot na secret na nabuo ng server.
Pamamahagi: ang K ay MUST naka-encode bilang URL-safe base64 (RFC 4648 §5, walang padding) at idinaragdag sa delivery URL bilang fragment component:
delivery_url = <origin>/c/<arweave_tx_id>#<base64url(K)>
Ang fragment ay hindi kailanman ipinapadala sa anumang server ng isang sumusunod na browser. Ang mga recovery channel (server-side history index, opt-in email auto-send) na nagpapanatili ng buong link sa paghahatid — kasama ang fragment — lampas sa device ng gumagamit ay isang tahasang trade laban sa default crypto-shredding posture at MUST naka-gate sa tahasang pahintulot ng gumagamit.
Pagkawala ng fragment. Kung mawawalan ang isang gumagamit ng URL fragment at walang recovery channel, ang qub ay hindi mababasa. Ito ay ang load-bearing trade-off ng disenyo at MUST ipakita sa gumagamit sa oras ng pag-selyo. Pinalalakas ng MVP ang seal-time disclosure na may tahasang "save this URL" copy at isang verified-email recovery channel para sa mga gumagamit na nag-opt in.
13.7 Wala sa Saklaw para sa Seksyong Ito
- Ang paglagda sa may-akda (§9) ay hindi nagbago: ang mga pirma ay kinukuwenta sa loob ng panloob
QubEnvelopeat naibabalik matapos i-unwrap → tlock decrypt → CBOR parse. - Pag-encrypt ng pampublikong susi ng tatanggap (ang nakalaan)
recipient_pubkeyang field) ay isang hinaharap na tampok na naiiba sa kasalukuyang pribado, mode ng wrapper na pinapahintulutan ng kakayahan sa link. - Ang kasalukuyang server-side na daloy ng pact co-sign ay naglalabas ng pampubliko/bakal
SealedQubCborna may kakayahang makita0x01; hindi nito kayang matugunan ang browser-only K-secrecy model dahil nagaganap ang huling sealing pagkatapos ng server-mediated co-sign. Maaaring gumamit ang isang susunod na private-pact producer ng parehong wrapper, na byte-blind sa uri ng panloob na nilalaman.
13.8 Mga Pampublikong qub (pag-alis ng wrapper)
Ang panlabas na pambalot ay opsyonal sa layer ng paghahatid. Maaaring selyuhan ng isang tagalikha ang isang qub bilang pampubliko, kung saan ang kanonikal SealedQubCbor pumasok sa imbakan na tubo direkta, na walang OuterWrapper layer at walang key K:
SealedQubCbor bytes ──(public)──▶ stored as-is
SealedQubCbor bytes ──(private)─▶ AES-256-GCM(K, …) ▶ OuterWrapper ▶ stored
Ang isang pampublikong qub ay nakalakip sa oras pero hindi naka-link na nakalakip: nananatiling hindi mabasa hanggang sa mailathala ang drand round nito (hindi nagbago ang tlock layer), pero pagkatapos ma-unlock, sinuman na may storage transaction id ay maaaring i-decrypt ito — hindi kailangan ang URL fragment, dahil wala K. Ito ang sinadyang kalakalan para sa mga surface na kailangang ipatupad ng server: mga email ng abiso sa pag-bunyag, mga link na oEmbed/auto-embed na walang fragment, at mas mayamang post-reveal SEO ay lahat nangangailangan ng link na gumagana nang walang lihim na hindi hawak ng server (§13.6). Maaari pa ring gumamit ang isang pribadong qub ng tahasang <qub-embed src="full_delivery_url"> form kapag nagbibigay ang tagapaglimbag ng kumpletong kakayahan nitong naglalaman ng pira-piraso.
Mga kahihinatnang DAPAT isaalang-alang ng isang producer:
- Walang imyunidad sa pagbibilang. Ang mga pampublikong qubs ay isinasantabi ang ari-arian ng immunidad-sa-enumerasyon ng §13.1 sa pamamagitan ng konstruksyon. Ang serbisyo ng pag-upload ng sanggunian ay nagtatak ng isang
Visibility: publicpermanent-storage tag sa kanila (at sa kanila lamang) upang sila ay sinadyang matuklasan; ang mga pribadong qub ay walang ganitong tag at pinananatili ang kanilang byte-indistinguishability. - Nakahayag ang pamagat na plain text sa oras ng selyo. Ang §3.2
titleang patlang ay simpleng teksto sa loobSealedQubCbor. Nakatago ito sa ilalim ng pambalot hanggang ang manonood ay magbigayK; kung wala ang pambalot, ito ay mababasa ng mundo sa permanenteng imbakan mula sa sandali ng pag-upload, bago i-unlock. Ang mga app na nilikha ng tagalikha na sumusunod sa alituntunin AY DAPAT ihayag ito sa oras ng selyo. - Ang pagtuklas ay estruktural at pinagsusuri. Isang sumusunod na manonood/embed ay naghihiwalay sa dalawang naka-imbak na hugis sa pamamagitan ng parse: mga byte na nai-parse bilang
OuterWrapperkunin ang buksan-sa-Kdaan; mga byte na nagpa-parse bilang isang payatSealedQubCboray tinatanggap nang direkta. Ang narekober na panloob na halaga AY DAPAT sumang-ayon (0x00para sa naka-balik/naka-pribado,0x01para sa hubad/pampubliko).qub_idhindi nagbubuklod ng nakikita, ngunit ang kanonikalSealedQubAng mga byte ay nagdadala nito, kaya ang pampubliko at pribadong panloob na mga encoding ay hindi magkapareho sa byte.
Ang pribado (naka-wrap) ay nananatiling default; ang pampubliko ay isang tahasang per-qub na pagpili ng tagalikha.
14. Mga Test Vector
14.1 qub_id Derivation
Input:
version = 0x01
content_type = 0x01
created_at = 1735689600 (2025-01-01 00:00:00 UTC)
unlock_at = 1736294400 (2025-01-08 00:00:00 UTC)
outcome_at = absent
drand_round = 4695446 (= floor((1736294400 - 1595431050) / 30) + 1, §4.3 mapping, drand mainnet params §14.2)
body = "Hello, future." (UTF-8, 14 bytes)
title = absent
Intermediate:
body_hash = SHA3-256("Hello, future.")
= 76ab8b3f843c6ed4f2d0fd75b9f457b4
ad49dd4450f9c22723ae430e3af3211d
title_hash = [0u8; 32] (title absent — §4.2.1 sentinel)
Domain separator (10 bytes):
[0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00]
Preimage (108 bytes—current protocol v1):
domain_separator || // 10 bytes
0x01 || // version
0x01 || // content_type
0x0000000067748580 || // created_at as i64 big-endian (1735689600)
0x00000000677DC000 || // unlock_at as i64 big-endian (1736294400)
0x0000000000000000 || // outcome_at_or_zero (outcome_at absent)
0x000000000047A596 || // drand_round as u64 big-endian (4695446)
body_hash || // 32 bytes
title_hash // 32 bytes (all-zeros sentinel; title absent)
Expected output:
qub_id = SHA3-256(preimage)
= 4a84e3dfaec32954949c30073f8e6506
fd3204c1bb97f9162b81c7587afe412e
Dapat mag-produce ng magkaparehong resulta ang mga pagpapatupad body_hash at qub_id mga halaga para sa input na ito. Ang test vector na ito AY DAPAT na unang unit test na isusulat. Ang canonical na mga halaga sa itaas ay kinompyut ng reference implementation at DAPAT tumugma nang bit-for-bit. Ang mga historikal na pre-launch prototype na layout (walang live qubs na umaasa sa unang dalawa) ay gumamit ng 92 bytes bago outcome_at (3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0) at 100 bytes pagkatapos idagdag outcome_at_or_zero (b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed). Ang kasalukuyang 108-byte na layout ay idinagdag na drand_round at ang QUB_ID_V2 tagapaghiwalay ng domain. Isang maagang 108-byte na vector na ginamit ang legacy ceil bilog na pagmamapa (drand_round = 4695445) at ginawa 3a9fcb31b750d985c262fada6d4f777fd6a28be831d941d85c131f5a4bbaf8a4—lagi pa ring balido qub_id para sa input na bilog na iyon, habang ang halimbawa sa itaas ay sumusunod sa §4.3 kasalukuyang-round na pagma-map.
14.2 Pag-unlock-Paglaban ng Mapa
Input:
unlock_at = 1735689600
chain_genesis_time = 1595431050
chain_period_seconds = 30
Calculation:
(1735689600 - 1595431050) / 30 = 4675285.0
floor(4675285.0) + 1 = 4675286
drand_round = 4675286
Ang Round 4675286 ay inilathala sa 1595431050 + (4675286 - 1) * 30 = 1735689600—eksakto sa unlock_at, hindi pa kailanman. (Ang paunang pagpapalabas ng legacy ceil nagbigay ng pagmamapa 4675285, inilathala sa 1735689570—30 segundo nang maaga; tinatanggap ng mga tagasuri ang legacy round ayon sa §4.3.)
14.3 Canonical CBOR Round-Trip
Ang mga implementasyon ay MUST magberipika na serialize(parse(serialize(qub))) == serialize(qub) para sa lahat ng valid na input. Ito ay isang property test, hindi iisang vector.
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)
Ang canonical CBOR bytes at SHA3-256 body_hash ay kinakalkula ng reference implementation. Ang mga implementasyon ay MUST gumawa ng byte-identical na CBOR para sa input na ito.
Ang mga implementasyon ay MUST din magberipika na serialize(parse(serialize(pact))) == serialize(pact) para sa lahat ng valid na PactTerms na input (property test).
14.5 Mga Cross-Language Vector ng Outer Wrapper
Ang outer wrapper (§13) ay may hiwalay na canonical fixture sa crates/qub-core/tests/vectors/wrapper_v1.json. Bawat kaso ay nag-aayos ng isang (key, nonce, qub_id, sealed_cbor) tuple bilang opaque hex inputs at nag-aassert ng tiyak na expected_wrapper_hex output. Parehong reference implementations ay kumokonsumo ng parehong JSON file:
- 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).
Ang fixture ay kasalukuyang nagtatakda ng tatlong mababang-level na wrapper na kaso. Sinusubukan nila ang deterministic OuterWrapper pag-encode at AEAD na pagkakatugma nang nakapag-iisa mula sa §13.8 na invariant ng hugis ng paghahatid; partikular, ang makasaysayang pangalan basic-text-public at ang loob nito visibility = 0x01 gawin hindi gawin ang nagresultang naka-wrap na bytes bilang isang alinsunod na pampublikong paghahatid. DAPAT pa ring itago ng isang producer ang pampublikong panloob na bytes nang walang takip at i-wrap lamang ang pribado (0x00) panloob na bytes.
| Kaso | Saklaw |
|---|---|
basic-text-public |
Pangkasaysayang pangalan ng mababang antas na kagamitan. Pinakamaliit na makatotohanan SealedQub hugis, na walang mga opsyonal na patlang; sinusuri lamang ang wrapper bytes at hindi ito sumusunod sa §13.8 na naka-imbak na paghahatid. |
with-recipient-pubkey |
SealedQub kasama recipient_pubkey itakda (nakalaan na hinaharap na landas). Gumagamit ng ibang panloob na hanay ng key ng CBOR; ang kakaibang nilalaman ng fixture nito ay nagbibigay nang hiwalay ng iba qub_id (recipient_pubkey ang sarili ay hindi nasa §4.1 preimage). |
longer-body |
~4 KiB na katawan — nagsasanay ng maramihang byte na CBOR na mga prefix ng haba sa loob ng panloob na sobre at panlabas na ciphertext. |
Ang mga implementasyon ay MUST gumawa ng byte-identical na expected_wrapper_hex para sa mga naitalang input. Ang pag-regenerate ng fixture ay nangangailangan ng QUB_REGEN_VECTORS=1 cargo test -p qub-core --test wrapper_vectors at nakalaan para sa mga sadyang pagbabago sa format.
15. Pamamahala ng Crypto Profile (Hinaharap)
Ang seksyong ito ay impormatibo para sa v1 at magiging normatibo sa unang pagkakataong pumasok ang ikalawang algorithm sa anuman sa mga kriptograpikong primitibo ng qub.
15.1 Kasalukuyang Posisyon
Ang protokol v1 ay nagbubuklod ng eksaktong isang algorithm bawat primitibo:
- Lagda: ML-DSA-65 (
sig_alg = 0x01; 1952-byte na pampublikong susi, 3309-byte na lagda) at hindi nilagdaan (sig_alg = 0x00). Ang codebase ay naglalaan0x02para sa Ed25519, ngunit hindi ito pinapagana ng protocol v1; DAPAT tanggihan ng v1 verifier ang bawatsig_alglabas{0x00, 0x01}. - Oras na naka-lock: drand quicknet lamang — ang chain hash, public key, oras ng simula, at panahon ay mga nakapirming parameter ng network na dala ng reference
DrandTimelockProvider::quicknet()(crates/qub-core/src/tlock.rs) atconfig/drand-endpoints.json. - Panlabas na pambalot: AES-256-GCM v1 lamang (§13).
Kasulukuyang ini-hardcode ng mga verifier ang haba ng key at lagda batay sa bawat aktibong primitibo. Ang sig_alg at ang wrapper-version bytes ay tahasang mga selector, ngunit ang v1 ay hindi gumagawa ng in-band negotiation at tinatanggap lamang ang mga aktibong halaga sa itaas.
15.2 Inaasahang Hugis
Kapag pumasok ang ikalawang algorithm sa protokol, ang verifier ay iko-configure para sa isang pinangalanang CryptoProfile (hal., ExqubV1) na naglilista sa eksaktong set ng mga pinahihintulutang value bawat primitibo — sig_algs, drand chains, wrapper versions, content types. Ang profile ay nakapirmi sa verify time, hindi kailanman pinag-uusapan in-band. Ang anumang value sa labas ng aktibong profile ay tinatanggihan.
Tinitiyak nito na ang pagdaragdag ng ML-DSA-87 o pag-activate ng Ed25519 ay hindi maaaring retroactively magpahina sa mga umiiral na verifier configuration: ang isang v1 verifier ay nananatiling isang v1 verifier kahit na pagkatapos i-publish ang v2 profile.
15.3 Mga Kondisyon ng Trigger
I-promote ang §15 sa normatibong status kapag ang sumusunod ay iminungkahi:
- Isang segundo
sig_algbyte (pag-activate ng Ed25519, ML-DSA-87, o anumang bagong entry sa §9 rehistro). - Isang pangalawang drand chain na ginagamit sa produksyon.
- Isang pangalawang bersyon ng panlabas na pambalot.
- Isang pag-ikot ng transparency-log na pinagkakatiwalaang ugat — ang
LogProfile.anchor_owneraddress o ang naka-pin na resibo-susi pampublikong susi (§16.6). AngLogProfilesumasali sa §15.2 na ibabaw ng profile bilang isang pinamamahalaang primitivo: ang isang pag-ikot ay may lagdaLogProfilenaipadala ang bump sa isang update ng verifier (ang naka-planong mga rotation ay nagkakasign silang cross-sign outgoing → incoming; ang mga rotation na dulot ng kompromiso ay hindi, at umaasa sa bump na ito kasama ang prev-anchor fork check upang limitahan ang pansamantalang pinsala). Ang mga version space ng transparency-log (LOG_VERSION,ANCHOR_FORMAT) umunlad bilang mga malalayang kapatid, eksakto tulad ng §12.5 wrapper na bersyon na malaya sa bersyon ng protocol.
Hanggang sa, ang §15 ay isang placeholder na nag-aayos ng migration shape upang ang mga hinaharap na PR ay mapunta sa isang kilalang target sa halip na muling pag-usapan ang negotiation surface mula sa simula.
16. Transparency Log at Mga Durability Tier (Disenyo — kumpleto na ang review)
Katayuan. Ang seksyong ito ay ipinatupad (W5/UP-B1, Yugto 1–8), kasama ang producer at trust-root na saklaw na nakasaad dito. Ang mga wire format, hashing, at verifier path ay aktibo: ang core Merkle + canonical-CBOR na mga uri (
qub-core), ang TypeScript mirror + ANS-104 bundler (workers/api/src/crypto/), ang nag-iisang manunulatLogDO+ naka-coordinate na R2 node store, ang/uploadpagsubok sa pagdagdag-log, ang pang-araw-araw na anchor + mga cron ng bundler-drain, angGET /api/v1/qub/:tx_id/proof(pagsasama) atGET /api/v1/log/consistency(RFC 9162) mga endpoint ng patunay, ang uri ng patunay ng pagkakasama na dala sa.qubpakete (§17.5), ang katutubong ANS-104 tagasuri ng angkla (tools/qub-verify), at ang dual self-published-heads hook (§16.6). Isang matagumpay/uploaday laging R2-matibay ngunit natatakpan lang ng kahoy na batay kapagLOG_DOay nakaayos at matagumpay ang inline append; doon lamang nagdadala ang tugon nitolog_seq,receipt, atanchor_status. KungRECEIPT_SKay wala o hindi wasto, ang resibong iyonsig_b64urlay walang laman at hindi nagbibigay ng non-repudiation. Ang kasalukuyan/sealat ang mga path ng publikasyon ng kasunduan ay nag-iskedyul ng indibidwal na mga transaksyon sa Arweave ngunit hindi nagdaragdag ng tala sa log. Walang kasalukuyang code ang gumagawa ng/uploadkomento sa iminungkahing panibagong pagkakasundo matapos ang pagkabigo sa append. Ang W5 panlabas na pagsusuri ay kumpleto: §16.15 nagtatala ng mga desisyon sa disenyo at mga limitasyon sa paglulunsad, ngunit ang mga limitasyong iyon ay hindi pinalalawak ang saklaw ng producer na binanggit lamang. Tatlong item ng tiwala/paglulunsad ang nananatiling nakakontra: (a) ang nakalaang anchor wallet (ANCHOR_JWK;LogProfile.anchor_owneray nananatili ang[0xAB; 32]placeholder); (b) ang susi sa pagpirma ng resibo at tumutugmang pampublikong susi na pin (RECEIPT_SKay opsyonal atLogProfile.receipt_pubkeyay kasalukuyang walang laman); at (c) ang self-published-heads na repositoryo sa GitHub + token (§16.6). Hanggang sa maibigay ang anchor/profile pins, ang isang standalone na tagasuri ay tapat na nag-uulat ng status ng patotoo kaysa mag-angkin ng ganap na naka-angkla, na naka-pin na beripikasyon. Ang disenyo ay mahigpit na pantambak at may walang pagbabago saSealedQub/QubEnvelopeformat ng kawad.
16.1 Katwiran at Mga Durability Tier
Ang kasalukuyang mga landas ng publikasyon ay pinaghiwalay ang pagkilala mula sa kumpirmasyon ng Arweave: sila ay kumukuha at pumipirma ng isang indibidwal na transaksyon, iniimbak ang artepakto at eksaktong estado ng pagsusumite sa R2, pagkatapos ay nagpo-post nang hindi sabay-sabay. Ang talaan ng transparency ay nagdaragdag ng isang independiyenteng nakaangkang patong ng pag-aayos para sa subset ng pangkalahatan /upload mga kahilingan na LogDO nagtagumpay ang append:
| Antas | Pangalan | Garantiya | Kailan |
|---|---|---|---|
| T1 | R2-unang sabayang kumpirmasyon | Laban sa pagkasira ng data — ang mga naka-seal na byte at eksaktong estado ng publikasyon ay isinusulat sa matibay na imbakan bago ibalik ang tagumpay. | Ipinatupad sa kasalukuyang mga landas ng publikasyon. |
| T2 | Pagsasama ng transparency-log ng maramihang batch | Tanging pagdaragdag lamang, may ebidensyang proteksyon laban sa pagbabago + kabuuang pagkakasunod-sunod kapag naisama at naitaguyod. | Kasalukuyang prodyuser: matagumpay LogDO idinagdag mula sa /upload; ang tugon ay nagdadala ng resibo na pares. Hindi pangkalahatan. |
| T3 | Per-qub katatagan ng Arweave | Isang indibidwal na transaksyon sa Arweave para sa qub. | Kasalukuyang inihanda para sa bawat tinanggap na paglathala at ipinapadala nang hindi sabay-sabay; ang eksaktong pinirmahang transaksyon ay nananatili sa drainable outbox hanggang ito ay maipadala. |
Inilalarawan ng mga tier ang magkakaibang katangian ng ebidensya at tibay, hindi ang kasalukuyang plano sa komersyo. Ang kasalukuyang code ay nag-iskedyul pa rin ng isang indibidwal na transaksyon sa Arweave para sa bawat tinanggap na publikasyon; hindi nito ipinapakita ang T3 bilang isang bayad na upsell lamang. Ang mga limitasyon ng quota para sa API-key/account ay nananatiling hiwalay na kontrol sa aplikasyon.
Katapatan sa tibay. Ang pagsusulat ng T1 ay synchronous, kaya ang matagumpay na tugon ay nagtatatag ng durability sa antas ng aplikasyon nang hindi naghihintay para sa Arweave gateway. Hindi nito nagtatatag ng isang independyenteng timestamp. Ang isang kinumpirmang indibidwal na transaksyon ay nagbibigay ng isang block-time upper bound. Para sa isang tugon na nagdadala ng kumpletong T2 receipt tuple, ang susunod na kinumpirmang anchor ay maaaring magbigay ng log proof na inilarawan sa ibaba. Kung wala ang tuple, walang ibabaw na maaaring magpahiwatig na ang qub na ito ay nasa transparency log na. Ang latency ng anchor at publikasyon ay walang numeric SLA sa antas ng protocol.
16.2 Istruktura ng LogLeaf (dalawang committed na hugis)
Ang isang log entry ay isang LogLeaf, na-encode bilang hand-written canonical CBOR sa ilalim ng §3.1 profile (definite-length, walang tag, walang float, shortest-form integer, NFC text, opsyonal na field na tinatanggal kapag wala, mga key na naka-order ayon sa encoded-byte length na pataas pagkatapos ay bytewise). Ang §3.1 parse → re-encode → compare canonical guard ay inilalapat sa encode path bago mag-hash (hindi lamang sa decode), kaya hindi maaaring hindi magkasundo ang dalawang implementasyon sa leaf bytes sa pamamagitan ng pagkakaiba ng integer-width o key-order. Ang lahat ng integer ay u8 / u64 / i64; ang lahat ng digest ay 32-byte byte string (bstr[32]). Ang isang nakaimbak na Arweave transaction id ay isang raw 32-byte SHA-256 digest na dinadala bilang bstr[32], hindi kailanman isang base64url text string (tumutugma sa §3.3).
Ang dahon ay may dalawang hugis na pinili ng isang kind bait, dahil ang pangkalahatang upload path ay byte-blind: POST /api/v1/upload sadyang tinatrato ang parehong tinanggap na hugis ng payload bilang opaque at tumatanggap qub_id at unlock_at bilang mga di-pinagkakatiwalaang pahayag ng kliyente lamang. Sa default na pribadong landas, body_hash, drand_round, created_at, at drand_chain_version ay karagdagan pang nakatago sa loob ng §13 panlabas na pambalot, na ang susi ay hindi kailanman hawak ng Manggagawa. Tinutukoy din ng sistema ng uri ang isang pinatunayan na anyo para sa isang prodyuser na nagmumula body_hash / drand_round sarili nito. Ang kasalukuyang /seal ang ruta ay may mga halagang iyon ngunit hindi tumatawag LogDO, kaya ang produksyon ay kasalukuyang naglalabas lamang ng pinatutunayan (0x02) nag-iiwan mula sa matagumpay na pangkalahatang-upload na mga append. Pinananatili ng paghahati ang bawat pinangakong halaga na tapat nang hindi nagpapanggap na ang pinatotohanang tagagawa ay konektado:
| Susi | Enc. haba | Uri | Presensya | Kahulugan |
|---|---|---|---|---|
seq |
apat | u64 |
kailangan | Pandaigdigang index ng dahon na nagsisimula sa 0; ang posisyon na kinukumpirma ng proof of inclusion. |
kind |
lima | u8 |
kailangan | 0x01 nasaksi-kayang gawin (tinukoy, hindi kasalukuyang inilalabas) o 0x02 inihayag (selyo ng kliyente / byte-blind na pag-upload). |
ref |
apat | bstr[32] |
kailangan | Paunang sanggunian ng dahon. Pinatutunayan → hilaw qub_id. Ipinahayag → ang nabulag pagkakakilanlan SHA3-256(qub_id ‖ log_blind_secret) (§16.2.1). |
chash |
anim | bstr[32] |
kailangan | Nilalaman ng address SHA3-256(stored_bytes) — ang iisang kontentong ugnayan na laging maingat na maaring kalkulahin ng Manggagawa, sa parehong landas. |
unlock_at |
sampu | i64 |
kailangan | Kinopya (pinatunayan) o ipinahayag (ipinahayag); sinuri > 0 bago ito pumasok sa dahon. |
received_at |
labindalawa | i64 |
kailangan | Orasan ng manggagawa sa R2-ack. Hindi patunay (pinatutunayan ng operator; §16.6). Naroroon para sa sariling paglalarawan, hindi kailanman patunay. Napatunayan > 0. |
body_hash |
sampu | bstr[32] |
kind=0x01 lamang |
Hindi isinama sa 0x02 — wala ito sa Manggagawa sa ilalim ng §13. |
drand_round |
labindalawa | u64 |
kind=0x01 lamang |
Hindi isinama sa 0x02. |
Ang isang kind=0x02 na leaf ay sadyang hindi kino-commit ang body_hash o drand_round: pinatutunayan nito ang commitment at ordering ng isang opaque ciphertext sa content-address chash, na nag-aangkin ng qub_id at unlock_at — hindi ang plaintext o round nito. Ang plaintext/round na mga leg para sa isang asserted na qub ay nanggagaling sa umiiral na §11 .qub-bundle verification, hindi mula sa log (§16.11). Ang drand_chain_version ay wala sa leaf (ito ay nasa loob ng wrapper sa default path); ang chain granularity ay nananatili sa anchor (§16.7). Encoder discipline: tanggihan ang isang all-zero na ref o chash, at tanggihan ang non-positive na unlock_at / received_at, na sumasalamin sa outcome_at > 0 sentinel guard sa cbor.rs.
16.2.1 Pag-blind ng pribadong qub
Ang log ay hindi dapat maging ang enumeration oracle na pinipigilan ng §13 outer wrapper (§13.1). Para sa isang pribadong (naka-wrap) na qub, kino-commit ng asserted na leaf ang blinded na identifier SHA3-256(qub_id ‖ log_blind_secret), kung saan ang log_blind_secret ay isang server-held na lihim, at tinatanggal ang body_hash. Hindi maitatali ng isang third party ang ganitong leaf sa isang tiyak na qub_id; ang may-hawak ng qub, na may delivery URL at samakatuwid ay may qub_id, ay maaaring muling kalkulahin ang blind upang kumpirmahin ang sarili nilang inclusion. Ang isang pampublikong qub (na enumerable na, na nagdadala na ng Visibility: public Arweave tag ayon sa §13.8) ay kino-commit ang raw na qub_id. Ito ang iisang lugar kung saan sadyang nagpapaubaya ang standalone verifiability sa isang load-bearing privacy invariant; ang standalone tie para sa mga pribadong qub ay ang chash (§16.9).
Custody ng log_blind_secret (naresolba — §16.15 Q4). Pinoprotektahan ng blind ang leaf unlinkability, hindi ang plaintext confidentiality (hawak iyon nang nakapag-iisa ng §13 wrapper). Sa isang log_blind_secret compromise, para sa anumang qub_id na hawak na o muling maibubuo ng adversary (bawat qub na may bundle/URL nito, kasama ang anumang low-entropy o pampublikong qub_id), muli nitong kinakalkula ang leaf ref sa isang hash at iniuugnay ito — ito ay direktang linkage ng isang kilalang populasyon, hindi isang brute-force sa isang hindi kilalang espasyo. Iuri ang log_blind_secret bilang isang correlation/Sybil-grade na lihim sa parehong custody tier ng iba pang server secret, at i-rotate lamang nang pasulong (ang isang rotation ay muling nag-blind ng mga future leaf; hindi nito maaaring retroactively i-unlink ang mga naka-anchor na).
16.3 Leaf at Node Hashing
RFC 6962 §2.1 domain-separated hashing na may SHA-256 na pinalitan ng SHA3-256:
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
Ang mga domain prefix byte na 0x02 (entry chain, §16.4) at 0x03 (STH hash, §16.6) ay nakareserba at disjoint mula sa mga ito. Ang mga ito ay single byte at samakatuwid ay hindi maaaring mag-collide sa umiiral na 10-byte ASCII domain separators (QUB_ID_V2, atbp.). Ang tree ay ang RFC 6962 left-full unbalanced na tree (bawat interior split sa pinakamalaking power of two na mahigpit na mas mababa sa subtree leaf count), na nagpapahintulot sa inclusion at consistency proofs na magbahagi ng iisang audit-path algorithm. Ang reference spec ay nagdadala ng tahasang left/right derivation pseudocode at nag-pin ng isang non-power-of-two (5-leaf) test vector upang ang right-edge promotion case — na itinatago ng isang 4-leaf vector — ay ma-exercise.
16.4 Hash Chaining (internal)
Ang LogDO ay nagpapanatili ng isang internal entry chain para sa crash-consistency lamang. Ito ay hindi kailanman naipa-publish at hindi kailanman verifier-facing:
entry_chain[seq] = SHA3-256(0x02 || entry_chain[seq-1] || leaf_hash[seq])
entry_chain[-1] = SHA3-256("QUB_TLOG_GENESIS_V1")
Ang naipa-publish na append-only authority ay ang cumulative Merkle root + ang anchor nito (§16.5–16.6), hindi kailanman ang raw order kung saan nagkataong nagse-serve ang operator ng mga leaf: ang chain ay muling kinakalkula para sa anumang order na ise-serve, kaya tanging ang naka-anchor na root ang nag-pin ng canonical position.
16.5 Cumulative Merkle Tree at Batching
May iisang patuloy na lumalaking RFC 6962 tree sa lahat ng leaf sa seq order — hindi mga hiwalay na per-batch tree. (Isang carry-leaf-chained per-batch construction ang tinanggihan: hindi ito isang tunay na prefix relation, kaya ang "consistency proofs" nito ay hindi maayos.) Ang cumulative tree ay nagbibigay ng tunay na RFC 9162 consistency proofs at nagpapahintulot sa isang iisang kamakailang anchor na patunayan ang inclusion para sa anumang mas lumang qub.
Ang LogDO Ang Durable Object ay ang nag-iisang manunulat (blockConcurrencyWhile, sumasalamin QuotaDO / EntitlementDO) — ang pagdaragdag sa isang ibinahaging talaan ay pagbabasa-modipika-pagsulat sa ibinahaging estado kaya DAPAT dumaan sa isang DO, hindi KV. Ini-cache nito ang kanang-dulo ng frontier ng puno (O(log n) hashes) kaya ang pagsasara ng isang batch ay O(batch). A pangkat ay ang hanay ng mga dahon na magkasamang naka-angkla; ang mga ipinatupad na trigger nito ay isang tree_size paunang hindi bababa sa LOG_BATCH_MAX_LEAVES (default 4096), edad na umaabot sa anchor cadence, o isang malinaw na administratibo/cron na pilit na pagsasara. root_i ay ang pinagsama-samang Merkle Tree Hash sa mga dahon 0 .. tree_size_i.
16.6 Signed Tree Head sa pamamagitan ng Arweave Anchor
Ang Arweave anchor transaction ay ang Signed Tree Head at pumapalit sa isang operator signature para sa tree head mismo: ang daily anchor ay hindi nangangailangan ng qub key dahil ang Arweave tx owner ay ang signature. Ang moat thesis ay nananatili — ang immutable substrate, hindi isang qub-held na lihim, ang load-bearing para sa naka-anchor na root.
Ang disenyo ng talaan ay nangangailangan ng isang mainit na matagumpay na pagdagdag susi ng resibo (§16.10), naka-pin sa LogProfile at pinagtibay ng lagda ng anchor_owner. Hindi pa nakumpleto ng kasalukuyang implementasyon ang pagbibigay ng trust-root na iyon: RECEIPT_SK ay opsyonal, ang nawawala/di-wastong susi ay nagbubunga sig_b64url: "", at ang pinagsama LogProfile.receipt_pubkey ay walang laman. Ang ganitong resibo ay maaaring ilarawan ang nakalakip na dahon ngunit ay hindi isang hindi maaaring itangging pinirmahang resibo. Ang mas matibay na pag-angkin sa disenyo ay naaangkop lamang pagkatapos ilabas ng tagasuri ang tumutugmang pampublikong susi at pamahalaan ng may-ari ng anchor ang paglagda dito. Ang tugon sa publikasyon na walang kumpletong tuple ng resibo ay hindi gumagawa ng pag-angkin sa pagtanggap ng log; ang isa na may walang laman na lagda ay gumagawa ng pag-angkin sa posisyon ng pagdaragdag ngunit walang pag-angkin sa beripikasyon ng lagda.
Ang SignedTreeHead ay canonical CBOR (mga key ayon sa encoded length): size:u64, root:bstr[32], batch:u64, prev:bstr[32] (prior sth_hash; genesis = 32 zero byte), log_id:bstr[32], first_seq:u64, anchored_at:i64. Ang hash nito ay sth_hash = SHA3-256(0x03 || canonical_cbor(SignedTreeHead)).
Naka-pin na trust root. log_id = SHA3-256("QUB_TLOG_V1" || anchor_owner_address). Ang isang conforming na verifier ay MUST mangailangan ng anchor_tx.owner == LogProfile.anchor_owner, kung saan ang anchor_owner (at ang receipt-key public key) ay naka-bake sa qub_core bilang ang LogProfile — kasama ang quicknet constants na nasa DrandTimelockProvider::quicknet() na — at ipinapamahagi kasama ang verifier binary. Ang verifier ay MUST din i-verify ang Arweave tx data → tx_id binding nang lokal sa halip na magtiwala sa isang gateway /raw/ response. Isinasara nito ang rogue-wallet equivocation hole: ang "naka-anchor sa Arweave" ay walang kahulugan hangga't hindi nag-pin ang verifier kung aling wallet.
Ang rotation ay isang §15 governance extension, hindi isang reuse (naresolba — §16.15 Q3). Ang profile surface ng §15.2 ay kasalukuyang naglilista lamang ng sig_algs / drand chains / wrapper versions / content types, at ang mga trigger ng §15.3 ay walang nililista sa mga ito — ang LogProfile / anchor_owner ay hindi pa nasa surface ng §15. Ang rotation governance samakatuwid ay dapat gawin: ang §15.3 ay pinalawak (sa ibaba) upang idagdag ang LogProfile trigger, at ang isang rotation ay isang signed LogProfile bump na ipinapadala sa isang verifier update. Ang isang planado na rotation ay nagdadala ng outgoing → incoming cross-signature; ang isang compromise-driven na rotation ay hindi makakaya (ang outgoing key ay untrusted/unavailable nang eksaktong iyon) at babagsak sa §15-governed bump, kung saan ang prev-anchor fork check (sa ibaba) ang naglilimita sa pinsala sa interim.
Bintana ng pag-iwas sa pagpapakahulugan (unang-klaseng parameter ng tiwala). Ang isang dahon ay tanging lumalaban sa pag-aalinlangan kapag ang takip nitong angkla ay Arweave-nakumpirma. Ang bintana ay received_at → anchor confirmation (cadence + katapusan ng Arweave, na walang garantiya sa latency ng protocol). Bago ang paglalaan ng trust-root, ang kasalukuyang implementasyon ay nagbibigay ng operational integrity ng qub pati na rin ang anumang unsigned append metadata na naroroon; hindi nito ibinibigay ang planadong garantiya ng non-repudiation. Tatlong accountability artifacts ang nagtatakda ng kumpletong disenyo (ang witness model ay resolusyon ng §16.15 Q2):
- Tatakan ng resibo (naka-depende sa probisyon) — ang SCT na kaukulang pabalik kapag nagtagumpay ang pagdaragdag ng log ng isang upload (§16.10). Nagiging hindi maipagkakaila lamang ito kapag
sig_b64urlay hindi walang laman at ang magkatugmang pampublikong susi/ugnayan ng may-ari ng anchor ay naka-pin sa tagapagsuri. Ang kasalukuyang walang laman na production profile pin ay hindi makasuporta sa hatol na iyon. Ang kontrol na ito ay hindi nalalapat sa isang tinanggal na receipt tuple o isang hindi pinirmahang resibo. - Na-publish na metodolohiya ng monitor + nakaraang chain walk — ang angkla
prevang kadena ay dinadala mula ulo→pinagmulan; isang sangay (dalawang angkla sa isa)sizena may iba't ibaroot, o sirangprev) ay mapapublish na patunay ng maling pag-uugali. Ang pagtukoy ng pagkakaroon ng doble-hulugan ay isang nakasaad na operational na pangako, hindi isang tahimik na palagay. - Dalawang sarili-lamang na inilathalang ulo — bawat bagong ulo
{sth_hash, tree_size}ay ipinost sa isang nakalaang pag-aari ng qub pampubliko, append-only na repositoryo sa GitHub (ang load-bearing tamper-evident na self-publication na paa), na may social post bilang pinakamahusay na pagsisikap na pagkumpirma lamang. Ang nabigong pag-post AY DAPAT mag-pahina (huwag manahimik na mabigo). Ipinatupad (Stage 8) bilang angpublishHeadisabit sa angkla cron (workers/api/src/utils/heads-publish.ts): isangPUTsa contents API nang walangshaay append-only (a422ibig sabihin ay ang ulo ay nailathala na, hindi kailanman napapalitan); pagpipilian / ipinapamahagi-sa-pagtitiyak saPUBLISH_HEAD_GITHUB_{TOKEN,OWNER,REPO}at hindi gumagalaw hanggang maibigay ang imbakan. Isang matigas na pahina ng pagkabigo ng GitHub sa pamamagitan nghealth_alertchannel at tumatama sa matibay na metric ng pagkabigo (m:tlog_publish_head_fail); ang mismong Arweave anchor ay hindi kailanman bumabalik kapag may publish failure. Ang "not fail silent" ay garantisado ng matibay na sukatan na iyon — na DAPAT i-dashboard alert ng mga ops — kahit hindi maihatid ang pinakamahusay na email page. Dalawang tapat na limitasyon ang sumusunod sa "anchor-on-advance" (ang cron ay naglalathala lamang kapag tumaas ang laki): ang pansamantalang pagkabigo sa GitHub ay nag-iiwan ng puwang sa sunud-sunod na mga ulo na nailathala para sa laki na iyon — limitado, hindi tahimik (ito ay nagpa-page), at dahil bawat ulo ay nagko-commit ng isang superset na puno, isang §16.9 na patunay ng pagkakatugma ang nagtatagpo ng agwat; mahalaga, ang patunay ng pagkakatugma ay kinokompyut mula sa awtoritatibong punong naka-angkla sa Arweave, hindi mula sa ibabaw ng GitHub, kaya ang kakulangan sa GitHub ay hindi kailanman nagpapahina sa beripikabilidad. Ang catch-up backfill na pumupuno sa mga puwang ng published-heads ay isang ipinagpalibang pagpapahusay.
Katapatan na nakakabit (nagbabanig na limitasyon). Dahil kinokontrol ng qub ang parehong pinaplanong mga ibabaw ng pag-post, ito ay self-published, hindi independiyenteng nasaksihan. Walang produkto, marketing, o legal na aspeto ang maaaring mag-angkin na ang tala ay "independiyenteng nasaksihan". Pagkatapos maibigay ang resibo/profile/head gates, ang pinapayagang pag-angkin ay na Ang pag-uugnay ng salita ay madaling matukoy at ang matagumpay na pinirmahang karagdagang dokumento ay nag-iiwan ng resibong hindi maikakaila. Bago noon, ang paghahabol na iyon ay hindi magagamit. Ang isang tunay na independiyenteng saksi na ikatlong partido ay ipagpapaliban sa isang hinaharap na §15 na pagtaas ng pamamahala.
Ang received_at ay operator-asserted at walang angkin na maaaring sumandal dito — hindi ito kailanman inilalantad bilang proof o bilang dispute corroboration sa anumang product / legal / API / proof-rendering surface. Ang Arweave anchor block time na T ay ang tanging trustless na timestamp (isang upper bound sa "logged by"). Ang anumang monitor sanity check sa received_at ay MUST ihambing laban sa T, hindi laban sa operator-controlled anchored_at STH field; ang ganitong check ay isang guard laban sa clock bug ng isang tapat na operator lamang, hindi isang accountability control laban sa isang malisyosong operator (§16.15 Q5).
16.7 Format at Cadence ng Anchor Transaction
Ang AnchorBundle ay ang canonical-CBOR na Arweave transaction body, na isinusulat sa pamamagitan ng §16.8 bundler: ver:u8, sth:bstr (canonical SignedTreeHead bytes), prev_anchor:bstr (prior anchor tx id raw bytes; tinatanggal sa genesis), chain_hash:tstr (ang drand chain na umiiral — quicknet), at ang leaf-CBOR stream ng batch sa seq order kaya ang anchor ay self-contained: muling de-derive ng isang monitor ang root mula sa body nang walang qub dependency. (Kung ang leaf stream ay lumaki sa mataas na volume, ang isang hinaharap na rebisyon ay maaaring mag-commit lamang ng isang leaf range sa pamamagitan ng reference; nabanggit, hindi inampon sa v1.)
Ang mga Arweave tag ay sadyang enumerable — ang log ay nilayon na matuklasan, hindi tulad ng mga pribadong qub: App-Name: qub-tlog, Anchor-Format: 1, Log-Id: <hex>, Batch: <n>, Tree-Size: <n>, Root: <hex>, Prev-Anchor: <tx>, Content-Type: application/cbor. Ang mga tag ay untrusted hint; ang CBOR body ang tanging awtoridad.
Tono: araw-araw bilang default, binisita muli kasama ang dami (ang trigger ng laki ay awtomatikong nagpapikli ng epektibong dalas sa ilalim ng load). Ang kasalukuyang tagagawa ay hindi nagpatupad ng paid-seal force-anchor hook. Ang pitak na pitaka ay nakalaan at mabagal ang bilis, hiwalay sa upload wallet — DAPAT ito ay sarili nito sariling JWK (isang natatanging susi, hindi isang lohikal na tungkulin sa upload wallet) kaya't hindi makakagawa ng pekeng anchors ang isang kompromiso sa upload-wallet — na may mahigpit na limitasyon sa per-araw na anchor-transaction. Ang postura sa pangangalaga ay malinaw na ipinahayag: isang makitid na saklaw na hot key na may mahigpit na circuit breaker at mababang balanse, hindi “malamig” — ang pitaka na awtomatikong pumipirma araw-araw ay hindi maaaring malamig, at ang espesipikasyon ay hindi nagpapanggap ng iba pa.
16.8 ANS-104 Bundler
Isang in-house na ANS-104 DataItem encoder at deep-hash signer, humigit-kumulang 300 linya, Web Crypto lamang, zero npm dependencies (parehong Turbo SDK ay nabibigo sa npm ci --ignore-scripts supply-chain gate). DataItem byte layout:
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
Ang signing ay Arweave deepHash — isang recursive na SHA-384 digest (Arweave's wire requirement, crypto.subtle.digest("SHA-384")) sa ["dataitem", "1", sig_type, owner, target, anchor, encoded_tags, data] — pagkatapos ay RSA-PSS sa deep hash gamit ang wallet JWK sa pamamagitan ng crypto.subtle; id = base64url(SHA-256(signature)). Ang SHA-384 dito ay naka-quarantine bilang isang Arweave-wire-only primitive, hindi kailanman isang qub trust primitive (itinatala ng §15 ang fence; ang qub trust hashing ay SHA3-256 sa buong saklaw).
Ang path ng ANS-104 code ay nagsisilbi sa naantalang fallback/drain na mekanismo at nagsusulat AnchorBundle DataItems. Ang karaniwang paraan ng publikasyon ay unang lumilikha ng eksaktong pinirmahang transaksyon sa Arweave at iniingatan ang JSON nito sa matibay na outbox; ang direktang pag-post ay isang pag-optimize ng pagkaantala, at inuulit ng drain path ang parehong transaksyon bago gamitin ang fallback ng bundler nito. Skema ng pirma (nalutas — §16.15 Q8): v1 pumirma gamit ang RSA-PSS (uri ng pirma 1) muling paggamit ng umiiral na mekanismo ng Arweave wallet JWK (walang bagong matagalang pangangalaga ng susi, nagsisilbi sa teorya ng "isang lihim na mas kaunti"); Ed25519 ay ipagpapaliban sa §15 landas ng PQ-migration.
Ang hand-rolled na deep hash ay ang pinakamataas-na-panganib, pinakamababang-natural-coverage na code sa W5, kaya ang gating nito ay hindi-mapag-uusapan (§16.15 Q8):
- Ang cross-language fixture na
tlog_v1.json(Rust + TS, ang §14.5wrapper_v1.jsonpattern) ay sumasaklaw sa deep-hash, DataItem bytes + id, leaf hashes, isang 5-leaf root + audit path, isang STH hash, isang inclusion proof, at isang consistency proof — sa parehong sign at verify na direksyon (ang verify na direksyon ay mahalaga dahil hinihila ng §16.6's local tx → tx_id check ang deep hash sa bawat standalone verifier, hindi lamang ang writer). - Isang one-time interop round-trip sa pamamagitan ng isang reference ANS-104 bundler, kinokonsumo bilang static test data lamang — hindi kailanman isang npm runtime dependency (ang Web-Crypto-only / no-install-scripts posture ay nananatili).
- Ang deep-hash + RSA-PSS path ay dapat mag-round-trip sa pamamagitan ng parehong
crypto.subtleprimitives na ginagamit ng production, kaya ang in-house encoder ay byte-compatible. - Isang patuloy na post-bundle acceptance monitor ang nagkukumpirma na ang bawat anchor / fallback DataItem ay tunay na nakakamit ng Arweave acceptance, na may alarm + circuit breaker — dahil ang deep hash ay naglilingkod din sa Arweave-unavailability fallback queue, kaya ang isang tahimik na regression ay pupunuin ang queue na iyon ng mga network-rejected item sa eksaktong outage na kung kaya umiiral ito.
16.9 Inclusion at Consistency Proofs
Pareho ay RFC 9162, SHA3-256, ini-serve bilang canonical CBOR.
InclusionProof — GET /api/v1/qub/:tx_id/proof: ver:u8, leaf:bstr (ang eksaktong leaf CBOR — muling kinakalkula mismo ng verifier ang leaf_hash at hindi kailanman nagtitiwala sa isang supplied hash), 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. Isang iisang hindi malabo na key list, naka-pin ng test vector.
Standalone verification (walang qub server, pinalalawak ang §11):
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).
Ang proof-serving storage ay MUST coordinate-keyed (naresolba — §16.15 Q7, blocking precondition). Ang cold-leaf proof generation ay correctness-neutral lamang kung ang R2 audit material ay isang persistent Merkle-node store na naka-key sa absolute tree coordinate (level, index) — hindi per-batch node delta. Sa isang coordinate-keyed na store, ang anumang (leaf i, size N) audit path ay isang set ng O(log N) direktang R2 GET na walang recomputation sa mga batch boundary; sa isang batch-keyed na store ay hindi, na siyang storage-layout gap na isinasara ng resolusyon na ito. Ang mga leaf body ay gayundin content-addressable ayon sa seq. Ang isang W5 test vector ay MUST patunayan ang isang genesis-era cold leaf laban sa isang mas-bandang root gamit lamang ang R2 + Arweave na may LogDO storage na nabura, kaya ang reclamation-safety claim sa §16.13 ay nasusuportahan sa halip na iginiit. Ang O(log N) sequential R2 GET ay nararapat lamang sa asynchronous proof endpoint — hindi kailanman sa seal hot path (§16.10) o isang per-tick cron.
16.10 R2-First Ack Ordering
Ang ipinatupad POST /api/v1/upload ang pagkakasunod-sunod ay:
- Mga harapang gate (auth, validation, idempotency shard key) — hindi nagbago.
- Lumikha, mag-tag, at pirmahan ang eksaktong indibidwal na transaksyon ng Arweave. Ito ay nagmula
tx_idsa lokal, kahit na ang paggawa ng transaksyon ay maaaring kunin ang reward/anchor metadata mula sa isang gateway. Ang pagkabigo sa paghahanda ay patuloy na nagtatapos sa kahilingan bago pa man ang pagkilala. - Sabay-sabay isulat ang napiling artipakto sa
qub-cache/<tx_id>at panatilihin ang matatag na tala ng creation-operation/outbox. Ito ang patag ng tibay at pagsubok muli; ang mga kabiguan bago ang pagsasaayos ay nagbabalik ng 503. - Kailan
LOG_DOay nakakonpigura, sabay na subukanLogDO.append(leaf). Ang iisang manunulat ay nagtatalagaseq, pinalalawak ang chain ng entry, at ina-update ang frontier. Ginagawa lang iyon ng append RPC; ang batch close ay tumatakbo off-path sa alarm. Sa kasalukuyan, isang append transport/application failure mag-fail nang mahinahon: maaari pa ring magtagumpay ang tugon kahit walalog_seq,receipt, oanchor_status. Sa kabila ng isang komento sa pagpapatupad, walang awtomatikong pagkakasundo ng log sa hinaharap ang nakaayos ngayon. - Ibalik ang pagkilala. Isama
{ log_seq, anchor_status: "pending", receipt }kapag lamang bumalik ang append ng kompletong matagumpay na tuple.receipt.sig_b64urlay walang laman kapag ang pumirma ng resibo ay hindi available; HINDI DAPAT tawagin ng mga kliyente na may pirma o hindi maitatatwa ang halaga na iyon. Ang kawalan ng tuple ay nangangahulugang matibay na publikasyon lamang, hindi pagtanggap ng transparency-log. - Gumamit ng isang deferred na gawain upang i-post ang eksaktong signed na transaksyon. Ang tagumpay ay nag-aalis ng outbox; ang kabiguan ay iiwan ito para sa bounded drain cron at hindi dapat baguhin ang naunang na-acknowledge.
tx_id. Ang pansamantalang metadata at iba pang mga sidecars na batay sa pinakamahusay na pagsisikap ay ipinagpaliban din.
Hangganan ng pagkaantala. Kasama sa kahilingan na landas ang front-half authority/quota na trabaho, paghahanda/paglalahad ng transaksyon, matibay na R2 na pagsusulat, at (kapag naka-configure) ang LogDO pagsubok. < 300 ms lumilitaw sa pagsusuri ng disenyo bilang isang operational na target, hindi isang garantiya ng protocol; ang kasalukuyang hakbang sa paghahanda ng transaksyon ay maaaring magsagawa ng kahilingan sa gateway metadata. Ang mga alarma sa pagkaantala at mga pintuan sa paglulunsad ay mga kontrol sa operasyon, hindi ebidensyang makukuha ng isang tagasuri.
16.11 Trust Model — ang tumpak na angkin, naka-scope ayon sa leaf kind
Para sa kind=0x01 (attested): "Ang content na ito — body na tumutugma sa body_hash, kinikilala ng qub_id — ay naka-commit sa append-only log ng qub sa posisyong seq at umiral nang hindi lalampas sa Arweave block time na T; ito ay cryptographically hindi mababasa hanggang drand round R = unlock_round(unlock_at)." Ito ang buong {tlock round binding + Merkle inclusion + anchored root} triple.
Para sa kind=0x02 (asserted, ang default): "Isang opaque ciphertext na may content-address chash, na nag-aangkin ng qub_id at unlock_at, ay naka-commit sa append-only log sa posisyong seq at umiral nang hindi lalampas sa Arweave block time na T." Ang round at body na mga leg ay ibinibigay ng umiiral na §11 .qub-bundle verification (qub_core::unlock), hindi ng log; ang idinadagdag ng log sa isang hubad na per-qub transaction ay tamper-evident ordering, isang trustless na upper-bound commitment time, at equivocation resistance.
Pareho ang mga angkin ay hindi kasama, ayon sa §11: authorship nang walang sig_alg ≥ 0x01, intent, at sub-anchor-granularity timing. Wala sa kanila ang nagpapahintulot sa anumang angkin na sumandal sa received_at.
Itakda ang kisame ng claim (nagbubuklod na limitasyon sa paglulunsad — nalutas §16.15 Q1). Para sa isang ipinahayag (kind=0x02) dahon, ang saklaw na pahayag sa itaas ay ang kisame sa anumang produkto, marketing, termino, o patunay na pagpapakita sa ibabaw na maaaring igiit. Walang ibabaw ang maaaring magsabi o magpahiwatig na ang tala ang nagpapatunay ng nilalaman o ng unlock round ng isang byte-blind na pag-upload — ang tala ay nagpapatunay ng pagkakasunud-sunod + isang trustless na itaas na limitasyon ng oras ng commitment ng isang opaque ciphertext. Ang pagpapatunay ng nilalaman at round ay nagmumula lamang sa umiiral na §11 .qub-pag-verify ng bundle, na hindi nakadepende sa log. Ang isang publikasyon na walang matagumpay na append/receipt ay walang anumang claim sa log.
16.12 Versioning at W3 Coordination
Mayroong hindi SealedQub tumubok na kawad at samakatuwid walang pagtaas ng bersyon ng protokol (§12.2): ang log ay isang sidecar na nagko-commit sa umiiral na mga patlang at byte, kaya hindi ito pumapasok sa kasaysayan ng bersyon ng protocol ng §12.3. Opsyonal ang W3 drand_chain_version ay hindi napahawakan at nananatiling nag-iisa sa pagpipilian SealedQub larangan. Sa halip, ipinapakilala ng log ang sarili nitong independiyenteng mga espasyo ng bersyon — LOG_VERSION_1, ANCHOR_FORMAT_1, InclusionProof.ver — na sumasalamin sa §12.5 na kalayaan ng bersyon ng wrapper (ang wrapper ay may bit na bersyon na hiwalay sa bersyon ng protocol, at ang mga bersyon ng log ay sumusunod sa parehong paghihiwalay).
Ang proof delivery ay fetched bilang default, na may opsyonal na ride-along. Ang isang proof ay hindi maaaring umiral sa seal time (ang anchor ay hindi pa naisusulat), kaya ang seal-time .qub bundle ay nananatiling proof-free. Ang W7's verifier ay nag-fe-fetch ng GET …/proof nang isang beses, o sa fully-offline mode ay muling binubuo ang proof mula sa pampublikong AnchorBundle sa pamamagitan ng isang Arweave query sa Log-Id. Ang .qub bundle (W7) ay nagrereserba ng isang opsyonal na inclusion_proof member — wala sa seal, pinupunan ng isang post-anchor re-export para sa cold archival — sumusunod sa parehong "opsyonal, tinatanggal bilang default, additive" pattern ng W3's drand_chain_version.
16.13 Retention
Ang mga retention window para sa LogDO open tail, ang R2 proof-serving substrate, ang anchor circuit-breaker counters, at ang bundler fallback queue ay tinukoy sa docs/DATA-RETENTION.md. Prinsipyo: ang hot per-entry storage ng log (LogDO) ay reclaimable post-anchor; ang audit material nito — ang coordinate-keyed (level, index) Merkle-node store + ang seq-addressed na leaf bodies (§16.9) + ang mga Arweave anchor — ay permanente. Ang pag-reclaim ng isang cold leaf mula sa DO ay hindi kailanman nag-iinvalidate ng isang naibigay na proof, dahil ang isang proof ay nireresolba laban sa permanenteng R2 node store na iyon at sa Arweave anchor, hindi sa DO (at pinatutunayan ito ng §16.9 wiped-DO test vector).
16.14 Mga Test Vector
Ang W5 ay nagpapadala ng cross-language fixture na tlog_v1.json (§16.8) kasama ang mga worked vector: isang kind=0x01 at isang kind=0x02 leaf → leaf_hash; ang 5-leaf cumulative root; isang inclusion proof; isang consistency proof; isang AnchorBundle; at isang DataItem id. Ang mga ito ay nananahan kasama ng §14.5 outer-wrapper vectors at ina-exercise ng parehong Rust (qub-core) at TypeScript (Worker) na implementasyon.
16.15 Pagsusuri ng Mga Desisyon (W5 — nalutas)
Kumpleto na ang W5 external review (isang adversarial design pass + pag-apruba ng may-ari). Bawat desisyon sa ibaba ay naayos at naipapakita sa teksto ng §16 sa itaas; ang mapilit na mga limitasyon sa paglulunsad ay muling binanggit sa dulo. Maaaring ipagpatuloy ang pagpapatupad sa ilalim ng mga ito.
- Default-path (
kind=0x02) katapatan ng dahon — PINAGPASYAAN. Ipadala ang hati na may dalawang dahon ayon sa tinukoy:kind=0x02hindi gumagawa ng alinmanbody_hashnidrand_round. Hindi*_body_hashlarangan sa byte-blind na daan (ito ang magiging pinakamabasa na maling “na-verify” na signal para sa mga integrator at ito ay isang kaginhawaan na ipinamamahagi na ng §11 mula sa bundle). Gawin hindi kailangan ang server-seal para sa log-attested qubs (na magtutulak ng plaintext sa pamamagitan ng Worker at sisirain ang crypto-shredding moat). Anumang self-describing short-circuit ay nararapat na nasa.qubipon / sobre ng patunay bilang isang patlang na nirecompute ng tagapagpatunay, hindi kailanman isang patlang na dahon. Pinagtibay ng may-ari ang pinakamataas na halaga ng paghahabol: §16.11. - Panag-urong / pananagutan sa pagkaligaw — NAIKATAPANG ANG DISENYO, HINDI KUMPLETO ANG PAGHAHANDOG. Kinakailangan ng disenyo na ma-pin ang seal-receipt key
LogProfileat pinagtibay ng lagda nganchor_owner, kasama ang monitor methodology, prev-chain walk, at dual self-published heads. Ang compiled profile at deployment hooks ay placeholder/opsyonal pa rin gaya ng detalyado sa §16.6, kaya ang mas malakas na detectable + receipted na claim ay hindi pa kasalukuyan hanggang sa magsara ang mga gate na iyon. Hindi ito dapat ipromote bilang independently witnessed. Ang totoong third-party witness ay ipagpapaliban sa §15 governance bump. - Na-pin na root ng trust ng may-ari ng anchor + pag-ikot — NAISOLBA. I-adopt ang
LogProfilepin (§16.6); sinusuri ng tagasurianchor_tx.owner == anchor_ownerat beripikahin ang tx data → tx_id na pagtali nang lokal. Ang pamamahala ng pag-ikot ay isang §15 ekstensyon upang bumuo (§15.3 trigger idinagdag), hindi muling paggamit; ang mga planadong pag-ikot ay magkakahiwalay na lagda, ang mga pag-ikot na pinamumunuan ng kompromiso ay bumabalik sa §15 bump kasama ang fork check na nililimitahan ang pinsala. - Pagpapasara ng dahon ng private-qub — NAISOLBA. Patuloy na bulagin para sa pribadong qubs (
ref = SHA3-256(qub_id ‖ log_blind_secret)), hilawqub_idpara sa pampublikong qubs (nasa §16.2.1 na),chashbilang mag-isa na kurbata.log_blind_secretay isang korrelasyon/lihim na antas-Sybil, paikutin-pasulong lamang (§16.2.1). received_at— NAPAGPASYAAN. Itago ito sa dahon, nakalaan ngunit malinaw na hindi ebidensya; hindi kailanman lumitaw bilang patunay o pagkumpirma ng pagtatalo sa anumang ibabaw. Anumang pagsuri sa katinuan ng monitor ay ikinumpara sa oras ng bloke ng ArweaveT, hindi kontrolado ng operatoranchored_at(§16.6).- Tiered na napatutunayang oras — DISENYO NG PAGLUTAS, HINDI KASALUKUYANG PAG-RURUTA. Ang nirepasong disenyo ay nagtatalaga ng anchor-block timing sa pinagsamang tier at exact-hour proof sa bayad na T3, na walang numerikong SLA para sa nauna. Ang kasalukuyang mga ruta ay hindi pa naitatalaga ang komersyal na pagkakaibang iyon: nag-iiskedyul sila ng isang indibidwal na transaksyon para sa bawat tinanggap na publikasyon, at ang pag-log ng coverage ay nananatiling kundisyonal gaya ng nakasaad sa §16.1/§16.10. Ang kopya ng produkto ay dapat ilarawan ang implementasyon, hindi ang hinaharap na paghahati ng tier na ito.
- Pinagsama-samang puno sa mga Manggagawa — NALUTAS. Isang nag-iisang pinagsamang RFC 9162 na puno + frontier-naka-cache na nag-iisang manunulat na LogDO (komportableng dagdag na espasyo kumpara sa ~1k writes/sec DO ceiling; ipagpaliban ang Merkle-of-shard-roots na paghahati hanggang malapit dito). Ang coordinate-keyed
(level, index)Ang R2 node store + wiped-DO cold-leaf test vector ay ipinatupad (§16.9).< 300 msnanatiling isang target ng disenyo/operasyon, hindi isang pangako ng protocol (§16.10). - Scheme ng pirma ng ANS-104 + deep-hash — NAAYOS NA. RSA-PSS (uri ng uri ng sig 1, muling paggamit ng dedikadong anchor-wallet JWK); Ed25519 ipinagpaliban sa §15 PQ path. Ang hand-rolled SHA-384 deep hash ay nakasalalay sa both-directions cross-impl fixture, isang static-only reference-bundler interop check, ang shared-
crypto.subtlepaikot-pabilang, at ang post-bundle na tagamasid ng pagtanggap ng Arweave (§16.8).
Pagbubuklod ng mga limitasyon sa paglunsad (ipatutupad + pagsusuri ng produkto/batas)
- Taas ng pag-claim (Q1/Q6). Walang ibabaw ang maaaring magsabi pinatutunayan ng troso ang nilalaman ng inihaing dahon o buksan ang bilog; ang pinapayagang paghahabol para sa matagumpay na nakapirming
kind=0x02ang dahon ay inaayos, na may ebidensiyang pagsasamantala, gamit ang isang walang-katiyakan na pang-itaas na pangako ng oras. Ang isang tugon na walang resibo na tuple ay walang claim sa talaan. Walang kopya ng timestamp ang nagdadala ng numerikong garantiya ng pagka-antala. - Saksiin ang katapatan (Q2). Pag-aalinlangan sa merkado bilang maaaring matukoy + may resibo, hindi kailanman nasaksihan nang nakapag-iisa.
- Resibo + mga susi ng anchor (Q2/Q8). Bago ipadala ang mga claim na non-repudiation/anchored-verification, ihanda at i-compile-pin ang pampublikong susi ng resibo, lagyan ng cross-sign kasama ang provisioned na may-ari ng anchor, at panatilihin ang anchor wallet bilang sariling JWK na hiwalay mula sa upload wallet.
- Malalim na hash gate (Q8). Walang anchor o T3 tx na barko hanggang sa pumasa ang parehas na direksyon na fixture + interop check; ang monitoring ng pagtanggap ay nag-pa-paging kapag nabigo.
- Paunang kundisyon sa imbakan (Q7). Ang coordinate-keyed node store + wiped-DO cold-leaf vector ay mga kinakailangan para sa garantiya na "ang reclamation ay hindi kailanman nagpapawalang-bisa ng patunay".
17. Napapasadyang Pakete ng Pagpapatunay (.qub)
Katayuan. Ang seksyong ito ay ipinatupad (W7 / UP-C2):
qub_core::exportgumagawa at sumusuri ng bundle, attools/qub-verifyay isang pampubliko, sariling nakahiwalay na CLI na nagve-verify nang offline. §11 at §16.9 ay tumutukoy na sa "the".qubbundle bilang yunit na kinokonsumo ng isang standalone na tagasuri; tinutukoy ng seksyong ito ang mga byte nito at ang hakbang-hakbang na pagsusuri. Ito ay mahigpit na pandagdag — ang bundle ay nagbabalot ng umiiral na §11 inputs at hindi binabago ang anumang on-chain wire format.
17.1 Layunin
§11 ay nagtatag na kahit sino pang ikatlong partido ay maaaring beripikahin ang kriptograpikong artipakto ng qub nang walang pakikipagtulungan ng qub. Ang .qub ginagawa ng bundle ang beripikasyong iyon madadala at walang koneksyon sa internet: ipinapaloob nito ang selyadong CBOR at ang drand round signature na nagbubukas nito sa isang solong artifact na nakahiwalay sa sarili, kaya't maaring i-verify ng tatanggap ang integridad ng nilalaman, round binding, at anumang lagda ng may akda kasama ang walang tawag sa network kahit kailan (walang pagkuha ng imbakan, walang live na kahilingan sa drand, walang qub API). Ang isang bundle lamang ay hindi nagpapatunay kung kailan nilikha ang ciphertext nito; ang isang independiyenteng napatunayang transaksyon sa imbakan o nakatali na patunay ng log ang nagbibigay ng hiwalay na pag-angkin ng oras ng pag-iral (§11, §17.5).
17.2 Format ng Bundle
A QubBundle ay mano-mano na nakasulat na canonical na CBOR sa ilalim ng §3.1 na profile (tiyak na haba, walang tags, walang floats, pinakamaikling anyo ng mga integer, teksto sa NFC, opsyonal na mga patlang ay hindi isinasama kapag wala, mga susi ay inayos ayon sa haba ng encoded-byte pataas at pagkatapos ay bytewise). Ang tatlong 15-character na mga susi ay inayos d < i < s. Hilaw .qub ang file ay eksaktong mga batayang ito; para sa URL o copy-paste na transportasyon ang parehong mga batayang ay base64url(walang pad).
| Susi | Enc. haba | Uri | Presensya | Kahulugan |
|---|---|---|---|---|
version |
walo | u8 |
kailangan | Bersyon ng format ng bundle (0x01). |
sealed_at |
sampu | i64 |
opsyonal | Oras ng selyo na itinakda ng tagalikha (segundo sa Unix); nagpapakilala sa sarili, hindi ebidensya. |
drand_round |
labindalawa | u64 |
kailangan | Ang bilog na nakakabilang sa qub. Isang batayang projection ng nakaselyong qub. |
arweave_tx_id |
labing-apat | tstr |
kailangan | Ang transaction id na kung saan naka-imbak ang mga sealed bytes (provenance pointer). |
drand_chain_id |
labinlima | tstr |
kailangan | Ang drand chain (hex). Isang proyeksiyon ng naka-embed na sealed qub. |
drand_signature |
labing-anim | bstr |
kailangan | Ang drand beacon na lagda para sa drand_round — ang halaga na nagbubukas ng ciphertext. |
inclusion_proof |
labing-anim | bstr |
opsyonal | Ang §16 transparency-log Merkle inclusion proof, pagkatapos maging available ang isang anchored proof (§17.5). |
sealed_qub_cbor |
labing-anim | bstr |
kailangan | Ang panloob SealedQubCbor bytes (post-§13-unwrap), i.e. ang §11 na input para sa beripikasyon. |
drand_round at drand_chain_id ay kaginhawahang pagtataya ng sealed_qub_cbor, dinadala upang mabasa ito ng mga kasangkapan nang hindi ini-parse ang panloob na CBOR. Ito ay hinango sa paggawa at muling sinuri sa pag-decode laban sa na-parse na selyadong qub; ang isang bundle na ang top-level na field ay hindi tugma sa kanyang payload ay tinatanggihan. Ang disiplina ng encoder ay sumasalamin sa natitirang bahagi ng format ng wire: tanggihan ang isang walang laman drand_signature o arweave_tx_id, at itinali ang bawat patlang na may variable na haba.
17.3 Ano ang pinatutunayan ng naka-embed na drand na pirma
Ang bungkos ay nagdadala ng pirma ng drand sa halip na kailanganin ang tagasuri na kunin ito. Ang dekripsyon ng timelock (tlock sa ibabaw ng drand chain, §8) ay maaari lamang magtagumpay sa tunay lagda ng beacon para sa nakatali na round—isang halaga na ipinalalathala ng chain isang beses lamang kapag natapos ang round na iyon, at na isang balidong BLS na lagda sa ilalim ng pampublikong susi ng chain. Ang peke o maling lagda ay nabibigo sa BLS na beripikasyon o IBE/AEAD na decryption. Ang isang bundle na nade-decrypt kaya't nagpapatunay: ang ciphertext ay nakatali sa round R, at ang round R ay lumipas na. Pinapako ng tagasuri ang kadena (DrandTimelockProvider::quicknet()) at inilalapat ang §11 na tseke sa round-binding, kaya’t ang isang bundle ay hindi maaaring mag-angkin ng round na ang ciphertext nito ay hindi nakatali sa round.
Ito ay isang patunay ng kundisyon ng pagpapalaya, hindi isang oras ng pagkakalikha. Pagkatapos ng round R ay
lumipas, kahit sino ay maaaring gumawa ng bagong ciphertext para sa R at ipackage ang ito na noon pa man ay pampubliko na
pirma. Samakatuwid ang bundle lamang HINDI DAPAT ilarawan bilang patunay na ang
ang ciphertext o nilalaman ay umiiral bago ang R, bago unlock_at, o bago ang anumang kaganapan.
17.4 Hakbang-hakbang na pagsuri nang offline
qub-verify <file.qub> pinapatakbo ang karaniwang §11 na pamamaraan nang buo mula sa bundle, na nagpapaandar qub_core::unlock::unlock na may nakapasking DrandTimelockProvider:
1. Parse the .qub bytes → QubBundle (canonical-CBOR guard; bound every field;
re-check drand_round / drand_chain_id against the embedded sealed qub).
2. BLS-verify bundle.drand_signature for the pinned chain and round, then
tlock_decrypt(sealed.tlock_ciphertext, bundle.drand_signature) → QubEnvelope.
3. Verify SHA3-256(body) == body_hash (§11 step 8).
4. Verify QubEnvelope.qub_id == SealedQub.qub_id (§11 step 9).
5. Verify QubEnvelope.unlock_at == SealedQub.unlock_at (§11 step 10).
6. Verify ciphertext round == unlock_round(unlock_at) and the chain binding.
7. If sig_alg != 0x00: verify author_signature (and any cosigner; §9.4).
8. Report integrity, round-elapsed/round-binding, authorship, and cosigner
verdicts separately, plus the recovered body. Do not report a commitment
timestamp unless step 9 succeeds.
9. Optional existence-time leg: verify an included §16 proof through its pinned
anchor, or independently verify the referenced storage transaction. Report
its block time as an upper bound on ciphertext existence.
Ang CLI ay lumalabas 0 (napatunayan), 1 (nabigong beripikasyon — nakasara pa, hindi tugmang body-hash, sirang round/chain binding, o pirma na nabigong beripikahin), o 2 (paggamit / maling ayos ng bundle). A --json ang ulat ay may parehong hatol para sa awtomasyon. Dahil ang bundle ay nakapaloob sa sarili, ang verifier crate (qub-core) at ang CLI (qub-verify) ang tanging software na kailangan ng ikatlong partido; parehong pampubliko at ginagamit muli ang umiiral na verification path ng protocol — walang espesyal na crypto.
17.5 Kaugnayan sa talaan ng transparency
inclusion_proof ay isang opsyonal na slot para sa §16 Merkle inclusion proof. Kumpleto ang bundle-only verification (§17.4) para sa integridad, paikot na paglalagom / paikot na lumipas, at opsyonal na may-akda, ngunit sadyang walang sariling independiyenteng pag-angkin ng oras ng pag-iral. Isang puno, ganap na beripikado sa pamamagitan ng anchoring inclusion_proof idinaragdag ang leaf-kind-specific commitment at ang upper-bound na oras mula sa §16.11 nang hindi binabago ang bersyon ng format ng bundle. Ang kawalan ng patunay ay nangangahulugang "walang kasama na patunay" lamang—hindi "baliw" at hindi kinakailangang "hindi naka-angkla."
Sa sanggunian na implementasyon ang slot ay ngayon naitype: qub_core::export::QubBundle::inclusion_proof_typed() nagbabalik ng Option<InclusionProof> dinadala ang buong §16.9 na istruktura (dahon, audit path, naka-angkla na ugat, at AnchorRef) sa pamamagitan ng parehong malabong CBOR field — walang pagtaas ng bersyon ng format ng bundle. Ang nakahiwalay qub-verify Kinokonsumo ito ng CLI sa pamamagitan ng --anchor binti, at — hanggang sa maibigay ang anchor wallet (§16, Status) — nag-uulat ng puno-nang-may-placeholder-na-eniwalidong patunay ng may-ari bilang inclusion-only sa halip na ganap na anchored-verified.