Spesifikasi Protokol qub

qub ialah protokol untuk komitmen temporal kriptografi: sistem untuk memeterai kata-kata kepada tarikh akan datang dan kemudiannya mengesahkan dengan tepat apa yang dimeterai, pusingan drand yang mengawal pelepasannya, dan—apabila transaksi storan atau bukti log ketelusan tersedia—had masa atas bercap masa bebas bagi saat teks sifer dikomited.

Tiga primitif menjadikannya berfungsi. drand ialah suar kerawakan ternyahpusat—tarikh pendedahan dikuatkuasakan secara kriptografi dan bukannya oleh niat baik qub. Storan tahan lama bersama log ketelusan tambah-sahaja memelihara bait dimeterai dan melabuhkan komitmen berkelompok kepada storan awam kekal; laluan T3 berbayar turut menulis transaksi storan kekal individu. ML-DSA-65 ialah tandatangan kriptografi pasca-kuantum—apabila kepengarangan didayakan, qub terikat kepada pasangan kunci yang rahsianya tidak pernah meninggalkan peranti pengarang.

Bersama-sama, primitif ini menghasilkan kenyataan yang terkunci waktu dan dapat mengesan pengusikan, boleh dikaitkan secara pilihan, dan boleh dicap masa secara bebas—resit yang nilainya bertambah selari dengan kemampuan dunia untuk memalsukan masa lalu.

Sebahagian dokumen yang tinggal ialah spesifikasi normatif yang diperlukan untuk implementasi yang saling kendali.


Spesifikasi Protokol qub

Medan Nilai
Keluaran dokumen 1.0.0 (protocol-v1.0.0)
Protokol wayar 0x01
Pembungkus luar 0x01
Tarikh berkuat kuasa 2026-09-23
Status Semasa
Disemak sehingga 2026-09-23

Dokumen ini ialah spesifikasi protokol normatif untuk sistem komitmen berwaktu qub. Ia mentakrifkan struktur data, peraturan pensirian, formula derivasi, dan prosedur pengesahan yang diperlukan untuk implementasi yang saling kendali.

Skop: lapisan protokol secara sengaja bersifat neutral-bahasa — badan qub ialah bait teks biasa / markdown / perjanjian yang legap, dan pemaparan mengikut lokal ialah tanggungjawab pembaca (aplikasi web qub.social, iframe <qub-embed>, klien MCP, dsb.).


1. Notasi dan Konvensi

Notasi Maksud
u8, u64, i64 Integer tanpa tanda/bertanda dengan lebar bit yang ditetapkan
[u8; N] Tatasusunan bait panjang tetap sebanyak N bait
Vec<u8> Tatasusunan bait panjang berubah
Option<T> Nilai jenis T, atau tiada
String Rentetan teks UTF-8, dinormalkan NFC
`
SHA3-256(x) Cincang NIST SHA3-256 bagi rentetan bait x (FIPS 202)
ceil(x) Fungsi siling: integer terkecil ≥ x
CBOR Concise Binary Object Representation (RFC 8949)
big-endian Bait paling signifikan didahulukan

Semua integer dalam pembinaan praimej dikodkan sebagai tatasusunan bait lebar tetap big-endian (i64 → 8 bait, u8 → 1 bait) melainkan dinyatakan sebaliknya.

Semua cap masa ialah saat Unix dalam UTC.


2. Struktur Data

2.1 ComposeQub (Keadaan Dalam-Memori Pencipta)

Tidak disirikan kepada CBOR. Tidak ditulis ke storan kekal. Tempatan pada aplikasi pencipta.

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 (Muatan Ternyahsulit)

Disirikan menggunakan CBOR berkanun (§3). Disulitkan di dalam SealedQub. Inilah struktur yang membuktikan integriti kandungan selepas penyahsulitan.

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
}

Asas (qub teks tanpa tandatangan): version = 0x01, content_type = 0x01, sig_alg = 0x00; medan tandatangan dan penandatangan bersama tiada. Metadata pilihan lain boleh hadir.

Konfigurasi v1 yang lain: content_type = 0x03 (badan perjanjian, lihat §6.1); sig_alg = 0x01 (ML-DSA-65) dengan author_signature dan author_pubkey hadir (lihat §9.3); cosigner_pubkey dan cosigner_signature hadir bersama-sama untuk perjanjian yang ditandatangani bersama (lihat §9.7); reply_to ditetapkan kepada qub_id qub induk untuk qub rantai balas (lihat §9.3 untuk implikasi skop tandatangan).

2.3 SealedQub (Format Wayar Berkanun)

Disirikan menggunakan CBOR berkanun (§3). Inilah artifak wayar dalaman: penghantaran awam menyimpan bait ini tanpa pembungkus, manakala penghantaran peribadi membungkusnya dalam OuterWrapper sebelum penyimpanan (§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 (Keadaan Aplikasi Pembaca)

Tidak disirikan kepada CBOR. Tempatan pada aplikasi pembaca. Dibina selepas penyahsulitan dan pengesahan berjaya.

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. Profil CBOR Berkanun

Semua pensirian SealedQub dan QubEnvelope MUST mematuhi profil ini. Dua implementasi yang diberikan struktur logik yang sama MUST menghasilkan bait yang serupa.

3.1 Peraturan Pengekodan

Peraturan Spesifikasi
Piawai RFC 8949 §4.2.1 (Core Deterministic Encoding Requirements)
Susunan kunci peta Diisih mengikut panjang bait terkod dahulu (yang lebih pendek didahulukan), kemudian secara leksikografi (bait demi bait untuk pengekodan panjang yang sama)
Pengekodan integer Bentuk terpendek: 0–23 dalam bait awal; 24–255 dalam 2 bait; 256–65535 dalam 3 bait; dsb.
Pengekodan panjang Panjang tentu sahaja. Tiada tatasusunan, peta, rentetan bait, atau rentetan teks panjang tak tentu (maklumat tambahan = 31 adalah dilarang).
Tag Tiada tag CBOR (jenis utama 6 adalah dilarang).
Titik apungan Tiada apungan (nilai jenis utama 7 0xF9–0xFB adalah dilarang).
Rentetan teks Dikod UTF-8, dinormalkan NFC (Unicode Normalization Form C).
Rentetan bait Bait mentah. Tiada pengekodan base64 pada lapisan CBOR.
Kunci pendua Tolak dengan ralat. Penghurai MUST NOT menerima kunci peta pendua secara senyap.
Kunci tidak dikenali Tolak dengan ralat. Penghurai MUST NOT bertolak ansur dengan kunci peta di luar set kunci berkanun jenis tersebut — dua rentetan bait berkanun yang berbeza tidak boleh sekali-kali menyahkod kepada nilai yang sama (encode(decode(x)) == x), dan bagi muatan yang ditandatangani, kunci tambahan akan menjadi kandungan tersembunyi yang dikomit oleh kedua-dua tandatangan. Evolusi skema berjalan melalui version, tidak sekali-kali melalui kunci tambahan.
Nilai mudah Hanya true (0xF5), false (0xF4), dan null (0xF6) dibenarkan.
Medan pilihan Medan pilihan yang tiada diabaikan daripada peta CBOR sepenuhnya (tidak dikodkan sebagai null). Medan pilihan yang hadir dimasukkan mengikut susunan kunci yang diisih.

3.2 Susunan Kunci Berkanun yang Disahkan

Susunan kunci ini bersifat normatif. Implementasi MUST mengeluarkan kunci dalam susunan yang tepat ini. Penegasan nyahpepijat SHOULD mengesahkan susunan dalam binaan bukan-keluaran.

QubEnvelope (versi 0x01, tanpa tandatangan, semua medan pilihan tiada):

"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)

Derivasi susunan kunci QubEnvelope: setiap kunci ialah rentetan teks CBOR. Panjang terkod = 1 bait pengepala + panjang rentetan (untuk rentetan di bawah 24 bait). Diisih mengikut jumlah panjang terkod dahulu, kemudian secara leksikografi bagi kunci panjang yang sama.

SealedQub (versi 0x01, awam, tiada penerima):

"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 (badan perjanjian, 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 (baris tatasusunan terms):

"key"    (4 encoded bytes)
"value"  (6 encoded bytes)

PartyIdentifier (peta party_a / party_b):

"label"    (6 encoded bytes)
"contact"  (8 encoded bytes)  ← only if present

3.3 Rujukan Pengekodan Bait

Jenis Pengekodan CBOR Contoh
Cincang SHA3-256 (32 bait) 0x58 0x20 + 32 bait body_hash, qub_id
Cap masa (i64) Jenis utama 0 (positif) atau 1 (negatif), pengekodan terpendek saat Unix
Versi (u8, nilai 1) 0x01 (bait tunggal)
Jenis kandungan (u8, nilai 1) 0x01 (bait tunggal)
sig_alg (u8, nilai 0) 0x00 (bait tunggal)
Tandatangan ML-DSA-65 (3,309 bait) 0x59 0x0C 0xED + 3,309 bait author_signature, cosigner_signature
Kunci awam ML-DSA-65 (1,952 bait) 0x59 0x07 0xA0 + 1,952 bait author_pubkey, cosigner_pubkey

4. Derivasi Normatif

4.1 qub_id

qub_id mengenal pasti qub secara unik dan mengikat QubEnvelope kepada SealedQub. Ia diterbitkan secara deterministik daripada kandungan 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

Pengekodan pemisah domain: Rentetan "QUB_ID_V2" ialah 9 bait ASCII. Satu bait pelapik 0x00 ditambah untuk mencapai 10 bait bagi penjajaran. Implementasi MUST menggunakan tepat 10 bait ini: [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00].

Pengekodan outcome_at: Satu semakan pelaksanaan prakeluaran melanjutkan praimej daripada 92 kepada 100 bait untuk melipat medan outcome_at pilihan ke dalam ikatan. outcome_at yang tiada dikod sebagai 8 bait sifar; pengesah protokol menolak outcome_at <= 0 di mana-mana sahaja, jadi sentinel ini tidak boleh berlanggar dengan nilai yang sah. Lihat §3.2 (format wayar) dan tasks/verdict-uplift-plan.md dalam pokok untuk mekanik keputusan yang mendorong medan ini.

Pengekodan drand_round: Semakan pelaksanaan prakeluaran kemudian melanjutkan praimej daripada 100 kepada 108 bait untuk melipat drand_round (pusingan drand sasaran, §4.3) ke dalam ikatan, dan menaikkan pemisah domain kepada QUB_ID_V2. Ini mengikat pusingan kunci masa ke dalam identiti qub: gateway tidak boleh mengikat semula teks sifer kepada pusingan lain (contohnya yang sudah berlalu) daripada yang disiratkan oleh unlock_at yang dipaparkan. Prosedur buka kunci (§8) turut mengesahkan bahawa pusingan dalam stanza teks sifer tlock sepadan dengan unlock_round(unlock_at), maka masa buka kunci yang dipaparkan terbukti ialah pusingan yang mengawal penyahsulitan.

Sifat:

4.2 body_hash

body_hash = SHA3-256(body)

Di mana body ialah muatan kandungan Vec<u8> mentah. Untuk qub teks, ini ialah badan qub yang dikod UTF-8.

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

Di mana title ialah tajuk teks biasa pilihan yang dipaparkan pada hitung mundur pembaca sebelum pendedahan (lihat §3.2). Penormalan NFC dijalankan pada masa pencincangan supaya cernaan stabil merentas urutan titik kod yang setara secara visual. Sentinel sifar-semua dikhaskan untuk kes tiada; rentetan kosong ditolak pada sempadan CBOR berkanun sebagai pengekodan bukan-berkanun bagi "tiada" (pengekodan berkanun mengabaikan medan sepenuhnya).

4.3 Pemetaan Pusingan-Buka-Kunci

drand_round = floor((unlock_at - chain_genesis_time) / chain_period_seconds) + 1
Parameter Sumber Contoh
unlock_at Saat Unix UTC yang dipilih pengguna 1735689600 (2025-01-01 00:00:00 UTC)
chain_genesis_time maklumat rantai drand (genesis_time) 1595431050
chain_period_seconds maklumat rantai drand (period) 30

Ini ialah pemetaan tlock rujukan (CurrentRound drand). drand menerbitkan pusingan N pada chain_genesis_time + (N - 1) * chain_period_seconds, maka formula memilih pusingan semasa pada unlock_at—pusingan yang tandatangannya pertama kali boleh digunakan oleh pembaca yang tiba pada unlock_at.

Sifat penjajaran (kes yang penting dalam amalan): apabila (unlock_at - chain_genesis_time) boleh dibahagikan tepat dengan chain_period_seconds, tandatangan pusingan terpilih diterbitkan tepat pada unlock_at, tidak pernah sebelumnya. Ini sentiasa benar untuk penyebaran rujukan: masa genesis quicknet (1692803367) boleh dibahagikan dengan tempoh 3 saatnya, dan aplikasi rujukan menyematkan masa buka kunci kepada minit penuh. Bagi unlock_at yang tidak sejajar, tandatangan pusingan terpilih diterbitkan kurang daripada satu tempoh sebelum unlock_at—ketepatan temporal komitmen ialah satu tempoh beacon.

Pemetaan prakeluaran legasi dan toleransi sisi buka kunci: pemetaan asal ialah ceil((unlock_at - chain_genesis_time) / chain_period_seconds), yang—bagi kes sejajar tempoh di atas—memilih pusingan yang diterbitkan satu tempoh penuh sebelum unlock_at, lalu membolehkan teks sifer dinyahsulit awal tepat satu tempoh. Kedua-dua pemetaan berbeza tepat +1 apabila delta boleh dibahagikan dengan tempoh, dan sama dalam kes lain. Oleh sebab drand_round dilipat ke dalam praimej qub_id yang tidak boleh diubah (§4.1), artifak yang dimeterai di bawah pemetaan legasi tidak boleh diterbitkan semula; pengesah yang melakukan semakan pusingan langkah 6a §8 MUST menerima drand_round tersimpan yang sama ada sama dengan pusingan terbitan atau pusingan terbitan tolak satu (dan MUST memerlukan pusingan stanza tlock sepadan tepat dengan pusingan tersimpan). Toleransi ini meluaskan tandatangan pengawal paling awal tidak lebih daripada satu tempoh. Perkhidmatan pementasan perjanjian menggunakan toleransi sama apabila menerbitkan semula qub_id perjanjian dipentaskan (ketika pementasan dan penandatanganan bersama): jika pusingan pemetaan semasa tidak menghasilkan qub_id yang dikomited dan delta boleh dibahagikan dengan tempoh, ia mencuba semula dengan pusingan tolak satu, lalu memeterai perjanjian muktamad kepada pusingan yang benar-benar diikat oleh qub_id—bukan secara membuta tuli kepada pusingan yang dikira semula, yang akan menjadikan artifak mustahil diterbitkan semula secara kekal.

Pengesahan: unlock_at MUST berada pada masa hadapan pada masa pemeteraian. unlock_at MUST NOT lebih daripada 10 tahun daripada created_at (untuk mengehadkan risiko kebergantungan drand jangka panjang; UI SHOULD memberi amaran untuk tarikh buka kunci melebihi 2 tahun).


5. Jenis Baharu Format Wayar

Jenis baharu format wayar menyediakan keselamatan masa-kompilasi terhadap mengelirukan bait CBOR dengan JSON, teks biasa mentah, atau pengekodan bait lain.

Jenis Mengandungi Dihasilkan Oleh Digunakan Oleh
SealedQubCbor CBOR berkanun bagi SealedQub serialize_sealed_qub() Artifak wayar dalaman; disimpan tanpa pembungkus untuk penghantaran awam atau dibungkus untuk penghantaran peribadi, kemudian dipulihkan oleh pembaca
QubEnvelopeCbor CBOR berkanun bagi QubEnvelope serialize_qub_envelope() Input penyulitan tlock, output penyahsulitan tlock

5.1 Peraturan Pembinaan

// 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 Pengesahan pada Pembinaan

from_encoded() SHOULD mengesahkan bahawa input bermula dengan pengepala peta CBOR yang sah. Pengesahan struktur penuh berlaku pada masa hurai, bukan masa pembinaan, untuk mengelakkan hurai-dua-kali.


6. Pendaftaran Jenis Kandungan

Nilai Jenis Saiz Badan Maks Nota
0x00 Dikhaskan (tidak sah) — MUST NOT digunakan
0x01 Teks biasa (UTF-8, Markdown terhad) 50 KB berbayar / 10 KB percuma Lihat §10 untuk peraturan pemaparan. Pemisahan percuma / berbayar dikuatkuasakan oleh perkhidmatan muat naik; siling keras lapisan protokol ialah 50 KB.
0x02 Dikhaskan (masa depan) — Diperuntukkan untuk jenis kandungan masa depan; tidak sah dalam v1. Pembaca MUST menolak mengikut peraturan di bawah.
0x03 Perjanjian (perjanjian dwihala, badan CBOR) 100 KB Badan ialah CBOR berkanun PactTerms (§6.1). Tandatangan bersama mengikut §9.7.
0x04 Keputusan (penilaian-diri pencipta, badan CBOR) 8 KB Badan ialah CBOR berkanun VerdictBody (§6.2). Dikeluarkan hanya oleh hasrat sisi-sistem verdict. Hubungan induk berada pada tag Arweave Parent-Tx-Id, bukan pada badan. Lihat verdict-uplift-plan §3.4.

Pembaca MUST menolak jenis kandungan yang tidak dikenali dengan ralat yang jelas kelihatan kepada pengguna. Pembaca MUST NOT cuba memaparkan jenis yang tidak dikenali sebagai teks.

6.1 Badan Perjanjian (content_type = 0x03)

Badan perjanjian ialah pengekodan CBOR berkanun bagi nilai PactTerms:

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)> }

Susunan kunci CBOR berkanun untuk ketiga-tiga peta diberikan dalam §3.2. Jumlah CBOR perjanjian yang disirikan MUST NOT melebihi 100 KB (sepadan dengan §6).

Pembeza skema. Baris pertama dalam terms untuk perjanjian structured/v1 MUST ialah { key: "pact_schema", value: "structured/v1" }. Baris tanpa penanda ini ialah perjanjian "tersuai" dan tidak menerima pengesahan berstruktur atau pemaparan sedar-skema.

Slot pengakuan yang dibekukan. Perjanjian structured/v1 membawa tepat empat baris pengakuan di bawah kunci berikut:

"initiator_standard_terms"
"initiator_capacity_terms"
"counterparty_standard_terms"
"counterparty_capacity_terms"

Nilai value bagi setiap satu ialah salah satu daripada lapan rentetan Inggeris dibekukan yang dipilih oleh pasangan (role, kind), di mana role ∈ { seller, buyer, provider, client } dan kind ∈ { standard, capacity }. Rentetan itu sendiri ialah data protokol normatif — tandatangan ML-DSA-65 kedua-dua pihak komited kepada bait yang tepat melalui body_hash. Ia TIDAK dilokalkan; badan yang ditandatangani bersifat neutral-bahasa. Apa-apa perubahan kata-kata memerlukan versi skema baharu (structured/v2).

Lapan rentetan, carian (acknowledgement_for(role, kind)), dan rasional bagi setiap satu disematkan oleh implementasi rujukan. Implementasi yang mematuhi MUST mengeluarkan nilai pengakuan yang serupa bait-demi-bait; ujian body-cincangan SHA3-256 lekapan-emas yang meliputi keempat-empat kombinasi peranan menangkap apa-apa hanyutan.

Susunan paparan pembaca. Rentetan pengakuan mengandungi frasa seperti "described above", yang menganggap baris penerangan / skop dipaparkan sebelum pengakuan. Pembaca MUST memaparkan tatasusunan terms dalam susunan CBOR; menyusun semula merosakkan semantik prosa.

Hubungan Pihak Lawan. Apabila contact Pihak B ialah alamat e-mel yang sah, perkhidmatan muat naik qub menghantar e-mel jemputan semakan / tandatangan bersama secara automatik pada masa pementasan dan mengikat tandatangan bersama akhirnya kepada pengesahan alamat yang sama itu (§9.7). Perjanjian yang contact Pihak B-nya tiada masih boleh ditandatangani bersama, tetapi hanya melalui saluran luar-jalur — perkhidmatan menolak permintaan tandatangan bersama yang tidak boleh menghasilkan penanda pengesahan-e-mel 15 minit yang sepadan.

6.2 Badan Keputusan (content_type = 0x04)

Badan keputusan ialah pengekodan CBOR berkanun bagi nilai VerdictBody:

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
}

Susunan kunci CBOR berkanun:

"outcome"          (8 encoded bytes)
"reflection"       (11 encoded bytes)  ← only if present
"evidence_url"     (13 encoded bytes)  ← only if present
"verdict_version"  (16 encoded bytes)

Jumlah CBOR keputusan yang disirikan MUST NOT melebihi 8 KB (sepadan dengan baris pendaftaran di atas).

Enum keputusan. Bait wayar bersifat hasrat-neutral; keempat-empat kategori Right / Partial / Wrong / Unfalsifiable meliputi ruang keputusan setiap hasrat yang membawa keputusan. Label setiap-hasrat ("Tepat sasaran" / "Saya menunaikannya" / "Dikeluarkan" / "Disahkan" untuk Right, dsb.) ialah kebimbangan pemaparan sisi-pembaca yang diselesaikan terhadap hasrat qub induk — wayar kekal neutral-bahasa dan neutral-hasrat. Nilai di luar 1..=4 MUST ditolak pada penyahkodan.

Pautan induk. Sebuah qub keputusan TIDAK membawa rujukan induk dalam badannya. Id transaksi Arweave qub induk dikeluarkan sebagai tag storan Parent-Tx-Id pada masa muat naik (§7 lapisan tag storan). Ini mengekalkan badan sebagai pernyataan penilaian-diri yang ditandatangani dan serba lengkap; rantai audit ("betul tentang apa?") ditubuhkan melalui carian tag Arweave.

Keselamatan URL bukti (normatif). Apabila evidence_url hadir, pengesah (sisi-karang, sisi-wayar, edge Worker) MUST menguatkuasakan:

  1. HTTPS sahaja. Rentetan MUST bermula dengan urutan bait https://. Apa-apa skema lain — http, ftp, javascript, data, file, dsb. — ditolak.
  2. Had panjang. ≤ 2,048 bait (had praktikal URL pelayar).
  3. Pemeriksaan NFC + kod-titik bermusuhan. Peraturan yang sama seperti title dan reflection — kod-titik bidi-override / lebar-sifar / blok-tag / BOM / C0 / C1 ditolak. Definisi sepadan dengan Rust crate::handle::contains_hostile_text_codepoint dan TS workers/api/src/utils/unicode.ts::isHostileCodepoint (kekalkan selari).
  4. Tiada ruang putih, tiada kawalan ASCII. Ruang putih / DEL / bait di bawah 0x20 di mana-mana dalam URL ditolak — menutup vektor suntikan \n/\t yang tidak diliputi peraturan bidi.
  5. Segmen hos tidak kosong. Semua yang berada di antara https:// dan /, ?, atau # yang pertama MUST tidak kosong.

Tiada pengambilan sisi-pelayan. Worker MUST NOT memproksi, mengambil, atau pratonton URL. Protokol menyimpan rentetan; pemaparan berlaku sisi-pembaca dengan rel="nofollow noopener noreferrer" target="_blank" dan hos yang kelihatan dipaparkan bersebelahan teks pautan.

Refleksi. Teks refleksi tulisan-pencipta pilihan ("apa yang berubah, apa yang anda pelajari"). Pengesahan NFC + kod-titik bermusuhan yang sama seperti title. Input kosong / hanya ruang putih menguncup kepada tiada pada masa pembinaan.

Versi skema. v1 menyokong verdict_version = 0x01 sahaja. Semakan skema masa depan menaikkan bait ini dan tiba bersama versi protokol baharu mengikut §12.


7. Protokol Meterai

Urutan pemeteraian lengkap. Setiap langkah bersifat normatif.

 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.

Lapisan tag storan (luar jalur). Perkhidmatan muat naik qub melampirkan set kecil tag transaksi storan yang disengajakan di samping muatan muat naik yang dipilih. Content-Type=application/octet-stream diperlukan secara normatif. Perkhidmatan rujukan turut melampirkan tiga tag pilihan apabila pencipta memilih untuk memaparkannya: Intent (niat gubahan yang disahkan berdasarkan senarai izin—announcement, thesis, prediction, letter, secret, commitment, proof, atau verdict yang dikeluarkan sistem), Author (cap jari kunci awam §9.3 pencipta sebagai heks huruf kecil 64 aksara), dan Parent-Tx-Id (id transaksi storan qub induk untuk rantai balas, base64url 43 aksara).

Tag Author ialah pilih masuk bagi setiap qub: aplikasi pencipta rujukan hanya melampirkannya apabila pengguna mendayakan atribusi awam secara nyata pada masa pemeteraian. Apabila togol dimatikan—lalainya—tiada tag Author ditulis dan qub tidak dikaitkan pada rantai: tiada apa-apa dalam storan kekal yang memautkan muat naik kepada handle, e-mel, atau qub lain pencipta. Apabila togol dihidupkan, cap jari Author menyelesaikan kepada @handle pilihan pencipta melalui rantai atestasi §9.5. Hubungan rantai balas dan Intent tidak mengenal pasti. Bagi penghantaran peribadi, pembungkus luar (§13) menyulitkan artifak dalaman SealedQub yang dapat dikenali, maka penuaian pembungkus tersimpan bersama tandatangan drand awam masih tidak mencukupi untuk memulihkan badan tanpa K; tag storan kekal sebagai metadata awam secara sengaja.

Perkhidmatan rujukan sengaja TIDAK melampirkan tag App-Name, App-Version, atau Type: apa-apa penapis bernilai-tunggal sebegini akan mengembalikan keseluruhan korpus qub kepada pertanyaan GraphQL, yang tidak konsisten dengan skop kerahsiaan badan-sahaja pembungkus.

Pengesah yang mematuhi MUST NOT bergantung pada apa-apa tag storan untuk pengesahan pihak-ketiga §11; cincang badan / qub_id / tandatangan komited hanya kepada CBOR dalaman, tidak pernah kepada set tag.


8. Protokol Buka Kunci

Urutan buka kunci lengkap. Setiap langkah bersifat normatif.

 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. Tandatangan Pengarang

9.1 Rasional

qub disimpan dalam storan kekal. Tandatangan pengarang mesti kekal tidak boleh dipalsukan selama-lamanya, sebab itulah v1.0 menggunakan skema ML-DSA-65 pasca-kuantum (FIPS 204) berbanding skema klasik yang keselamatannya boleh merosot dalam hayat kekal qub.

9.2 Pendaftaran Algoritma

sig_alg Skema Saiz Kunci Saiz Tandatangan Status
0x00 Tiada tandatangan (tanpa tandatangan) — — Aktif
0x01 ML-DSA-65 (FIPS 204) 1,952 bait 3,309 bait Aktif
0x02 Ed25519 32 bait 64 bait Pemalar dikhaskan; tidak disokong dalam protokol v1

Pembaca protokol v1 MUST menolak setiap nilai di luar {0x00, 0x01}, termasuk nilai 0x02 yang dikhaskan. Tempahan mencegah penggunaan semula secara tidak sengaja; ia bukan pengaktifan. Pengaktifannya memerlukan perubahan tertadbir yang diterangkan dalam §15.

9.3 Pembinaan Praimej Bertandatangan

Dua versi praimej pernah wujud. Semua tandatangan MUST menggunakan V2, dan pengesah MUST menerima V2 sahaja. Praimej V1 warisan (didokumenkan di bawah untuk rujukan sejarah) diterima sebagai sandaran pengesahan-sahaja semasa migrasi V2; sandaran itu telah ditamatkan dan tandatangan V1-sahaja kini ditolak.

V2 (semasa — dihasilkan oleh semua penandatanganan pengarang baharu, dan oleh kedua-dua tandatangan aliran pementasan / tandatangan bersama perjanjian):

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)

sender_label_hash mengikut konvensyen penunjuk-ketiadaan yang sama seperti title_hash (§4.2.1): 32 bait sifar bukan output SHA3-256 yang sah, jadi "ketiadaan" tidak akan pernah berlanggar dengan label yang hadir. Semua medan mempunyai lebar tetap, jadi praimej tidak taksa tanpa awalan panjang.

V1 (warisan — DITAMATKAN; tidak lagi dihasilkan dan tidak lagi diterima semasa pengesahan):

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

Praimej V1 meninggalkan sender_label dan reply_to. Ia diterima sebagai sandaran pengesahan-sahaja semasa migrasi ke V2; sandaran itu sejak itu telah ditamatkan — pengesah MUST menerima praimej V2 sahaja. Takrif ini dikekalkan di sini untuk rujukan sejarah dan untuk menerangkan pemisah domain di bawah. Tandatangan yang hanya disahkan terhadap V1 MUST dianggap sebagai kegagalan pengesahan.

Pemisah domain: "QUB_AUTHOR_SIG_V1" / "QUB_AUTHOR_SIG_V2" ialah 17 bait ASCII setiap satu ([0x51, 0x55, 0x42, 0x5F, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x5F, 0x53, 0x49, 0x47, 0x5F, 0x56, 0x31/0x32]). Tiada pelapik. Pemisah yang berbeza memisahkan-domain kedua-dua binaan, jadi tandatangan atas satu praimej tidak akan pernah disahkan sebagai yang satu lagi.

Bait org_id_present: bait yang mengikuti unlock_at MUST ialah 0x00. Implementasi rujukan mendedahkan ini sebagai pemalar ORG_ID_PRESENT_INDIVIDUAL = 0x00 dalam crates/qub-core/src/signing.rs; pembaca yang membina semula sig_input untuk pengesahan MUST mengeluarkan bait yang sama.

Skop tandatangan — apa yang diliputi dan apa yang tidak. sig_input V2 komited secara langsung kepada version, qub_id, body_hash, unlock_at, sender_label, dan reply_to (tambah pemisah domain tetap dan bait org_id_present). qub_id itu sendiri diterbitkan daripada version, content_type, created_at, unlock_at, outcome_at, drand_round, dan body_hash melalui praimej §4.1, jadi apa-apa perubahan kepada medan-medan itu menghasilkan qub_id yang berbeza dan membatalkan tandatangan secara transitif. Permukaan yang disahkan dengan itu ialah:

Medan Disahkan oleh tandatangan Bagaimana
version ✓ Input langsung kepada sig_input
qub_id ✓ Input langsung
body_hash ✓ Input langsung
unlock_at ✓ Input langsung
sender_label ✓ Input langsung melalui sender_label_hash (praimej V2 — satu-satunya bentuk yang diterima)
reply_to ✓ Input langsung melalui reply_to_or_zero (praimej V2 — satu-satunya bentuk yang diterima)
content_type ✓ Secara transitif, melalui praimej qub_id
created_at ✓ Secara transitif, melalui praimej qub_id
outcome_at ✓ Secara transitif, melalui praimej qub_id
drand_round ✓ Secara transitif, melalui praimej qub_id
body ✓ Secara transitif, melalui body_hash = SHA3-256(body)
author_pubkey — (tersirat) Kunci yang mengesahkan tandatangan ialah pengarang, secara takrif
cosigner_pubkey / cosigner_signature — Ditandatangani secara bebas pada sig_input yang sama (lihat §9.7)
drand_chain_id, tlock_ciphertext, visibility — Medan SealedQub luaran, bukan di dalam envelope — diliputi oleh invarian struktur mereka sendiri (konsistensi pusingan / rantai) tetapi bukan oleh tandatangan pengarang. (drand_round kini diikat secara transitif melalui praimej qub_id — lihat di atas.)

Mengapa V2 ialah satu-satunya praimej yang diterima.

Implementasi yang memaparkan sender_label atau reply_to kepada pengguna akhir MUST mempamerkan identiti yang disahkan (cap jari kunci awam, pengesahan) sebagai isyarat identiti utama, bukan label.

9.4 Prosedur Pengesahan

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."

Pengesahan tandatangan ialah operasi yang paling mahal (terutamanya ML-DSA-65). Ia SHOULD dilakukan selepas semua pemeriksaan yang lebih murah (cincang, qub_id, unlock_at) telah lulus.

9.5 Pengesahan Identiti

Pengesahan identiti — pemetaan author_pubkey kepada tuntutan identiti yang boleh dikenali manusia seperti pemegang qub, alamat e-mel, pemegang sosial, atau kelayakan passkey — ialah peningkatan progresif sisi-pembaca dan tidak diperlukan untuk pengesahan tandatangan. Pembaca yang menyelesaikan pengesahan kepada identiti paparan MUST menggunakan kekananan:

handle > email > social > fingerprint

Sandaran cap jari ialah heks huruf kecil bagi SHA3-256(author_pubkey); ia sentiasa tersedia untuk mana-mana qub bertandatangan. Pembaca MAY meringkaskannya untuk paparan — pembaca rujukan memaparkan qub: diikuti oleh empat bait pertama dan terakhir (qub:<8 hex>…<8 hex>).

Pengesah yang mematuhi boleh melengkapkan setiap pemeriksaan dalam §9.4 tanpa menghubungi API qub, tanpa apa-apa rangkaian melebihi storan kekal dan drand, dan tanpa apa-apa carian sisi-pelayan. Penyelesaian pengesahan ialah langkah terbaik-cuba yang berasingan yang dilakukan hanya selepas pengesahan tandatangan berjaya.

9.6 Kesan Saiz

Ed25519 ML-DSA-65
Tandatangan 64 bait 3,309 bait
Kunci awam 32 bait 1,952 bait
Jumlah setiap qub 96 bait 5,261 bait
Delta kos storan (pada ~$5/MB) ~$0.0005 ~$0.026

Untuk qub teks 500–2,000 bait, ML-DSA-65 kira-kira menggandakan tiga kali ganda saiz yang disimpan. Kos mutlak adalah boleh diabaikan.

9.7 Pengesahan Penandatangan Bersama (Perjanjian Dwihala)

Untuk perjanjian dwihala (content_type = 0x03), lapisan tandatangan kedua membuktikan kedua-dua pihak bersetuju dengan terma yang sama.

Medan envelope:

Kedua-dua medan MUST hadir bersama-sama atau kedua-duanya tiada. Jika tepat satu hadir, pembaca MUST melaporkan ralat integriti.

Prosedur pengesahan:

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."

Sifat:

Pintu pengikatan-e-mel (operasi). Apabila perjanjian yang dipentaskan membawa hubungan e-mel Pihak B (§6.1), perkhidmatan muat naik qub MUST menolak permintaan tandatangan bersama melainkan penanda pengesahan-e-mel jangka pendek wujud yang sepadan dengan kedua-dua id pementasan dan cincang e-mel ternormal hubungan tersebut. Penanda itu ditulis oleh /api/v1/auth/verify apabila token pautan-ajaib membawa staging_id dan alamat yang disahkan sepadan dengan SHA-256(normalise_email(party_b.contact)) — di mana normalise_email(addr) mengekalkan kes bahagian-tempatan dan menurunkan huruf kecil hanya bahagian domain (mengikut RFC 5321 §2.3.11), dan SHA-256 di sini ialah cincang NIST FIPS 180-4 (berbeza daripada SHA3-256 yang digunakan dalam derivasi §4) — dan tamat tempoh 900 saat (15 minit) selepas dikeluarkan. Ini ialah pintu anti-penyamaran operasi, BUKAN sebahagian daripada bukti qub atas-rantai — pengesah pihak-ketiga yang memainkan semula §11 hanya memerlukan storan kekal dan drand, tanpa apa-apa carian sisi-pelayan. Penanda wujud sisi-pelayan sahaja dan tidak pernah menjadi sebahagian daripada badan yang ditandatangani.

Kesan saiz (pengarang ML-DSA-65 + penandatangan bersama):

Komponen Saiz
Tandatangan pengarang 3,309 bait
Kunci awam pengarang 1,952 bait
Tandatangan penandatangan bersama 3,309 bait
Kunci awam penandatangan bersama 1,952 bait
Jumlah overhed kripto 10,522 bait
Delta kos storan ~$0.05

10. Pemaparan dan Sanitasi Markdown

Bahagian ini kritikal keselamatan. Pembaca memaparkan qub teks (content_type = 0x01) menggunakan subset Markdown yang terhad.

10.1 Elemen Dibenarkan

10.2 Elemen Dilarang

Elemen Pengendalian
HTML mentah (<div>, <script>, dsb.) Dibuang sepenuhnya. Tiada HTML melepasi.
Imej (![alt](url)) Dibuang. Sintaks imej dialih keluar daripada output.
Pautan ([text](url)) URL dipaparkan sebagai teks biasa yang kelihatan. Tidak auto-pautkan. Tidak boleh diklik tanpa tindakan pengguna yang eksplisit.
Skema URL berbahaya javascript:, data:, vbscript:, file: — dibuang.
Iframe, embed, objek Dibuang.
Entiti HTML Dinyahkod kepada aksara paparan hanya jika selamat.

10.3 Implementasi

Implementasi MUST menggunakan penghurai senarai dibenarkan ketat, bukan senarai disekat. Pendekatan yang disyorkan:

  1. Hurai Markdown menggunakan pulldown-cmark (atau setara).
  2. Susuri AST dan buang mana-mana nod yang tidak dalam senarai dibenarkan (§10.1).
  3. Untuk nod pautan: keluarkan URL sebagai teks yang kelihatan, bukan sebagai elemen <a> yang boleh diklik.
  4. Tukarkan AST yang ditapis kepada perwakilan perantaraan bertaip (cth., enum MarkdownNode dengan hanya varian selamat). HTML mentah tidak boleh diwakili secara struktur dalam IR ini.
  5. Paparkan daripada IR bertaip kepada lapisan pandangan sasaran (cth., komponen pandangan reaktif, nod DOM). Tiada penyambungan rentetan HTML atau innerHTML pada bila-bila masa.

Pendekatan senarai disekat adalah rapuh kerana sambungan Markdown baharu atau keanehan penghurai boleh memperkenalkan elemen yang tidak ditapis. Pendekatan AST bertaip menjadikan XSS mustahil secara struktur — tiada varian yang boleh membawa HTML sewenang-wenangnya.

10.4 Had Saiz dan Struktur


11. Pengesahan Pihak Ketiga

Mana-mana pihak ketiga yang memegang bait tersimpan (dan K bagi qub peribadi/dibungkus) boleh mengesahkan artifak kriptografi tanpa kerjasama qub. Dakwaan kewujudan bercap masa bebas turut memerlukan sama ada kemasukan storan kekal setiap qub yang disahkan atau bukti log ketelusan §16 yang disahkan.

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.

Apa yang dibuktikan oleh pengesahan:

Input bukti Apa yang ditetapkan
Bundle / artifak dimeterai yang sah + tandatangan drand Badan dipulihkan sepadan dengan body_hash; metadata yang terikat dalam qub_id kekal utuh; teks sifer terikat kepada pusingan drand yang dinyatakan; dan pusingan itu telah berlalu. Ini tidak menetapkan bila teks sifer dicipta.
Tandatangan pengarang/penandatangan bersama V2 yang sah Pemegang kunci rahsia sepadan mengesahkan permukaan bertandatangan dalam §9.3.
Transaksi storan setiap qub yang disahkan secara bebas Teks sifer tersimpan yang tepat telah wujud selewat-lewatnya pada cap masa bloknya.
Bukti log ketelusan berlabuh yang sah Dakwaan khusus jenis daun dalam §16.11, termasuk had masa atas komitmen daripada blok labuh.

Apa yang TIDAK dibuktikan oleh pengesahan:

Bukan-bukti Mengapa
Kepengarangan sender_label bersifat hiasan. Tanpa sig_alg ≥ 0x01, sesiapa sahaja boleh memeterai kandungan ini.
Niat Artifak membuktikan bait dan hubungan kriptografi, bukan maksud subjektif pencipta.
Komitmen sedia ada daripada .qub sahaja Pencipta boleh menghimpunkan bundle yang sah selepas pusingan terikat berlalu. Tandatangan drand terbenam membuktikan pusingan telah berlalu, bukan bahawa teks sifer telah wujud sebelumnya.
Masa tepat butang meterai Cap masa blok storan atau labuh ialah had atas yang boleh disahkan secara bebas dan mungkin lewat daripada tindakan tempatan pengguna. Dakwaan sealed_at / received_at bukan bukti.

Log ketelusan yang dilaksanakan (§16) memperluas pengesahan merentas qub dengan susunan yang dapat mengesan pengusikan dan had masa atas komitmen tanpa amanah (masa blok labuh), berskop mengikut jenis daun (§16.11). Ia tidak menambah kepengarangan atau niat; bagi laluan muat naik lalai yang buta bait, log itu sendiri tidak membuktikan body_hash atau drand_round, yang terus datang daripada semakan artifak.


12. Kawalan Versi dan Keluaran

Keluaran dokumen, protokol wayar dalaman, dan pembungkus luar ialah ruang versi yang berasingan. Oleh itu, penjelasan dokumen sahaja tidak mengubah bait secara senyap, dan migrasi wayar masa hadapan tidak boleh menyamar sebagai semakan editorial.

12.1 Versi Keluaran Dokumen

Spesifikasi ini menggunakan keluaran dokumen semantik (MAJOR.MINOR.PATCH) dan tag Git kekal bernama protocol-v<release>.

Status keluaran ialah salah satu daripada Draf (belum normatif), Semasa (satu-satunya sasaran pelaksanaan yang disyorkan), atau Digantikan (dikekalkan untuk pengesahan sejarah). Laluan /protokol tanpa versi memaparkan keluaran Semasa; tag keluaran memelihara sumber tepat dan setiap lokal yang diterbitkan bersamanya. Perubahan status atau nombor keluaran memerlukan jadual ini dan sejarah keluaran dikemas kini dalam perubahan semakan yang sama.

Keluaran dokumen Tarikh berkuat kuasa Status Protokol wayar Pembungkus Sumber
1.0.0 2026-09-23 Semasa 0x01 0x01 protocol-v1.0.0

12.2 Versi Protokol

Medan version (u8) dalam kedua-dua SealedQub dan QubEnvelope mengenal pasti versi protokol utama.

12.3 Sejarah Versi Protokol

Versi Nilai Penerangan
v1 0x01 Penghantaran peribadi/dibungkus dan awam/tanpa pembungkus; badan teks (0x01), perjanjian (0x03), dan keputusan (0x04); penandatanganan pengarang/penandatangan bersama ML-DSA-65 V2; tlock drand quicknet; SHA3-256.

12.4 Keserasian Ke Hadapan

Pembaca v1 yang menjumpai QubEnvelope dengan kunci peta CBOR yang tidak dikenali (kunci yang tiada dalam susunan berkanun §3.2) MUST menolaknya dengan ralat nyahkod (§3.1). Keserasian ke hadapan bergantung pada medan version, bukan pada tolak ansur kunci: penambahan pada masa hadapan — walaupun metadata kecil — dihantar di bawah nilai version baharu, yang ditolak oleh pembaca v1 dengan ralat "protokol lebih baharu" yang jelas, bukannya secara senyap menggugurkan kandungan yang dikomit oleh tandatangan.

Pembaca v1 yang menjumpai sig_alg = 0x01 (ML-DSA-65) tetapi kekurangan sokongan pengesahan ML-DSA-65 SHOULD memaparkan kandungan qub dengan notis "tandatangan hadir tetapi tidak boleh disahkan", bukannya menolak qub sepenuhnya. Implementasi rujukan hari ini menolak setiap nilai sig_alg selain daripada 0x00 dan 0x01 kerana pendaftaran v1 tidak mengandungi algoritma sah lain — penolakan ketat dan gagal-lembut adalah serupa dari segi pemerhatian sehingga algoritma ketiga didaftarkan. Tingkah laku gagal-lembut di atas menjadi memikul-beban sebaik sahaja §9.2 menerima entri baharu, dan pembaca rujukan akan dikemas kini kepada gagal-lembut pada ketika itu.

12.5 Versi Pembungkus Luar

OuterWrapper yang diterangkan dalam §13 membawa bait version-nya sendiri, bebas daripada SealedQub.version dan QubEnvelope.version. Kedua-dua ruang versi berkembang secara berasingan: penggantian simetrik selamat-pasca-kuantum pada masa hadapan menolak bait pembungkus tanpa menyentuh versi protokol dalaman, dan penambahan lapisan protokol pada masa hadapan (cth., medan envelope baharu) menolak versi dalaman tanpa menyentuh bait pembungkus.

OUTER_WRAPPER_VERSION_* Nilai Algoritma Status
OUTER_WRAPPER_VERSION_1 0x01 AES-256-GCM dengan nonce 12-bait, tag pengesahan 16-bait, AAD terikat kepada qub_id Aktif untuk penghantaran peribadi
— 0x02–0xFF Dikhaskan Masa Hadapan

Pembaca MUST menolak versi pembungkus yang tidak dikenali dengan ralat yang jelas. Protokol sengaja mengekalkan ruang versi pembungkus yang sempit sehingga pemacu migrasi konkrit muncul (cth., panduan NIST yang mengutamakan AEAD yang berbeza); slot 0x02 akan diperuntukkan dalam semakan yang sama yang memperkenalkan algoritma.


13. Pembungkus Penyulitan Luar

13.1 Rasional

Lapisan protokol (QubEnvelope → tlock → SealedQub) menjadikan qub yang dimeterai terkunci-waktu: badan tidak boleh dibaca sehingga unlock_at dan tandatangan pusingan drand telah diterbitkan. Walau bagaimanapun, selepas buka kunci, tandatangan pusingan adalah awam dan bentuk CBOR berkanun SealedQub boleh dikenali, jadi penuai yang mengindeks transaksi storan kekal boleh menyahsulit korpus qub keseluruhan secara pukal.

Bagi penghantaran peribadi, pembungkus penyulitan luar menutup saluran itu dengan menyelitkan lapisan AEAD simetri tambahan antara SealedQubCbor berkanun dan bait yang disimpan. Dalam laluan pemeteraian pelayar, kunci 256-bit K wujud hanya dalam fragmen URL pautan penghantaran dan pada peranti pengguna; pelayar tidak menghantar fragmen URL kepada pelayan, maka qub.social, setiap gateway storan, dan setiap CDN di hadapan kedua-duanya tidak dapat melihat K. Perwakilan tersimpan qub peribadi oleh itu ialah teks sifer legap yang teks biasanya tidak boleh dipulihkan tanpa URL yang dipilih pencipta untuk dikongsi. Penghantaran awam sengaja meninggalkan lapisan ini (§13.8).

Kesan bersih:

13.2 Berlapis

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

Meterai dan buka kunci pada lapisan protokol (§7, §8) tidak berubah di bawah sempadan pembungkus; pembungkus dilekatkan pada laman panggilan seal() dan ditanggalkan pada laman panggilan unlock().

13.3 Struktur Data 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
}

Invarian medan.

Pengekodan CBOR. CBOR berkanun mengikut §3, dengan peraturan susunan-kunci yang sama (diisih mengikut panjang bait terkod menaik, kemudian secara leksikografi). Empat kunci tersebut ialah:

Kunci Bait terkod Susunan
nonce 6 1
qub_id 7 2
version 8 3
ciphertext 11 4

Bait pertama OuterWrapper CBOR oleh itu ialah pengepala peta panjang-tentu untuk peta 4-entri (0xA4).

13.4 Pengikatan AAD kepada qub_id

Pembungkus mengikat qub_id sebagai data pengesahan tambahan AEAD. Ini ialah pertahanan struktur yang memikul beban terhadap tiga kelas serangan:

Serangan Pertahanan
Alih siferteks di bawah medan qub_id yang berbeza dalam pembungkus Ketidakpadanan AAD → pengesahan AEAD gagal
Campurkan fragmen URL qub A dengan bait tersimpan qub B Kunci salah (serta AAD yang terikat secara bebas) → pengesahan AEAD gagal
Usik medan qub_id pembungkus selepas muat naik Ketidakpadanan AAD → pengesahan AEAD gagal

Membawa qub_id dalam teks biasa pembungkus tidak melemahkan imuniti penghitungan dengan ketara — qub_id itu sendiri ialah cincang SHA3-256 bagi praimej §4.1 tanpa praimej boleh-pulih daripada cernaan, dan penghitung yang telah menuai bait pembungkus tidak belajar apa-apa daripada qub_id yang kelihatan yang tidak boleh disimpulkan daripada kewujudan muat naik itu sendiri.

13.5 Algoritma Bungkus dan Nyahbungkus

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

Keruntuhan mod-kegagalan. K yang salah, nonce yang salah, ketidakpadanan AAD, dan siferteks yang diusik semuanya menghasilkan ralat DECRYPT_FAILED yang sama. Ini ialah sifat AEAD yang disengajakan: membezakan mod kegagalan akan mencipta saluran sampingan yang penyerang jauh boleh siasat dengan menghantar pembungkus cacat dan mengetik tindak balas. Implementasi rujukan MUST meruntuhkan semua kegagalan AEAD kepada satu bentuk ralat.

13.6 Bahan Kunci dan Pengedaran

Kunci pembungkusan K ialah nilai rawak seragam 256-bit yang dihasilkan setiap-qub oleh CSPRNG. Implementasi rujukan mendapatkannya daripada:

Pengedaran: K MUST dikodkan sebagai base64 URL-selamat (RFC 4648 §5, tanpa pelapik) dan ditambah kepada pautan penghantaran sebagai komponen fragmen:

delivery_url = <origin>/c/<arweave_tx_id>#<base64url(K)>

Fragmen tidak pernah dihantar kepada mana-mana pelayan oleh pelayar yang mematuhi. Saluran pemulihan (indeks sejarah sisi-pelayan, hantar-auto e-mel pilih-masuk) yang mengekalkan pautan penghantaran penuh — termasuk fragmen — di luar peranti pengguna ialah pertukaran eksplisit terhadap postur kripto-pemusnahan lalai dan MUST dipintu pada persetujuan eksplisit pengguna.

Kehilangan fragmen. Jika pengguna kehilangan fragmen URL dan tiada saluran pemulihan, qub tidak boleh dibaca. Inilah pertukaran memikul-beban reka bentuk dan MUST didedahkan kepada pengguna pada masa pemeteraian. MVP mengukuhkan pendedahan masa-pemeteraian dengan salinan eksplisit "simpan URL ini" dan saluran pemulihan e-mel disahkan untuk pengguna yang pilih-masuk.

13.7 Di Luar Skop bagi Bahagian Ini

13.8 qub awam (peninggalan pembungkus)

Pembungkus luar bersifat pilihan pada lapisan penghantaran. Pencipta boleh memeterai qub sebagai awam, dan dalam kes itu SealedQubCbor berkanun memasuki saluran storan secara langsung, tanpa lapisan OuterWrapper dan tanpa kunci K:

SealedQubCbor bytes  ──(public)──▶  stored as-is
SealedQubCbor bytes  ──(private)─▶  AES-256-GCM(K, …) ▶ OuterWrapper ▶ stored

qub awam terkunci waktu tetapi tidak dikawal pautan: ia kekal tidak boleh dibaca sehingga pusingan drandnya diterbitkan (lapisan tlock tidak berubah), tetapi selepas dibuka kunci sesiapa yang mempunyai id transaksi storan boleh menyahsulitnya—tiada fragmen URL diperlukan kerana tiada K. Inilah pertukaran yang disengajakan untuk permukaan yang mesti dipacu pelayan: e-mel pemberitahuan pendedahan, pautan oEmbed/sematan automatik tanpa fragmen, dan SEO pascapendedahan yang lebih kaya semuanya memerlukan pautan yang berfungsi tanpa rahsia yang tidak pernah dipegang pelayan (§13.6). qub peribadi masih boleh menggunakan bentuk <qub-embed src="full_delivery_url"> yang nyata apabila penerbit membekalkan keupayaan lengkap yang mengandungi fragmen.

Akibat yang pengeluar MUST ambil kira:

Peribadi (terbungkus) kekal sebagai lalai; awam ialah pilihan pencipta setiap-qub yang eksplisit.


14. Vektor Ujian

14.1 Derivasi qub_id

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

Implementasi MUST menghasilkan nilai body_hash dan qub_id yang sama untuk input ini. Vektor ujian ini SHOULD menjadi ujian unit pertama yang ditulis. Nilai berkanun di atas dikira oleh pelaksanaan rujukan dan MUST sepadan bit demi bit. Susun atur prototaip prapelancaran bersejarah (tiada qub langsung bergantung pada dua yang pertama) menggunakan 92 bait sebelum outcome_at (3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0) dan 100 bait selepas menambah outcome_at_or_zero (b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed). Susun atur 108 bait semasa kemudian menambah drand_round dan pemisah domain QUB_ID_V2. Vektor awal 108 bait menggunakan pemetaan pusingan ceil legasi (drand_round = 4695445) dan menghasilkan 3a9fcb31b750d985c262fada6d4f777fd6a28be831d941d85c131f5a4bbaf8a4—masih qub_id yang sah bagi input pusingan itu, manakala contoh di atas mengikuti pemetaan pusingan semasa §4.3.

14.2 Pemetaan Pusingan-Buka-Kunci

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

Pusingan 4675286 diterbitkan pada 1595431050 + (4675286 - 1) * 30 = 1735689600—tepat pada unlock_at, tidak pernah sebelumnya. (Pemetaan ceil prakeluaran legasi menghasilkan 4675285, diterbitkan pada 1735689570—30 saat awal; pengesah menerima pusingan legasi itu mengikut §4.3.)

14.3 Pergi-Balik CBOR Berkanun

Implementasi MUST mengesahkan bahawa serialize(parse(serialize(qub))) == serialize(qub) untuk semua input yang sah. Ini ialah ujian sifat, bukan vektor tunggal.

14.4 CBOR PactTerms (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)

Bait CBOR berkanun dan body_hash SHA3-256 dikira oleh implementasi rujukan. Implementasi MUST menghasilkan CBOR yang serupa bait-demi-bait untuk input ini.

Implementasi juga MUST mengesahkan bahawa serialize(parse(serialize(pact))) == serialize(pact) untuk semua input PactTerms yang sah (ujian sifat).

14.5 Vektor Silang-Bahasa Pembungkus Luar

Pembungkus luar (§13) mempunyai lekapan berkanun yang berasingan di crates/qub-core/tests/vectors/wrapper_v1.json. Setiap kes menetapkan tupel (key, nonce, qub_id, sealed_cbor) sebagai input heks legap dan menegaskan output expected_wrapper_hex tertentu. Kedua-dua implementasi rujukan menggunakan fail JSON yang sama:

Lekapan tersebut kini menyemat tiga kes pembungkus aras rendah. Kes ini menguji pengekodan OuterWrapper deterministik dan kebolehoperasian AEAD secara berasingan daripada invarian bentuk penghantaran §13.8; khususnya, nama bersejarah basic-text-public dan visibility = 0x01 dalamannya tidak menjadikan bait dibungkus yang terhasil sebagai penghantaran awam yang mematuhi. Pengeluar MUST tetap menyimpan bait dalaman awam tanpa pembungkus dan hanya membungkus bait dalaman peribadi (0x00).

Kes Liputan
basic-text-public Nama lekapan aras rendah bersejarah. Bentuk SealedQub realistik terkecil, tanpa medan pilihan; hanya menguji bait pembungkus dan bukan penghantaran tersimpan §13.8 yang mematuhi.
with-recipient-pubkey SealedQub dengan recipient_pubkey ditetapkan (laluan masa hadapan yang dikhaskan). Menguji set kunci CBOR dalaman berbeza; kandungan lekapan yang tersendiri secara bebas menghasilkan qub_id berbeza (recipient_pubkey sendiri tiada dalam praimej §4.1).
longer-body Badan ~4 KiB — melatih awalan panjang CBOR pelbagai bait dalam kedua-dua envelope dalaman dan siferteks luar.

Implementasi MUST menghasilkan expected_wrapper_hex yang serupa bait-demi-bait untuk input yang direkodkan. Penjanaan semula lekapan memerlukan QUB_REGEN_VECTORS=1 cargo test -p qub-core --test wrapper_vectors dan dikhaskan untuk perubahan format yang disengajakan.


15. Tadbir Urus Profil Kripto (Masa Hadapan)

Bahagian ini bersifat informatif untuk v1 dan menjadi normatif kali pertama algoritma kedua memasuki mana-mana primitif kriptografi qub.

15.1 Postur Semasa

Protokol v1 mengikat tepat satu algoritma setiap primitif:

Pengesah kini mengekod keras panjang kunci dan tandatangan setiap primitif aktif. Bait sig_alg dan versi pembungkus ialah pemilih nyata, tetapi v1 tidak melakukan rundingan dalam jalur dan hanya menerima nilai aktif di atas.

15.2 Bentuk yang Dimaksudkan

Apabila algoritma kedua memasuki protokol, pengesah akan dikonfigurasi untuk CryptoProfile bernama (cth., ExqubV1) yang menyenaraikan set tepat nilai dibenarkan setiap primitif — sig_alg, rantai drand, versi pembungkus, jenis kandungan. Profil ditetapkan pada masa pengesahan, tidak pernah dirunding dalam-jalur. Apa-apa nilai di luar profil aktif ditolak.

Ini menjamin bahawa menambah ML-DSA-87 atau mengaktifkan Ed25519 tidak boleh secara retroaktif melemahkan konfigurasi pengesah sedia ada: pengesah v1 kekal sebagai pengesah v1 walaupun selepas profil v2 diterbitkan.

15.3 Syarat Pencetus

Naikkan §15 kepada status normatif apabila mana-mana yang berikut dicadangkan:

Sehingga itu §15 ialah pemegang tempat yang menetapkan bentuk migrasi supaya PR masa hadapan mendarat terhadap sasaran yang diketahui dan bukannya bertikai semula permukaan rundingan dari awal.


16. Log Ketelusan dan Peringkat Ketahanan (Dilaksanakan — semakan lengkap)

Status. Bahagian ini adalah dilaksanakan (W5/UP-B1, Tahap 1–8), dengan pengeluar dan skop amanah yang dinyatakan di sini. Format wayar, penghashan, dan laluan pemeriksa adalah langsung: jenis Merkle teras + CBOR kanonik (qub-core), cermin TypeScript + penggabung ANS-104 (workers/api/src/crypto/), penulis tunggal LogDO + stor nod R2 berkoordinat-kunci, itu /upload percubaan log-tambah, anchor harian + cron bundler-kuras, itu GET /api/v1/qub/:tx_id/proof (inklusi) dan GET /api/v1/log/consistency (RFC 9162) titik akhir bukti, bukti penyertaan bercetak yang dibawa dalam .qub bundle (§17.5), pengesah sauh ANS-104 asli (tools/qub-verify), dan kait kepala dua yang diterbitkan sendiri (§16.6). Yang berjaya /upload sentiasa tahan R2 tetapi hanya dilindungi oleh log apabila LOG_DO disediakan dan lampiran selari berjaya; hanya kemudian tindak balasnya dibawa log_seq, receipt, dan anchor_status. Jika RECEIPT_SK tidak hadir atau tidak sah, resit itu sig_b64url adalah kosong dan tidak menyediakan penafian. Semasa /seal dan laluan penerbitan pakatan menjadualkan transaksi Arweave individu tetapi tidak menambah daun log. Tiada kod yang kini melaksanakan /upload komen mengenai cadangan penyatuan kemudian selepas kegagalan append. Semakan luaran W5 telah selesai: §16.15 merekodkan keputusan reka bentuk dan had pelancaran, tetapi had tersebut tidak memperluas liputan pengeluar yang dinyatakan sebelum ini. Tiga item amanah/penempatan masih terkawal: (a) dompet sauh khusus (ANCHOR_JWK; LogProfile.anchor_owner masih lagi [0xAB; 32] penanda tempat); (b) kunci tandatangan resit dan pin kunci awam yang sepadan (RECEIPT_SK adalah pilihan dan LogProfile.receipt_pubkey sementara ini kosong); dan (c) repositori GitHub self-published-heads + token (§16.6). Sehingga pin jangkar/profil disediakan, pemeriksa bersendirian melaporkan status bukti dengan jujur dan bukannya mendakwa pengesahan yang sepenuhnya berjangkar dan dipasangkan. Reka bentuk adalah secara ketat tambahan dan terdapat tiada perubahan kepada SealedQub / QubEnvelope format wayar.

16.1 Rasional dan Peringkat Ketahanan

Laluan penerbitan semasa memisahkan pengakuan daripada pengesahan Arweave: ia menurunkan dan menandatangani transaksi individu, menyimpan artifak dan keadaan penyerahan tepat dalam R2, kemudian menghantar secara tak segerak. Log ketelusan menambah lapisan susunan yang dipautkan secara bebas untuk subset umum /upload permintaan yang LogDO lampir berjaya:

Tingkat Nama Jaminan Bila
T1 R2-balas serentak pertama Daya tahan lantai — bait yang disegel dan keadaan penerbitan yang tepat ditulis ke storan tahan lama sebelum kejayaan dikembalikan. Dilaksanakan di semua laluan penerbitan semasa.
T2 Penyertaan log ketelusan berkumpulan Hanya boleh ditambah, komitmen bukti-rusak + susunan total setelah dimasukkan dan diikat. Pengeluar semasa: berjaya LogDO menambah daripada /upload; respons membawa tupel resit. Tidak universal.
T3 Kekal Per-qub Arweave Satu transaksi Arweave individu untuk qub tersebut. Pada masa ini disediakan untuk setiap penerbitan yang diterima dan dihantar secara tak segerak; transaksi yang ditandatangani dengan tepat kekal dalam kotak keluar yang boleh dikuras sehingga dihantar.

Tingkat tersebut menggambarkan bukti dan sifat ketahanan yang berbeza, bukan rancangan komersial semasa. Kod sekarang masih menjadualkan transaksi Arweave individu untuk setiap penerbitan yang diterima; ia tidak mendedahkan T3 hanya sebagai peningkatan berbayar. Had kuota kunci API/akaun kekal sebagai kawalan aplikasi berasingan.

Ketahanan kejujuran. Penulisan T1 adalah segerak, jadi respons yang berjaya menetapkan ketahanan tahap aplikasi tanpa menunggu gerbang Arweave. Ia sendiri tidak menetapkan cap waktu yang bebas. Transaksi individu yang disahkan menyediakan had atas masa bloknya. Untuk respons yang membawa tuple resit T2 lengkap, anchor yang disahkan seterusnya boleh menyediakan bukti log yang diterangkan di bawah. Jika tuple tidak ada, tiada permukaan yang boleh menunjukkan bahawa qub ini sudah berada dalam log ketelusan. Latensi anchor dan penerbitan tidak mempunyai SLA angka pada tahap protokol.

16.2 Struktur Daun Log (dua bentuk yang ditetapkan)

Satu entri log adalah LogLeaf, disandikan sebagai CBOR kanonik bertulis tangan di bawah profil §3.1 (panjang tertentu, tiada tag, tiada nombor perpuluhan, integer bentuk paling pendek, teks NFC, medan pilihan diabaikan apabila tiada, kunci disusun mengikut panjang-bait yang disandikan menaik kemudian mengikut bait). §3.1 parse → re-encode → compare pengawal kanonik digunakan pada laluan pengekodan sebelum menghash (bukan hanya pada pengekodan), jadi dua pelaksanaan tidak boleh berbeza pada bait daun melalui perbezaan lebar integer atau susunan kunci. Semua integer adalah u8 / u64 / i64; semua digest adalah rentetan bait 32-bait (bstr[32]). ID transaksi Arweave yang disimpan adalah digest SHA-256 32-bait mentah yang dibawa sebagai bstr[32], tidak pernah rentetan teks base64url (memadankan §3.3).

Daun itu mempunyai dua bentuk dipilih oleh seorang kind bait, kerana laluan muat naik umum adalah buta-bait: POST /api/v1/upload dengan sengaja menganggap kedua-dua bentuk muatan yang diterima sebagai kabur dan menerima qub_id dan unlock_at hanya sebagai pernyataan klien yang tidak dipercayai. Pada laluan persendirian lalai, body_hash, drand_round, created_at, dan drand_chain_version juga disembunyikan di dalam pembungkus luar §13, yang kunci nya tidak pernah dipegang oleh Pekerja. Sistem jenis juga mentakrifkan bentuk yang disahkan untuk pengeluar yang berasal body_hash / drand_round itu sendiri. Semasa /seal laluan mempunyai nilai-nilai itu tetapi tidak memanggil LogDO, jadi pengeluaran pada masa ini hanya mengeluarkan yang dinyatakan (0x02) meninggalkan daripada lampiran muat naik umum yang berjaya. Pecahan ini memastikan setiap nilai yang telah dipersetujui kekal jujur tanpa berpura-pura bahawa pengeluar yang disahkan itu bersambung:

Kunci Bilangan Enc. Jenis Kehadiran Makna
seq empat u64 diperlukan Indeks daun global berasaskan 0; kedudukan yang dibuktikan oleh bukti kemasukan.
kind lima u8 diperlukan 0x01 mampu disahkan (ditakrifkan, tidak dipancarkan pada masa ini) atau 0x02 menegaskan (muat naik cap klien / buta bait).
ref empat bstr[32] diperlukan ID rujukan daun. Disahkan → mentah qub_id. Menegaskan → the butakan id SHA3-256(qub_id ‖ log_blind_secret) (§16.2.1).
chash enam bstr[32] diperlukan Alamat kandungan SHA3-256(stored_bytes) — satu-satunya pautan kandungan yang boleh sentiasa dikira dengan jujur oleh Pekerja, pada kedua-dua laluan.
unlock_at sepuluh i64 diperlukan Disalin (disahkan) atau dinyatakan (dinyatakan); disahihkan > 0 sebelum ia memasuki daun.
received_at dua belas i64 diperlukan Jam dinding pekerja di R2-ack. Bukan bukti (disahkan oleh pengendali; §16.6). Hadir untuk penerangan diri, bukan bukti. Disahkan > 0.
body_hash sepuluh bstr[32] kind=0x01 hanya Dikecualikan pada 0x02 — pekerja itu tidak memilikinya di bawah §13.
drand_round dua belas u64 kind=0x01 hanya Dikecualikan pada 0x02.

A kind=0x02 daun dengan sengaja tidak melakukan apa-apa body_hash mahupun drand_round: ia mengesahkan komitmen dan susunan teks tersulit yang tidak telus pada alamat kandungan chash, mendakwa qub_id dan unlock_at — bukan teks jelas atau pusingannya. Kaki teks jelas/pusingan untuk qub yang ditegaskan datang dari §11 yang sedia ada .qub-pengesahan bundel, bukan dari log (§16.11). drand_chain_version tidak berada di dalam daun (ia berada di dalam pembungkus pada laluan lalai); ketepatan rantaian berada pada sauh (§16.7). Disiplin pengekod: tolak semua sifar ref atau chash, dan menolak yang bukan positif unlock_at / received_at, mencerminkan outcome_at > 0 pengawal pengawas di cbor.rs.

16.2.1 Buta-kub peribadi

Log tersebut tidak boleh menjadi orakel pengiraan yang wujud untuk dicegah oleh pembungkus luar §13 (§13.1). Untuk qub persendirian (dibungkus) yang asserted daun melakukan butakan pengenal SHA3-256(qub_id ‖ log_blind_secret), di mana log_blind_secret adalah rahsia yang disimpan oleh pelayan, dan mengabaikan body_hash. Pihak ketiga tidak boleh mengikat daun sedemikian kepada tertentu qub_id; pemegang qub, yang mempunyai URL penghantaran dan oleh itu qub_id, boleh mengira semula orang buta untuk mengesahkan penyertaan mereka sendiri. Sebuah qub awam (sudah boleh disenaraikan, sudah dibawa oleh Visibility: public Tag Arweave per §13.8) mengikat data mentah qub_id. Inilah satu-satunya tempat kebolehpercayaan berdiri sendiri sengaja tunduk kepada invarian privasi yang menanggung beban; ikatan berdiri sendiri untuk qubs peribadi adalah chash (§16.9).

log_blind_secret penjagaan (diselesaikan — §16.15 S4). Butakan melindungi ketidakhubungan daun, bukan kerahsiaan teks jelas (pembungkus §13 menanganinya secara bebas). Pada satu log_blind_secret kompromi, untuk mana-mana qub_id pihak lawan sudah memegang atau boleh membina semula (setiap qub yang ikatannya/URL-nya dimiliki, ditambah dengan sebarang entropi rendah atau awam qub_id) ia mengira semula daun ref dalam satu hash dan menghubungkannya — ini adalah pautan langsung bagi populasi yang diketahui, bukan serangan secara brute-force ke atas ruang yang tidak diketahui. Klasifikasikan log_blind_secret sebagai rahsia darjah korelasi/Sybil dalam tier penjagaan yang sama seperti rahsia pelayan lain, dan putar ke hadapan sahaja (putaran akan menutup semula daun masa depan; ia tidak boleh memutuskan kaitan daun yang telah berlabuh secara retrospektif).

16.3 Penghashan Daun dan Nodus

RFC 6962 §2.1 penghashan berasingan domain dengan SHA-256 digantikan oleh 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

bait awalan domain 0x02 (rantaian kemasukan, §16.4) dan 0x03 (STH hash, §16.6) adalah dikhaskan dan berasingan daripada ini. Ia adalah bait tunggal dan oleh itu tidak boleh bertembung dengan pemisah domain ASCII 10-bait sedia ada (QUB_ID_V2, dan sebagainya). Pokok itu adalah RFC 6962 kiri-penuh tidak seimbang pokok (setiap bahagian dalaman dipecahkan pada kuasa dua terbesar yang kurang daripada bilangan daun subpokok), yang membolehkan bukti penyertaan dan konsistensi berkongsi satu algoritma laluan audit. Spesifikasi rujukan membawa pseudokod penurunan kiri/kanan secara eksplisit dan menetapkan vektor ujian bukan kuasa-dua (5-daun) jadi kes promosi tepi-kanan — yang disembunyikan oleh vektor 4-daun — digunakan.

16.4 Rantaian Hash (dalaman)

LogDO mengekalkan rantai entri dalaman hanya untuk konsistensi kemalangan. Ia adalah tidak pernah diterbitkan dan tidak pernah menghadap pengesah:

entry_chain[seq] = SHA3-256(0x02 || entry_chain[seq-1] || leaf_hash[seq])
entry_chain[-1]  = SHA3-256("QUB_TLOG_GENESIS_V1")

Pihak berkuasa yang diterbitkan hanya boleh ditambah ialah akar Merkle terkumpul + sauhannya (§16.5–16.6), tidak pernah susunan mentah di mana operator kebetulan menjaga daun: rantai mengira semula untuk sebarang susunan yang dijaga, jadi hanya akar berangkai yang memacak kedudukan kanonik.

16.5 Pokok Merkle Kumulatif dan Pengumpulan

Ada satu pokok RFC 6962 yang sentiasa berkembang di atas semua daun seq urutan — bukan pokok per-batch yang terasing. (Pembinaan per-batch berantai daun-bawa telah ditolak: ia bukan hubungan awalan sebenar, jadi "bukti konsistensinya" tidak sah.) Pokok terkumpul memberikan bukti konsistensi RFC 9162 yang sebenar dan membolehkan satu pengangkaian terkini membuktikan penyertaan untuk mana-mana qub lama.

Itu LogDO Objek Tahan Lama adalah penulis tunggal (blockConcurrencyWhile, mencerminkan QuotaDO / EntitlementDO) — menambah ke log berkongsi adalah baca-ubah-tulis pada keadaan berkongsi dan oleh itu MESTI melalui DO, jangan pernah melalui KV. Ia menyimpan sementara sempadan tepi kanan pokok (O(log n) hashes) jadi menutup satu kumpulan adalah O(batch). A kumpulan ialah set daun yang dipasang bersama; pencetus yang dilaksanakannya ialah a tree_size sekurang-kurangnya ke hadapan LOG_BATCH_MAX_LEAVES (lalai 4096), umur mencapai irama sauh, atau penutupan paksa pentadbiran/cron yang jelas. root_i adalah Hash Pokok Merkle terkumpul ke atas daun 0 .. tree_size_i.

16.6 Kepala Pokok Ditandatangani melalui Arweave Anchor

Transaksi sauh Arweave ialah Kepala Pokok Bertandatangan dan menggantikan tandatangan pengendali untuk kepala pokok itu sendiri: sauh harian tidak memerlukan kunci qub kerana transaksi Arweave owner ialah tandatangan. Teori parit menyatakan — substrat yang tidak berubah, bukan rahsia yang dipegang qub, adalah penanggung beban bagi akar yang berlabuh.

Reka bentuk log memerlukan satu sambungan berjaya yang hangat kunci resit (§16.10), dipasang dalam LogProfile dan ditandatangani bersama oleh anchor_owner. Pelaksanaan semasa belum menyiapkan penyediaan akar-kepercayaan itu: RECEIPT_SK adalah pilihan, kunci yang tidak hadir/tidak sah menghasilkan sig_b64url: "", dan yang telah disusun LogProfile.receipt_pubkey adalah kosong. Resit seperti itu boleh menerangkan helaian yang dilampirkan tetapi adalah tidak resit bertandatangan yang tidak boleh disangkal. Tuntutan reka bentuk yang lebih kukuh hanya terpakai selepas penjejak pengesah melepaskan pin yang sepadan dengan kunci awam dan pemilik sauh menandatangani silanginya. Tindak balas terbitan tanpa tuple resit lengkap tidak membuat tuntutan penerimaan log; yang mempunyai tandatangan kosong membuat tuntutan kedudukan tambah tetapi tidak membuat tuntutan pengesahan tandatangan.

Itu SignedTreeHead adalah CBOR kanonik (kunci mengikut panjang yang ditaip) : size:u64, root:bstr[32], batch:u64, prev:bstr[32] (sebelum sth_hash; genesis = 32 bait sifar), log_id:bstr[32], first_seq:u64, anchored_at:i64. Hashnya ialah sth_hash = SHA3-256(0x03 || canonical_cbor(SignedTreeHead)).

Akar amanah yang disematkan. log_id = SHA3-256("QUB_TLOG_V1" || anchor_owner_address). Satu penyemak yang mematuhi MESTI memerlukan anchor_tx.owner == LogProfile.anchor_owner, di mana anchor_owner (dan kunci awam penerimaan) telah dimasukkan ke dalam qub_core sebagai LogProfile — bersama dengan pemalar quicknet yang sudah ada DrandTimelockProvider::quicknet() — dan diedarkan bersama binari pengecek. Pengecek JUGA MESTI mengesahkan tx Arweave data → pengikatan tx_id secara tempatan daripada mempercayai sebuah pintu masuk /raw/ tindak balas. Ini menutup lubang kekeliruan dompet liar: "berpaut pada Arweave" tidak bermakna sehingga pemeriksa menanda dompet yang mana.

Putaran adalah perluasan tadbir urus §15, bukan penggunaan semula (diselesaikan — §16.15 S3). Permukaan profil §15.2 pada masa ini hanya menyenaraikan rantaian sig_algs / drand / versi pembungkus / jenis kandungan, dan senarai pencetus §15.3 tidak menyenaraikan mana-mana daripada ini — LogProfile / anchor_owner ialah tidak namun di permukaan §15. Oleh itu, tadbir urus putaran mesti dibina: §15.3 diperluas (di bawah) untuk menambah LogProfile pencetus, dan putaran adalah bernilai tanda LogProfile bump dihantar dalam kemas kini pengesah. A dirancang putaran membawa tandatangan silang keluar → masuk; a dipacu oleh kompromi rotasi tidak dapat dilakukan (kunci keluar tidak dipercayai/tidak tersedia tepat pada masa itu) dan kembali ke peningkatan yang dikawal oleh §15, dengan pemeriksaan cabang prev-anchor (di bawah) mengehadkan kerosakan sementara itu.

Tetingkap ekivokasi (parameter kepercayaan kelas pertama). Daun hanya tahan terhadap penipuan setara setelah sauh penutupnya berada di Arweave-disahkan. Tingkap itu received_at → anchor confirmation (cadence + kesudahan Arweave, tanpa jaminan kelewatan protokol). Sebelum penyediaan akar kepercayaan, pelaksanaan semasa menyediakan integriti operasi qub serta sebarang metadata tambah yang tidak ditandatangani; ia tidak menyediakan jaminan bukan-penafian yang dirancang. Tiga artifak akauntabiliti menentukan reka bentuk yang lengkap (model saksi ialah resolusi §16.15 Q2):

  1. Resit meterai (bergantung pada pembekalan) — analog SCT dikembalikan apabila penambahan log muat naik berjaya (§16.10). Ia menjadi tidak boleh dinafikan hanya apabila sig_b64url tidak kosong dan hubungan kunci awam/pemilik pemancar yang sepadan dipasang dalam pemeriksa. Pin profil pengeluaran yang kini kosong tidak dapat menyokong keputusan itu. Kawalan ini tidak terpakai kepada tuple resit yang diabaikan atau resit yang tidak ditandatangani.
  2. Metodologi monitor yang diterbitkan + jalan rantai sebelumnya — sauh prev rantai berjalan kepala→kejadian; satu garpu (dua sauh pada satu size dengan berbeza root, atau patah prev) adalah bukti kelakuan tidak wajar yang boleh diterbitkan. Pengesanan persamaan perkataan adalah komitmen operasi yang dinyatakan, bukan andaian senyap.
  3. Dua kepala yang diterbitkan sendiri — setiap kepala baharu {sth_hash, tree_size} dihantar ke milik qub khas repositori GitHub awam, hanya tambah (kaki penerbitan sendiri yang menanggung beban dan menunjukkan tamper-evident), dengan pos sosial sebagai pengesahan usaha terbaik sahaja. Pos yang gagal MESTI memberikan pemberitahuan (tidak gagal secara senyap). Dilaksanakan (Tahap 8) sebagai publishHead cangkuk pada jangkar cron (workers/api/src/utils/heads-publish.ts): a PUT kepada API kandungan tanpa sha hanya boleh ditambah (a 422 bermaksud kepala sudah diterbitkan, tidak pernah ditimpa); opt-in / dikawal pelaksanaan pada PUBLISH_HEAD_GITHUB_{TOKEN,OWNER,REPO} dan tidak aktif sehingga repositori disediakan. Halaman kegagalan GitHub keras melalui health_alert saluran dan menumbuk metrik kegagalan yang tahan lama (m:tlog_publish_head_fail); sauh Arweave itu sendiri tidak pernah mundur apabila kegagalan penerbitan. "Tidak gagal senyap" dijamin oleh metrik tahan lama itu — yang mana operator MESTI memberi amaran papan pemuka — walaupun halaman emel usaha terbaik tidak dapat dihantar. Dua had jujur timbul dari "anchor-on-advance" (cron hanya menerbitkan apabila saiz meningkat): kegagalan sementara GitHub meninggalkan jurang dalam urutan kepala yang diterbitkan untuk saiz itu — terhad, bukan senyap (ia menukar halaman), dan kerana setiap kepala mengikat pokok superset, bukti konsistensi §16.9 merentasi jurang; yang penting, bukti konsistensi itu dikira daripada pokok berketuan yang berlabuh Arweave, bukan dari permukaan GitHub, jadi jurang GitHub tidak pernah melemahkan kebolehverifikasian. Pengisian semula tangkapan yang mengisi jurang kepala yang diterbitkan adalah peningkatan yang ditangguhkan.

Kejujuran yang mengikat (sekatan yang mengikat). Kerana qub mengawal kedua-dua permukaan penempatan yang dirancang, ini adalah diterbitkan sendiri, tidak disaksikan secara sendiri. Tiada produk, pemasaran, atau permukaan undang-undang boleh mendakwa log itu 'disaksikan secara sendiri'. Selepas resit/profil/pintu kepala disediakan, tuntutan yang dibenarkan ialah pertindihan makna boleh dikesan dan lampiran yang berjaya ditandatangani meninggalkan resit yang tidak boleh dinafikan. Sebelum itu, tuntutan tersebut tidak tersedia. Saksi pihak ketiga yang benar-benar bebas akan ditangguhkan kepada kenaikan tadbir urus §15 yang akan datang.

received_at disahkan oleh pengendali dan tiada tuntutan boleh bergantung padanya — ia tidak pernah dipaparkan sebagai bukti atau sebagai pengesahan pertikaian pada mana-mana produk / undang-undang / API / permukaan penjanaan bukti. Masa blok sauh Arweave T adalah satu-satunya cap masa tanpa kepercayaan (sebagai batas atas pada "dicatat oleh"). Sebarang pemeriksaan kewarasan pemantau pada received_at MESTI dibandingkan dengan T, bukan terhadap yang dikawal oleh pengendali anchored_at Medan STH; semakan sedemikian adalah langkah pengawasan terhadap pepijat jam pengendali yang jujur sahaja, tidak satu kawalan akauntabiliti terhadap pengendali berniat jahat (§16.15 Q5).

16.7 Format Transaksi dan Kekerapan Anchor

Itu AnchorBundle adalah badan transaksi Arweave canonical-CBOR, ditulis melalui bundler §16.8: ver:u8, sth:bstr (kanonik SignedTreeHead bait), prev_anchor:bstr (id tx sauh sebelum ini bait mentah; diabaikan pada permulaan), chain_hash:tstr (rantai drand yang berkuat kuasa — quicknet), dan aliran CBOR daun kumpulan masuk seq pesanan jadi sauh itu berdiri sendiri: sebuah monitor menurunkan semula root dari badan dengan tiada pergantungan qub. (Jika aliran daun menjadi besar pada volume tinggi, semakan masa depan mungkin hanya akan melaksanakan julat daun berdasarkan rujukan; dicatat, tidak diterima pakai dalam v1.)

Tag Arweave sengaja boleh disenaraikan — log itu dimaksudkan untuk ditemui, tidak seperti qub peribadi: App-Name: qub-tlog, Anchor-Format: 1, Log-Id: <hex>, Batch: <n>, Tree-Size: <n>, Root: <hex>, Prev-Anchor: <tx>, Content-Type: application/cbor. Tag adalah petunjuk yang tidak dipercayai; badan CBOR adalah satu-satunya pihak berkuasa.

Irama: harian secara lalai, dikaji semula dengan volum (pencetus saiz secara automatik memendekkan kadar berkesan di bawah beban). Pengeluar semasa tidak melaksanakan cangkuk daya-penutup berbayar. The dompet anchor didedikasikan dan berkelajuan rendah, berasingan dari dompet muat naik — ia MESTI menjadi miliknya JWK sendiri (kunci yang berbeza, bukan peranan logik pada dompet muat naik) jadi kompromi dompet muat naik tidak boleh memalsukan sauh — dengan had transaksi-sauh harian yang ketat. Pendekatan penjagaan dinyatakan dengan jelas: satu pintasan kekunci capaian terhad dengan pemutus litar yang ketat dan baki rendah, bukan "sejuk" — dompet yang menandatangani secara automatik setiap hari tidak boleh dianggap sejuk, dan spesifikasi tidak berpura-pura sebaliknya.

16.8 ANS-104 Pengikat

Penyandi DataItem ANS-104 dalaman dan penandatangan hash-mendalam, lebih kurang 300 baris, Hanya Web Crypto, tiada kebergantungan npm (kedua-dua Turbo SDK gagal npm ci --ignore-scripts pintu rantaian bekalan). Susunan bait DataItem:

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

Menandatangani adalah Arweave deepHash — suatu rekursif SHA-384 digest (keperluan wayar Arweave, crypto.subtle.digest("SHA-384")) lebih ["dataitem", "1", sig_type, owner, target, anchor, encoded_tags, data] — kemudian RSA-PSS ke atas hash mendalam dengan JWK dompet melalui crypto.subtle; id = base64url(SHA-256(signature)). SHA-384 di sini adalah dikuarantin sebagai primitif Arweave-wayar sahaja, tidak pernah menjadi primitif kepercayaan qub (§15 merekodkan pagar; penghakisan amanah qub adalah SHA3-256 sepanjang masa).

Laluan kod ANS-104 berkhidmat untuk mekanisme sandaran/tangguhan yang ditangguhkan dan menulis AnchorBundle DataItems. Laluan penerbitan biasa mula-mula mencipta transaksi Arweave yang ditandatangani dengan tepat dan menyimpan JSONnya dalam peti keluar yang tahan lama; penghantaran terus adalah pengoptimuman kelewatan, dan laluan penyaliran mencuba semula transaksi yang sama sebelum menggunakan cadangan bundlernya. Skema tandatangan (diselesaikan — §16.15 Q8): v1 menandatangani dengan RSA-PSS (jenis tandatangan 1) menggunakan semula mekanisme JWK dompet Arweave sedia ada (tiada pemegangan kunci jangka panjang baru, menyokong tesis "satu rahsia kurang"); Ed25519 ditangguhkan ke laluan migrasi PQ §15.

Hash dalam yang digulung dengan tangan adalah kod berisiko paling tinggi, liputan semula jadi terendah dalam W5, jadi pengawalnya adalah tidak boleh dirunding (§16.15 S8):

  1. Perkakas antara bahasa tlog_v1.json (Rust + TS, seksyen §14.5 wrapper_v1.json corak) merangkumi deep-hash, DataItem bait + id, hash daun, akar 5-daun + laluan audit, hash STH, bukti penyertaan, dan bukti konsistensi — dalam kedua-dua arah tandatangan dan pengesahan (arah pengesahan penting kerana semakan tx tempatan → tx_id §16.6 menarik hash mendalam ke dalam setiap verifier berdiri sendiri, bukan hanya penulis).
  2. Satu pusingan interop sekali melalui pengikat rujukan ANS-104, digunakan sebagai hanya data ujian statik — tidak pernah menjadi kebergantungan runtime npm (pendirian hanya Web-Crypto / tiada skrip pemasangan tetap).
  3. Laluan deep-hash + RSA-PSS mesti melalui laluan pusing balik melalui sama crypto.subtle primitif penggunaan pengeluaran, jadi pengekod dalaman adalah serasi bait.
  4. Sedang berlangsung monitor penerimaan pasca-bungkusan meng确认 setiap DataItem jangkar / sandaran sebenarnya mencapai penerimaan Arweave, dengan penggera + pemutus litar — kerana hash mendalam juga berfungsi sebagai barisan sandaran ketidaktersediaan Arweave, jadi regresi senyap akan mengisi barisan itu dengan item ditolak rangkaian semasa gangguan tepat yang wujud untuk dilindungi.

16.9 Bukti Kemasukan dan Konsistensi

Kedua-duanya adalah RFC 9162, SHA3-256, disajikan sebagai CBOR kanonik.

BuktiKepelbagaian — GET /api/v1/qub/:tx_id/proof: ver:u8, leaf:bstr (CBOR daun yang tepat — pengesah mengira semula leaf_hash sendiri dan tidak pernah mempercayai hash yang dibekalkan), 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 }.

BuktiKonsistensi — 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. Satu senarai kunci yang jelas dan tidak mengelirukan, dijadikan rujukan oleh vektor ujian.

Pengesahan berdiri sendiri (tiada pelayan qub, melanjutkan §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).

Simpanan yang berfungsi sebagai bukti MESTI dipadankan dengan kunci koordinat (diselesaikan — §16.15 Q7, prasyarat penyekatan). Penjanaan bukti daun sejuk adalah neutral terhadap ketepatan hanya jika bahan audit R2 adalah penyimpanan nod Merkle yang berterusan yang dikunci dengan koordinat pokok mutlak (level, index) — bukan per-batch delta nod. Dengan stor yang dikunci oleh koordinat, mana-mana (leaf i, size N) laluan audit adalah satu set O(log N) R2 langsung GETdengan tiada pengiraan semula merentasi sempadan kelompok; dengan stor berkey-batch ia tidak, yang merupakan jurang susun atur penyimpanan yang ditutup oleh penyelesaian ini. Badan daun juga boleh diakses mengikut kandungan oleh seq. Vektor ujian W5 MESTI membuktikan sebuah daun sejuk era genesis melawan akar yang jauh kemudian menggunakan hanya R2 + Arweave dengan storan LogDO dipadam, jadi tuntutan keselamatan penebusan dalam §16.13 disokong dan bukannya dinyatakan. The O(log N) R2 berurutan GETmilik s hanya pada titik akhir bukti tak segerak — jangan sekali-kali pada laluan panas meterai (§16.10) atau cron setiap tik.

16.10 R2-Pesanan Pengesahan Pertama

Yang dilaksanakan POST /api/v1/upload urutan ialah:

  1. Pintu hadapan separuh (auth, pengesahan, kunci pecahan idempotensi) — tidak diubah.
  2. Cipta, tandakan, dan tandatangan transaksi Arweave individu yang tepat. Ini berasal tx_id secara tempatan, walaupun penciptaan transaksi mungkin mengambil metadata ganjaran/pegang dari gerbang. Kegagalan persediaan masih menyebabkan permintaan gagal sebelum pengesahan.
  3. Secara serentak tulis artifak yang dipilih di qub-cache/<tx_id> dan mengekalkan rekod penciptaan-operasi/outbox yang stabil. Ini adalah ketahanan dan asas cubaan semula; kegagalan sebelum penyelesaian akan mengembalikan 503.
  4. Bila LOG_DO dikonfigurasikan, mencuba secara serentak LogDO.append(leaf). Penulis tunggal menetapkan seq, meluaskan rantaian kemasukan, dan mengemas kini sempadan. RPC append hanya melakukan itu; batch close dijalankan secara luar laluan pada penggera. Kegagalan pengangkutan/aplikasi append pada masa ini gagal-lembut: tindak balas masih boleh berjaya tanpa log_seq, receipt, atau anchor_status. Walaupun terdapat komen pelaksanaan, tiada penyelarasan log automatik kemudian yang dipasang pada hari ini.
  5. Kembalikan pengesahan. Sertakan { log_seq, anchor_status: "pending", receipt } hanya apabila append mengembalikan tuple berjaya sepenuhnya. receipt.sig_b64url adalah kosong apabila penandatangan resit tidak tersedia; pelanggan TIDAK HARUS menganggap nilai itu ditandatangani atau tidak boleh disangkal. Ketiadaan tuple bermakna penerbitan yang berpanjangan sahaja, bukan penerimaan log ketelusan.
  6. Gunakan satu tugas tertangguh untuk menghantar transaksi yang ditandatangani dengan tepat. Kejayaan akan menghapuskan outbox; kegagalan meninggalkannya untuk cron saliran terhad dan tidak boleh mengubah apa yang telah diakui tx_id. Metadata sementara dan barangan sampingan lain yang dibuat dengan usaha terbaik juga ditangguhkan.

Sempadan kelewatan. Jalur permintaan termasuk kerja kuasa/kawalan had separuh depan, penyediaan/tandatangan transaksi, penulisan R2 yang tahan lama, dan (apabila dikonfigurasikan) LogDO cubaan. < 300 ms muncul dalam kajian reka bentuk sebagai sasaran operasi, bukan jaminan protokol; langkah penyediaan transaksi semasa mungkin melaksanakan permintaan metadata pintu masuk. Amaran kelewatan dan pintu pelancaran adalah kawalan operasi, bukan bukti yang boleh diperoleh oleh pemeriksa.

16.11 Model Kepercayaan — tuntutan tepat, diperkatakan mengikut jenis daun

Untuk kind=0x01 (disahkan): Kandungan ini — padanan badan body_hash, dikenal pasti oleh qub_id — telah dicatatkan ke dalam log append-only qub pada posisi seq dan wujud tidak lewat daripada masa blok Arweave T; ia tidak boleh dibaca secara kriptografi sehingga pusingan drand R = unlock_round(unlock_at). Ini adalah penuh {tlock round binding + Merkle inclusion + anchored root} tiga kali ganda.

Untuk kind=0x02 (ditegaskan, lalai): Satu teks cipher yang kabur dengan alamat kandungan chash, mendakwa qub_id dan unlock_at, telah dicatatkan ke dalam log hanya-tambahan pada kedudukan seq dan wujud tidak lewat daripada masa blok Arweave T. Kaki bulat dan badan dibekalkan oleh §11 yang sedia ada .qub-pengesahan bundle (qub_core::unlock), tidak oleh log; apa yang log tambah berbanding transaksi per-qub kosong adalah susunan yang jelas tampered, masa komitmen had atas tanpa kepercayaan, dan rintangan terhadap penipuan.

Kedua-dua tuntutan mengecualikan, menurut §11: kepengarangan tanpa sig_alg ≥ 0x01, niat, dan masa sub-anker-kepadatan. Tiada satu pun membenarkan sebarang tuntutan bergantung pada received_at.

Siling tuntutan (had pelancaran yang mengikat — diselesaikan §16.15 Q1). Untuk sebuah yang dipertahankan (kind=0x02) daun, tuntutan yang dinyatakan di atas ialah siling mengenai apa-apa produk, pemasaran, terma, atau permukaan bukti-paparan boleh menegaskan. Tiada permukaan boleh menyatakan atau menyiratkan bahawa log membuktikan kandungan atau pusingan buka muat naik buta-bait — log membuktikan susunan + komitmen masa had atas yang tidak bergantung ke atas cipherteks yang kabur. Bukti kandungan dan pusingan datang secara eksklusif dari §11 yang sedia ada .qub-pengesahan bundel, yang bebas daripada log. Sesebuah penerbitan yang tidak mempunyai penambahan/penerimaan yang berjaya langsung tidak mempunyai tuntutan log.

16.12 Penversian dan Penyelarasan W3

Ada tidak SealedQub benjolan wayar dan oleh itu tiada peningkatan versi protokol (§12.2): log adalah sidecar yang melakukan komit pada medan dan bait sedia ada, jadi ia tidak masuk ke dalam sejarah versi protokol §12.3. W3 adalah pilihan drand_chain_version tidak disentuh dan kekal sebagai satu-satunya pilihan SealedQub lapangan. Sebaliknya, log memperkenalkan ruang versi sendiri yang bebas — LOG_VERSION_1, ANCHOR_FORMAT_1, InclusionProof.ver — mencerminkan §12.5 bebas versi pembungkus (pembungkus membawa byte versi yang bebas daripada versi protokol, dan versi log mengikuti pemisahan yang sama).

Penghantaran bukti diambil secara lalai, dengan pilihan ikut serta. Satu bukti tidak boleh wujud pada masa meterai (sulit belum ditulis lagi), jadi pada masa meterai .qub gugusan tetap bebas bukti. Pemeriksa W7 mengambil GET …/proof sekali, atau dalam mod sepenuhnya luar talian menyusun semula bukti daripada orang awam AnchorBundle melalui pertanyaan Arweave pada Log-Id. The .qub bundle (W7) menempah sebuah pilihan inclusion_proof ahli — tiada pada meterai, diisi oleh eksport semula selepas sauh untuk arkib sejuk — mengikuti corak yang sama 'pilihan, diabaikan secara lalai, tambahan' seperti W3's drand_chain_version.

16.13 Penahanan

Tetingkap pengekalan untuk LogDO ekor terbuka, substrat penyampaian bukti R2, kaunter pemutus litar sauh, dan barisan sandaran pengikat ditentukan dalam docs/DATA-RETENTION.md. Prinsip: storan entri panas log (LogDO) boleh diperoleh semula selepas berlabuh; bahan auditnya — kunci-koordinat (level, index) Stor nod Merkle + itu seq-badan daun yang ditangani (§16.9) + sauh Arweave — adalah kekal. Menuntut semula daun sejuk daripada DO tidak pernah membatalkan bukti yang dikeluarkan, kerana bukti itu diselesaikan terhadap simpanan nod R2 yang kekal itu dan sauh Arweave, bukan DO (dan vektor ujian DO yang dipadamkan §16.9 membuktikannya).

16.14 Vektor Ujian

W5 menghantar peranti rentas-bahasa tlog_v1.json (§16.8) tambah vector yang telah dihasilkan: a kind=0x01 dan sebuah kind=0x02 daun → leaf_hash; akar kumulatif 5-helai; satu bukti inklusi; satu bukti konsistensi; satu AnchorBundle; dan satu id DataItem. Ini wujud bersama-sama dengan vektor pembungkus luaran §14.5 dan digunakan oleh kedua-dua Rust (qub-core) dan pelaksanaan TypeScript (Pekerja).

16.15 Kajian Keputusan (W5 — diselesaikan)

Ulasan luaran W5 (satu laluan reka bentuk adversarial + kelulusan pemilik) telah lengkap. Setiap keputusan di bawah telah diputuskan dan tercermin dalam teks §16 di atas; kekangan pelancaran yang mengikat disatakan semula di akhir. Pelaksanaan boleh diteruskan di bawahnya.

  1. Laluan-lalai (kind=0x02) kejujuran daun — DIPUTUSKAN. Hantar jenis dua daun yang dibahagikan seperti yang ditetapkan: kind=0x02 tidak melakukan apa-apa body_hash mahupun drand_round. Tidak *_body_hash lapangan di laluan buta-bait (ia akan menjadi isyarat 'disahkan' palsu yang paling jelas untuk pengintegrasi dan merupakan kemudahan yang §11 sudah sediakan dari bundel tersebut). Lakukan tidak memerlukan server-seal untuk qubs yang disahkan-log (yang akan memaksa plaintext melalui Worker dan memusnahkan parit pemusnahan kripto). Mana-mana litar pintas yang menerangkan diri sendiri patut berada dalam .qub sampul bundel / bukti sebagai medan pengesah yang dikira semula, bukan medan daun. Had tuntutan yang disahkan pemilik: §16.11.
  2. Tanggungjawab keliru / pengabaian — REKA BENTUK SELESAI, PERUNTUKAN TIDAK LENGKAP. Reka bentuk memerlukan kekunci setem-penerimaan dipasangkan LogProfile dan ditandatangani bersama oleh anchor_owner, tambah metodologi pemantauan, berjalan rantai sebelumnya, dan dua kepala yang diterbitkan sendiri. Profil terkompilasi dan kaitan pelaksanaan masih merupakan tempat letak/opsyen seperti yang diperincikan dalam §16.6, jadi tuntutan yang lebih kuat boleh dikesan + diterima tidak sah pada masa ini sehingga pintu tersebut ditutup. Ia tidak boleh dipasarkan sebagai disaksikan secara bebas. Saksi pihak ketiga yang sebenar ditangguhkan kepada kenaikan tadbir urus §15.
  3. Pemilik anchor yang dipin + putaran — SELESAI. Mengambil LogProfile pin (§16.6); pemeriksa menyemak anchor_tx.owner == anchor_owner dan mengesahkan data tx → pengikatan tx_id secara tempatan. Tadbir urus putaran adalah §15 sambungan untuk bina (§15.3 pencetus ditambah), bukan guna semula; putaran yang dirancang silang-tandatangan, putaran berpaksikan kompromi kembali ke lonjakan §15 dengan pemeriksaan garpu yang mengehadkan kerosakan.
  4. Butiran daun qub peribadi mengaburi — SELESAI. Teruskan membutakan untuk qubs peribadi (ref = SHA3-256(qub_id ‖ log_blind_secret)), mentah qub_id untuk kuil awam (sudah §16.2.1), chash sebagai tali leher bersendirian. log_blind_secret adalah rahsia hubungan/gred Sybil, hanya pusing ke depan (§16.2.1).
  5. received_at — DIPUTUSKAN. Simpan ia dalam daun, komited tetapi secara jelas tidak bersifat bukti; tidak pernah ditampilkan sebagai bukti atau pengesahan pertikaian di mana-mana permukaan. Sebarang pemeriksaan kesihatan pemantau dibandingkan dengan masa blok Arweave T, bukan dikawal oleh pengendali anchored_at (§16.6).
  6. Penentuan masa boleh dibuktikan berperingkat — REKA BENTUK RESOLUSI, BUKAN PENGHANTARAN SEMASA. Reka bentuk yang dikaji semula menetapkan penentuan masa blok-penanda kepada lapisan berkelompok dan bukti jam tepat kepada T3 berbayar, tanpa SLA berangka untuk yang pertama. Laluan semasa tidak membezakan komersial itu: mereka menjadualkan transaksi individu untuk setiap penerbitan yang diterima, dan liputan log kekal bersyarat seperti yang dinyatakan dalam §16.1/§16.10. Salinan produk mesti menerangkan pelaksanaan, bukan pemisahan lapisan masa depan ini.
  7. Pokok terkumpul pada Pekerja — DIPUTUSKAN. Pokok RFC 9162 kumulatif tunggal + LogDO penulis tunggal yang di-cache di frontier (ruang kepala yang selesa berbanding dengan siling DO ~1k tulis/saat; tangguhkan sharding Merkle-of-shard-roots sehingga hampir mencapainya). Kunci-penyelaras (level, index) Simpanan nod R2 + vektor ujian daun sejuk wiped-DO telah dilaksanakan (§16.9). < 300 ms masih merupakan sasaran reka bentuk/operasi, bukan janji protokol (§16.10).
  8. Skema tandatangan ANS-104 + hash-mendalam — SELESAI. RSA-PSS (jenis sig 1, menggunakan semula JWK dompet-penanda khusus); Ed25519 ditangguhkan kepada laluan PQ §15. Hash mendalam SHA-384 buatan tangan dikawal pada alat persimpangan-impl kedua-dua arah, semakan interop pengikat rujukan statik sahaja, yang dikongsi-crypto.subtle perjalanan pergi balik, dan pemantau penerimaan Arweave pasca-bungkusan (§16.8).

Mengikat kekangan pelancaran (laksanakan ke dalam pelaksanaan + semakan produk/undang-undang):


17. Bundle Pengesahan Mudah Alih (.qub)

Status. Bahagian ini telah dilaksanakan (W7 / UP-C2): qub_core::export menghasilkan dan menghuraikan bundle, manakala tools/qub-verify ialah CLI awam serba lengkap yang mengesahkannya di luar talian. §11 dan §16.9 sudah merujuk kepada "bundle .qub" sebagai unit yang digunakan pengesah berdiri sendiri; bahagian ini menetapkan baitnya dan panduan langkah pengesahan. Ia benar-benar tambahan—bundle membungkus input §11 sedia ada dan tidak mengubah format wayar dalam storan.

17.1 Tujuan

§11 menetapkan bahawa mana-mana pihak ketiga boleh mengesahkan artifak kriptografi qub tanpa kerjasama qub. Bundle .qub menjadikan pengesahan itu mudah alih dan di luar talian: ia membungkus CBOR dimeterai dan tandatangan pusingan drand yang membukanya ke dalam satu artifak serba lengkap, maka penerima boleh mengesahkan integriti kandungan, pengikatan pusingan, dan sebarang tandatangan kepengarangan dengan langsung tanpa panggilan rangkaian (tiada pengambilan storan, tiada permintaan drand langsung, tiada API qub). Bundle sahaja tidak membuktikan bila teks sifernya dicipta; transaksi storan yang disahkan secara bebas atau bukti log berlabuh membekalkan dakwaan masa kewujudan yang berasingan (§11, §17.5).

17.2 Format Bundle

QubBundle ialah CBOR berkanun tulisan tangan di bawah profil §3.1 (panjang tentu, tiada tag, tiada apungan, integer bentuk terpendek, teks NFC, medan pilihan ditinggalkan apabila tiada, kunci diisih mengikut panjang bait terkod menaik kemudian mengikut bait). Tiga kunci 15 aksara disusun d < i < s. Fail .qub mentah tepat sama dengan bait ini; untuk pengangkutan URL atau salin-tampal, bait yang sama menggunakan base64url (tanpa pelapik).

Kunci Pjg. terkod Jenis Kehadiran Maksud
version 8 u8 wajib Versi format bundle (0x01).
sealed_at 10 i64 pilihan Masa pemeteraian yang ditegaskan pencipta (saat Unix); perihalan diri, bukan bukti.
drand_round 12 u64 wajib Pusingan yang mengunci qub. Unjuran daripada qub dimeterai yang terbenam.
arweave_tx_id 14 tstr wajib Id transaksi tempat bait dimeterai disimpan (penunjuk asal-usul).
drand_chain_id 15 tstr wajib Rantai drand (heks). Unjuran daripada qub dimeterai yang terbenam.
drand_signature 16 bstr wajib Tandatangan beacon drand bagi drand_round—nilai yang membuka teks sifer.
inclusion_proof 16 bstr pilihan Bukti kemasukan Merkle log ketelusan §16 (§17.5).
sealed_qub_cbor 16 bstr wajib Bait SealedQubCbor dalaman (selepas nyahbungkus §13), iaitu input pengesahan §11.

drand_round dan drand_chain_id ialah unjuran kemudahan daripada sealed_qub_cbor, dibawa supaya alat boleh membacanya tanpa menghuraikan CBOR dalaman. Kedua-duanya diterbitkan semasa pembinaan dan disemak semula semasa penyahkodan terhadap qub dimeterai yang dihuraikan; bundle yang medan aras atasnya tidak sepadan dengan muatannya ditolak. Disiplin pengekod mencerminkan format wayar lain: tolak drand_signature atau arweave_tx_id yang kosong, dan hadkan setiap medan panjang berubah.

17.3 Apa yang Dibuktikan oleh Tandatangan drand Terbenam

Bundle membawa tandatangan drand dan bukannya memerlukan pengesah mengambilnya. Penyahsulitan kunci masa (tlock pada rantai drand, §8) hanya boleh berjaya dengan tandatangan beacon tulen bagi pusingan terikat—nilai yang diterbitkan rantai hanya selepas pusingan itu berlalu dan yang merupakan tandatangan BLS sah di bawah kunci awam rantai. Tandatangan palsu atau salah gagal pengesahan BLS atau penyahsulitan IBE/AEAD. Oleh itu, bundle yang dapat dinyahsulit membuktikan: teks sifer terikat kepada pusingan R dan pusingan R telah berlalu. Pengesah menyematkan rantai (DrandTimelockProvider::quicknet()) dan menggunakan semakan pengikatan pusingan §11, maka bundle tidak boleh mendakwa pusingan yang tidak diikat oleh teks sifernya.

Ini ialah bukti syarat pelepasan, bukan cap masa penciptaan. Selepas pusingan R berlalu, sesiapa boleh mencipta teks sifer baharu untuk R dan membungkus tandatangannya yang sudah awam. Oleh itu, bundle sahaja MUST NOT digambarkan sebagai bukti bahawa teks sifer atau kandungan telah wujud sebelum R, sebelum unlock_at, atau sebelum apa-apa peristiwa.

17.4 Panduan Pengesahan Luar Talian

qub-verify <file.qub> menjalankan prosedur §11 standard sepenuhnya daripada bundle, memacu qub_core::unlock::unlock dengan DrandTimelockProvider yang disematkan:

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.

CLI keluar dengan 0 (disahkan), 1 (pengesahan gagal—masih terkunci, ketidakpadanan cincangan badan, pengikatan pusingan/rantai rosak, atau tandatangan gagal disahkan), atau 2 (penggunaan / bundle cacat). Laporan --json membawa keputusan sama untuk automasi. Oleh sebab bundle serba lengkap, crate pengesah (qub-core) dan CLI (qub-verify) ialah satu-satunya perisian yang diperlukan pihak ketiga; kedua-duanya awam dan menggunakan semula laluan pengesahan protokol sedia ada—tiada kriptografi khusus.

17.5 Hubungan dengan Log Ketelusan

inclusion_proof ialah slot pilihan untuk bukti kemasukan Merkle §16. Pengesahan bundle sahaja (§17.4) lengkap bagi integriti, pengikatan pusingan / pusingan telah berlalu, dan kepengarangan pilihan, tetapi sengaja tidak mempunyai dakwaan kewujudan bercap masa bebas. inclusion_proof yang diisi dan disahkan sepenuhnya melalui labuh menambah komitmen khusus jenis daun serta masa had atas daripada §16.11 tanpa mengubah versi format bundle. Bukti yang tiada hanya bermaksud "tiada bukti disertakan"—bukan "tidak sah" dan tidak semestinya "tidak dilabuh".

Dalam pelaksanaan rujukan, slot itu kini bertaip: qub_core::export::QubBundle::inclusion_proof_typed() mengembalikan Option<InclusionProof> yang membawa struktur §16.9 lengkap (daun, laluan audit, akar berlabuh, dan AnchorRef) melalui medan CBOR legap yang sama—tiada kenaikan versi format bundle. CLI berdiri sendiri qub-verify menggunakannya melalui kaki --anchor, dan—sehingga dompet labuh diperuntukkan (§16, Status)—melaporkan bukti yang diisi tetapi mempunyai pemilik pemegang tempat sebagai kemasukan sahaja, bukannya disahkan berlabuh sepenuhnya.