qub Protokol Spesifikasyonu

qub, kriptografik zamansal taahhütler için bir protokoldür: sözleri gelecekteki bir tarihe mühürlemek ve o tarih geldiğinde tam olarak ne söylendiğini ve ne zaman söylendiğini kanıtlamak için bir sistem.

Bunu mümkün kılan üç ilkel öğe vardır. drand, merkezsiz bir rastgelelik işaretçisidir — açıklama tarihi herhangi bir tarafın iyi niyetiyle değil, fizik tarafından uygulanır. Kalıcı herkese açık depolama, kurcalanamaz bir kamu deposudur — bir qub mühürlendikten sonra hiçbir taraf onu düzenleyemez veya silemez. ML-DSA-65, post-kuantum bir dijital imzadır — her qub, gizli anahtarı yazarın cihazından asla çıkmayan bir anahtar çiftine bağlıdır.

Bu ilkel öğeler birlikte, zamana kilitli, kurcalama kanıtlı ve atfedilebilir bir ifade oluşturur — dünyanın geçmişi uydurma yeteneği geliştikçe değeri artan bir makbuz.

Bu belgenin geri kalanı, birlikte çalışabilir uygulamalar için gerekli olan normatif spesifikasyondur.


qub Protokol Spesifikasyonu

Alan Değer
Sürüm 1.0 (protokol sürümü 0x01, dış sarmalayıcı sürümü 0x01)
Tarih 2026-05-01
Durum Taslak
İncelendiği tarih 2026-05-01

Bu belge, qub zamanlı taahhüt sistemi için normatif protokol spesifikasyonudur. Birlikte çalışabilir uygulamalar için gerekli olan veri yapılarını, serileştirme kurallarını, türetme formüllerini ve doğrulama prosedürlerini tanımlar.

Kapsam: protokol katmanı kasıtlı olarak dilden bağımsızdır — qub gövdesi opak düz metin / markdown / pakt baytlarıdır ve yerel ayarlara duyarlı sunum izleyicinin sorumluluğundadır (qub.social web uygulaması, <qub-embed> iframe'i, MCP istemcileri, vb.).


1. Gösterim ve sözleşmeler

Gösterim Anlam
u8, u64, i64 Belirtilen bit genişliğinde işaretsiz/işaretli tam sayılar
[u8; N] N bayttan oluşan sabit uzunluklu bayt dizisi
Vec<u8> Değişken uzunluklu bayt dizisi
Option<T> T türünde değer veya yok
String UTF-8 metin dizesi, NFC normalleştirilmiş
`
SHA3-256(x) x bayt dizisinin NIST SHA3-256 özeti (FIPS 202)
ceil(x) Tavan fonksiyonu: x'ten büyük veya eşit en küçük tam sayı
CBOR Concise Binary Object Representation (RFC 8949)
big-endian En anlamlı bayt önce

Ön görüntü yapılarındaki tüm tam sayılar, aksi belirtilmedikçe big-endian sabit genişlikli bayt dizileri olarak kodlanır (i64 → 8 bayt, u8 → 1 bayt).

Tüm zaman damgaları UTC cinsinden Unix saniyeleridir.


2. Veri yapıları

2.1 ComposeQub (Yaratıcının bellek içi durumu)

CBOR'a serileştirilmez. Kalıcı depolamada saklanmaz. Yaratıcı uygulamasına yereldir.

ComposeQub {
    draft_id:       [u8; 16],        // Random, generated locally
    created_at:     i64,             // Unix seconds UTC
    unlock_at:      Option<i64>,     // Unix seconds UTC; None while composing
    visibility:     u8,              // 0x01 = public (only value in MVP)
    content_type:   u8,              // 0x01 = text (only value in MVP)
    plaintext:      Vec<u8>,         // UTF-8 qub body
    sender_label:   Option<String>,  // Decorative display name; not authenticated
    status:         DraftStatus,     // Composing | Sealed | Uploaded | Failed
}

2.2 QubEnvelope (Şifresi çözülmüş yük)

Kanonik CBOR (§3) kullanılarak serileştirilir. SealedQub içinde şifrelenir. Bu, şifre çözüldükten sonra içerik bütünlüğünü kanıtlayan yapıdır.

QubEnvelope {
    version:             u8,              // Protocol major version (0x01 for v1)
    qub_id:              [u8; 32],        // Derived (see §4.1)
    content_type:        u8,              // Content type registry (see §6)
    created_at:          i64,             // Unix seconds UTC
    unlock_at:           i64,             // Unix seconds UTC
    outcome_at:          Option<i64>,     // V1.1 — when reality renders judgment (verdict-uplift-plan §3.1)
    sender_label:        Option<String>,  // Decorative; not authenticated in MVP
    reply_to:            Option<[u8; 32]>,// Parent qub_id for reply chains; not in qub_id preimage; not signed (see §9.3)
    body:                Vec<u8>,         // Content payload (UTF-8 for text, CBOR for pact)
    body_hash:           [u8; 32],        // SHA3-256(body) (see §4.2)
    sig_alg:             u8,              // Signature algorithm (see §9.2)
    author_signature:    Option<Vec<u8>>, // Set when sig_alg != 0x00
    author_pubkey:       Option<Vec<u8>>, // Set when sig_alg != 0x00
    cosigner_pubkey:     Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
    cosigner_signature:  Option<Vec<u8>>, // Set for cosigned pact bilateral agreements
}

Temel hat (imzasız metin qub): version = 0x01, content_type = 0x01, sig_alg = 0x00, tüm Option alanları yok.

Diğer v1 yapılandırmaları: content_type = 0x03 (pakt gövdesi, bkz. §6.1); author_signature ve author_pubkey mevcut olarak sig_alg = 0x01 (ML-DSA-65) (bkz. §9.3); birlikte imzalanan paktlar için cosigner_pubkey ve cosigner_signature birlikte mevcut (bkz. §9.7); yanıt zinciri qub'ları için reply_to, üst qub'un qub_id'sine ayarlanır (imza kapsamı sonuçları için bkz. §9.3).

2.3 SealedQub (Kanonik aktarım biçimi)

Kanonik CBOR (§3) kullanılarak serileştirilir. Kalıcı depolamaya yazılır. Bu, zincir üzerindeki artefakttır.

SealedQub {
    version:           u8,              // Protocol major version (0x01 for v1)
    qub_id:            [u8; 32],        // Same as QubEnvelope.qub_id
    visibility:        u8,              // 0x01 = public; v1 viewers reject other values
    unlock_at:         i64,             // Unix seconds UTC
    outcome_at:        Option<i64>,     // V1.1 — surfaced on the verdict-watch CTA
                                        //   before reveal; mirrors QubEnvelope.outcome_at;
                                        //   bound to qub_id via the §4.1 preimage.
    drand_chain_id:    String,          // drand chain hash (hex string)
    drand_round:       u64,             // Target drand round number
    tlock_ciphertext:  Vec<u8>,         // tlock-encrypted QubEnvelope CBOR bytes
    recipient_pubkey:  Option<[u8; 32]>,// Reserved field; accepted by canonical CBOR
                                        //   but not interpreted by the v1 reference viewer
    title:             Option<String>,  // Plaintext title surfaced on the viewer
                                        //   countdown before reveal. Bound to qub_id
                                        //   via title_hash (§4.1). 1..=100 NFC code
                                        //   points, no control characters.
}

2.4 RevealedQub (İzleyici uygulama durumu)

CBOR'a serileştirilmez. İzleyici uygulamasına yereldir. Başarılı şifre çözme ve doğrulamadan sonra inşa edilir.

RevealedQub {
    qub_id:              [u8; 32],
    arweave_tx_id:       String,
    visibility:          u8,
    content_type:        u8,
    created_at:          i64,
    unlock_at:           i64,
    outcome_at:          Option<i64>,       // V1.1 — QubEnvelope.outcome_at / SealedQub.outcome_at'tan taşınır; açıklama sayfasındaki karar-izleme bloğunu sürer (verdict-uplift-plan §5.1)
    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. Kanonik CBOR profili

Tüm SealedQub ve QubEnvelope serileştirme bu profille uyumlu OLMALIDIR. Aynı mantıksal yapı verildiğinde iki uygulama aynı baytları üretmek ZORUNDADIR.

3.1 Kodlama kuralları

Kural Spesifikasyon
Standart RFC 8949 §4.2.1 (Çekirdek Deterministik Kodlama Gereksinimleri)
Harita anahtarı sıralaması Önce kodlanmış bayt uzunluğuna göre sıralanır (kısa olan önce gelir), sonra sözlüksel olarak (aynı uzunluktaki kodlamalar için bayt bayt)
Tam sayı kodlaması En kısa biçim: ilk baytta 0–23; 2 baytta 24–255; 3 baytta 256–65535; vb.
Uzunluk kodlaması Yalnızca kesin uzunluklar. Belirsiz uzunluklu diziler, haritalar, bayt dizileri veya metin dizeleri yoktur (ek bilgi = 31 yasaktır).
Etiketler CBOR etiketi yoktur (ana tür 6 yasaktır).
Kayan nokta Kayan nokta yoktur (ana tür 7, 0xF9–0xFB değerleri yasaktır).
Metin dizeleri UTF-8 kodlamalı, NFC normalleştirilmiş (Unicode Normalleştirme Formu C).
Bayt dizeleri Ham baytlar. CBOR katmanında base64 kodlaması yoktur.
Yinelenen anahtarlar Hata ile reddet. Ayrıştırıcılar yinelenen harita anahtarlarını sessizce kabul ETMEMELİDİR.
Bilinmeyen anahtarlar Hata ile reddet. Ayrıştırıcılar, türün kanonik anahtar kümesi dışındaki harita anahtarlarını tolere ETMEMELİDİR — iki farklı kanonik bayt dizesinin kodu asla aynı değere çözülmemelidir (encode(decode(x)) == x) ve imzalı yükler için fazladan bir anahtar, her iki imzanın da taahhüt ettiği gizli içerik olurdu. Şema evrimi version üzerinden ilerler, asla fazladan anahtarlar üzerinden değil.
Basit değerler Yalnızca true (0xF5), false (0xF4) ve null (0xF6) izin verilir.
İsteğe bağlı alanlar Mevcut olmayan isteğe bağlı alanlar CBOR haritasından tamamen çıkarılır (null olarak kodlanmaz). Mevcut isteğe bağlı alanlar sıralı anahtar düzeninde dahil edilir.

3.2 Doğrulanmış kanonik anahtar sıraları

Bu anahtar sıraları normatiftir. Uygulamalar anahtarları tam olarak bu sırayla yaymak ZORUNDADIR. Hata ayıklama onaylamaları, üretim dışı yapılarda sıralamayı doğrulamalıdır (SHOULD).

QubEnvelope (sürüm 0x01, imzasız, tüm isteğe bağlı alanlar yok):

"body"                (5 encoded bytes)
"qub_id"              (7 encoded bytes)
"sig_alg"             (8 encoded bytes)
"version"             (8 encoded bytes)
"reply_to"            (9 encoded bytes)   ← only if present (reply chains)
"body_hash"           (10 encoded bytes)
"unlock_at"           (10 encoded bytes)
"created_at"          (11 encoded bytes)
"outcome_at"          (11 encoded bytes)  ← only if present (V1.1 verdict mechanic)
"content_type"        (13 encoded bytes)
"sender_label"        (13 encoded bytes)  ← only if present
"author_pubkey"       (14 encoded bytes)  ← only if present
"cosigner_pubkey"     (16 encoded bytes)  ← only if present (pact cosign)
"author_signature"    (17 encoded bytes)  ← only if present
"cosigner_signature"  (19 encoded bytes)  ← only if present (pact cosign)

QubEnvelope anahtar sırası türetmesi: her anahtar bir CBOR metin dizesidir. Kodlanmış uzunluk = 1 baytlık başlık + dize uzunluğu (24 bayttan kısa dizeler için). Önce toplam kodlanmış uzunluğa göre, aynı uzunluktaki anahtarlar için sözlüksel olarak sıralayın.

SealedQub (sürüm 0x01, herkese açık, alıcı yok):

"title"             (6 encoded bytes)   ← only if present
"qub_id"            (7 encoded bytes)
"version"           (8 encoded bytes)
"unlock_at"         (10 encoded bytes)
"outcome_at"        (11 encoded bytes)  ← only if present (V1.1 verdict mechanic)
"visibility"        (11 encoded bytes)
"drand_round"       (12 encoded bytes)
"drand_chain_id"    (15 encoded bytes)
"recipient_pubkey"  (17 encoded bytes)  ← only if present
"tlock_ciphertext"  (17 encoded bytes)

PactTerms (pakt gövdesi, 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 (terms dizisinin satırı):

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

PartyIdentifier (party_a / party_b haritası):

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

3.3 Bayt kodlama referansı

Tür CBOR kodlaması Örnek
SHA3-256 özeti (32 bayt) 0x58 0x20 + 32 bayt body_hash, qub_id
Zaman damgaları (i64) Ana tür 0 (pozitif) veya 1 (negatif), en kısa kodlama Unix saniyeleri
Sürüm (u8, değer 1) 0x01 (tek bayt)
İçerik türü (u8, değer 1) 0x01 (tek bayt)
sig_alg (u8, değer 0) 0x00 (tek bayt)
ML-DSA-65 imzası (3.309 bayt) 0x59 0x0C 0xED + 3.309 bayt author_signature, cosigner_signature
ML-DSA-65 açık anahtarı (1.952 bayt) 0x59 0x07 0xA0 + 1.952 bayt author_pubkey, cosigner_pubkey

4. Normatif türetmeler

4.1 qub_id

qub_id, bir qub'u benzersiz şekilde tanımlar ve QubEnvelope'u SealedQub'a bağlar. Zarf içeriğinden deterministik olarak türetilir.

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

Etki alanı ayırıcı kodlaması: "QUB_ID_V2" dizesi 9 ASCII bayttır. Hizalama için 10 bayta ulaşmak amacıyla tek bir 0x00 dolgu baytı eklenir. Uygulamalar tam olarak bu 10 baytı kullanmak ZORUNDADIR: [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00].

outcome_at kodlaması: V1.1, isteğe bağlı outcome_at alanını bağlamaya katmak için ön görüntüyü 92 bayttan 100 bayta genişletti. Yok olan outcome_at, 8 sıfır bayt olarak kodlanır; protokol doğrulayıcıları her yerde outcome_at <= 0 değerini reddeder, böylece bu nöbetçi değer meşru bir değerle çakışamaz. Bkz. §3.2 (aktarım biçimi) ve bu alanı motive eden hüküm mekaniği için ağaç içi tasks/verdict-uplift-plan.md.

drand_round kodlaması: V1.2, drand_round'u (hedef drand turu, §4.3) bağlamaya katmak için ön görüntüyü 100 bayttan 108 bayta genişletti ve etki alanı ayırıcısını QUB_ID_V2'ye yükseltti. Bu, zaman kilidi turunu qub kimliğine bağlar: bir ağ geçidi, şifreli metni gösterilen unlock_at'ın ima ettiğinden farklı bir tura (örneğin halihazırda geçmiş bir tura) yeniden bağlayamaz. Açılma yordamı (§8) ayrıca tlock şifreli metin stanzasına gömülü turun unlock_round(unlock_at) ile eşleştiğini doğrular, böylece gösterilen açılma zamanının, şifre çözmeyi kapılayan tur olduğu kanıtlanabilir.

Özellikler:

4.2 body_hash

body_hash = SHA3-256(body)

Burada body, ham Vec<u8> içerik yüküdür. Metin qub'ları için bu, UTF-8 kodlamalı qub gövdesidir.

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

Burada title, açıklama öncesinde izleyici geri sayımında gösterilen isteğe bağlı düz metin başlığıdır (bkz. §3.2). NFC normalleştirme, özetin görsel olarak eşdeğer kod-nokta dizileri arasında kararlı olması için özet zamanında çalışır. Tümü sıfır olan işaretçi, yok durumu için ayrılmıştır; boş bir dize, kanonik CBOR sınırında "yok"un kanonik olmayan kodlaması olarak reddedilir (kanonik kodlama alanı tamamen çıkarır).

4.3 Açılma turu eşleştirmesi

drand_round = ceil((unlock_at - chain_genesis_time) / chain_period_seconds)
Parametre Kaynak Örnek
unlock_at Kullanıcı tarafından seçilen UTC Unix saniyeleri 1735689600 (2025-01-01 00:00:00 UTC)
chain_genesis_time drand zincir bilgisi (genesis_time) 1595431050
chain_period_seconds drand zincir bilgisi (period) 30

ceil() işlemi, açıklama zamanı ≥ unlock_at olan ilk drand turunu seçer. Bu, qub'un seçilen açılma zamanından önce şifresinin çözülememesini sağlar.

Sınır durumu: (unlock_at - chain_genesis_time) tam olarak chain_period_seconds'a bölünebiliyorsa, sonuç tam olarak o turdur — qub o turun açıklama zamanında tam olarak açılır.

Doğrulama: unlock_at, mühürleme anında gelecekte olmak ZORUNDADIR. unlock_at, created_at'tan en fazla 10 yıl uzakta olmak ZORUNDADIR (uzun ufuklu drand bağımlılık riskini sınırlamak için; arayüz 2 yılın ötesindeki açılma tarihleri için uyarı vermelidir — SHOULD).


5. Aktarım biçimi yeni tipleri

Aktarım biçimi yeni tipleri (newtypes), CBOR baytlarını JSON, ham düz metin veya diğer bayt kodlamalarıyla karıştırmaya karşı derleme zamanı güvenliği sağlar.

Tür İçerir Üreten Tüketen
SealedQubCbor SealedQub'ın kanonik CBOR'u serialize_sealed_qub() Kalıcı depolama yüklemesi, izleyici alımı
QubEnvelopeCbor QubEnvelope'un kanonik CBOR'u serialize_qub_envelope() tlock şifreleme girdisi, tlock şifre çözme çıktısı

5.1 İnşa kuralları

// 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 İnşada doğrulama

from_encoded(), çift ayrıştırmayı önlemek için girdinin geçerli bir CBOR harita başlığıyla başladığını doğrulamalıdır (SHOULD). Tam yapısal doğrulama inşa zamanında değil, ayrıştırma zamanında gerçekleşir.


6. İçerik türü kayıt defteri

Değer Tür Maksimum gövde boyutu Notlar
0x00 Ayrılmış (geçersiz) Kullanılmamalıdır (MUST NOT)
0x01 Düz metin (UTF-8, kısıtlı Markdown) 50 KB ücretli / 10 KB ücretsiz Sunum kuralları için bkz. §10. Ücretsiz / ücretli ayrımı yükleme hizmeti tarafından uygulanır; protokol katmanı kesin tavanı 50 KB'dir.
0x02 Ayrılmış (gelecek) Gelecekteki bir içerik türü için ayrılmıştır; v1'de geçerli değildir. İzleyiciler aşağıdaki kural uyarınca reddetmek ZORUNDADIR.
0x03 Pakt (ikili anlaşma, CBOR gövdesi) 100 KB Gövde kanonik CBOR PactTerms'tür (§6.1). §9.7 uyarınca birlikte imzalayan imzalama.
0x04 Karar (yaratıcı öz-değerlendirmesi, CBOR gövdesi) 8 KB Gövde kanonik CBOR VerdictBody'dir (§6.2). Yalnızca sistem tarafı verdict niyeti tarafından yayılır. Üst ilişki, gövdede değil, Parent-Tx-Id Arweave etiketindedir. Bkz. verdict-uplift-plan §3.4.

İzleyiciler bilinmeyen içerik türlerini açık bir kullanıcıya görünür hata ile reddetmek ZORUNDADIR. İzleyiciler bilinmeyen türleri metin olarak sunmaya çalışMAMALIDIR.

6.1 Pakt gövdesi (content_type = 0x03)

Bir pakt gövdesi, bir PactTerms değerinin kanonik CBOR kodlamasıdır:

PactTerms {
    pact_version:  u8,                    // 0x01 for structured/v1
    title:         String,                // ≤ 200 bytes, NFC
    terms:         Vec<PactTerm>,         // ≤ 20 rows
    party_a:       PartyIdentifier,       // initiator
    party_b:       PartyIdentifier,       // counter-signer
    notes:         Option<String>,        // ≤ 5,000 bytes, NFC; absent key if none
}

PactTerm       { key: String (≤ 100), value: String (≤ 2,000) }   // NFC on both sides
PartyIdentifier{ label: String (≤ 100), contact: Option<String (≤ 320)> }

Üç harita için kanonik CBOR anahtar sıraları §3.2'de verilmiştir. Toplam serileştirilmiş pakt CBOR 100 KB'yi aşMAMALIDIR (§6 ile eşleşir).

Şema ayırt edicisi. Bir structured/v1 paktında terms'teki ilk satır { key: "pact_schema", value: "structured/v1" } OLMALIDIR. Bu işareti olmayan satırlar "özel" paktlardır ve yapılandırılmış doğrulama veya şemaya duyarlı sunum almazlar.

Donmuş onay yuvaları. structured/v1 paktları bu anahtarlar altında tam olarak dört onay satırı taşır:

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

Her birinin value'su, (role, kind) çifti ile seçilen sekiz donmuş İngilizce dizeden biridir; burada role ∈ { seller, buyer, provider, client } ve kind ∈ { standard, capacity }. Dizelerin kendisi normatif protokol verisidir — her iki tarafın ML-DSA-65 imzaları, body_hash aracılığıyla tam baytlara taahhüt eder. Bunlar yerelleştirilMEZ; imzalanan gövde dilden bağımsızdır. Herhangi bir ifade değişikliği yeni bir şema sürümü gerektirir (structured/v2).

Sekiz dize, aramaları (acknowledgement_for(role, kind)) ve her birinin gerekçesi referans uygulama tarafından sabitlenir. Uyumlu uygulamalar bayt-aynı onay değerleri yaymak ZORUNDADIR; dört rol kombinasyonunun tamamını kapsayan altın-fikstür SHA3-256 gövde-özeti testleri herhangi bir kaymayı yakalar.

İzleyici görüntüleme sırası. Onay dizeleri, açıklama / kapsam satırlarının onaylardan önce sunulduğunu varsayan "yukarıda açıklandığı gibi" ("described above") gibi ifadeler içerir. İzleyiciler terms dizisini CBOR sırasında sunmak ZORUNDADIR; yeniden sıralama metnin anlamsal bütünlüğünü bozar.

Karşı taraf iletişimi. Taraf B'nin contact bilgisi geçerli bir e-posta adresi olduğunda, qub yükleme hizmeti, hazırlama anında otomatik olarak bir inceleme / birlikte imzalama davet e-postası gönderir ve nihai birlikte imzayı aynı adresin doğrulamasına bağlar (§9.7). Taraf B iletişimi olmayan paktlar yine de birlikte imzalanabilir, ancak yalnızca bant dışı bir kanal aracılığıyla — hizmet, eşleşen bir 15 dakikalık e-posta doğrulama işaretçisi üretemeyen birlikte imzalama isteklerini reddeder.

6.2 Karar gövdesi (content_type = 0x04)

Bir karar gövdesi, bir VerdictBody değerinin kanonik CBOR kodlamasıdır:

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
}

Kanonik CBOR anahtar sırası:

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

Toplam serileştirilmiş karar CBOR'u 8 KB'yi aşMAMALIDIR (yukarıdaki kayıt defteri satırıyla eşleşir).

Sonuç sıralı türü (enum). Tel baytı niyetten bağımsızdır; dört kategori — Right / Partial / Wrong / Unfalsifiable — karar taşıyan her niyetin sonuç uzayını kapsar. Niyete özgü etiketler (Right için "Bildim" / "Tuttum" / "Yayımlandı" / "Doğrulandı" gibi) izleyici tarafı sunum işidir ve üst qub'un niyetine göre çözümlenir — tel, dilden ve niyetten bağımsız kalır. 1..=4 dışındaki değerler kod çözmede reddedilmek ZORUNDADIR.

Üst bağlantısı. Bir karar qub'u, üst referansını gövdesinde taşıMAZ. Üst qub'un Arweave işlem kimliği, yükleme anında Parent-Tx-Id depolama etiketi olarak yayılır (§7 depolama-etiketi katmanı). Bu, gövdeyi kendi kendine yeten, imzalı bir öz-değerlendirme bildirimi olarak tutar; denetim zinciri ("ne hakkında haklı?") Arweave-etiketi araması üzerinden kurulur.

Kanıt URL güvenliği (normatif). evidence_url mevcut olduğunda, doğrulayıcılar (hazırlama tarafı, tel tarafı, Worker kenarı) şunları uygulamak ZORUNDADIR:

  1. Yalnızca HTTPS. Dize, https:// bayt dizisiyle başlamak ZORUNDADIR. Başka herhangi bir şema — http, ftp, javascript, data, file vb. — reddedilir.
  2. Uzunluk üst sınırı. ≤ 2.048 bayt (tarayıcı URL pratik sınırı).
  3. NFC + düşmanca kod noktası denetimi. title ve reflection ile aynı kural — bidi-override / sıfır genişlik / etiket bloğu / BOM / C0 / C1 kod noktaları reddedilir. Tanım, Rust crate::handle::contains_hostile_text_codepoint ve TS workers/api/src/utils/unicode.ts::isHostileCodepoint ile eşleşir (üçü birlikte ilerletilmek ZORUNDADIR).
  4. Boşluk yok, ASCII denetim karakteri yok. URL'nin herhangi bir yerindeki boşluk / DEL / 0x20 altındaki baytlar reddedilir — bidi kuralının kapsamadığı \n/\t enjeksiyon vektörünü kapatır.
  5. Boş olmayan ana bilgisayar bölümü. https:// ile ilk /, ? veya # arasındaki her şey boş olmayan ZORUNDADIR.

Sunucu tarafında getirme yok. Worker, URL'yi vekille çekMEMELİ, getirMEMELİ ya da önizleMEMELİDİR. Protokol bir dize saklar; sunum, rel="nofollow noopener noreferrer" target="_blank" ile izleyici tarafında gerçekleşir ve bağlantı metniyle birlikte görünür bir ana bilgisayar gösterilir.

Düşünce. İsteğe bağlı, yaratıcının yazdığı düşünce metni ("ne değişti, ne öğrendin"). title ile aynı NFC + düşmanca kod noktası doğrulaması. Boş / yalnızca boşluk içeren girdi, oluşturma anında yok sayılır.

Şema sürümü. v1 yalnızca verdict_version = 0x01'i destekler. Gelecekteki şema güncellemeleri bu baytı artırır ve §12 uyarınca yeni bir protokol sürümüyle birlikte iner.


7. Mühürleme protokolü

Tam mühürleme dizisi. Her adım normatiftir.

 1. User composes plaintext and metadata in ComposeQub.
 2. Validate:
    a. body is non-empty.
    b. body size ≤ max for content_type and user tier (see §6).
    c. unlock_at is in the future.
    d. unlock_at ≤ created_at + 10 years.
    e. content_type is a known, supported value.
 3. Compute body_hash = SHA3-256(body).
 4. Set created_at = current Unix seconds UTC.
 5. Select drand chain. Load chain_genesis_time and chain_period_seconds, and
    compute drand_round = ceil((unlock_at - chain_genesis_time) / chain_period_seconds).
    (Computed here, before qub_id, because drand_round is bound into the qub_id
    preimage — §4.1, V1.2.)
 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,
    unlock_at, drand_chain_id, drand_round.
12. Serialise SealedQub using canonical CBOR → SealedQubCbor.
12a. Generate K = 32 random bytes (CSPRNG) and N = 12 random bytes (CSPRNG).
     Compute W = wrap_sealed_qub(SealedQubCbor, qub_id=qub_id, key=K, nonce=N)
     per §13. The bytes uploaded to permanent storage are the OuterWrapper CBOR W,
     never the bare SealedQubCbor. K leaves the device only as the URL
     fragment in step 16.
13. Display seal-time disclosure. User confirms.
14. Validate upload eligibility via the qub upload service (bot-detection, entitlement, rate limits).
15. Submit W (the OuterWrapper bytes) to the qub upload service; the service
    signs and uploads to permanent storage. The service is byte-blind to the inner
    SealedQubCbor and never receives K.
16. Receive arweave_tx_id from the service. Construct delivery URL as
    `<origin>/c/<arweave_tx_id>#<base64url(K)>` (or `<origin>/s/<short_code>#<base64url(K)>`
    when a short code is allocated). Browsers do not transmit URL fragments
    to servers, so K is never observed by qub.social or any storage gateway.

Depolama etiket katmanı (bant dışı). qub yükleme hizmeti, sarmalanmış yüke ek olarak kasıtlı olarak küçük bir depolama işlem etiketi seti ekler. Content-Type=application/octet-stream normatif olarak gereklidir. Referans hizmet ayrıca, yaratıcı bunları yüzeye çıkarmayı seçtiğinde üç isteğe bağlı etiket ekler: Intent (izin listesi doğrulamalı oluşturma niyeti — örneğin quote, reply, commitment), Author (yaratıcının §9.3 açık anahtar parmak izi 64 karakterli küçük harf onaltılık olarak) ve Parent-Tx-Id (yanıt zincirleri için üst qub'un depolama işlem kimliği, 43 karakterli base64url).

Author etiketi qub başına opsiyoneldir: referans yaratıcı uygulaması bunu yalnızca kullanıcı mühürleme anında kamu atıfını açıkça etkinleştirdiğinde ekler. Geçiş kapalıyken — varsayılan — hiçbir Author etiketi yazılmaz ve qub zincirde atfedilmemiştir: kalıcı depolamadaki hiçbir şey yüklemeyi bir yaratıcının kullanıcı adına, e-postasına veya diğer qub'larına bağlamaz. Geçiş açıkken, Author parmak izi §9.5 onay zinciri aracılığıyla yaratıcının seçtiği @handle'a çözümlenir. Yanıt zinciri ilişkileri ve Intent tanımlayıcı değildir. Dış sarmalayıcı (§13), iç gövdeyi şifreli metin korelasyonundan korur — bir hasatçının drand turu yayınlandıktan sonra qub-şekilli yüklemeleri tanımasını ve toplu olarak şifresini çözmesini engeller.

Referans hizmet kasıtlı olarak App-Name, App-Version veya Type etiketlerini eklemez: bu tür herhangi bir tek değerli filtre, bir GraphQL sorgusuna tüm qub corpus'unu döndürür ki bu, sarmalayıcının yalnızca-gövde gizlilik kapsamıyla tutarsızdır.

Uyumlu bir doğrulayıcı, §11 üçüncü taraf doğrulaması için herhangi bir depolama etiketine bağımlı olMAMALIDIR; gövde özeti / qub_id / imza yalnızca iç CBOR'a taahhüt eder, asla etiket setine değil.


8. Açma protokolü

Tam açma dizisi. Her adım normatiftir.

 1. Viewer opens delivery URL. Extract arweave_tx_id from path AND
    K = base64url_decode(fragment) from the URL fragment. If the fragment
    is absent or malformed → display "this URL is missing its decryption
    key" and stop; the viewer MUST NOT contact the storage gateway
    without K, since fetching wrapped bytes the viewer cannot decrypt
    serves no purpose and only leaks the access attempt.
 2. Check denylist. If tx_id is denylisted → display block message. Stop.
 3. Fetch OuterWrapper bytes from permanent storage (with multi-gateway fallback).
 3a. Unwrap: parse the bytes as OuterWrapper (§13), verify the wrapper
    `version` byte is `0x01`, and compute SealedQubCbor =
    unwrap_sealed_qub(OuterWrapper, key=K). Any AEAD authentication
    failure (wrong K, tampered ciphertext, swapped qub_id-as-AAD,
    swapped nonce) → display "this URL's decryption key does not match
    the stored qub" and stop. Authentication failures are
    indistinguishable to the viewer per §13.5.
 4. Parse SealedQubCbor → SealedQub.
 5. Validate: SealedQub.version is known (0x01). Reject unknown versions.
 6. If current time < SealedQub.unlock_at → display countdown. Poll or wait.
 6a. Round-binding check (V1.2). Recompute expected_round =
    ceil((SealedQub.unlock_at - chain_genesis_time) / chain_period_seconds).
    Reject unless SealedQub.drand_round == expected_round AND the round baked
    into the tlock ciphertext stanza (read via the age/tlock header, no signature
    required) == expected_round. 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.
13. Verify: QubEnvelope.content_type is known and renderable.
    Known values: 0x01 (text), 0x03 (pact). Unknown → display error.
14. If QubEnvelope.sig_alg != 0x00 → verify author signature (see §9.4).
15. If cosigner_pubkey or cosigner_signature present → verify cosigner (see §9.7).
16. Render content using appropriate renderer (see §10 for text, §6 for pact).
17. Construct RevealedQub for display.

9. Yazarlık imzalama

9.1 Gerekçe

qub'lar kalıcı depolamada saklanır. Yazarlık imzaları süresiz olarak sahteciliğe karşı dirençli kalmalıdır, bu nedenle v1.0, güvenliği qub'un kalıcı yaşam süresi içinde bozulabilecek klasik bir şema yerine post-kuantum ML-DSA-65 şemasını (FIPS 204) kullanır.

9.2 Algoritma kayıt defteri

sig_alg Şema Anahtar boyutu İmza boyutu
0x00 İmza yok (imzasız)
0x01 ML-DSA-65 (FIPS 204) 1.952 bayt 3.309 bayt

İzleyiciler bilinmeyen sig_alg değerlerini reddetmek ZORUNDADIR.

9.3 İmzalı ön görüntü inşası

İki ön görüntü sürümü var olmuştur. Tüm imzalar V2 kullanmak ZORUNDADIR ve doğrulayıcılar yalnızca V2'yi kabul etmek ZORUNDADIR. Eski V1 ön görüntüsü (tarihsel referans için aşağıda belgelenmiştir), V2 geçişi sırasında yalnızca doğrulama amaçlı bir yedek olarak kabul ediliyordu; bu yedek kullanımdan kaldırılmıştır ve yalnızca V1 olan bir imza artık reddedilir.

V2 (güncel — tüm yeni yazar imzalaması tarafından ve pakt hazırlama / birlikte imzalama akışının her iki imzası tarafından üretilir):

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, title_hash (§4.2.1) ile aynı yokluk-nöbetçisi kuralını izler: 32 sıfır bayt geçerli bir SHA3-256 çıktısı değildir, bu nedenle "yok" hiçbir zaman mevcut bir etiketle çakışamaz. Tüm alanlar sabit genişliktedir, bu nedenle ön görüntü, uzunluk önekleri olmadan belirsizlik taşımaz.

V1 (eski — KULLANIMDAN KALDIRILDI; artık üretilmez ve doğrulamada artık kabul edilmez):

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

V1 ön görüntüsü sender_label ve reply_to'yu dışarıda bırakıyordu. V2'ye geçiş sırasında yalnızca doğrulama amaçlı bir yedek olarak kabul ediliyordu; bu yedek o zamandan beri kullanımdan kaldırılmıştır — doğrulayıcılar yalnızca V2 ön görüntüsünü kabul etmek ZORUNDADIR. Tanım burada tarihsel referans için ve aşağıdaki etki alanı ayırıcısını açıklamak için tutulmuştur. Yalnızca V1'e karşı doğrulanan bir imza, bir doğrulama hatası olarak ele alınmak ZORUNDADIR.

Etki alanı ayırıcıları: "QUB_AUTHOR_SIG_V1" / "QUB_AUTHOR_SIG_V2" her biri 17 ASCII bayttır ([0x51, 0x55, 0x42, 0x5F, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x5F, 0x53, 0x49, 0x47, 0x5F, 0x56, 0x31/0x32]). Dolgu yok. Farklı ayırıcı, iki yapıyı etki alanı olarak ayırır, bu nedenle bir ön görüntü üzerindeki bir imza asla diğeri olarak doğrulanamaz.

org_id_present baytı: unlock_at'ı izleyen bayt 0x00 OLMALIDIR. Referans uygulama bunu crates/qub-core/src/signing.rs içinde ORG_ID_PRESENT_INDIVIDUAL = 0x00 sabiti olarak sunar; doğrulama için sig_input'u yeniden oluşturan izleyiciler aynı baytı yaymak ZORUNDADIR.

İmza kapsamı — neyi kapsar ve neyi kapsamaz. V2 sig_input'u doğrudan version, qub_id, body_hash, unlock_at, sender_label ve reply_to'ya taahhüt eder (artı sabit etki alanı ayırıcısı ve org_id_present baytı). qub_id'nin kendisi §4.1 ön görüntüsü aracılığıyla version, content_type, created_at, unlock_at, outcome_at, drand_round ve body_hash'ten türetilir, bu nedenle bu alanlarda yapılan herhangi bir değişiklik farklı bir qub_id üretir ve imzayı geçişli olarak geçersiz kılar. Bu nedenle kimliği doğrulanmış yüzey şudur:

Alan İmza ile kimliği doğrulanır Nasıl
version sig_input'a doğrudan girdi
qub_id Doğrudan girdi
body_hash Doğrudan girdi
unlock_at Doğrudan girdi
sender_label sender_label_hash aracılığıyla doğrudan girdi (V2 ön görüntüsü — kabul edilen tek biçim)
reply_to reply_to_or_zero aracılığıyla doğrudan girdi (V2 ön görüntüsü — kabul edilen tek biçim)
content_type qub_id ön görüntüsü aracılığıyla geçişli olarak
created_at qub_id ön görüntüsü aracılığıyla geçişli olarak
outcome_at qub_id ön görüntüsü aracılığıyla geçişli olarak
drand_round qub_id ön görüntüsü aracılığıyla geçişli olarak (V1.2)
body body_hash = SHA3-256(body) aracılığıyla geçişli olarak
author_pubkey — (örtük) İmzayı doğrulayan anahtar, tanım gereği yazardır
cosigner_pubkey / cosigner_signature Aynı sig_input üzerinde bağımsız olarak imzalanır (bkz. §9.7)
drand_chain_id, tlock_ciphertext, visibility Dış SealedQub alanları, zarfın içinde değil — kendi yapısal değişmezleri (tur / zincir tutarlılığı) tarafından kapsanır ancak yazar imzası tarafından kapsanmaz. (drand_round artık qub_id ön görüntüsü aracılığıyla geçişli olarak bağlanır — yukarıya bakın.)

Neden yalnızca V2 kabul edilen ön görüntüdür.

sender_label veya reply_to'yu son kullanıcılara gösteren uygulamalar, kimliği doğrulanmış kimliği (açık anahtar parmak izi, onay) etiket yerine birincil kimlik sinyali olarak yüzeye çıkarmak ZORUNDADIR.

9.4 Doğrulama prosedürü

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

İmza doğrulama en pahalı işlemdir (özellikle ML-DSA-65). Daha ucuz tüm kontroller (özet, qub_id, unlock_at) geçtikten sonra yapılmalıdır (SHOULD).

9.5 Kimlik onayları

Kimlik onayları — author_pubkey'in qub kullanıcı adı, e-posta adresi, sosyal kullanıcı adı veya parola anahtarı kimlik bilgisi gibi insan tarafından tanınabilen kimlik iddialarına eşlenmesi — izleyici tarafında aşamalı bir geliştirmedir ve imza doğrulaması için gerekli değildir. Onayları bir görüntüleme kimliğine çözen izleyiciler şu önceliği uygulamak ZORUNDADIR:

handle > email > social > fingerprint

Parmak izi yedeği, SHA3-256(author_pubkey)'in küçük harf onaltılığıdır; herhangi bir imzalı qub için her zaman kullanılabilir. İzleyiciler bunu görüntüleme için kısaltABİLİR — referans izleyici, qub: ardından ilk ve son dört baytı sunar (qub:<8 hex>…<8 hex>).

Uyumlu bir doğrulayıcı, qub API'sine başvurmadan, kalıcı depolama ve drand'ın ötesinde herhangi bir ağ olmadan ve herhangi bir sunucu tarafı araması olmadan §9.4'teki her kontrolü tamamlayabilir. Onay çözümleme, yalnızca imza doğrulaması başarılı olduktan sonra gerçekleştirilen ayrı bir en iyi çaba adımıdır.

9.6 Boyut etkisi

Ed25519 ML-DSA-65
İmza 64 bayt 3.309 bayt
Açık anahtar 32 bayt 1.952 bayt
qub başına toplam 96 bayt 5.261 bayt
Depolama maliyet farkı (~5$/MB ile) ~0,0005$ ~0,026$

500–2.000 bayt'lık bir metin qub için ML-DSA-65 depolanan boyutu kabaca üç katına çıkarır. Mutlak maliyet ihmal edilebilir düzeydedir.

9.7 Birlikte imzalayan doğrulaması (Pakt ikili anlaşmaları)

İkili anlaşmalar için (content_type = 0x03), ikinci bir imza katmanı her iki tarafın da aynı koşullara onay verdiğini kanıtlar.

Zarf alanları:

Her iki alan da birlikte mevcut olmak veya her ikisi de yok olmak ZORUNDADIR. Yalnızca biri mevcutsa, izleyiciler bir bütünlük hatası bildirmek ZORUNDADIR.

Doğrulama prosedürü:

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

Özellikler:

E-posta bağlama kapısı (operasyonel). Hazırlanan bir pakt bir Taraf B e-posta iletişimi taşıdığında (§6.1), qub yükleme hizmeti, hem hazırlama kimliği hem de bu iletişimin normalleştirilmiş e-posta özeti ile eşleşen kısa ömürlü bir e-posta doğrulama işaretçisi mevcut olmadıkça birlikte imzalama isteğini reddetmek ZORUNDADIR. İşaretçi, sihirli bağlantı belirteci bir staging_id taşıdığında ve doğrulanmış adres SHA-256(normalise_email(party_b.contact)) ile eşleştiğinde /api/v1/auth/verify tarafından yazılır — burada normalise_email(addr) yerel bölümün büyük/küçük harfini korur ve yalnızca etki alanı bölümünü küçük harfe çevirir (RFC 5321 §2.3.11 uyarınca) ve buradaki SHA-256, NIST FIPS 180-4 özetidir (§4 türetmelerinde kullanılan SHA3-256'dan farklı) — ve verildikten 900 saniye (15 dakika) sonra sona erer. Bu operasyonel bir kimlik taklidine karşı kapıdır, zincir üzerindeki qub kanıtının bir parçası DEĞİLDİR — §11'i yeniden oynayan üçüncü taraf bir doğrulayıcının yalnızca kalıcı depolama ve drand'a ihtiyacı vardır, herhangi bir sunucu tarafı araması olmadan. İşaretçi yalnızca sunucu tarafında bulunur ve asla imzalanmış gövdenin bir parçası değildir.

Boyut etkisi (ML-DSA-65 yazar + birlikte imzalayan):

Bileşen Boyut
Yazar imzası 3.309 bayt
Yazar açık anahtarı 1.952 bayt
Birlikte imzalayan imzası 3.309 bayt
Birlikte imzalayan açık anahtarı 1.952 bayt
Toplam kripto ek yükü 10.522 bayt
Depolama maliyet farkı ~0,05$

10. Markdown sunumu ve temizleme

Bu bölüm güvenlik açısından kritiktir. İzleyici, metin qub'larını (content_type = 0x01) kısıtlı bir Markdown alt kümesi kullanarak sunar.

10.1 İzin verilen öğeler

10.2 Yasaklanan öğeler

Öğe İşleme
Ham HTML (<div>, <script>, vb.) Tamamen çıkarılır. HTML'den hiçbiri geçmez.
Görseller (![alt](url)) Çıkarılır. Görsel söz dizimi çıktıdan kaldırılır.
Bağlantılar ([text](url)) URL görünür düz metin olarak sunulur. Otomatik bağlantılanmaz. Açık kullanıcı eylemi olmadan tıklanabilir değildir.
Tehlikeli URL şemaları javascript:, data:, vbscript:, file: — çıkarılır.
iframe'ler, gömülenler, nesneler Çıkarılır.
HTML varlıkları Yalnızca güvenliyse görüntüleme karakterlerine kod çözülür.

10.3 Uygulama

Uygulamalar bir kara liste değil, katı bir izin listesi ayrıştırıcısı kullanmak ZORUNDADIR. Önerilen yaklaşım:

  1. Markdown'ı pulldown-cmark (veya eşdeğeri) kullanarak ayrıştırın.
  2. AST'de gezinin ve izin listesinde olmayan herhangi bir düğümü atın (§10.1).
  3. Bağlantı düğümleri için: URL'yi tıklanabilir bir <a> öğesi olarak değil, görünür metin olarak yayın.
  4. Filtrelenmiş AST'yi tipli bir ara temsile dönüştürün (örneğin, yalnızca güvenli varyantları olan bir MarkdownNode enum'u). Bu IR'de ham HTML yapısal olarak temsil edilemez.
  5. Tipli IR'den hedef görünüm katmanına (örneğin, reaktif görünüm bileşenleri, DOM düğümleri) sunum yapın. Hiçbir noktada HTML dize birleştirme veya innerHTML kullanılmaz.

Kara liste yaklaşımları kırılgandır çünkü yeni Markdown uzantıları veya ayrıştırıcı tuhaflıkları filtrelenmemiş öğeler getirebilir. Tipli AST yaklaşımı, XSS'yi yapısal olarak imkansız hale getirir — keyfi HTML taşıyabilecek bir varyant yoktur.

10.4 Boyut ve yapı sınırları


11. Üçüncü taraf doğrulaması

Herhangi bir üçüncü taraf, qub işbirliği olmadan bir kamu qub'unu doğrulayabilir. Doğrulama prosedürü:

1. Obtain arweave_tx_id (from delivery URL or direct knowledge).
2. Fetch SealedQubCbor from any storage gateway.
3. Confirm storage block inclusion (block height, block timestamp).
4. Parse SealedQubCbor → SealedQub.
5. Fetch drand round signature for SealedQub.drand_round.
6. tlock_decrypt(tlock_ciphertext, round_signature) → QubEnvelope CBOR bytes.
7. Parse → QubEnvelope.
8. Verify SHA3-256(body) == body_hash.
9. Verify QubEnvelope.qub_id == SealedQub.qub_id.
10. Verify QubEnvelope.unlock_at == SealedQub.unlock_at.
11. If sig_alg != 0x00: verify author_signature (see §9.4).
12. All checks pass → qub is verified.

Doğrulamanın kanıtladıkları:

Kanıt Ne kurar
Taahhüt Şifreli metin depolama blok zaman damgasına kadar var olmuştur.
Bütünlük Düz metin gövdesi taahhüt edilen özetle eşleşir ve değiştirilmemiştir.
Zamanlama İçerik, seçilen açılma zamanına karşılık gelen drand turuna kadar okunamazdı (tlock ve drand güvenlik varsayımlarına tabidir).

Doğrulamanın kanıtlaMADIKLARI:

Kanıtlanamayan Neden
Yazarlık sender_label dekoratiftir. sig_alg0x01 olmadan, bu içeriği herhangi biri mühürlemiş olabilir.
Niyet qub içeriği ve zamanlamayı kanıtlar, yaratıcının öznel olarak ne demek istediğini değil.
Olay öncesi zamanlama Depolama blok dahil edilmesi gerçek yüklemeden dakikalarca gecikebilir. Taahhüt zaman damgası blok zamanıdır, kullanıcının "mühürle"ye bastığı an değildir.

12. Sürümleme

12.1 Protokol sürümü

Hem SealedQub hem de QubEnvelope içindeki version alanı (u8), birincil protokol sürümünü tanımlar.

12.2 Sürüm geçmişi

Sürüm Değer Açıklama
v1 0x01 Kamu metin qub'ları (content_type 0x01), pakt ikili anlaşmaları (0x03, structured/v1 şeması, ML-DSA-65 yazar + birlikte imzalayan), tlock, SHA3-256

12.3 İleriye dönük uyumluluk

Bilinmeyen CBOR harita anahtarlarına (§3.2 kanonik sırasında olmayan anahtarlar) sahip bir QubEnvelope ile karşılaşan bir v1 izleyicisi, onu bir kod çözme hatası ile reddetmek ZORUNDADIR (§3.1). İleriye dönük uyumluluk version alanına dayanır, anahtar toleransına değil: gelecekteki eklemeler — küçük meta veriler bile — yeni bir version değeri altında yayımlanır ve bir v1 izleyicisi bunu, imzaların taahhüt ettiği içeriği sessizce düşürmek yerine açık bir "daha yeni protokol" hatasıyla reddeder.

sig_alg = 0x01 (ML-DSA-65) ile karşılaşan ancak ML-DSA-65 doğrulama desteğinden yoksun bir v1 izleyicisi, qub'u tamamen reddetmek yerine "imza mevcut ancak doğrulanamaz" notu ile qub içeriğini görüntülemelidir (SHOULD). Bugünkü referans uygulama, 0x00 ve 0x01 dışındaki her sig_alg değerini reddeder çünkü v1 kayıt defterinde başka geçerli algoritma yoktur — üçüncü bir algoritma kaydedilene kadar katı reddetme ve yumuşak hata gözlemsel olarak aynıdır. Yukarıdaki yumuşak hata davranışı, §9.2 yeni bir giriş kabul ettikten sonra yük taşır hale gelir ve referans izleyici o noktada yumuşak hataya güncellenecektir.

12.4 Dış sarmalayıcı sürümü

§13'te açıklanan OuterWrapper, SealedQub.version ve QubEnvelope.version'dan bağımsız olarak kendi version baytını taşır. İki sürüm alanı ayrı ayrı evrimleşir: gelecekteki post-kuantum-güvenli bir simetrik değiştirme, iç protokol sürümüne dokunmadan sarmalayıcı baytını yükseltir ve gelecekteki bir protokol katmanı eklemesi (örneğin yeni bir zarf alanı), sarmalayıcı baytına dokunmadan iç sürümü yükseltir.

OUTER_WRAPPER_VERSION_* Değer Algoritma Durum
OUTER_WRAPPER_VERSION_1 0x01 12-baytlık nonce, 16-baytlık kimlik doğrulama etiketi, qub_id'ye bağlı AAD ile AES-256-GCM v1 varsayılan
0x020xFF Ayrılmış Gelecek

İzleyiciler bilinmeyen sarmalayıcı sürümlerini açık bir hata ile reddetmek ZORUNDADIR. Protokol, somut bir geçiş itici gücü ortaya çıkana kadar (örneğin farklı bir AEAD'yi destekleyen NIST kılavuzu) sarmalayıcı sürüm alanını kasıtlı olarak dar tutar; bir 0x02 yuvası, algoritmayı tanıtan aynı revizyonda tahsis edilecektir.


13. Dış şifreleme sarmalayıcısı

13.1 Gerekçe

Protokol katmanları (QubEnvelope → tlock → SealedQub) mühürlü bir qub'u zamana kilitli yapar: gövde unlock_at'a ve drand tur imzası yayınlanana kadar okunamaz. Ancak açılmadan sonra, tur imzası kamuya açıktır ve SealedQub'un kanonik CBOR şekli tanınabilirdir, bu nedenle kalıcı depolama işlemlerini indeksleyen bir hasatçı, tüm qub corpus'unu toplu olarak şifresini çözebilir.

Dış şifreleme sarmalayıcısı, kanonik SealedQubCbor ile kalıcı depolamaya yazılan baytlar arasına ek bir simetrik AEAD katmanı yerleştirerek bu kanalı kapatır. 256-bitlik anahtar K, yalnızca teslim URL'sinin URL parçasında ve kullanıcı cihazlarında bulunur; tarayıcılar URL parçalarını sunuculara iletmez, bu nedenle qub.social, her depolama ağ geçidi ve her ikisinin önündeki her CDN, K'ye gözlemsel olarak kördür. Bu nedenle kalıcı depolamadaki her qub, düz metni yaratıcının paylaşmayı seçtiği URL olmadan kurtarılamayan opak bir şifreli metindir.

Net etki:

13.2 Katmanlama

plaintext body                       ← QubEnvelope.body (§2.2)
  ↓ canonical CBOR (§3)
envelope CBOR
  ↓ tlock encrypt to drand round (§7 step 10)
tlock_ciphertext (inside SealedQub) (§2.3)
  ↓ canonical CBOR (§3)
SealedQubCbor bytes                  ← inner wire artifact
  ↓ AES-256-GCM(K, nonce, AAD=qub_id) (§7 step 12a, this section)
OuterWrapper CBOR bytes              ← uploaded to permanent storage (§7 step 15)

Protokol katmanındaki mühürleme ve açma (§7, §8) sarmalayıcı sınırının altında değişmez; sarmalayıcı seal()'ın çağrı yerinde takılır ve unlock()'ın çağrı yerinde çıkarılır.

13.3 OuterWrapper veri yapısı

struct OuterWrapper {
    version:    u8,           // 0x01, see §12.4
    qub_id:     [u8; 32],     // copied from inner SealedQub; AEAD AAD
    nonce:      [u8; 12],     // 96-bit AEAD nonce
    ciphertext: Vec<u8>,      // AES-256-GCM(K, nonce, SealedQubCbor, AAD=qub_id) || 16-byte tag
}

Alan değişmezleri.

CBOR kodlaması. §3 uyarınca kanonik CBOR, aynı anahtar sıralama kuralıyla (artan kodlanmış bayt uzunluğuna göre sıralı, sonra sözlüksel olarak). Dört anahtar şudur:

Anahtar Kodlanmış baytlar Sıra
nonce 6 1
qub_id 7 2
version 8 3
ciphertext 11 4

Bu nedenle OuterWrapper CBOR'unun ilk baytı, 4-girişli bir harita için kesin uzunluklu harita başlığıdır (0xA4).

13.4 qub_id'ye AAD bağlama

Sarmalayıcı, qub_id'yi AEAD ek kimliği doğrulanmış veri olarak bağlar. Bu, üç sınıf saldırıya karşı yük taşıyan yapısal savunmadır:

Saldırı Savunma
Şifreli metni sarmalayıcıdaki farklı bir qub_id alanı altında taşımak AAD uyuşmazlığı → AEAD kimlik doğrulaması başarısız olur
qub A'nın URL parçasını qub B'nin depolama baytları ile karıştırmak AAD uyuşmazlığı → AEAD kimlik doğrulaması başarısız olur
Yüklemeden sonra sarmalayıcının qub_id alanını kurcalamak AAD uyuşmazlığı → AEAD kimlik doğrulaması başarısız olur

qub_id'yi sarmalayıcı düz metninde taşımak, numaralandırma bağışıklığını anlamlı ölçüde zayıflatmaz — qub_id'nin kendisi §4.1 ön görüntüsünün özetten kurtarılamayan ön görüntüsüz bir SHA3-256 özetidir ve sarmalayıcı baytlarını zaten toplayan bir numaralandırıcı, görünür qub_id'den yüklemenin varlığından çıkarabileceğinden daha fazla bir şey öğrenmez.

13.5 Sarmalama ve sarmalama açma algoritmaları

wrap_sealed_qub(SealedQubCbor S, qub_id Q, key K, nonce N):
    require K.len() == 32 and N.len() == 12 and Q.len() == 32
    C := AES_256_GCM_encrypt(key=K, nonce=N, msg=S, aad=Q)
    // C includes the 16-byte authentication tag at the end
    return canonical_cbor_encode(OuterWrapper{
        version:    0x01,
        qub_id:     Q,
        nonce:      N,
        ciphertext: C,
    })

unwrap_sealed_qub(OuterWrapper bytes W, key K):
    require K.len() == 32
    O := canonical_cbor_decode(W) as OuterWrapper
    require O.version == 0x01           // §12.4
    P := AES_256_GCM_decrypt(
            key=K, nonce=O.nonce, ciphertext=O.ciphertext, aad=O.qub_id
         )
    // any AEAD failure → DECRYPT_FAILED, indistinguishable to caller
    return P                            // P is the inner SealedQubCbor

Hata modu çöküşü. Yanlış K, yanlış nonce, AAD uyuşmazlığı ve kurcalanmış şifreli metin, hepsi aynı DECRYPT_FAILED hatasını üretir. Bu, kasıtlı bir AEAD özelliğidir: hata modunu ayırt etmek, uzaktan bir saldırganın hatalı biçimlendirilmiş sarmalayıcılar göndererek ve yanıtı zamanlayarak araştırabileceği bir yan kanal oluşturur. Referans uygulamalar tüm AEAD hatalarını tek bir hata şekline daraltmak ZORUNDADIR.

13.6 Anahtar materyali ve dağıtım

Sarmalama anahtarı K, bir CSPRNG tarafından qub başına üretilen 256-bitlik tek tip rastgele bir değerdir. Referans uygulamalar bunu şuradan alır:

Dağıtım: K, URL-güvenli base64 (RFC 4648 §5, dolgu yok) olarak kodlanmak ve teslim URL'sine parça bileşeni olarak eklenmek ZORUNDADIR:

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

Parça, uyumlu bir tarayıcı tarafından hiçbir sunucuya iletilmez. Tam teslim URL'sini — parça dahil — kullanıcının cihazının ötesinde kalıcı kılan kurtarma kanalları (sunucu tarafı geçmiş dizini, opt-in e-posta otomatik gönderme), varsayılan kripto-parçalama duruşuna karşı açık bir takastır ve açık kullanıcı onayına kapılı olmak ZORUNDADIR.

Parça kaybı. Bir kullanıcı URL parçasını kaybeder ve kurtarma kanalı yoksa, qub okunamaz. Bu, tasarımın yük taşıyan takasıdır ve mühürleme anında kullanıcıya açıklanmak ZORUNDADIR. MVP, mühürleme anı açıklamasını açık "bu URL'yi kaydedin" metni ve opt-in yapan kullanıcılar için doğrulanmış-e-posta kurtarma kanalı ile güçlendirir.

13.7 Bu bölümün kapsamı dışında

13.8 Kamu qub'ları (sarmalayıcı atlanması)

Dış sarmalayıcı, teslim katmanında isteğe bağlıdır. Bir yaratıcı bir qub'u kamu olarak mühürleyebilir; bu durumda kanonik SealedQubCbor, OuterWrapper katmanı ve K anahtarı olmadan kalıcı depolamaya doğrudan yazılır:

SealedQubCbor bytes  ──(public)──▶  uploaded to permanent storage as-is
SealedQubCbor bytes  ──(private)─▶  AES-256-GCM(K, …) ▶ OuterWrapper ▶ uploaded

Bir kamu qub'u zamana kilitlidir ancak bağlantı kontrollü değildir: drand turu yayınlanana kadar okunamaz durumda kalır (tlock katmanı değişmez), ancak açılmadan sonra arweave_tx_id'ye sahip olan herkes onun şifresini çözebilir — hiçbir URL parçası gerekmez, çünkü bir K yoktur. Bu, sunucunun yürütmesi gereken yüzeyler için kasıtlı bir takastır: açılma bildirimi e-postaları, üçüncü taraf gömme öğeleri ve daha zengin açılma sonrası SEO'nun tümü, sunucunun asla elinde tutmadığı bir gizli değer olmadan çalışan bir bağlantıya ihtiyaç duyar (§13.6).

Bir üreticinin hesaba katmak ZORUNDA olduğu sonuçlar:

Özel (sarmalanmış) varsayılan olarak kalır; kamu, açık bir qub-başına yaratıcı seçimidir.


14. Test vektörleri

14.1 qub_id türetmesi

Input:
  version      = 0x01
  content_type = 0x01
  created_at   = 1735689600 (2025-01-01 00:00:00 UTC)
  unlock_at    = 1736294400 (2025-01-08 00:00:00 UTC)
  outcome_at   = absent
  drand_round  = 4695445  (= (1736294400 - 1595431050) / 30, drand mainnet params §14.2)
  body         = "Hello, future."  (UTF-8, 14 bytes)
  title        = absent

Intermediate:
  body_hash  = SHA3-256("Hello, future.")
             = 76ab8b3f843c6ed4f2d0fd75b9f457b4
               ad49dd4450f9c22723ae430e3af3211d
  title_hash = [0u8; 32]   (title absent — §4.2.1 sentinel)

Domain separator (10 bytes):
  [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00]

Preimage (108 bytes — V1.2):
  domain_separator   ||  // 10 bytes
  0x01               ||  // version
  0x01               ||  // content_type
  0x0000000067748580 ||  // created_at as i64 big-endian (1735689600)
  0x00000000677DC000 ||  // unlock_at as i64 big-endian (1736294400)
  0x0000000000000000 ||  // outcome_at_or_zero (outcome_at absent)
  0x000000000047A595 ||  // drand_round as u64 big-endian (4695445)
  body_hash          ||  // 32 bytes
  title_hash             // 32 bytes (all-zeros sentinel; title absent)

Expected output:
  qub_id = SHA3-256(preimage)
         = 3a9fcb31b750d985c262fada6d4f777f
           d6a28be831d941d85c131f5a4bbaf8a4

Uygulamalar bu girdi için aynı body_hash ve qub_id değerlerini üretmek ZORUNDADIR. Bu test vektörü yazılan ilk birim testi olmalıdır (SHOULD). Yukarıdaki kanonik değerler referans uygulama tarafından hesaplanmıştır ve bit-bit eşleşmek ZORUNDADIR. Tarihsel ön görüntü düzenleri (lansman öncesi — bu değerlere bağlı canlı qub yoktu): 92 baytlık V1.0 qub_id şuydu: 3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0; 100 baytlık V1.1 qub_id (outcome_at_or_zero katlandıktan sonra) şuydu: b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed. V1.2, drand_round'u katlar ve etki alanı ayırıcısını QUB_ID_V2'ye yükseltir.

14.2 Açılma turu eşleştirmesi

Input:
  unlock_at           = 1735689600
  chain_genesis_time  = 1595431050
  chain_period_seconds = 30

Calculation:
  (1735689600 - 1595431050) / 30 = 4675285.0
  ceil(4675285.0) = 4675285

drand_round = 4675285

14.3 Kanonik CBOR gidiş-dönüşü

Uygulamalar, tüm geçerli girdiler için serialize(parse(serialize(qub))) == serialize(qub) olduğunu doğrulamak ZORUNDADIR. Bu tek bir vektör değil, bir özellik testidir.

14.4 PactTerms CBOR (content_type 0x03)

Input:
  pact_version = 1
  title        = "Scooter deposit"
  terms        = [
    { key: "Item",    value: "Honda Metropolitan scooter" },
    { key: "Price",   value: "$100" },
    { key: "Deposit", value: "$10" }
  ]
  party_a      = { label: "Alice" }
  party_b      = { label: "Bob", contact: "bob@example.com" }
  notes        = absent

Canonical CBOR key order (PactTerms):
  "notes"(6) < "terms"(6) < "title"(6) < "party_a"(8) < "party_b"(8) < "pact_version"(13)

Canonical CBOR key order (PactTerm):
  "key"(4) < "value"(6)

Canonical CBOR key order (PartyIdentifier):
  "label"(6) < "contact"(8)

Kanonik CBOR baytları ve SHA3-256 body_hash, referans uygulama tarafından hesaplanır. Uygulamalar bu girdi için bayt-aynı CBOR üretmek ZORUNDADIR.

Uygulamalar ayrıca, tüm geçerli PactTerms girdileri için serialize(parse(serialize(pact))) == serialize(pact) olduğunu doğrulamak ZORUNDADIR (özellik testi).

14.5 Dış sarmalayıcı diller arası vektörler

Dış sarmalayıcı (§13), crates/qub-core/tests/vectors/wrapper_v1.json konumunda ayrı bir kanonik fikstüre sahiptir. Her vaka, opak onaltılık girdiler olarak bir (key, nonce, qub_id, sealed_cbor) demetini sabitler ve belirli bir expected_wrapper_hex çıktısını onaylar. Her iki referans uygulama da aynı JSON dosyasını tüketir:

Fikstür şu anda üç vakayı sabitler:

Vaka Kapsam
basic-text-public En küçük gerçekçi SealedQub şekli; isteğe bağlı alan yok. v1.0-tipik bir qub için kanonik sarmalayıcı şeklini kurar.
with-recipient-pubkey recipient_pubkey ayarlı SealedQub (Faz 2 yolu). Farklı iç CBOR anahtar seti, farklı qub_id.
longer-body ~4 KiB gövde — hem iç zarfta hem de dış şifreli metinde çok baytlı CBOR uzunluk öneklerini sınar.

Uygulamalar, kaydedilen girdiler için bayt-aynı expected_wrapper_hex üretmek ZORUNDADIR. Fikstürü yeniden oluşturmak QUB_REGEN_VECTORS=1 cargo test -p qub-core --test wrapper_vectors gerektirir ve kasıtlı biçim değişiklikleri için ayrılmıştır.


15. Kripto profil yönetişimi (Gelecek)

Bu bölüm v1 için bilgilendiricidir ve qub'un kriptografik ilkellerinden herhangi birine ikinci bir algoritma girdiği ilk anda normatif hale gelir.

15.1 Mevcut duruş

Protokol v1, ilkel başına tam olarak bir algoritmaya bağlanır:

Doğrulayıcılar şu anda ilkel başına anahtar ve imza uzunluklarını sabit kodlar. Aktarım biçimi tarafından çeviklik yüzeyi sunulmaz.

15.2 Hedeflenen şekil

Protokole ikinci bir algoritma girdiğinde, doğrulayıcı, ilkel başına izin verilen değerlerin tam setini — sig_alg'ler, drand zincirleri, sarmalayıcı sürümleri, içerik türleri — listeleyen adlandırılmış bir CryptoProfile (örneğin ExqubV1) için yapılandırılacaktır. Profil doğrulama zamanında sabitlenir, asla bant içinde müzakere edilmez. Aktif profilin dışındaki herhangi bir değer reddedilir.

Bu, ML-DSA-87 eklemenin veya Ed25519'u etkinleştirmenin mevcut doğrulayıcı yapılandırmalarını geriye dönük olarak zayıflatamamasını garanti eder: bir v1 doğrulayıcısı, bir v2 profili yayınlandıktan sonra bile bir v1 doğrulayıcısı olarak kalır.

15.3 Tetikleyici koşullar

§15'i şunlardan herhangi biri önerildiğinde normatif duruma yükseltin:

O zamana kadar §15, gelecekteki PR'ların müzakere yüzeyini sıfırdan yeniden tartışmak yerine bilinen bir hedefe karşı inmesi için geçiş şeklini sabitleyen bir yer tutucudur.


16. Şeffaflık günlüğü ve dayanıklılık katmanları (Tasarım — inceleme tamamlandı)

Durum. Bu bölüm bir tasarım belirtimidir. Aşağıdaki kablo biçimleri, özetleme ve güven modeli uygulama açısından normatiftir, ancak henüz hiçbir şeffaflık günlüğü kodu yayınlanmamıştır. W5 dış incelemesi tamamlandı: §16.15, çözülen kararları ve incelemeden çıkan bağlayıcı lansman kısıtlarını kaydeder. Uygulama bu kısıtlar altında ilerleyebilir. §16, §15 ile aynı anlamda ileriye dönük kalır — uygulamanın güven modelini kod incelemesinde yeniden türetmek yerine yerleşmiş bir tasarıma karşı inmesi için hedefi sabitler. Kesinlikle eklemelidir — mevcut her qub kendi bireysel Arweave işlemini korur ve SealedQub / QubEnvelope kablo biçiminde hiçbir değişiklik yoktur.

16.1 Gerekçe ve dayanıklılık katmanları

Bugün bir qub'un dayanıklılığı ve zamansal taahhüdü, her ikisi de tek bir qub-başına Arweave işlemine dayanır (§11). Bu, mühürleme gecikmesini Arweave kesinliğine bağlar, qub-başına yüklemeyi bir ürün maliyet tavanı yapar (ARWEAVE_DAILY_CEILING) ve qub'lar arasında kurcalamaya karşı kanıt sunan bir sıralama sağlamaz. Şeffaflık günlüğü, bu tek katmanın altına ve etrafına iki katman ekler:

Katman Ad Garanti Ne zaman
T1 R2-öncelikli senkron onay Dayanıklılık tabanı — mühürlenmiş baytlar, mühürleme dönmeden önce dayanıklı depolamaya yazılır (< 300 ms p95). Her qub, senkron olarak (§16.10).
T2 Toplu şeffaflık günlüğü dahil edilmesi Evrensel ekleme-yalnızca, kurcalamaya karşı kanıt sunan taahhüt + toplam sıralama, Arweave'e demirlenmiş. Her qub, ertelenmiş + toplu (§16.5–16.7).
T3 qub-başına Arweave kalıcılığı qub için bireysel bir Arweave işlemi. Ücretli ek satış ve Arweave-erişilemezlik yedeği (§16.8).

T2, qub-başına Arweave'i tek dayanıklılık yolu yerine bir seçim (T3) yapar. ARWEAVE_DAILY_CEILING, bir ürün tavanı olmaktan çıkarılır ve yalnızca özel demir cüzdanı üzerinde bir devre kesiciye indirgenir (§16.7); kullanıcı mühürlemeleri bunu aştığı için asla reddedilmez.

Dayanıklılık dürüstlüğü (çözüldü — §16.15 Q6). Dayanıklılık gerilemez: T1 R2 yazması senkron ve tek-yazımlıktır, bu nedenle T3 satın almamış ücretsiz katman bir qub'u, mühürleme döndüğü anda tamamen dayanıklıdır. Kabalaşan şey, kanıtlanabilir üst sınır taahhüt zamanıdır: ücretsiz bir qub için bu, qub-başına işlem blok zamanı yerine demir blok zamanı olur. Düşük hacimde — gerçekçi erken-lansman ve yoğun olmayan durum — tam günlük tempo, nadir bir uç durum değil, tipik tabandır. Bu nedenle ürün çerçevelemesi, taahhüt edilmiş hiçbir sayısal gecikme olmadan bir üst sınırdır — "şimdi mühürlü ve dayanıklı; bir sonraki günlük demirinde bağımsız bir kamu zaman damgası eklenir (tipik olarak günlük)" — ve tam-saat taahhüt kanıtı, ücretli bir T3 özelliğidir, katman-karşılaştırma yüzeyinde ve koşullarda açıklanır (§16.11, §16.15 Q6). Herhangi bir zaman sınırı yalnızca dahili bir SLO'dur, asla pazarlanan bir SLA değildir.

16.2 LogLeaf yapısı (iki taahhüt edilmiş şekil)

Bir günlük girdisi, §3.1 profili altında elle yazılmış kanonik CBOR olarak kodlanan bir LogLeaf'tir (kesin uzunluklu, etiket yok, kayan nokta yok, en kısa biçimli tamsayılar, NFC metin, yoksa atlanan isteğe bağlı alanlar, anahtarlar artan kodlanmış-bayt uzunluğuna sonra bayt-bazında sıralı). §3.1 ayrıştır → yeniden kodla → karşılaştır kanonik koruması, özetlemeden önce kodlama yolunda uygulanır (yalnızca kod çözmede değil), bu nedenle iki uygulama bir tamsayı-genişliği veya anahtar-sırası farkı yoluyla yaprak baytları üzerinde anlaşmazlığa düşemez. Tüm tamsayılar u8 / u64 / i64'tür; tüm özetler 32-baytlık bayt dizgeleridir (bstr[32]). Depolanan bir Arweave işlem kimliği, asla bir base64url metin dizgesi olarak değil, bstr[32] olarak taşınan ham 32-baytlık bir SHA-256 özetidir (§3.3 ile eşleşir).

Yaprağın bir kind baytı ile seçilen iki şekli vardır, çünkü varsayılan yükleme yolunda Worker bayta kördür: POST /api/v1/upload yalnızca qub_id ve unlock_atgüvenilmeyen istemci iddiaları olarak alır — body_hash, drand_round, created_at ve drand_chain_version'ın tümü, Worker'ın anahtarını asla tutmadığı §13 dış sarmalayıcısı içinde mühürlüdür. Yalnızca sunucu-mühürleme yolu (POST /api/v1/seal), body_hash / drand_round'u düz metinden türetir. Bu nedenle body_hash + drand_round taşıyan tek bir yaprak şekli, gerçek qub'ların çoğunluğu için operatörün asla doğrulamadığı değerleri taahhüt ederdi. Bu bölünme, taahhüt edilen her değeri dürüst tutar:

Anahtar Kod. uzunluğu Tür Bulunuş Anlam
seq 4 u64 gerekli Genel 0-tabanlı yaprak indeksi; dahil edilme kanıtının taahhüt ettiği konum.
kind 5 u8 gerekli 0x01 onaylı (sunucu-mühürleme) veya 0x02 iddia edilen (istemci-mühürleme / bayta kör yükleme).
ref 4 bstr[32] gerekli Yaprak referans kimliği. Onaylı → ham qub_id. İddia edilen → körleştirilmiş kimlik SHA3-256(qub_id ‖ log_blind_secret) (§16.2.1).
chash 6 bstr[32] gerekli İçerik adresi SHA3-256(stored_bytes) — Worker'ın her iki yolda da her zaman dürüstçe hesaplayabileceği tek içerik bağı.
unlock_at 10 i64 gerekli Kopyalanmış (onaylı) veya iddia edilen (iddia edilen); yaprağa girmeden önce > 0 doğrulanır.
received_at 12 i64 gerekli R2-onayında Worker duvar saati. Kanıt değeri taşımaz (operatör-iddiası; §16.6). Kendini tanımlama için vardır, asla bir kanıt değildir. > 0 doğrulanır.
body_hash 10 bstr[32] yalnızca kind=0x01 0x02'de atlanır — Worker §13 altında ona sahip değildir.
drand_round 12 u64 yalnızca kind=0x01 0x02'de atlanır.

Bir kind=0x02 yaprağı, kasıtlı olarak ne body_hash ne de drand_round taahhüt eder: qub_id ve unlock_at iddia eden, içerik-adresi chash'teki opak bir şifreli metnin taahhüdünü ve sıralamasını onaylar — düz metnini veya turunu değil. İddia edilen bir qub için düz metin/tur ayakları, günlükten değil, mevcut §11 .qub-paket doğrulamasından gelir (§16.11). drand_chain_version yaprakta değildir (varsayılan yolda sarmalayıcının içindedir); zincir ayrıntısı demirde bulunur (§16.7). Kodlayıcı disiplini: tümü-sıfır bir ref veya chash'i reddedin ve cbor.rs'deki outcome_at > 0 sentinel korumasını yansıtarak, pozitif olmayan unlock_at / received_at'ı reddedin.

16.2.1 Özel-qub körleştirmesi

Günlük, §13 dış sarmalayıcısının önlemek için var olduğu numaralandırma kâhini haline gelmemelidir (§13.1). Özel (sarmalanmış) bir qub için asserted yaprağı, log_blind_secret'in sunucu-tutulan bir gizli olduğu körleştirilmiş tanımlayıcı SHA3-256(qub_id ‖ log_blind_secret)'i taahhüt eder ve body_hash'i atlar. Üçüncü bir taraf böyle bir yaprağı belirli bir qub_id'ye bağlayamaz; teslim URL'sine ve dolayısıyla qub_id'ye sahip olan qub'un sahibi, kendi dahil edilmesini doğrulamak için körleştirmeyi yeniden hesaplayabilir. Kamu bir qub (zaten numaralandırılabilir, §13.8 uyarınca Visibility: public Arweave etiketini zaten taşıyan), ham qub_id'yi taahhüt eder. Bu, bağımsız doğrulanabilirliğin yük taşıyan bir gizlilik değişmezine kasıtlı olarak boyun eğdiği tek yerdir; özel qub'lar için bağımsız bağ chash'tir (§16.9).

log_blind_secret muhafazası (çözüldü — §16.15 Q4). Körleştirme, düz metin gizliliğini değil, yaprak bağlanamazlığını korur (§13 sarmalayıcısı bunu bağımsız olarak tutar). Bir log_blind_secret ele geçirildiğinde, saldırganın zaten elinde tuttuğu veya yeniden inşa edebileceği herhangi bir qub_id için (paketine/URL'sine sahip olduğu her qub, artı düşük-entropili veya kamu herhangi bir qub_id) yaprak ref'ini tek bir özette yeniden hesaplar ve onu bağlar — bu, bilinmeyen bir uzay üzerinde kaba kuvvet değil, bilinen bir popülasyonun doğrudan bağlanmasıdır. log_blind_secret'i diğer sunucu gizlileriyle aynı muhafaza katmanında bir korelasyon/Sybil-derecesi gizli olarak sınıflandırın ve yalnızca ileriye dönük döndürün (bir döndürme, gelecekteki yaprakları yeniden körleştirir; zaten demirlenmiş olanları geriye dönük olarak ayıramaz).

16.3 Yaprak ve düğüm özetlemesi

RFC 6962 §2.1 etki-alanı-ayrılmış özetleme, SHA-256 yerine SHA3-256 ile:

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

Etki-alanı önek baytları 0x02 (girdi zinciri, §16.4) ve 0x03 (STH özeti, §16.6) ayrılmıştır ve bunlardan ayrıktır. Bunlar tek baytlardır ve bu nedenle mevcut 10-baytlık ASCII etki-alanı ayırıcılarıyla (QUB_ID_V2, vb.) çakışamazlar. Ağaç, RFC 6962 sol-dolu dengesiz ağaçtır (her iç bölünme, alt-ağaç yaprak sayısından kesinlikle küçük en büyük ikinin kuvvetinde), bu da dahil edilme ve tutarlılık kanıtlarının tek bir denetim-yolu algoritmasını paylaşmasını sağlar. Referans belirtimi, açık sol/sağ türetme sözde kodunu taşır ve sağ-kenar terfi durumunu — ki bunu 4-yapraklı bir vektör gizler — uygulayan bir ikinin-kuvveti-olmayan (5-yapraklı) test vektörü sabitler.

16.4 Özet zincirleme (dahili)

LogDO, yalnızca çökme tutarlılığı için bir dahili girdi zinciri tutar. Bu asla yayınlanmaz ve asla doğrulayıcıya dönük değildir:

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

Yayınlanan ekleme-yalnızca otorite, operatörün yaprakları sunmaya denk geldiği ham sıra değil, kümülatif Merkle kökü + demiridir (§16.5–16.6): zincir, sunulan herhangi bir sıra için yeniden hesaplanır, bu nedenle yalnızca demirlenmiş kök kanonik konumu sabitler.

16.5 Kümülatif Merkle ağacı ve toplama

İzole edilmiş toplama-başına ağaçlar değil, tüm yapraklar üzerinde seq sırasıyla sürekli büyüyen tek bir RFC 6962 ağacı vardır. (Taşıma-yaprağı-zincirli bir toplama-başına inşa reddedildi: bu gerçek bir önek ilişkisi değildir, bu yüzden "tutarlılık kanıtları" sağlam değildir.) Kümülatif ağaç, gerçek RFC 9162 tutarlılık kanıtları verir ve tek bir yakın demirin herhangi bir eski qub için dahil edilmeyi kanıtlamasını sağlar.

LogDO Durable Object tek yazıcıdır (blockConcurrencyWhile, QuotaDO / EntitlementDO'yu yansıtır) — paylaşılan bir günlüğe ekleme, paylaşılan durum üzerinde oku-değiştir-yaz'dır ve bu nedenle asla KV değil, bir DO'dan geçmek ZORUNDADIR. Ağacın sağ-kenar sınırını (O(log n) özet) önbelleğe alır, böylece bir toplamayı kapatmak O(batch)'tir. Bir toplama, birlikte demirlenen yaprakların setidir; tetikleyicileri yapılandırılabilirdir, protokole sabitlenmemiştir: en az LOG_BATCH_MAX_LEAVES (varsayılan 4096) kadar bir tree_size ilerlemesi, ya da yaşın demirleme temposuna ulaşması, ya da ücretli bir T3 mühürlemesi indiğinde zorlanan bir boşaltma. root_i, 0 .. tree_size_i yaprakları üzerindeki kümülatif Merkle Ağaç Özetidir.

16.6 Arweave demiri aracılığıyla imzalı ağaç başlığı

Arweave demir işlemi, İmzalı Ağaç Başlığı'dır (Signed Tree Head) ve ağaç başlığının kendisi için bir operatör imzasının yerini alır: günlük demir, qub anahtarına ihtiyaç duymaz çünkü Arweave tx owner imzadır. Moat tezi geçerlidir — demirlenmiş kök için yük taşıyan, bir qub-tutulan gizli değil, değişmez alt yapıdır.

Tasarımda tam olarak bir sıcak qub imzalama anahtarı vardır ve sabitlenmiştir: mühürleme-başına makbuz anahtarı (§16.10). Açık anahtarı LogProfile'da (doğrulayıcı ile dağıtılır) taahhüt edilir ve anchor_owner tarafından çapraz-imzalanır, böylece bir doğrulayıcı bir makbuzu demirle aynı sabitlenmiş köke karşı doğrular. Bu, §16.15 Q2'nin çözümüdür — sabitlenmemiş, operatör-döndürülebilir bir makbuz anahtarı reddedilebilir olurdu (operatör anahtarın kendisine ait olduğunu inkâr edebilirdi), bu da makbuzun var olma amacı olan operatör-seviyesi düşmana karşı hesap verebilirlik değerini geçersiz kılardı. Yani: qub hiçbir sabitlenmemiş günlük-imzalama anahtarı tutmaz; makbuz anahtarı sabitlenmiş ve anchor_owner-çapraz-imzalanmıştır.

SignedTreeHead, kanonik CBOR'dur (anahtarlar kodlanmış uzunluğa göre): size:u64, root:bstr[32], batch:u64, prev:bstr[32] (önceki sth_hash; doğuş = 32 sıfır bayt), log_id:bstr[32], first_seq:u64, anchored_at:i64. Özeti sth_hash = SHA3-256(0x03 || canonical_cbor(SignedTreeHead))'tür.

Sabitlenmiş güven kökü. log_id = SHA3-256("QUB_TLOG_V1" || anchor_owner_address). Uyumlu bir doğrulayıcı, anchor_tx.owner == LogProfile.anchor_owner'ı gerektirmek ZORUNDADIR; burada anchor_owner (ve makbuz-anahtarı açık anahtarı), DrandTimelockProvider::quicknet()'te zaten bulunan quicknet sabitlerinin yanında LogProfile olarak qub_core'a yerleştirilir ve doğrulayıcı ikilisiyle dağıtılır. Doğrulayıcı ayrıca, bir ağ geçidi /raw/ yanıtına güvenmek yerine Arweave tx veri → tx_id bağlamasını yerel olarak doğrulamak ZORUNDADIR. Bu, sahte-cüzdan eşitsizlik (equivocation) açığını kapatır: doğrulayıcı hangi cüzdanı sabitlediğine kadar "Arweave'e demirlenmiş" anlamsızdır.

Döndürme, bir reuse değil, bir §15 yönetişim uzantısıdır (çözüldü — §16.15 Q3). §15.2'nin profil yüzeyi şu anda yalnızca sig_alg'ler / drand zincirleri / sarmalayıcı sürümleri / içerik türlerini sıralar ve §15.3'ün tetikleyicileri bunların hiçbirini listelemez — LogProfile / anchor_owner henüz §15'in yüzeyinde değildir. Bu nedenle döndürme yönetişimi inşa edilmelidir: §15.3 (aşağıda) LogProfile tetikleyicisini ekleyecek şekilde genişletilir ve bir döndürme, bir doğrulayıcı güncellemesinde sevk edilen imzalı bir LogProfile yükseltmesidir. Planlı bir döndürme, giden → gelen çapraz-imza taşır; ele geçirme-kaynaklı bir döndürme bunu yapamaz (giden anahtar tam o anda güvenilmez/erişilemezdir) ve önceki-demir çatallanma kontrolünün (aşağıda) ara dönemde hasarı sınırladığı §15-yönetimli yükseltmeye geri döner.

Eşitsizlik penceresi (birinci-sınıf güven parametresi). Bir yaprak, yalnızca onu kapsayan demiri Arweave-onaylandığında eşitsizliğe dirençlidir. Pencere received_at → demir onayı'dır (≤ tempo + Arweave kesinliği). İçinde tek garantiler, sabitlenmiş mühürleme makbuzu (§16.10) ve qub'un operasyonel bütünlüğüdür. Üç hesap verebilirlik eseri bunu el sallamak yerine dürüst kılar (tanık modeli §16.15 Q2'nin çözümüdür):

  1. Sabitlenmiş imzalı mühürleme makbuzu — yükleme yanıtında döndürülen SCT analoğu (§16.10), sabitlenmiş, anchor_owner-çapraz-imzalanmış makbuz anahtarıyla imzalanır. Demirinden önce düşürülen bir yaprak, kurbana yayınlayacağı reddedilemez bir makbuz bırakır ve sessiz-atlama açığını kapatır.
  2. Yayınlanan izleme metodolojisi + önceki-zincir yürüyüşü — demir prev zinciri baştan→doğuşa yürünür; bir çatallanma (bir size'da farklı root ile iki demir, ya da bozuk bir prev) yayınlanabilir bir kötü davranış kanıtıdır. Eşitsizlik tespiti, sessiz bir varsayım değil, belirtilmiş bir operasyonel taahhüttür.
  3. Çift kendi-yayınlanan başlık — her yeni başlık {sth_hash, tree_size}, özel bir qub-sahipli kamu, ekleme-yalnızca GitHub deposuna gönderilir (yük taşıyan kurcalamaya-karşı-kanıt kendi-yayınlama ayağı), yalnızca en iyi-çaba teyidi olarak bir sosyal gönderiyle. Başarısız bir gönderim, sessiz başarısız olmak yerine sayfa açmak (page) ZORUNDADIR.

Dürüstlük sınırı (bağlayıcı kısıt). qub her iki gönderim yüzeyini de kontrol ettiğinden, bu bağımsız tanıklı değil, kendi-yayınlanmıştır. Hiçbir ürün, pazarlama veya yasal yüzey günlüğün "bağımsız tanıklı" olduğunu iddia edemez; izin verilen iddia, eşitsizliğin tespit edilebilir olduğu ve reddedilemez bir makbuz bıraktığıdır. Gerçek bir bağımsız üçüncü-taraf tanığı, gelecekteki bir §15 yönetişim yükseltmesine ertelenir.

received_at operatör-iddiasıdır ve hiçbir iddia ona dayanamaz — herhangi bir ürün / yasal / API / kanıt-sunma yüzeyinde asla kanıt veya anlaşmazlık teyidi olarak yüzeye çıkarılmaz. Arweave demir blok zamanı T, tek güvensiz zaman damgasıdır ("şu zamana kadar günlüğe alındı" üzerinde bir üst sınır). received_at üzerindeki herhangi bir izleme akıl-sağlığı kontrolü, operatör-kontrollü anchored_at STH alanına karşı değil, T'ye karşı karşılaştırmak ZORUNDADIR; böyle bir kontrol, yalnızca dürüst bir operatörün saat hatasına karşı bir korumadır, kötü niyetli bir operatöre karşı bir hesap verebilirlik kontrolü değildir (§16.15 Q5).

16.7 Demir işlemi biçimi ve tempo

AnchorBundle, §16.8 paketleyicisi aracılığıyla yazılan kanonik-CBOR Arweave işlem gövdesidir: ver:u8, sth:bstr (kanonik SignedTreeHead baytları), prev_anchor:bstr (önceki demir tx kimliği ham baytları; doğuşta atlanır), chain_hash:tstr (yürürlükteki drand zinciri — quicknet) ve demir kendi kendine yeterli olacak şekilde toplamanın yaprak-CBOR akışı seq sırasında: bir izleyici, root'u sıfır qub bağımlılığıyla gövdeden yeniden türetir. (Yaprak akışı yüksek hacimde büyürse, gelecekteki bir revizyon yalnızca bir yaprak aralığını referansla taahhüt edebilir; not edildi, v1'de benimsenmedi.)

Arweave etiketleri kasıtlı olarak numaralandırılabilirdir — özel qub'ların aksine, günlüğün bulunması amaçlanmıştır: App-Name: qub-tlog, Anchor-Format: 1, Log-Id: <hex>, Batch: <n>, Tree-Size: <n>, Root: <hex>, Prev-Anchor: <tx>, Content-Type: application/cbor. Etiketler güvenilmeyen ipuçlarıdır; CBOR gövdesi tek otoritedir.

Tempo: varsayılan olarak günlük, hacimle yeniden gözden geçirilir (boyut tetikleyicisi yük altında etkin tempoyu otomatik olarak kısaltır); ücretli bir T3 mühürlemesi bir demiri zorlar, böylece ödeme yapan müşteriler asla bir gün beklemez. Demir cüzdanı özel ve düşük-hızlıdır, yükleme cüzdanından ayrıdır — kendi JWK'si OLMALIDIR (yükleme cüzdanında mantıksal bir rol değil, ayrı bir anahtar), böylece bir yükleme-cüzdanı ele geçirilmesi demirler sahteleyemez — günde sert bir demir-işlem bütçesi ile (indirgenen ARWEAVE_DAILY_CEILING). Muhafaza duruşu açıkça belirtilir: "soğuk" değil, sıkı bir devre kesicisi ve düşük bakiyesi olan dar-kapsamlı bir sıcak anahtar — günlük otomatik imzalayan bir cüzdan soğuk olamaz ve belirtim aksini iddia etmez.

16.8 ANS-104 paketleyici

İçeride üretilmiş bir ANS-104 DataItem kodlayıcı ve derin-özet imzalayıcı, kabaca 300 satır, yalnızca Web Crypto, sıfır npm bağımlılığı (her iki Turbo SDK de npm ci --ignore-scripts tedarik-zinciri kapısında başarısız olur). DataItem bayt düzeni:

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

İmzalama, Arweave deepHash'tir — ["dataitem", "1", sig_type, owner, target, anchor, encoded_tags, data] üzerinde özyinelemeli bir SHA-384 özeti (Arweave'in kablo gereksinimi, crypto.subtle.digest("SHA-384")) — ardından cüzdan JWK'si ile crypto.subtle aracılığıyla derin özet üzerinde RSA-PSS; id = base64url(SHA-256(signature)). Buradaki SHA-384, bir qub güven ilkeli değil, yalnızca-Arweave-kablosu bir ilkel olarak karantinaya alınmıştır (§15 çiti kaydeder; qub güven özetlemesi baştan sona SHA3-256'dır).

Tek bir kod yolu üç tüketiciye hizmet eder: ücretli T3 qub-başına kalıcılık, Arweave-erişilemezlik yedeği (DataItem'ı kuyruğa al, ne olursa olsun R2-öncelikli onayı döndür — bu mevcut ARWEAVE_UNAVAILABLE 503 çıkmazını kapatır) ve AnchorBundle'ı yazma. İmza şeması (çözüldü — §16.15 Q8): v1, RSA-PSS (imza türü 1) ile imzalar, mevcut Arweave cüzdan JWK mekanizmasını yeniden kullanarak (sıfır yeni uzun-ömürlü anahtar muhafazası, "bir gizli daha az" tezine hizmet eder); Ed25519, §15 PK-geçiş yoluna ertelenir.

Elle yazılmış derin özet, W5'teki en yüksek-riskli, en düşük-doğal-kapsamlı koddur, bu nedenle kapılaması pazarlık konusu değildir (§16.15 Q8):

  1. Diller arası fikstür tlog_v1.json (Rust + TS, §14.5 wrapper_v1.json deseni), derin-özeti, DataItem baytlarını + kimliğini, yaprak özetlerini, bir 5-yapraklı kökü + denetim yolunu, bir STH özetini, bir dahil edilme kanıtını ve bir tutarlılık kanıtını — hem imzalama hem de doğrulama yönlerinde kapsar (doğrulama yönü önemlidir çünkü §16.6'nın yerel tx → tx_id kontrolü, derin özeti yalnızca yazıcıya değil, her bağımsız doğrulayıcıya çeker).
  2. Bir referans ANS-104 paketleyicisi aracılığıyla tek seferlik bir birlikte-çalışabilirlik gidiş-dönüşü, yalnızca statik test verisi olarak tüketilir — asla bir npm çalışma-zamanı bağımlılığı değil (yalnızca-Web-Crypto / kurulum-betiği-yok duruşu geçerlidir).
  3. Derin-özet + RSA-PSS yolu, üretimin kullandığı aynı crypto.subtle ilkelleri üzerinden gidiş-dönüş yapmalıdır, böylece içeride üretilmiş kodlayıcı bayt-uyumludur.
  4. Süregelen bir paket-sonrası kabul izleyicisi, her demir / yedek DataItem'ın gerçekten Arweave kabulüne ulaştığını bir alarm + devre kesici ile doğrular — çünkü derin özet, Arweave-erişilemezlik yedek kuyruğuna da hizmet eder, bu nedenle sessiz bir gerileme, var olduğu kesin kesinti sırasında o kuyruğu ağ-tarafından-reddedilen öğelerle doldurur.

16.9 Dahil edilme ve tutarlılık kanıtları

Her ikisi de RFC 9162, SHA3-256'dır, kanonik CBOR olarak sunulur.

InclusionProofGET /api/v1/qub/:tx_id/proof: ver:u8, leaf:bstr (tam yaprak CBOR — doğrulayıcı leaf_hash'i kendisi yeniden hesaplar ve asla sağlanan bir özete güvenmez), 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 }.

ConsistencyProofGET /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. Tek bir kesin anahtar listesi, test vektörü ile sabitlenmiş.

Bağımsız doğrulama (qub sunucusu yok, §11'i genişletir):

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

Kanıt-sunma depolaması koordinat-anahtarlı OLMALIDIR (çözüldü — §16.15 Q7, engelleyici önkoşul). Soğuk-yaprak kanıt üretimi, yalnızca R2 denetim materyali, toplama-başına düğüm deltaları değil, mutlak ağaç koordinatı (level, index) ile anahtarlanmış kalıcı bir Merkle-düğüm deposu ise doğruluk açısından nötrdür. Koordinat-anahtarlı bir depo ile, herhangi bir (leaf i, size N) denetim yolu, toplama sınırları arasında yeniden hesaplama olmaksızın O(log N) doğrudan R2 GET'lik bir settir; toplama-anahtarlı bir depo ile değildir, ki bu, bu çözümün kapattığı depolama-düzeni boşluğudur. Yaprak gövdeleri de aynı şekilde seq ile içerik-adreslenebilirdir. Bir W5 test vektörü, doğuş-dönemi bir soğuk yaprağı, LogDO depolaması silinmiş olarak yalnızca R2 + Arweave kullanarak çok-sonraki bir köke karşı kanıtlamak ZORUNDADIR, böylece §16.13'teki geri-kazanım-güvenliği iddiası iddia edilmek yerine desteklenir. O(log N) ardışık R2 GET'ler, yalnızca asenkron kanıt uç noktasına aittir — asla mühürleme sıcak yoluna (§16.10) veya tik-başına bir crona değil.

16.10 R2-öncelikli onay sıralaması

POST /api/v1/upload dizisi şöyle olur:

  1. Ön-yarı kapıları (kimlik doğrulama, doğrulama, eşsizlik (idempotency) parça anahtarı) — değişmedi.
  2. Senkron olarak await QUB_CACHE.put(qub-cache/<tx_id>, wrappedBytes) — dayanıklılık tabanı; ayrıca W1'in ön-önbellek yarışını kapatır (eskiden Arweave gönderimi sonrası bir ctx.waitUntil).
  3. Senkron olarak await LogDO.append(leaf) — bir colo-içi DO RPC'si; tek yazıcı seq atar, girdi zincirini genişletir ve sınırı günceller. (Paylaşılan durum üzerinde RMW → DO, asla KV değil.) append RPC'si yalnızca bunu yapar — O(batch) Merkle toplama-kapatma işi, bu RPC'nin dışında LogDO alarmında çalışır, yoksa append p95'i her LOG_BATCH_MAX_LEAVES'inci mühürlemede sıçrar.
  4. Onayı şimdi döndür — mühürleme makbuzu (sabitlenmiş makbuz anahtarıyla imzalı, §16.6) ve { tx_id, log_seq, anchor_status: "pending" } ile. Çok-saniyelik Arweave fan-out'u kritik yoldan kaldırılır.
  5. Tek bir ctx.waitUntil, ertelenen işi kuyruğa alır: qub-başına Arweave gönderimi (artık en iyi-çaba / ücretli; başarısızlıkta kullanıcıyı 503'lemek yerine paketleyici yedek kuyruğuna yönlendirir) artı mevcut geçici-meta yazmaları. Toplama kapatma ve demirleme, LogDO alarmından ve günlük demir cronundan bağımsız çalışır. Bir döngü içinde ctx.waitUntil yok; mevcut eşsizlik parça anahtarı korunur.

Gecikme bütçesi (çözüldü — §16.15 Q7). < 300 ms p95 hedefi bir varsayım değil, bir ölçülen lansman kapısıdır. Dürüst kritik yol, ön-yarı KV okumaları + bir R2 PUT + iki sıralı Durable Object'tir — mevcut QuotaDO mühürleme-kotası borçlandırması ve yeni LogDO eklemesi — bu nedenle bütçe, bir değil, iki colo-içi DO gidiş-dönüşünü hesaba katmak ZORUNDADIR. QuotaDO'nunkini yansıtan bir LogDO gecikme alarmı sevk edin ve bir p95 gerilemesini bir sürüm engelleyicisi olarak ele alın.

16.11 Güven modeli — yaprak türüne göre kapsamlanan kesin iddia

kind=0x01 (onaylı) için: "Bu içerik — body_hash'le eşleşen gövde, qub_id ile tanımlanan — seq konumunda qub'un ekleme-yalnızca günlüğüne taahhüt edildi ve en geç Arweave blok zamanı T'de var olmuştu; drand turu R = unlock_round(unlock_at)'a kadar kriptografik olarak okunamazdı." Bu, tam {tlock tur bağlama + Merkle dahil edilmesi + demirlenmiş kök} üçlüsüdür.

kind=0x02 (iddia edilen, varsayılan) için: "İçerik-adresi chash olan, qub_id ve unlock_at iddia eden opak bir şifreli metin, seq konumunda ekleme-yalnızca günlüğüne taahhüt edildi ve en geç Arweave blok zamanı T'de var olmuştu." Tur ve gövde ayakları, günlük tarafından değil, mevcut §11 .qub-paket doğrulaması (qub_core::unlock) tarafından sağlanır; günlüğün çıplak bir qub-başına işleme kattığı şey, kurcalamaya karşı kanıt sunan sıralama, güvensiz bir üst-sınır taahhüt zamanı ve eşitsizlik direncidir.

Her iki iddia da §11 uyarınca şunları hariç tutar: sig_alg ≥ 0x01 olmadan yazarlık, niyet ve demir-altı-ayrıntı zamanlama. İkisi de hiçbir iddianın received_at'a dayanmasına izin vermez.

İddia tavanı (bağlayıcı lansman kısıtı — çözüldü §16.15 Q1). Ücretsiz / varsayılan (kind=0x02) qub'lar için, yukarıdaki kapsamlanan kind=0x02 iddiası, herhangi bir ürün, pazarlama, koşul veya kanıt-sunma yüzeyinin öne sürebileceği şeyin tavanıdır. Hiçbir yüzey, günlüğün varsayılan bir qub'un içeriğini veya açılma turunu kanıtladığını belirtemez veya ima edemez — günlük, opak bir şifreli metnin sıralamasını + güvensiz bir üst-sınır taahhüt zamanını kanıtlar. İçerik ve tur kanıtı, yalnızca günlük-bağımsız olan mevcut §11 .qub-paket doğrulamasından gelir. Bu, stilistik bir tercih değil, kopya üzerinde sert bir lansman engelleyicisidir; bayta-kör varsayılan yolu dürüst tutan çözüm budur.

16.12 Sürümleme ve W3 koordinasyonu

Hiçbir SealedQub kablo yükseltmesi yoktur ve bu nedenle hiçbir protokol-sürümü yükseltmesi yoktur (§12.1): günlük, mevcut alanlara ve baytlara taahhüt eden bir yan dosyadır, bu nedenle §12.2 protokol-sürümü geçmişine girmez. W3'ün isteğe bağlı drand_chain_version'ı dokunulmamış kalır ve tek isteğe bağlı SealedQub alanı olarak kalır. Günlük bunun yerine kendi bağımsız sürüm uzaylarını tanıtır — LOG_VERSION_1, ANCHOR_FORMAT_1, InclusionProof.ver — §12.4 sarmalayıcı-sürüm bağımsızlığını yansıtarak (sarmalayıcı, protokol sürümünden bağımsız bir sürüm baytı taşır ve günlük sürümleri aynı ayrımı izler).

Kanıt teslimi varsayılan olarak çekilir, isteğe bağlı bir yanında-binme ile. Mühürleme anında bir kanıt var olamaz (demir henüz yazılmamıştır), bu nedenle mühürleme-anı .qub paketi kanıt-içermez kalır. W7'nin doğrulayıcısı GET …/proof'u bir kez çeker ya da tamamen-çevrimdışı modda kanıtı Log-Id üzerinde bir Arweave sorgusu aracılığıyla kamu AnchorBundle'dan yeniden inşa eder. .qub paketi (W7), W3'ün drand_chain_version'ıyla aynı "isteğe bağlı, varsayılan olarak atlanan, eklemeli" desenini izleyerek bir isteğe bağlı inclusion_proof üyesi ayırır — mühürlemede yok, soğuk arşiv için demir-sonrası bir yeniden-dışa-aktarımla doldurulur.

16.13 Saklama

LogDO açık kuyruğu, R2 kanıt-sunma alt yapısı, demir devre-kesici sayaçları ve paketleyici yedek kuyruğu için saklama pencereleri docs/DATA-RETENTION.md'de belirtilmiştir. İlke: günlüğün sıcak girdi-başına depolaması (LogDO) demir-sonrası geri-kazanılabilirdir; denetim materyali — koordinat-anahtarlı (level, index) Merkle-düğüm deposu + seq-adresli yaprak gövdeleri (§16.9) + Arweave demirleri — kalıcıdır. Bir soğuk yaprağı DO'dan geri kazanmak, asla yayınlanmış bir kanıtı geçersiz kılmaz, çünkü bir kanıt DO'ya karşı değil, o kalıcı R2 düğüm deposuna ve Arweave demirine karşı çözülür (ve §16.9 silinmiş-DO test vektörü bunu kanıtlar).

16.14 Test vektörleri

W5, diller arası fikstür tlog_v1.json'u (§16.8) artı işlenmiş vektörleri sevk eder: bir kind=0x01 ve bir kind=0x02 yaprağı → leaf_hash; 5-yapraklı kümülatif kök; bir dahil edilme kanıtı; bir tutarlılık kanıtı; bir AnchorBundle; ve bir DataItem kimliği. Bunlar, §14.5 dış-sarmalayıcı vektörlerinin yanında bulunur ve hem Rust (qub-core) hem de TypeScript (Worker) uygulamaları tarafından uygulanır.

16.15 İnceleme kararları (W5 — çözüldü)

W5 dış incelemesi (bir hasım tasarım geçişi + sahip onayı) tamamlandı. Aşağıdaki her karar yerleşmiştir ve yukarıdaki §16 metnine yansıtılmıştır; bağlayıcı lansman kısıtları sonda yeniden belirtilir. Uygulama bunlar altında ilerleyebilir.

  1. Varsayılan-yol (kind=0x02) yaprak dürüstlüğü — ÇÖZÜLDÜ. İki-yaprak-türü bölünmesini belirtildiği gibi sevk edin: kind=0x02 ne body_hash ne de drand_round taahhüt eder. Bayta-kör yolda *_body_hash alanı yok (entegratörler için en okunaklı sahte "doğrulanmış" sinyal olurdu ve §11'in paketten zaten sağladığı bir kolaylıktır). Günlük-onaylı qub'lar için sunucu-mühürleme gerektirmeyin (bu, düz metni Worker'dan zorlar ve kripto-parçalama moat'ını yok ederdi). Herhangi bir kendini-tanımlayan kısayol, bir yaprak alanına değil, .qub paketinde / kanıt zarfında doğrulayıcı-tarafından-yeniden-hesaplanan bir alana aittir. Sahip-onaylı iddia tavanı: §16.11.
  2. Eşitsizlik / atlama hesap verebilirliği — ÇÖZÜLDÜ. Mühürleme-makbuzu anahtarı, LogProfile'da sabitlenmiş + anchor_owner-çapraz-imzalanmıştır (önceki "imzalama anahtarı yok" çelişkisini kapatır; §16.6). Lansman tanık modeli: sabitlenmiş makbuz + izleme metodolojisi + önceki-zincir yürüyüşü + çift kendi-yayınlanan başlık (qub-sahipli kamu GitHub deposu, sosyal en iyi-çaba), tespit edilebilir + makbuzlu olarak pazarlanır, asla bağımsız tanıklı değil. Gerçek bir üçüncü-taraf tanığı bir §15 yönetişim yükseltmesine ertelenir.
  3. Sabitlenmiş demir-sahibi güven kökü + döndürme — ÇÖZÜLDÜ. LogProfile sabitlemesini benimseyin (§16.6); doğrulayıcı anchor_tx.owner == anchor_owner'ı kontrol eder ve tx veri → tx_id bağlamasını yerel olarak doğrular. Döndürme yönetişimi bir reuse değil, bir §15 inşa edilecek uzantıdır (§15.3 tetikleyici eklendi); planlı döndürmeler çapraz-imzalar, ele geçirme-kaynaklı döndürmeler çatallanma kontrolünün hasarı sınırladığı §15 yükseltmesine geri döner.
  4. Özel-qub yaprak körleştirmesi — ÇÖZÜLDÜ. Özel qub'lar için körleştirmeyi koruyun (ref = SHA3-256(qub_id ‖ log_blind_secret)), kamu qub'lar için ham qub_id (zaten §16.2.1), bağımsız bağ olarak chash. log_blind_secret bir korelasyon/Sybil-derecesi gizlidir, yalnızca-ileriye-döndürülür (§16.2.1).
  5. received_at — ÇÖZÜLDÜ. Onu yaprakta tutun, taahhüt edilmiş ama açıkça kanıt değeri taşımayan; herhangi bir yüzeyde asla kanıt veya anlaşmazlık teyidi olarak yüzeye çıkarılmaz. Herhangi bir izleme akıl-sağlığı kontrolü, operatör-kontrollü anchored_at'a karşı değil, Arweave blok zamanı T'ye karşı karşılaştırır (§16.6).
  6. Ücretsiz-katman kanıtlanabilir-zamanlama — ÇÖZÜLDÜ (sahip onayı). Dayanıklılık gerilemez; yalnızca kanıtlanabilir üst-sınır taahhüt zamanı demir blok zamanına kabalaşır. Ücretsiz-katman kopyası hiçbir sayısal SLA kullanmaz ("…bir sonraki günlük demirinde, tipik olarak günlük eklenir"); tam-saat kanıtı ücretli bir T3 özelliğidir, katman-karşılaştırma yüzeyinde + koşullarda açıklanır (§16.1).
  7. Workers üzerinde kümülatif ağaç — ÇÖZÜLDÜ. Tek kümülatif RFC 9162 ağaç + sınır-önbellekli tek-yazıcı LogDO (~1k yazma/saniye DO tavanına karşı rahat üst boşluk; Merkle-of-shard-roots parçalamasını ona yaklaşana kadar ertele). Engelleyici önkoşul: koordinat-anahtarlı (level, index) R2 düğüm deposu + silinmiş-DO soğuk-yaprak test vektörü (§16.9); < 300 ms, iki sıralı DO üzerinde bir ölçülen lansman kapısıdır (§16.10).
  8. ANS-104 imza şeması + derin-özet — ÇÖZÜLDÜ. RSA-PSS (imza türü 1, özel demir-cüzdan JWK'sini yeniden kullanır); Ed25519, §15 PK yoluna ertelenir. Elle yazılmış SHA-384 derin özeti, her-iki-yön diller-arası fikstüre, yalnızca-statik bir referans-paketleyici birlikte-çalışabilirlik kontrolüne, paylaşılan-crypto.subtle gidiş-dönüşüne ve paket-sonrası Arweave-kabul izleyicisine kapılıdır (§16.8).

Bağlayıcı lansman kısıtları (uygulamaya + ürün/yasal incelemeye taşıyın):