Προδιαγραφή Πρωτοκόλλου qub

Το qub είναι ένα πρωτόκολλο κρυπτογραφικών χρονικών δεσμεύσεων: ένα σύστημα για τη σφράγιση λέξεων σε μια μελλοντική ημερομηνία και τη μεταγενέστερη επαλήθευση του τι ακριβώς σφραγίστηκε, ποιος γύρος drand έλεγχε την απελευθέρωσή του και — όταν είναι διαθέσιμη συναλλαγή αποθήκευσης ή απόδειξη αρχείου διαφάνειας — ενός ανεξάρτητα χρονοσημασμένου ανώτατου ορίου για το πότε δεσμεύτηκε το κρυπτοκείμενο.

Τρεις πρωταρχικοί μηχανισμοί το κάνουν να λειτουργεί. Το drand είναι ένας αποκεντρωμένος φάρος τυχαιότητας — η ημερομηνία αποκάλυψης επιβάλλεται κρυπτογραφικά και όχι από την καλή θέληση του qub. Η ανθεκτική αποθήκευση μαζί με ένα αρχείο διαφάνειας μόνο για προσθήκες διατηρεί τα σφραγισμένα bytes και αγκυρώνει ομαδοποιημένες δεσμεύσεις στη μόνιμη δημόσια αποθήκευση· η επί πληρωμή διαδρομή T3 γράφει επίσης μια μεμονωμένη συναλλαγή μόνιμης αποθήκευσης. Η ML-DSA-65 είναι μια μετα-κβαντική ψηφιακή υπογραφή — όταν είναι ενεργοποιημένη η συγγραφή, το qub συνδέεται με ένα ζεύγος κλειδιών του οποίου το μυστικό δεν εγκαταλείπει ποτέ τη συσκευή του συγγραφέα.

Μαζί, αυτοί οι μηχανισμοί παράγουν μια δήλωση χρονοκλειδωμένη και ανθεκτική σε παραποίηση, προαιρετικά αποδιδόμενη και ανεξάρτητα χρονοσημάνσιμη — μια απόδειξη της οποίας η αξία αυξάνεται καθώς βελτιώνεται η ικανότητα του κόσμου να κατασκευάζει το παρελθόν.

Το υπόλοιπο αυτού του εγγράφου είναι η κανονιστική προδιαγραφή που απαιτείται για διαλειτουργικές υλοποιήσεις.


Προδιαγραφή Πρωτοκόλλου qub

Πεδίο Τιμή
Έκδοση εγγράφου 1.0.0 (protocol-v1.0.0)
Πρωτόκολλο σύρματος 0x01
Εξωτερικό περιτύλιγμα 0x01
Ημερομηνία ισχύος 2026-09-23
Κατάσταση Τρέχον
Αναθεωρημένο μέχρι 2026-09-23

Το παρόν έγγραφο είναι η κανονιστική προδιαγραφή πρωτοκόλλου για το σύστημα χρονικής δέσμευσης qub. Καθορίζει δομές δεδομένων, κανόνες σειριοποίησης, τύπους παραγωγής και διαδικασίες επαλήθευσης που απαιτούνται για διαλειτουργικές υλοποιήσεις.

Εμβέλεια: το επίπεδο του πρωτοκόλλου είναι σκόπιμα γλωσσικά ουδέτερο — το σώμα του qub είναι αδιαφανές απλό κείμενο / markdown / bytes συμφώνου, και η απόδοση με συναίσθηση τοπικότητας είναι ευθύνη του θεατή (εφαρμογή web qub.social, iframe <qub-embed>, πελάτες MCP, κ.λπ.).


1. Σύμβαση και Συμβολισμοί

Συμβολισμός Σημασία
u8, u64, i64 Μη προσημασμένοι/προσημασμένοι ακέραιοι καθορισμένου εύρους bit
[u8; N] Πίνακας bytes σταθερού μήκους N bytes
Vec<u8> Πίνακας bytes μεταβλητού μήκους
Option<T> Τιμή τύπου T, ή απούσα
String Συμβολοσειρά κειμένου UTF-8, κανονικοποιημένη σε NFC
`
SHA3-256(x) Κατακερματισμός NIST SHA3-256 της συμβολοσειράς bytes x (FIPS 202)
ceil(x) Συνάρτηση οροφής: μικρότερος ακέραιος ≥ x
CBOR Concise Binary Object Representation (RFC 8949)
big-endian Πρώτα το πιο σημαντικό byte

Όλοι οι ακέραιοι σε κατασκευές προεικόνας κωδικοποιούνται ως πίνακες bytes σταθερού εύρους big-endian (i64 → 8 bytes, u8 → 1 byte) εκτός αν προδιαγράφεται διαφορετικά.

Όλες οι χρονοσημάνσεις είναι δευτερόλεπτα Unix σε UTC.


2. Δομές Δεδομένων

2.1 ComposeQub (Κατάσταση στη Μνήμη του Δημιουργού)

Δεν σειριοποιείται σε CBOR. Δεν εγγράφεται σε μόνιμη αποθήκευση. Τοπικό στην εφαρμογή του δημιουργού.

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 (Αποκρυπτογραφημένο Ωφέλιμο Φορτίο)

Σειριοποιείται με κανονικό CBOR (§3). Κρυπτογραφημένο μέσα στο SealedQub. Αυτή είναι η δομή που αποδεικνύει την ακεραιότητα του περιεχομένου μετά την αποκρυπτογράφηση.

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
}

Βάση (μη υπογεγραμμένο qub κειμένου): version = 0x01, content_type = 0x01, sig_alg = 0x00· τα πεδία υπογραφής και συν-υπογραφέα απουσιάζουν. Άλλα προαιρετικά πεδία μεταδεδομένων μπορεί να υπάρχουν.

Άλλες διαμορφώσεις v1: content_type = 0x03 (σώμα συμφώνου, βλέπε §6.1)· sig_alg = 0x01 (ML-DSA-65) με author_signature και author_pubkey παρόντα (βλέπε §9.3)· cosigner_pubkey και cosigner_signature παρόντα μαζί για συν-υπογεγραμμένα σύμφωνα (βλέπε §9.7)· reply_to ορισμένο στο qub_id του γονικού qub για qubs αλυσίδας απάντησης (βλέπε §9.3 για τις επιπτώσεις στην εμβέλεια υπογραφής).

2.3 SealedQub (Κανονικό Μορφότυπο Σύρματος)

Σειριοποιείται με κανονικό CBOR (§3). Αυτό είναι το εσωτερικό τεκμήριο σύρματος: η δημόσια παράδοση αποθηκεύει αυτά τα bytes γυμνά, ενώ η ιδιωτική παράδοση τα περιτυλίγει σε OuterWrapper πριν από την αποθήκευση (§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 (Κατάσταση Εφαρμογής Θεατή)

Δεν σειριοποιείται σε CBOR. Τοπικό στην εφαρμογή του θεατή. Κατασκευάζεται μετά από επιτυχή αποκρυπτογράφηση και επαλήθευση.

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. Προφίλ Κανονικού CBOR

Όλη η σειριοποίηση SealedQub και QubEnvelope ΠΡΕΠΕΙ να συμμορφώνεται με αυτό το προφίλ. Δύο υλοποιήσεις δοθείσας της ίδιας λογικής δομής ΠΡΕΠΕΙ να παράγουν πανομοιότυπα bytes.

3.1 Κανόνες Κωδικοποίησης

Κανόνας Προδιαγραφή
Πρότυπο RFC 8949 §4.2.1 (Core Deterministic Encoding Requirements)
Διάταξη κλειδιών χάρτη Ταξινόμηση κατά κωδικοποιημένο μήκος bytes πρώτα (μικρότερο πριν το μεγαλύτερο), μετά λεξικογραφικά (byte-προς-byte για κωδικοποιήσεις του ίδιου μήκους)
Κωδικοποίηση ακεραίων Συντομότερη μορφή: 0–23 στο αρχικό byte· 24–255 σε 2 bytes· 256–65535 σε 3 bytes· κ.λπ.
Κωδικοποίηση μήκους Μόνο καθορισμένα μήκη. Όχι πίνακες, χάρτες, συμβολοσειρές bytes ή συμβολοσειρές κειμένου αόριστου μήκους (επιπλέον πληροφορία = 31 απαγορεύεται).
Ετικέτες Όχι ετικέτες CBOR (κύριος τύπος 6 απαγορεύεται).
Κινητής υποδιαστολής Όχι floats (τιμές κύριου τύπου 7 0xF9–0xFB απαγορεύονται).
Συμβολοσειρές κειμένου Κωδικοποιημένες σε UTF-8, κανονικοποιημένες σε NFC (Unicode Normalization Form C).
Συμβολοσειρές bytes Ακατέργαστα bytes. Όχι κωδικοποίηση base64 στο επίπεδο CBOR.
Διπλά κλειδιά Απόρριψη με σφάλμα. Οι αναλυτές ΔΕΝ ΠΡΕΠΕΙ να αποδέχονται σιωπηρά διπλά κλειδιά χάρτη.
Άγνωστα κλειδιά Απόρριψη με σφάλμα. Οι αναλυτές ΔΕΝ ΠΡΕΠΕΙ να ανέχονται κλειδιά χάρτη εκτός του κανονικού συνόλου κλειδιών του τύπου — δύο διαφορετικές κανονικές συμβολοσειρές bytes δεν πρέπει ποτέ να αποκωδικοποιούνται στην ίδια τιμή (encode(decode(x)) == x), και για υπογεγραμμένα ωφέλιμα φορτία ένα επιπλέον κλειδί θα ήταν κρυφό περιεχόμενο στο οποίο δεσμεύονται και οι δύο υπογραφές. Η εξέλιξη σχήματος γίνεται μέσω του version, ποτέ μέσω επιπλέον κλειδιών.
Απλές τιμές Επιτρέπονται μόνο true (0xF5), false (0xF4) και null (0xF6).
Προαιρετικά πεδία Τα απόντα προαιρετικά πεδία παραλείπονται εξ ολοκλήρου από τον χάρτη CBOR (δεν κωδικοποιούνται ως null). Τα παρόντα προαιρετικά πεδία περιλαμβάνονται με την ταξινομημένη σειρά κλειδιών.

3.2 Επαληθευμένες Κανονικές Σειρές Κλειδιών

Αυτές οι σειρές κλειδιών είναι κανονιστικές. Οι υλοποιήσεις ΠΡΕΠΕΙ να εκπέμπουν κλειδιά ακριβώς με αυτή τη σειρά. Οι ισχυρισμοί εντοπισμού σφαλμάτων ΘΑ ΕΠΡΕΠΕ να επαληθεύουν την ταξινόμηση σε μη-εκδόσεις παραγωγής.

QubEnvelope (έκδοση 0x01, μη υπογεγραμμένο, όλα τα προαιρετικά πεδία απόντα):

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

Παραγωγή σειράς κλειδιών QubEnvelope: κάθε κλειδί είναι μια συμβολοσειρά κειμένου CBOR. Κωδικοποιημένο μήκος = 1 byte κεφαλίδα + μήκος συμβολοσειράς (για συμβολοσειρές κάτω των 24 bytes). Ταξινομήστε πρώτα κατά συνολικό κωδικοποιημένο μήκος, μετά λεξικογραφικά για κλειδιά ίδιου μήκους.

SealedQub (έκδοση 0x01, δημόσιο, χωρίς παραλήπτη):

"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 (σώμα συμφώνου, 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):

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

PartyIdentifier (χάρτης party_a / party_b):

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

3.3 Αναφορά Κωδικοποίησης Bytes

Τύπος Κωδικοποίηση CBOR Παράδειγμα
Κατακερματισμός SHA3-256 (32 bytes) 0x58 0x20 + 32 bytes body_hash, qub_id
Χρονοσημάνσεις (i64) Κύριος τύπος 0 (θετικός) ή 1 (αρνητικός), συντομότερη κωδικοποίηση Δευτερόλεπτα Unix
Έκδοση (u8, τιμή 1) 0x01 (ένα byte)
Τύπος περιεχομένου (u8, τιμή 1) 0x01 (ένα byte)
sig_alg (u8, τιμή 0) 0x00 (ένα byte)
Υπογραφή ML-DSA-65 (3.309 bytes) 0x59 0x0C 0xED + 3.309 bytes author_signature, cosigner_signature
Δημόσιο κλειδί ML-DSA-65 (1.952 bytes) 0x59 0x07 0xA0 + 1.952 bytes author_pubkey, cosigner_pubkey

4. Κανονιστικές Παραγωγές

4.1 qub_id

Το qub_id αναγνωρίζει μοναδικά ένα qub και συνδέει το QubEnvelope με το SealedQub. Παράγεται ντετερμινιστικά από το περιεχόμενο του φακέλου.

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

Κωδικοποίηση διαχωριστή πεδίου: Η συμβολοσειρά "QUB_ID_V2" είναι 9 ASCII bytes. Ένα μοναδικό byte γεμίσματος 0x00 προστίθεται για να φτάσει τα 10 bytes για ευθυγράμμιση. Οι υλοποιήσεις ΠΡΕΠΕΙ να χρησιμοποιούν ακριβώς αυτά τα 10 bytes: [0x51, 0x55, 0x42, 0x5F, 0x49, 0x44, 0x5F, 0x56, 0x32, 0x00].

Κωδικοποίηση outcome_at: Μια αναθεώρηση της υλοποίησης πριν από την έκδοση επέκτεινε την προεικόνα από 92 σε 100 bytes ώστε να ενσωματώσει το προαιρετικό πεδίο outcome_at στη δέσμευση. Το απόν outcome_at κωδικοποιείται ως 8 μηδενικά bytes· οι επικυρωτές του πρωτοκόλλου απορρίπτουν outcome_at <= 0 παντού, ώστε αυτή η ένδειξη να μην μπορεί να συγκρουστεί με νόμιμη τιμή. Βλέπε §3.2 και το ενσωματωμένο tasks/verdict-uplift-plan.md.

Κωδικοποίηση drand_round: Μια μεταγενέστερη αναθεώρηση της υλοποίησης πριν από την έκδοση επέκτεινε την προεικόνα από 100 σε 108 bytes ώστε να ενσωματώσει το drand_round στη δέσμευση και αναβάθμισε τον διαχωριστή πεδίου σε QUB_ID_V2. Αυτό δεσμεύει τον γύρο timelock στην ταυτότητα του qub: μια πύλη δεν μπορεί να επαναδεσμεύσει το κρυπτοκείμενο σε διαφορετικό, για παράδειγμα ήδη παρελθόντα, γύρο από αυτόν που υπονοεί το εμφανιζόμενο unlock_at. Η διαδικασία ξεκλειδώματος (§8) επαληθεύει επιπλέον ότι ο γύρος μέσα στο stanza του κρυπτοκειμένου tlock ταιριάζει με το unlock_round(unlock_at).

Ιδιότητες:

4.2 body_hash

body_hash = SHA3-256(body)

Όπου body είναι το ακατέργαστο ωφέλιμο φορτίο περιεχομένου Vec<u8>. Για qubs κειμένου, αυτό είναι το σώμα του qub κωδικοποιημένο σε 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

Όπου title είναι ο προαιρετικός τίτλος απλού κειμένου που εμφανίζεται στην αντίστροφη μέτρηση του θεατή πριν την αποκάλυψη (βλέπε §3.2). Η κανονικοποίηση NFC εκτελείται κατά τον χρόνο κατακερματισμού ώστε η σύνοψη να είναι σταθερή σε οπτικά ισοδύναμες ακολουθίες κωδικοσημείων. Η ένδειξη απουσίας με όλα μηδενικά διατηρείται για την περίπτωση απουσίας· μια κενή συμβολοσειρά απορρίπτεται στο όριο κανονικού CBOR ως μη-κανονική κωδικοποίηση του "απών" (η κανονική κωδικοποίηση παραλείπει το πεδίο εξ ολοκλήρου).

4.3 Αντιστοίχιση Γύρου Ξεκλειδώματος

drand_round = floor((unlock_at - chain_genesis_time) / chain_period_seconds) + 1
Παράμετρος Πηγή Παράδειγμα
unlock_at Δευτερόλεπτα Unix UTC επιλεγμένα από τον χρήστη 1735689600 (2025-01-01 00:00:00 UTC)
chain_genesis_time πληροφορίες αλυσίδας drand (genesis_time) 1595431050
chain_period_seconds πληροφορίες αλυσίδας drand (period) 30

Αυτή είναι η αντιστοίχιση αναφοράς του tlock (CurrentRound του drand). Το drand δημοσιεύει τον γύρο r τη στιγμή chain_genesis_time + (r - 1) * chain_period_seconds, επομένως ο τύπος επιλέγει τον πρώτο γύρο του οποίου η υπογραφή δεν έχει δημοσιευτεί πριν από το unlock_at.

Ιδιότητα ευθυγράμμισης: όταν το (unlock_at - chain_genesis_time) διαιρείται ακριβώς με το chain_period_seconds, η υπογραφή του επιλεγμένου γύρου δημοσιεύεται ακριβώς στο unlock_at, ποτέ νωρίτερα. Αυτό ισχύει πάντα για την ανάπτυξη αναφοράς: ο χρόνος γένεσης του quicknet (1692803367) διαιρείται με την περίοδο των 3 δευτερολέπτων και οι εφαρμογές αναφοράς καρφιτσώνουν τους χρόνους ξεκλειδώματος σε ολόκληρα λεπτά. Για μη ευθυγραμμισμένο unlock_at, η υπογραφή του επιλεγμένου γύρου δημοσιεύεται αυστηρά λιγότερο από μία περίοδο πριν από το unlock_at· η χρονική ακρίβεια της δέσμευσης είναι μία περίοδος του φάρου.

Παλαιά αντιστοίχιση πριν από την έκδοση και ανοχή κατά το ξεκλείδωμα: η αρχική αντιστοίχιση ήταν ceil((unlock_at - chain_genesis_time) / chain_period_seconds), η οποία, στην ευθυγραμμισμένη περίπτωση, επέλεγε τον γύρο που δημοσιευόταν μία πλήρη περίοδο πριν από το unlock_at. Οι δύο αντιστοιχίσεις διαφέρουν κατά ακριβώς +1 όταν η διαφορά διαιρείται με την περίοδο και συμφωνούν διαφορετικά. Επειδή το drand_round ενσωματώνεται στην αμετάβλητη προεικόνα του qub_id (§4.1), οι επαληθευτές του ελέγχου γύρου στο βήμα 6a της §8 ΠΡΕΠΕΙ να δέχονται αποθηκευμένο drand_round ίσο είτε με τον παραγόμενο γύρο είτε με τον παραγόμενο γύρο μείον ένα, και ΠΡΕΠΕΙ να απαιτούν ο γύρος του stanza tlock να είναι ακριβώς ίσος με τον αποθηκευμένο γύρο. Η ίδια ανοχή εφαρμόζεται στην υπηρεσία προετοιμασίας συμφώνου, η οποία σφραγίζει το οριστικοποιημένο σύμφωνο στον γύρο που πράγματι δεσμεύει το qub_id.

Επαλήθευση: το unlock_at ΠΡΕΠΕΙ να είναι στο μέλλον κατά τον χρόνο σφράγισης. Το unlock_at ΔΕΝ ΠΡΕΠΕΙ να είναι περισσότερο από 10 χρόνια από το created_at (για τον περιορισμό του κινδύνου εξάρτησης drand σε μακρύ ορίζοντα· η διεπαφή χρήστη ΘΑ ΕΠΡΕΠΕ να προειδοποιεί για ημερομηνίες ξεκλειδώματος πέρα από 2 χρόνια).


5. Newtypes Μορφότυπου Σύρματος

Τα newtypes μορφότυπου σύρματος παρέχουν ασφάλεια κατά τον χρόνο μεταγλώττισης ενάντια στη σύγχυση των bytes CBOR με JSON, ακατέργαστο απλό κείμενο ή άλλες κωδικοποιήσεις bytes.

Τύπος Περιέχει Παράγεται από Καταναλώνεται από
SealedQubCbor Κανονικό CBOR του SealedQub serialize_sealed_qub() Εσωτερικό τεκμήριο σύρματος· αποθηκεύεται γυμνό για δημόσια παράδοση ή περιτυλιγμένο για ιδιωτική και κατόπιν ανακτάται από τον θεατή
QubEnvelopeCbor Κανονικό CBOR του QubEnvelope serialize_qub_envelope() Είσοδος κρυπτογράφησης tlock, έξοδος αποκρυπτογράφησης tlock

5.1 Κανόνες Κατασκευής

// 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 Επαλήθευση κατά την Κατασκευή

Η from_encoded() ΘΑ ΕΠΡΕΠΕ να επαληθεύει ότι η είσοδος ξεκινά με έγκυρη κεφαλίδα χάρτη CBOR. Η πλήρης δομική επαλήθευση συμβαίνει στον χρόνο ανάλυσης, όχι στον χρόνο κατασκευής, για να αποφευχθεί η διπλή ανάλυση.


6. Μητρώο Τύπων Περιεχομένου

Τιμή Τύπος Μέγιστο Μέγεθος Σώματος Σημειώσεις
0x00 Δεσμευμένο (μη έγκυρο) — ΔΕΝ ΠΡΕΠΕΙ να χρησιμοποιηθεί
0x01 Απλό κείμενο (UTF-8, περιορισμένο Markdown) 50 KB επί πληρωμή / 10 KB δωρεάν Βλέπε §10 για κανόνες απόδοσης. Ο διαχωρισμός δωρεάν / επί πληρωμή επιβάλλεται από την υπηρεσία ανεβάσματος· το αυστηρό ανώτατο όριο επιπέδου πρωτοκόλλου είναι 50 KB.
0x02 Δεσμευμένο (μελλοντικό) — Κατανεμημένο για έναν μελλοντικό τύπο περιεχομένου· μη έγκυρο στην v1. Οι θεατές ΠΡΕΠΕΙ να το απορρίπτουν σύμφωνα με τον παρακάτω κανόνα.
0x03 Σύμφωνο (διμερής συμφωνία, σώμα CBOR) 100 KB Το σώμα είναι κανονικό CBOR PactTerms (§6.1). Συν-υπογραφή ανά §9.7.
0x04 Ετυμηγορία (αυτο-αξιολόγηση δημιουργού, σώμα CBOR) 8 KB Το σώμα είναι κανονικό CBOR VerdictBody (§6.2). Εκπέμπεται μόνο από την πρόθεση verdict της πλευράς του συστήματος. Η γονική σχέση βρίσκεται στην ετικέτα Arweave Parent-Tx-Id, όχι στο σώμα. Βλέπε verdict-uplift-plan §3.4.

Οι θεατές ΠΡΕΠΕΙ να απορρίπτουν άγνωστους τύπους περιεχομένου με σαφές μήνυμα σφάλματος ορατό στον χρήστη. Οι θεατές ΔΕΝ ΠΡΕΠΕΙ να επιχειρούν να αποδώσουν άγνωστους τύπους ως κείμενο.

6.1 Σώμα Συμφώνου (content_type = 0x03)

Ένα σώμα συμφώνου είναι η κανονική κωδικοποίηση CBOR μιας τιμής 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)> }

Οι κανονικές σειρές κλειδιών CBOR και για τους τρεις χάρτες δίνονται στην §3.2. Το συνολικό σειριοποιημένο CBOR του συμφώνου ΔΕΝ ΠΡΕΠΕΙ να υπερβαίνει τα 100 KB (ταιριάζει με την §6).

Διακριτής σχήματος. Η πρώτη γραμμή στα terms για ένα σύμφωνο structured/v1 ΠΡΕΠΕΙ να είναι { key: "pact_schema", value: "structured/v1" }. Οι γραμμές χωρίς αυτό το σήμα είναι "προσαρμοσμένα" σύμφωνα και δεν λαμβάνουν δομημένη επικύρωση ή απόδοση που γνωρίζει το σχήμα.

Παγωμένες υποδοχές αναγνώρισης. Τα σύμφωνα structured/v1 φέρουν ακριβώς τέσσερις γραμμές αναγνώρισης κάτω από αυτά τα κλειδιά:

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

Το value για κάθε μία είναι μία από οκτώ παγωμένες αγγλικές συμβολοσειρές που επιλέγονται από το ζεύγος (role, kind), όπου role ∈ { seller, buyer, provider, client } και kind ∈ { standard, capacity }. Οι ίδιες οι συμβολοσειρές είναι κανονιστικά δεδομένα πρωτοκόλλου — οι υπογραφές ML-DSA-65 και των δύο μερών δεσμεύονται στα ακριβή bytes μέσω του body_hash. ΔΕΝ είναι τοπικοποιημένες· το υπογεγραμμένο σώμα είναι γλωσσικά ουδέτερο. Οποιαδήποτε αλλαγή διατύπωσης απαιτεί νέα έκδοση σχήματος (structured/v2).

Οι οκτώ συμβολοσειρές, η αναζήτησή τους (acknowledgement_for(role, kind)) και η λογική για κάθε μία είναι καρφιτσωμένες από την υλοποίηση αναφοράς. Οι συμμορφούμενες υλοποιήσεις ΠΡΕΠΕΙ να εκπέμπουν byte-πανομοιότυπες τιμές αναγνώρισης· τα golden-fixture τεστ SHA3-256 body-hash που καλύπτουν και τους τέσσερις συνδυασμούς ρόλων εντοπίζουν οποιαδήποτε απόκλιση.

Σειρά εμφάνισης θεατή. Οι συμβολοσειρές αναγνώρισης περιέχουν φράσεις όπως "described above", οι οποίες προϋποθέτουν ότι οι γραμμές περιγραφής / εμβέλειας αποδίδονται πριν τις αναγνωρίσεις. Οι θεατές ΠΡΕΠΕΙ να αποδίδουν τον πίνακα terms με τη σειρά CBOR· η αναδιάταξη σπάει τη σημασιολογία του πεζού λόγου.

Επικοινωνία αντισυμβαλλόμενου. Όταν το contact του Party B είναι μια έγκυρη διεύθυνση email, η υπηρεσία ανεβάσματος qub αποστέλλει αυτόματα ένα email πρόσκλησης ανασκόπησης / συν-υπογραφής κατά τον χρόνο προετοιμασίας και δεσμεύει την τελική συν-υπογραφή στην επαλήθευση αυτής της ίδιας διεύθυνσης (§9.7). Τα σύμφωνα των οποίων η επικοινωνία Party B απουσιάζει μπορούν ακόμα να συν-υπογραφούν, αλλά μόνο μέσω εξωτερικού καναλιού — η υπηρεσία αρνείται αιτήματα συν-υπογραφής που δεν μπορούν να παράγουν ταιριαστό δείκτη επαλήθευσης email 15 λεπτών.

6.2 Σώμα Ετυμηγορίας (content_type = 0x04)

Ένα σώμα ετυμηγορίας είναι η κανονική κωδικοποίηση CBOR μιας τιμής 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
}

Κανονική σειρά κλειδιών CBOR:

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

Το συνολικό σειριοποιημένο CBOR της ετυμηγορίας ΔΕΝ ΠΡΕΠΕΙ να υπερβαίνει τα 8 KB (ταιριάζει με τη γραμμή του μητρώου παραπάνω).

Απαρίθμηση έκβασης. Το byte του πρωτοκόλλου είναι ουδέτερο ως προς την πρόθεση· οι τέσσερις επιλογές Right / Partial / Wrong / Unfalsifiable καλύπτουν τον χώρο εκβάσεων κάθε πρόθεσης που φέρει ετυμηγορία. Οι ετικέτες ανά πρόθεση («Το προέβλεψα σωστά» / «Την τήρησα» / «Παραδόθηκε» / «Επιβεβαιώθηκε» για το Right, κ.ο.κ.) είναι ζήτημα απόδοσης από την πλευρά του θεατή, που επιλύεται έναντι της πρόθεσης του γονικού qub — το πρωτόκολλο παραμένει ουδέτερο ως προς τη γλώσσα και την πρόθεση. Τιμές εκτός του 1..=4 ΠΡΕΠΕΙ να απορρίπτονται κατά την αποκωδικοποίηση.

Γονική σύνδεση. Ένα qub ετυμηγορίας ΔΕΝ μεταφέρει τη γονική αναφορά στο σώμα του. Το αναγνωριστικό συναλλαγής Arweave του γονικού qub εκπέμπεται ως η ετικέτα αποθήκευσης Parent-Tx-Id κατά τον χρόνο ανεβάσματος (§7, επίπεδο ετικετών αποθήκευσης). Αυτό κρατά το σώμα ως αυτοτελή υπογεγραμμένη δήλωση αυτο-αξιολόγησης· η αλυσίδα ελέγχου («σωστά για το τι;») θεμελιώνεται μέσω της αναζήτησης ετικετών Arweave.

Ασφάλεια του URL τεκμηρίωσης (κανονιστική). Όταν το evidence_url είναι παρόν, οι επικυρωτές (πλευρά σύνθεσης, πλευρά πρωτοκόλλου, άκρο Worker) ΠΡΕΠΕΙ να επιβάλλουν:

  1. Μόνο HTTPS. Η συμβολοσειρά ΠΡΕΠΕΙ να ξεκινά με την ακολουθία bytes https://. Κάθε άλλο σχήμα — http, ftp, javascript, data, file κ.λπ. — απορρίπτεται.
  2. Ανώτατο όριο μήκους. ≤ 2.048 bytes (πρακτικό όριο URL περιηγητή).
  3. Έλεγχος NFC + εχθρικών κωδικών. Ο ίδιος κανόνας με το title και το reflection — κωδικοί παράκαμψης κατεύθυνσης (bidi) / μηδενικού πλάτους / μπλοκ ετικετών / BOM / C0 / C1 απορρίπτονται. Ο ορισμός ταιριάζει με το Rust crate::handle::contains_hostile_text_codepoint και το TS workers/api/src/utils/unicode.ts::isHostileCodepoint (διατηρούνται σε βηματισμό).
  4. Χωρίς κενά, χωρίς χαρακτήρες ελέγχου ASCII. Κενά / DEL / bytes κάτω από 0x20 οπουδήποτε στο URL απορρίπτονται — κλείνει τον φορέα έγχυσης \n/\t που ο κανόνας bidi δεν καλύπτει.
  5. Μη κενό τμήμα κεντρικού υπολογιστή. Όλα όσα βρίσκονται μεταξύ του https:// και του πρώτου /, ? ή # ΠΡΕΠΕΙ να είναι μη κενά.

Καμία ανάκτηση από την πλευρά του διακομιστή. Ο Worker ΔΕΝ ΠΡΕΠΕΙ να διαμεσολαβεί, να ανακτά ή να προεπισκοπεί το URL. Το πρωτόκολλο αποθηκεύει μια συμβολοσειρά· η απόδοση συμβαίνει από την πλευρά του θεατή με rel="nofollow noopener noreferrer" target="_blank" και ορατό όνομα κεντρικού υπολογιστή που εμφανίζεται δίπλα στο κείμενο του συνδέσμου.

Αναστοχασμός. Προαιρετικό κείμενο αναστοχασμού γραμμένο από τον δημιουργό («τι άλλαξε, τι μάθατε»). Ίδια επικύρωση NFC + εχθρικών κωδικών με το title. Κενή είσοδος ή είσοδος μόνο με κενά συμπτύσσεται σε απουσία κατά τον χρόνο κατασκευής.

Έκδοση σχήματος. Η v1 υποστηρίζει μόνο verdict_version = 0x01. Μελλοντικές αναθεωρήσεις σχήματος αυξάνουν αυτό το byte και προσγειώνονται μαζί με μια νέα έκδοση πρωτοκόλλου ανά §12.


7. Πρωτόκολλο Σφράγισης

Η πλήρης ακολουθία σφράγισης. Κάθε βήμα είναι κανονιστικό.

 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.

Επίπεδο ετικετών αποθήκευσης (εκτός ζώνης). Η υπηρεσία μεταφόρτωσης qub επισυνάπτει ένα σκόπιμα μικρό σύνολο ετικετών συναλλαγής αποθήκευσης μαζί με το επιλεγμένο payload μεταφόρτωσης. Το Content-Type=application/octet-stream απαιτείται κανονιστικά. Η υπηρεσία αναφοράς επισυνάπτει επιπλέον τρεις προαιρετικές ετικέτες όταν ο δημιουργός επιλέγει να τις εμφανίσει: Intent (πρόθεση σύνθεσης επικυρωμένη με ακριβή allowlist — announcement, thesis, prediction, letter, secret, commitment, proof ή το εκπεμπόμενο από το σύστημα verdict), Author (το αποτύπωμα δημόσιου κλειδιού του δημιουργού κατά §9.3 ως 64 πεζοί δεκαεξαδικοί χαρακτήρες) και Parent-Tx-Id (το αναγνωριστικό συναλλαγής αποθήκευσης του γονικού qub για αλυσίδες απάντησης, 43 χαρακτήρες base64url).

Η ετικέτα Author είναι opt-in ανά qub: η εφαρμογή δημιουργού αναφοράς την επισυνάπτει μόνο όταν ο χρήστης ενεργοποιεί ρητά τη δημόσια απόδοση κατά τον χρόνο σφράγισης. Όταν ο διακόπτης είναι απενεργοποιημένος — η προεπιλογή — δεν γράφεται ετικέτα Author και το qub δεν αποδίδεται στην αλυσίδα: τίποτα στη μόνιμη αποθήκευση δεν συνδέει τη μεταφόρτωση με το handle, το email ή άλλα qubs του δημιουργού. Όταν ο διακόπτης είναι ενεργοποιημένος, το αποτύπωμα Author επιλύεται στο επιλεγμένο @handle του δημιουργού μέσω της αλυσίδας πιστοποίησης §9.5. Οι σχέσεις αλυσίδας απάντησης και το Intent δεν είναι αναγνωριστικά. Για ιδιωτική παράδοση, το εξωτερικό περιτύλιγμα (§13) κρυπτογραφεί το αναγνωρίσιμο εσωτερικό τεκμήριο SealedQub, ώστε η συλλογή αποθηκευμένων περιτυλιγμάτων και η απόκτηση δημόσιων υπογραφών drand να εξακολουθούν να μην αρκούν για την ανάκτηση του σώματος χωρίς K· οι ετικέτες αποθήκευσης παραμένουν σκόπιμα δημόσια μεταδεδομένα.

Η υπηρεσία αναφοράς σκόπιμα ΔΕΝ επισυνάπτει ετικέτες App-Name, App-Version ή Type: οποιοδήποτε τέτοιο φίλτρο μονής τιμής θα επέστρεφε το σύνολο του σώματος qubs σε ένα ερώτημα GraphQL, το οποίο είναι ασύμβατο με την εμβέλεια εμπιστευτικότητας μόνο-σώματος του περιτυλίγματος.

Ένας συμμορφούμενος επαληθευτής ΔΕΝ ΠΡΕΠΕΙ να εξαρτάται από οποιαδήποτε ετικέτα αποθήκευσης για την §11 επαλήθευση τρίτου μέρους· ο κατακερματισμός σώματος / qub_id / υπογραφή δεσμεύονται μόνο στο εσωτερικό CBOR, ποτέ στο σύνολο ετικετών.


8. Πρωτόκολλο Ξεκλειδώματος

Η πλήρης ακολουθία ξεκλειδώματος. Κάθε βήμα είναι κανονιστικό.

 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. Υπογραφή Συγγραφής

9.1 Λογική

Τα qubs αποθηκεύονται σε μόνιμη αποθήκευση. Οι υπογραφές συγγραφής πρέπει να παραμείνουν μη-πλαστογραφήσιμες επ' αόριστον, και γι' αυτό η v1.0 χρησιμοποιεί το μετα-κβαντικό σχήμα ML-DSA-65 (FIPS 204) και όχι ένα κλασικό σχήμα του οποίου η ασφάλεια μπορεί να υποβαθμιστεί εντός της μόνιμης διάρκειας ζωής του qub.

9.2 Μητρώο Αλγορίθμων

sig_alg Σχήμα Μέγεθος Κλειδιού Μέγεθος Υπογραφής Κατάσταση
0x00 Χωρίς υπογραφή (μη υπογεγραμμένο) — — Ενεργό
0x01 ML-DSA-65 (FIPS 204) 1.952 bytes 3.309 bytes Ενεργό
0x02 Ed25519 32 bytes 64 bytes Δεσμευμένη σταθερά· δεν υποστηρίζεται στο πρωτόκολλο v1

Οι θεατές πρωτοκόλλου v1 ΠΡΕΠΕΙ να απορρίπτουν κάθε τιμή εκτός του {0x00, 0x01}, συμπεριλαμβανομένης της δεσμευμένης τιμής 0x02. Η δέσμευση αποτρέπει τυχαία επαναχρησιμοποίηση· δεν αποτελεί ενεργοποίηση. Η ενεργοποίησή της απαιτεί τη διέπουσα αλλαγή της §15.

9.3 Κατασκευή Υπογεγραμμένης Προεικόνας

Έχουν υπάρξει δύο εκδόσεις προεικόνας. Όλες οι υπογραφές ΠΡΕΠΕΙ να χρησιμοποιούν την V2, και οι επαληθευτές ΠΡΕΠΕΙ να αποδέχονται μόνο την V2. Η παλαιού τύπου προεικόνα V1 (τεκμηριώνεται παρακάτω για ιστορικούς λόγους) γινόταν αποδεκτή ως εφεδρική διαδρομή μόνο για επαλήθευση κατά τη μετάβαση στην V2· αυτή η εφεδρική διαδρομή έχει αποσυρθεί και μια υπογραφή μόνο-V1 πλέον απορρίπτεται.

V2 (τρέχουσα — παράγεται από κάθε νέα υπογραφή συγγραφέα, καθώς και από αμφότερες τις υπογραφές της ροής προετοιμασίας / συν-υπογραφής συμφώνου):

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): 32 μηδενικά bytes δεν αποτελούν έγκυρη έξοδο SHA3-256, οπότε η «απουσία» δεν μπορεί ποτέ να συγκρουστεί με μια παρούσα ετικέτα. Όλα τα πεδία έχουν σταθερό πλάτος, οπότε η προεικόνα είναι μονοσήμαντη χωρίς προθέματα μήκους.

V1 (παλαιού τύπου — ΑΠΟΣΥΡΘΗΚΕ· δεν παράγεται πλέον και δεν γίνεται πλέον αποδεκτή κατά την επαλήθευση):

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 παρέλειπε τα sender_label και reply_to. Γινόταν αποδεκτή ως εφεδρική διαδρομή μόνο για επαλήθευση κατά τη μετάβαση στην V2· αυτή η εφεδρική διαδρομή έκτοτε έχει αποσυρθεί — οι επαληθευτές ΠΡΕΠΕΙ να αποδέχονται μόνο την προεικόνα V2. Ο ορισμός διατηρείται εδώ για ιστορικούς λόγους και για να εξηγήσει τον διαχωριστή πεδίου παρακάτω. Μια υπογραφή που επαληθεύεται μόνο έναντι της V1 ΠΡΕΠΕΙ να αντιμετωπίζεται ως αποτυχία επαλήθευσης.

Διαχωριστές πεδίου: τα "QUB_AUTHOR_SIG_V1" / "QUB_AUTHOR_SIG_V2" είναι 17 ASCII bytes το καθένα ([0x51, 0x55, 0x42, 0x5F, 0x41, 0x55, 0x54, 0x48, 0x4F, 0x52, 0x5F, 0x53, 0x49, 0x47, 0x5F, 0x56, 0x31/0x32]). Χωρίς γέμισμα. Ο διαφορετικός διαχωριστής διαχωρίζει τα δύο κατασκευάσματα ως προς τον τομέα, οπότε μια υπογραφή πάνω στη μία προεικόνα δεν μπορεί ποτέ να επαληθευτεί ως η άλλη.

Το byte org_id_present: το byte που ακολουθεί το unlock_at ΠΡΕΠΕΙ να είναι 0x00. Η υλοποίηση αναφοράς εκθέτει αυτό ως τη σταθερά ORG_ID_PRESENT_INDIVIDUAL = 0x00 στο crates/qub-core/src/signing.rs· οι θεατές που ανακατασκευάζουν το sig_input για επαλήθευση ΠΡΕΠΕΙ να εκπέμπουν το ίδιο byte.

Εμβέλεια υπογραφής — τι καλύπτεται και τι όχι. Το sig_input της V2 δεσμεύεται άμεσα στα version, qub_id, body_hash, unlock_at, sender_label και reply_to (συν τον σταθερό διαχωριστή πεδίου και το byte org_id_present). Το ίδιο το qub_id παράγεται από τα version, content_type, created_at, unlock_at, outcome_at, drand_round και body_hash μέσω της προεικόνας §4.1, οπότε οποιαδήποτε αλλαγή σε αυτά τα πεδία παράγει διαφορετικό qub_id και ακυρώνει μεταβατικά την υπογραφή. Η πιστοποιημένη επιφάνεια είναι επομένως:

Πεδίο Πιστοποιημένο από υπογραφή Πώς
version ✓ Άμεση είσοδος στο sig_input
qub_id ✓ Άμεση είσοδος
body_hash ✓ Άμεση είσοδος
unlock_at ✓ Άμεση είσοδος
sender_label ✓ Άμεση είσοδος μέσω του sender_label_hash (προεικόνα V2 — η μόνη αποδεκτή μορφή)
reply_to ✓ Άμεση είσοδος μέσω του reply_to_or_zero (προεικόνα V2 — η μόνη αποδεκτή μορφή)
content_type ✓ Μεταβατικά, μέσω της προεικόνας qub_id
created_at ✓ Μεταβατικά, μέσω της προεικόνας qub_id
outcome_at ✓ Μεταβατικά, μέσω της προεικόνας qub_id
drand_round ✓ Μεταβατικά, μέσω της προεικόνας qub_id
body ✓ Μεταβατικά, μέσω του body_hash = SHA3-256(body)
author_pubkey — (έμμεσα) Το κλειδί που επαλήθευσε την υπογραφή είναι ο συγγραφέας, εξ ορισμού
cosigner_pubkey / cosigner_signature — Υπογράφονται ανεξάρτητα πάνω στο ίδιο sig_input (βλέπε §9.7)
drand_chain_id, tlock_ciphertext, visibility — Εξωτερικά πεδία του SealedQub, όχι μέσα στον φάκελο — καλύπτονται από τις δικές τους δομικές αναλλοιότητες (συνέπεια γύρου / αλυσίδας) αλλά όχι από την υπογραφή του συγγραφέα. (Το drand_round δεσμεύεται πλέον μεταβατικά μέσω της προεικόνας qub_id — βλέπε παραπάνω.)

Γιατί η V2 είναι η μόνη αποδεκτή προεικόνα.

Οι υλοποιήσεις που εμφανίζουν sender_label ή reply_to σε τελικούς χρήστες ΠΡΕΠΕΙ να εμφανίζουν την πιστοποιημένη ταυτότητα (αποτύπωμα δημόσιου κλειδιού, πιστοποίηση) ως το κύριο σήμα ταυτότητας, όχι την ετικέτα.

9.4 Διαδικασία Επαλήθευσης

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

Η επαλήθευση υπογραφής είναι η πιο δαπανηρή λειτουργία (ειδικά το ML-DSA-65). ΘΑ ΕΠΡΕΠΕ να εκτελείται αφού έχουν περάσει όλοι οι φθηνότεροι έλεγχοι (κατακερματισμός, qub_id, unlock_at).

9.5 Πιστοποιήσεις Ταυτότητας

Οι πιστοποιήσεις ταυτότητας — η αντιστοίχιση του author_pubkey σε αξιώσεις ταυτότητας αναγνωρίσιμες από ανθρώπους όπως ένα handle qub, διεύθυνση email, κοινωνικό handle ή διαπιστευτήριο passkey — είναι μια προοδευτική ενίσχυση από την πλευρά του θεατή και δεν απαιτούνται για την επαλήθευση της υπογραφής. Οι θεατές που αναλύουν πιστοποιήσεις σε ταυτότητα εμφάνισης ΠΡΕΠΕΙ να εφαρμόζουν την προτεραιότητα:

handle > email > social > fingerprint

Το εφεδρικό αποτύπωμα είναι το hex μικρών γραμμάτων του SHA3-256(author_pubkey)· είναι πάντα διαθέσιμο για οποιοδήποτε υπογεγραμμένο qub. Οι θεατές ΜΠΟΡΟΥΝ να το συντομεύουν για εμφάνιση — ο θεατής αναφοράς αποδίδει qub: ακολουθούμενο από τα πρώτα και τα τελευταία τέσσερα bytes (qub:<8 hex>…<8 hex>).

Ένας συμμορφούμενος επαληθευτής μπορεί να ολοκληρώσει κάθε έλεγχο της §9.4 χωρίς να επικοινωνήσει με το API του qub, χωρίς κανένα δίκτυο πέραν της μόνιμης αποθήκευσης και drand και χωρίς αναζήτηση από την πλευρά του διακομιστή. Η ανάλυση πιστοποίησης είναι ένα ξεχωριστό βήμα μέγιστης προσπάθειας που εκτελείται μόνο μετά την επιτυχή επαλήθευση της υπογραφής.

9.6 Επίπτωση Μεγέθους

Ed25519 ML-DSA-65
Υπογραφή 64 bytes 3.309 bytes
Δημόσιο κλειδί 32 bytes 1.952 bytes
Σύνολο ανά qub 96 bytes 5.261 bytes
Επίπτωση κόστους αποθήκευσης (στα ~$5/MB) ~$0,0005 ~$0,026

Για ένα qub κειμένου 500–2.000 bytes, το ML-DSA-65 περίπου τριπλασιάζει το αποθηκευμένο μέγεθος. Το απόλυτο κόστος είναι αμελητέο.

9.7 Επαλήθευση Συν-υπογραφέα (Διμερείς Συμφωνίες Συμφώνου)

Για διμερείς συμφωνίες (content_type = 0x03), ένα δεύτερο επίπεδο υπογραφής αποδεικνύει ότι και τα δύο μέρη συναίνεσαν στους ίδιους όρους.

Πεδία φακέλου:

Και τα δύο πεδία ΠΡΕΠΕΙ να είναι παρόντα μαζί ή και τα δύο απόντα. Εάν ακριβώς ένα είναι παρόν, οι θεατές ΠΡΕΠΕΙ να αναφέρουν σφάλμα ακεραιότητας.

Διαδικασία επαλήθευσης:

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

Ιδιότητες:

Πύλη δέσμευσης email (επιχειρησιακή). Όταν ένα προετοιμασμένο σύμφωνο φέρει επικοινωνία email του Party B (§6.1), η υπηρεσία ανεβάσματος qub ΠΡΕΠΕΙ να αρνηθεί το αίτημα συν-υπογραφής εκτός αν υπάρχει βραχύβιος δείκτης επαλήθευσης email που ταιριάζει τόσο το staging id όσο και τον κατακερματισμό κανονικοποιημένου-email αυτής της επικοινωνίας. Ο δείκτης γράφεται από το /api/v1/auth/verify όταν το token magic-link φέρει staging_id και η επαληθευμένη διεύθυνση ταιριάζει με SHA-256(normalise_email(party_b.contact)) — όπου το normalise_email(addr) διατηρεί τη γραμματοσειρά του τοπικού μέρους και μετατρέπει σε μικρά μόνο το τμήμα τομέα (κατά RFC 5321 §2.3.11), και το SHA-256 εδώ είναι ο κατακερματισμός NIST FIPS 180-4 (διακριτός από το SHA3-256 που χρησιμοποιείται στις παραγωγές §4) — και λήγει 900 δευτερόλεπτα (15 λεπτά) μετά την έκδοση. Αυτή είναι μια επιχειρησιακή πύλη anti-πλαστοπροσωπίας, ΟΧΙ μέρος της απόδειξης qub on-chain — ένας τρίτος επαληθευτής που επαναλαμβάνει την §11 χρειάζεται μόνο μόνιμη αποθήκευση και drand, χωρίς αναζήτηση από την πλευρά του διακομιστή. Ο δείκτης υπάρχει μόνο από την πλευρά του διακομιστή και δεν είναι ποτέ μέρος του υπογεγραμμένου σώματος.

Επίπτωση μεγέθους (συγγραφέας ML-DSA-65 + συν-υπογραφέας):

Συστατικό Μέγεθος
Υπογραφή συγγραφέα 3.309 bytes
Δημόσιο κλειδί συγγραφέα 1.952 bytes
Υπογραφή συν-υπογραφέα 3.309 bytes
Δημόσιο κλειδί συν-υπογραφέα 1.952 bytes
Συνολικό κρυπτογραφικό overhead 10.522 bytes
Επίπτωση κόστους αποθήκευσης ~$0,05

10. Απόδοση και Καθαρισμός Markdown

Αυτή η ενότητα είναι κρίσιμη για την ασφάλεια. Ο θεατής αποδίδει qubs κειμένου (content_type = 0x01) χρησιμοποιώντας ένα περιορισμένο υποσύνολο Markdown.

10.1 Επιτρεπόμενα Στοιχεία

10.2 Απαγορευμένα Στοιχεία

Στοιχείο Χειρισμός
Ακατέργαστο HTML (<div>, <script>, κ.λπ.) Αφαιρείται εξ ολοκλήρου. Κανένα HTML δεν περνά.
Εικόνες (![alt](url)) Αφαιρούνται. Η σύνταξη εικόνας αφαιρείται από την έξοδο.
Σύνδεσμοι ([text](url)) Η διεύθυνση URL αποδίδεται ως ορατό απλό κείμενο. Δεν συνδέεται αυτόματα. Δεν είναι κλικαρίσιμη χωρίς ρητή ενέργεια του χρήστη.
Επικίνδυνα σχήματα URL javascript:, data:, vbscript:, file: — αφαιρούνται.
Iframes, embeds, objects Αφαιρούνται.
Οντότητες HTML Αποκωδικοποιούνται σε χαρακτήρες εμφάνισης μόνο εάν είναι ασφαλείς.

10.3 Υλοποίηση

Οι υλοποιήσεις ΠΡΕΠΕΙ να χρησιμοποιούν έναν αυστηρό αναλυτή allowlist, όχι blocklist. Η προτεινόμενη προσέγγιση:

  1. Ανάλυση Markdown με χρήση pulldown-cmark (ή ισοδύναμου).
  2. Διάσχιση του AST και απόρριψη οποιουδήποτε κόμβου δεν είναι στο allowlist (§10.1).
  3. Για κόμβους συνδέσμων: εκπομπή της διεύθυνσης URL ως ορατό κείμενο, όχι ως κλικαρίσιμο στοιχείο <a>.
  4. Μετατροπή του φιλτραρισμένου AST σε τυποποιημένη ενδιάμεση αναπαράσταση (π.χ., enum MarkdownNode με μόνο ασφαλείς παραλλαγές). Το ακατέργαστο HTML είναι δομικά μη αναπαραστάσιμο σε αυτό το IR.
  5. Απόδοση από το τυποποιημένο IR στο επίπεδο προβολής στόχου (π.χ., αντιδραστικά στοιχεία προβολής, κόμβοι DOM). Καμία συνένωση συμβολοσειρών HTML ή innerHTML σε κανένα σημείο.

Οι προσεγγίσεις blocklist είναι εύθραυστες επειδή νέες επεκτάσεις Markdown ή ιδιοτροπίες αναλυτή μπορούν να εισάγουν μη-φιλτραρισμένα στοιχεία. Η προσέγγιση τυποποιημένου AST κάνει το XSS δομικά αδύνατο — δεν υπάρχει παραλλαγή που μπορεί να φέρει αυθαίρετο HTML.

10.4 Όρια Μεγέθους και Δομής


11. Επαλήθευση Τρίτου Μέρους

Κάθε τρίτο μέρος που κατέχει τα αποθηκευμένα bytes, καθώς και το K για ένα ιδιωτικό/περιτυλιγμένο qub, μπορεί να επαληθεύσει το κρυπτογραφικό τεκμήριο χωρίς συνεργασία του qub. Ένας ανεξάρτητα χρονοσημασμένος ισχυρισμός ύπαρξης απαιτεί επιπλέον είτε επαληθευμένη συμπερίληψη σε μόνιμη αποθήκευση ανά qub είτε επαληθευμένη απόδειξη αρχείου διαφάνειας κατά §16.

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.

Τι αποδεικνύει η επαλήθευση:

Είσοδος απόδειξης Τι τεκμηριώνει
Έγκυρη δέσμη / σφραγισμένο τεκμήριο + υπογραφή drand Το ανακτημένο σώμα ταιριάζει με το body_hash· τα μεταδεδομένα που δεσμεύονται στο qub_id είναι άθικτα· το κρυπτοκείμενο δεσμεύεται στον δηλωμένο γύρο drand· και ο γύρος έχει παρέλθει. Αυτό δεν τεκμηριώνει πότε δημιουργήθηκε το κρυπτοκείμενο.
Έγκυρη υπογραφή V2 συγγραφέα/συν-υπογραφέα Οι κάτοχοι των αντίστοιχων μυστικών κλειδιών πιστοποίησαν την υπογεγραμμένη επιφάνεια της §9.3.
Ανεξάρτητα επαληθευμένη συναλλαγή αποθήκευσης ανά qub Το ακριβές αποθηκευμένο κρυπτοκείμενο υπήρχε το αργότερο κατά τη χρονοσήμανση του block της.
Έγκυρη αγκυρωμένη απόδειξη αρχείου διαφάνειας Τον ισχυρισμό που αντιστοιχεί στο είδος φύλλου κατά §16.11, μαζί με ανώτατο χρόνο δέσμευσης από το block αγκύρωσης.

Τι ΔΕΝ αποδεικνύει η επαλήθευση:

Μη-απόδειξη Γιατί
Συγγραφή Το sender_label είναι διακοσμητικό. Χωρίς sig_alg ≥ 0x01, οποιοσδήποτε θα μπορούσε να σφραγίσει αυτό το περιεχόμενο.
Πρόθεση Το τεκμήριο αποδεικνύει bytes και κρυπτογραφικές σχέσεις, όχι τι εννοούσε υποκειμενικά ο δημιουργός.
Προϋπάρχουσα δέσμευση μόνο από .qub Ένας δημιουργός μπορεί να συναρμολογήσει έγκυρη δέσμη αφού έχει παρέλθει ο δεσμευμένος γύρος. Η ενσωματωμένη υπογραφή drand αποδεικνύει ότι ο γύρος παρήλθε, όχι ότι το κρυπτοκείμενο υπήρχε νωρίτερα.
Ακριβής χρόνος πατήματος της σφράγισης Η χρονοσήμανση block αποθήκευσης ή αγκύρωσης είναι ένα ανεξάρτητα επαληθεύσιμο ανώτατο όριο και μπορεί να υστερεί της τοπικής ενέργειας του χρήστη. Οι δηλώσεις sealed_at / received_at δεν αποτελούν αποδεικτικά στοιχεία.

Το υλοποιημένο αρχείο διαφάνειας (§16) επεκτείνει την επαλήθευση μεταξύ qubs με ανθεκτική σε παραποίηση διάταξη και ένα χωρίς εμπιστοσύνη ανώτατο όριο χρόνου δέσμευσης, τη χρονοσήμανση του block αγκύρωσης, οριοθετημένο ανά είδος φύλλου (§16.11). Δεν προσθέτει συγγραφή ή πρόθεση· για την προεπιλεγμένη byte-blind διαδρομή μεταφόρτωσης δεν αποδεικνύει από μόνο του τα body_hash ή drand_round, τα οποία συνεχίζουν να προκύπτουν από τους ελέγχους του τεκμηρίου.


12. Διαχείριση Εκδόσεων και Κυκλοφορίας

Οι εκδόσεις εγγράφου, το εσωτερικό πρωτόκολλο σύρματος και το εξωτερικό περιτύλιγμα αποτελούν ξεχωριστούς χώρους εκδόσεων. Έτσι, μια διευκρίνιση μόνο του εγγράφου δεν αλλάζει σιωπηρά bytes και μια μελλοντική μετάβαση σύρματος δεν μπορεί να παρουσιαστεί ως συντακτική αναθεώρηση.

12.1 Έκδοση Κυκλοφορίας Εγγράφου

Αυτή η προδιαγραφή χρησιμοποιεί σημασιολογικές εκδόσεις εγγράφου (MAJOR.MINOR.PATCH) και μια αμετάβλητη ετικέτα Git με όνομα protocol-v<release>.

Η κατάσταση κυκλοφορίας είναι μία από Προσχέδιο (όχι ακόμη κανονιστικό), Τρέχον (ο μοναδικός συνιστώμενος στόχος υλοποίησης) ή Αντικατασταθέν (διατηρείται για ιστορική επαλήθευση). Η διαδρομή χωρίς έκδοση /protocol εμφανίζει την Τρέχουσα κυκλοφορία· η ετικέτα κυκλοφορίας διατηρεί την ακριβή πηγή και κάθε τοπική έκδοση που δημοσιεύτηκε μαζί της. Η αλλαγή κατάστασης ή αριθμού κυκλοφορίας απαιτεί ενημέρωση αυτού του πίνακα και του ιστορικού κυκλοφορίας στην ίδια ελεγμένη αλλαγή.

Έκδοση εγγράφου Ημερομηνία ισχύος Κατάσταση Πρωτόκολλο σύρματος Περιτύλιγμα Πηγή
1.0.0 2026-09-23 Τρέχον 0x01 0x01 protocol-v1.0.0

12.2 Έκδοση Πρωτοκόλλου

Το πεδίο version (u8) και στο SealedQub και στο QubEnvelope αναγνωρίζει την κύρια έκδοση του πρωτοκόλλου.

12.3 Ιστορικό Εκδόσεων Πρωτοκόλλου

Έκδοση Τιμή Περιγραφή
v1 0x01 Ιδιωτική/περιτυλιγμένη και δημόσια/γυμνή παράδοση· σώματα κειμένου (0x01), συμφώνου (0x03) και ετυμηγορίας (0x04)· υπογραφή συγγραφέα/συν-υπογραφέα ML-DSA-65 V2· tlock quicknet του drand· SHA3-256.

12.4 Συμβατότητα προς τα εμπρός

Ένας θεατής v1 που συναντά QubEnvelope με άγνωστα κλειδιά χάρτη CBOR (κλειδιά που δεν είναι στην κανονική σειρά §3.2) ΠΡΕΠΕΙ να το απορρίπτει με σφάλμα αποκωδικοποίησης (§3.1). Η συμβατότητα προς τα εμπρός στηρίζεται στο πεδίο version, όχι στην ανοχή κλειδιών: μελλοντικές προσθήκες — ακόμη και μικρά μεταδεδομένα — παραδίδονται με νέα τιμή version, την οποία ένας θεατής v1 απορρίπτει με σαφές σφάλμα «νεότερο πρωτόκολλο» αντί να παραλείπει σιωπηρά περιεχόμενο στο οποίο δεσμεύονται οι υπογραφές.

Ένας θεατής v1 που συναντά sig_alg = 0x01 (ML-DSA-65) αλλά χωρίς υποστήριξη επαλήθευσης ML-DSA-65 ΘΑ ΕΠΡΕΠΕ να εμφανίσει το περιεχόμενο του qub με μια ειδοποίηση "η υπογραφή υπάρχει αλλά δεν είναι επαληθεύσιμη", και όχι να απορρίψει το qub εξ ολοκλήρου. Η σημερινή υλοποίηση αναφοράς απορρίπτει κάθε τιμή sig_alg εκτός από 0x00 και 0x01 επειδή το μητρώο v1 δεν περιέχει άλλο έγκυρο αλγόριθμο — η αυστηρή απόρριψη και το soft-fail είναι παρατηρητικά ταυτόσημα μέχρι να εγγραφεί τρίτος αλγόριθμος. Η παραπάνω συμπεριφορά soft-fail γίνεται κρίσιμη μόλις η §9.2 δεχθεί νέα εγγραφή, και ο θεατής αναφοράς θα ενημερωθεί ώστε να κάνει soft-fail σε εκείνο το σημείο.

12.5 Έκδοση Εξωτερικού Περιτυλίγματος

Το OuterWrapper που περιγράφεται στην §13 φέρει το δικό του byte version, ανεξάρτητο από τα SealedQub.version και QubEnvelope.version. Οι δύο χώροι έκδοσης εξελίσσονται ξεχωριστά: μια μελλοντική μετα-κβαντικά ασφαλής συμμετρική αντικατάσταση αυξάνει το byte περιτυλίγματος χωρίς να αγγίξει την εσωτερική έκδοση πρωτοκόλλου, και μια μελλοντική προσθήκη στο επίπεδο πρωτοκόλλου (π.χ., νέο πεδίο φακέλου) αυξάνει την εσωτερική έκδοση χωρίς να αγγίξει το byte περιτυλίγματος.

OUTER_WRAPPER_VERSION_* Τιμή Αλγόριθμος Κατάσταση
OUTER_WRAPPER_VERSION_1 0x01 AES-256-GCM με 12-byte nonce, 16-byte ετικέτα πιστοποίησης, AAD δεσμευμένο στο qub_id Ενεργό για ιδιωτική παράδοση
— 0x02–0xFF Δεσμευμένο Μελλοντικό

Οι θεατές ΠΡΕΠΕΙ να απορρίπτουν άγνωστες εκδόσεις περιτυλίγματος με σαφές σφάλμα. Το πρωτόκολλο σκόπιμα διατηρεί τον χώρο εκδόσεων περιτυλίγματος στενό μέχρι να εμφανιστεί συγκεκριμένος οδηγός μετάβασης (π.χ., οδηγία NIST που ευνοεί διαφορετικό AEAD)· μια θέση 0x02 θα κατανεμηθεί στην ίδια αναθεώρηση που εισάγει τον αλγόριθμο.


13. Εξωτερικό Περιτύλιγμα Κρυπτογράφησης

13.1 Λογική

Τα επίπεδα πρωτοκόλλου (QubEnvelope → tlock → SealedQub) κάνουν ένα σφραγισμένο qub χρονοκλειδωμένο: το σώμα είναι μη αναγνώσιμο μέχρι το unlock_at και τη δημοσίευση της υπογραφής γύρου drand. Μετά το ξεκλείδωμα, ωστόσο, η υπογραφή γύρου είναι δημόσια και το κανονικό σχήμα CBOR του SealedQub είναι αναγνωρίσιμο, οπότε ένας συλλέκτης που έχει ευρετηριάσει συναλλαγές μόνιμης αποθήκευσης θα μπορούσε να αποκρυπτογραφήσει μαζικά ολόκληρο το σώμα qubs.

Για την ιδιωτική παράδοση, το εξωτερικό περιτύλιγμα κρυπτογράφησης κλείνει αυτό το κανάλι παρεμβάλλοντας ένα επιπλέον συμμετρικό επίπεδο AEAD μεταξύ του κανονικού SealedQubCbor και των αποθηκευμένων bytes. Στη διαδρομή σφράγισης του περιηγητή, το κλειδί 256-bit K ζει μόνο στο fragment της URL παράδοσης και στις συσκευές των χρηστών· οι περιηγητές δεν μεταδίδουν fragments URL σε διακομιστές, επομένως το qub.social, κάθε πύλη αποθήκευσης και κάθε CDN μπροστά τους δεν βλέπουν το K. Η αποθηκευμένη αναπαράσταση ενός ιδιωτικού qub είναι συνεπώς αδιαφανές κρυπτοκείμενο, του οποίου το απλό κείμενο δεν ανακτάται χωρίς την URL που επέλεξε να μοιραστεί ο δημιουργός. Η δημόσια παράδοση παραλείπει σκόπιμα αυτό το επίπεδο (§13.8).

Καθαρό αποτέλεσμα:

13.2 Στρώσεις

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

Η σφράγιση και το ξεκλείδωμα στο επίπεδο του πρωτοκόλλου (§7, §8) δεν αλλάζουν κάτω από το όριο του περιτυλίγματος· το περιτύλιγμα προσαρμόζεται στη θέση κλήσης του seal() και αποσπάται στη θέση κλήσης του unlock().

13.3 Δομή Δεδομένων 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
}

Αναλλοίωτα πεδίων.

Κωδικοποίηση CBOR. Κανονικό CBOR ανά §3, με τον ίδιο κανόνα ταξινόμησης κλειδιών (ταξινόμηση κατά κωδικοποιημένο μήκος bytes σε αύξουσα σειρά, μετά λεξικογραφικά). Τα τέσσερα κλειδιά είναι:

Κλειδί Κωδικοποιημένα bytes Σειρά
nonce 6 1
qub_id 7 2
version 8 3
ciphertext 11 4

Το πρώτο byte του CBOR OuterWrapper είναι επομένως η κεφαλίδα χάρτη καθορισμένου μήκους για χάρτη 4 εισόδων (0xA4).

13.4 Δέσμευση AAD στο qub_id

Το περιτύλιγμα δεσμεύει το qub_id ως πρόσθετα πιστοποιημένα δεδομένα AEAD. Αυτή είναι η κρίσιμη δομική άμυνα έναντι τριών κατηγοριών επίθεσης:

Επίθεση Άμυνα
Μετακίνηση κρυπτογραφημένου κειμένου κάτω από διαφορετικό πεδίο qub_id στο περιτύλιγμα Αναντιστοιχία AAD → αποτυγχάνει η πιστοποίηση AEAD
Ανάμιξη του fragment URL του qub A με τα αποθηκευμένα bytes του qub B Λάθος κλειδί (και ανεξάρτητα δεσμευμένο AAD) → αποτυγχάνει η πιστοποίηση AEAD
Αλλοίωση του πεδίου qub_id του περιτυλίγματος μετά το ανέβασμα Αναντιστοιχία AAD → αποτυγχάνει η πιστοποίηση AEAD

Η μεταφορά του qub_id στο απλό κείμενο του περιτυλίγματος δεν αποδυναμώνει ουσιαστικά την ανοσία απαρίθμησης — το qub_id το ίδιο είναι κατακερματισμός SHA3-256 της προεικόνας §4.1 χωρίς ανακτήσιμη προεικόνα από τη σύνοψη, και ένας απαριθμητής που έχει ήδη συλλέξει τα bytes του περιτυλίγματος δεν μαθαίνει τίποτα από το ορατό qub_id που δεν θα μπορούσε να συμπεράνει από την ίδια την ύπαρξη του ανεβάσματος.

13.5 Αλγόριθμοι Περιτυλίγματος και Ξεπεριτυλίγματος

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

Συμπύκνωση τρόπου αποτυχίας. Λάθος K, λάθος nonce, αναντιστοιχία AAD και αλλοιωμένο κρυπτογραφημένο κείμενο όλα παράγουν το ίδιο σφάλμα DECRYPT_FAILED. Αυτή είναι σκόπιμη ιδιότητα AEAD: η διάκριση του τρόπου αποτυχίας θα δημιουργούσε ένα πλευρικό κανάλι που ένας απομακρυσμένος επιτιθέμενος θα μπορούσε να εξετάσει στέλνοντας κακοδιαμορφωμένα περιτυλίγματα και χρονομετρώντας την απάντηση. Οι υλοποιήσεις αναφοράς ΠΡΕΠΕΙ να συμπυκνώνουν όλες τις αποτυχίες AEAD σε ένα μόνο σχήμα σφάλματος.

13.6 Υλικό Κλειδιού και Διανομή

Το κλειδί περιτυλίγματος K είναι μια 256-bit ομοιόμορφη τυχαία τιμή που παράγεται ανά-qub από ένα CSPRNG. Οι υλοποιήσεις αναφοράς το πηγάζουν από:

Διανομή: το K ΠΡΕΠΕΙ να κωδικοποιείται ως URL-safe base64 (RFC 4648 §5, χωρίς γέμισμα) και να προσαρτάται στην URL παράδοσης ως το συστατικό fragment:

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

Το τμήμα fragment δεν μεταδίδεται ποτέ σε κανέναν διακομιστή από συμμορφούμενο περιηγητή. Τα κανάλια ανάκτησης (ευρετήριο ιστορικού από την πλευρά του διακομιστή, opt-in αυτόματη αποστολή email) που διατηρούν την πλήρη URL παράδοσης — συμπεριλαμβανομένου του τμήματος fragment — πέραν της συσκευής του χρήστη είναι ρητός συμβιβασμός έναντι της προεπιλεγμένης κρυπτο-τεμαχιστικής θέσης και ΠΡΕΠΕΙ να ελέγχονται από ρητή συγκατάθεση του χρήστη.

Απώλεια τμήματος fragment. Εάν ένας χρήστης χάσει το τμήμα fragment της URL και δεν έχει κανάλι ανάκτησης, το qub είναι μη αναγνώσιμο. Αυτός είναι ο κρίσιμος συμβιβασμός του σχεδιασμού και ΠΡΕΠΕΙ να αποκαλύπτεται στον χρήστη κατά τον χρόνο σφράγισης. Το MVP ενισχύει την αποκάλυψη χρόνου σφράγισης με ρητό κείμενο «αποθηκεύστε αυτή τη URL» και κανάλι ανάκτησης με επαληθευμένο email για χρήστες που επιλέγουν.

13.7 Εκτός Εμβέλειας για αυτή την Ενότητα

13.8 Δημόσια qubs (παράλειψη περιτυλίγματος)

Το εξωτερικό περιτύλιγμα είναι προαιρετικό στο επίπεδο παράδοσης. Ένας δημιουργός μπορεί να σφραγίσει ένα qub ως δημόσιο, οπότε το κανονικό SealedQubCbor εισέρχεται απευθείας στη ροή αποθήκευσης, χωρίς επίπεδο OuterWrapper και χωρίς κλειδί K:

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

Ένα δημόσιο qub είναι χρονοκλειδωμένο αλλά όχι ελεγχόμενο από σύνδεσμο: παραμένει μη αναγνώσιμο μέχρι να δημοσιευθεί ο γύρος drand του (το επίπεδο tlock δεν αλλάζει), αλλά μετά το ξεκλείδωμα οποιοσδήποτε έχει το αναγνωριστικό συναλλαγής αποθήκευσης μπορεί να το αποκρυπτογραφήσει — δεν απαιτείται fragment URL, επειδή δεν υπάρχει K. Αυτός είναι ο σκόπιμος συμβιβασμός για επιφάνειες που πρέπει να καθοδηγεί ο διακομιστής: τα email ειδοποίησης αποκάλυψης, οι σύνδεσμοι oEmbed/αυτόματης ενσωμάτωσης χωρίς fragment και το πλουσιότερο SEO μετά την αποκάλυψη χρειάζονται σύνδεσμο που λειτουργεί χωρίς μυστικό που ο διακομιστής δεν κατέχει ποτέ (§13.6). Ένα ιδιωτικό qub μπορεί να συνεχίσει να χρησιμοποιεί τη ρητή μορφή <qub-embed src="full_delivery_url"> όταν ο εκδότης παρέχει την πλήρη δυνατότητα που περιέχει το fragment.

Συνέπειες που ένας παραγωγός ΠΡΕΠΕΙ να λάβει υπόψη:

Το ιδιωτικό (περιτυλιγμένο) παραμένει η προεπιλογή· το δημόσιο είναι ρητή επιλογή του δημιουργού ανά qub.


14. Δοκιμαστικά Διανύσματα

14.1 Παραγωγή 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

Οι υλοποιήσεις ΠΡΕΠΕΙ να παράγουν πανομοιότυπες τιμές body_hash και qub_id για αυτή την είσοδο. Αυτό το δοκιμαστικό διάνυσμα ΘΑ ΕΠΡΕΠΕ να είναι το πρώτο unit test που γράφεται. Οι κανονικές τιμές παραπάνω υπολογίστηκαν από την υλοποίηση αναφοράς και ΠΡΕΠΕΙ να ταιριάζουν bit προς bit. Ιστορικές διατάξεις πρωτοτύπων πριν από την κυκλοφορία, από τις οποίες δεν εξαρτήθηκε κανένα ενεργό qub στις πρώτες δύο περιπτώσεις, χρησιμοποιούσαν 92 bytes πριν από το outcome_at (3d9fc2390eab043d38a1669ed3b71be76f9eefe872b9569ab1aaa027b88392b0) και 100 bytes μετά την προσθήκη του outcome_at_or_zero (b0d032898ad629795150fdcb3f84e518f59ed05b7a2a82bc24ebdb87f52144ed). Η τρέχουσα διάταξη 108 bytes πρόσθεσε κατόπιν το drand_round και τον διαχωριστή πεδίου QUB_ID_V2. Ένα πρώιμο διάνυσμα 108 bytes χρησιμοποιούσε την παλαιά αντιστοίχιση γύρου ceil (drand_round = 4695445) και παρήγαγε 3a9fcb31b750d985c262fada6d4f777fd6a28be831d941d85c131f5a4bbaf8a4 — εξακολουθεί να αποτελεί έγκυρο qub_id για εκείνη την είσοδο γύρου, ενώ το παραπάνω παράδειγμα ακολουθεί την τρέχουσα αντιστοίχιση γύρου της §4.3.

14.2 Αντιστοίχιση Γύρου Ξεκλειδώματος

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

Ο γύρος 4675286 δημοσιεύεται τη στιγμή 1595431050 + (4675286 - 1) * 30 = 1735689600 — ακριβώς στο unlock_at, ποτέ νωρίτερα. Η παλαιά αντιστοίχιση ceil πριν από την έκδοση έδινε 4675285, που δημοσιευόταν στο 1735689570, δηλαδή 30 δευτερόλεπτα νωρίτερα· οι επαληθευτές δέχονται αυτόν τον παλαιό γύρο σύμφωνα με την §4.3.

14.3 Κανονικό CBOR Round-Trip

Οι υλοποιήσεις ΠΡΕΠΕΙ να επαληθεύουν ότι serialize(parse(serialize(qub))) == serialize(qub) για όλες τις έγκυρες εισόδους. Αυτό είναι ένα property test, όχι ένα μεμονωμένο διάνυσμα.

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)

Τα κανονικά bytes CBOR και ο SHA3-256 body_hash υπολογίζονται από την υλοποίηση αναφοράς. Οι υλοποιήσεις ΠΡΕΠΕΙ να παράγουν byte-πανομοιότυπο CBOR για αυτή την είσοδο.

Οι υλοποιήσεις ΠΡΕΠΕΙ επίσης να επαληθεύουν ότι serialize(parse(serialize(pact))) == serialize(pact) για όλες τις έγκυρες εισόδους PactTerms (property test).

14.5 Διανύσματα Εξωτερικού Περιτυλίγματος Πολλαπλών Γλωσσών

Το εξωτερικό περιτύλιγμα (§13) έχει ξεχωριστό κανονικό fixture στο crates/qub-core/tests/vectors/wrapper_v1.json. Κάθε περίπτωση καρφιτσώνει μια τετράδα (key, nonce, qub_id, sealed_cbor) ως αδιαφανείς εισόδους hex και ισχυρίζεται μια συγκεκριμένη έξοδο expected_wrapper_hex. Και οι δύο υλοποιήσεις αναφοράς καταναλώνουν το ίδιο αρχείο JSON:

Το fixture καρφιτσώνει τρεις περιπτώσεις περιτυλίγματος χαμηλού επιπέδου. Ελέγχουν τη ντετερμινιστική κωδικοποίηση OuterWrapper και τη διαλειτουργικότητα AEAD ανεξάρτητα από το invariant σχήματος παράδοσης της §13.8· ειδικότερα, το ιστορικό όνομα basic-text-public και η εσωτερική του visibility = 0x01 δεν καθιστούν τα περιτυλιγμένα bytes συμμορφούμενη δημόσια παράδοση. Ένας παραγωγός ΠΡΕΠΕΙ να αποθηκεύει τα δημόσια εσωτερικά bytes γυμνά και να περιτυλίγει μόνο ιδιωτικά (0x00) εσωτερικά bytes.

Περίπτωση Κάλυψη
basic-text-public Ιστορικό όνομα fixture χαμηλού επιπέδου. Το μικρότερο ρεαλιστικό σχήμα SealedQub, χωρίς προαιρετικά πεδία· ελέγχει μόνο bytes περιτυλίγματος και δεν αποτελεί συμμορφούμενη αποθηκευμένη παράδοση κατά §13.8.
with-recipient-pubkey SealedQub με ορισμένο recipient_pubkey, μια δεσμευμένη μελλοντική διαδρομή. Ασκεί διαφορετικό σύνολο εσωτερικών κλειδιών CBOR· το διακριτό περιεχόμενο του fixture παράγει ανεξάρτητα διαφορετικό qub_id — το ίδιο το recipient_pubkey δεν ανήκει στην προεικόνα της §4.1.
longer-body Σώμα ~4 KiB — εξασκεί προθέματα μήκους CBOR πολλαπλών bytes τόσο μέσα στον εσωτερικό φάκελο όσο και στο εξωτερικό κρυπτογραφημένο κείμενο.

Οι υλοποιήσεις ΠΡΕΠΕΙ να παράγουν byte-πανομοιότυπο expected_wrapper_hex για τις καταγεγραμμένες εισόδους. Η αναγέννηση του fixture απαιτεί QUB_REGEN_VECTORS=1 cargo test -p qub-core --test wrapper_vectors και προορίζεται για σκόπιμες αλλαγές μορφής.


15. Διακυβέρνηση Κρυπτογραφικού Προφίλ (Μελλοντικά)

Αυτή η ενότητα είναι πληροφοριακή για την v1 και γίνεται κανονιστική την πρώτη φορά που ένας δεύτερος αλγόριθμος εισέρχεται σε οποιοδήποτε από τα κρυπτογραφικά πρωτεύοντα του qub.

15.1 Τρέχουσα Στάση

Το πρωτόκολλο v1 δεσμεύει ακριβώς έναν αλγόριθμο ανά πρωτεύον:

Οι επαληθευτές κωδικοποιούν επί του παρόντος σταθερά τα μήκη κλειδιών και υπογραφών ανά ενεργό πρωταρχικό. Τα bytes sig_alg και έκδοσης περιτυλίγματος είναι ρητοί επιλογείς, αλλά η v1 δεν εκτελεί διαπραγμάτευση εντός ζώνης και δέχεται μόνο τις παραπάνω ενεργές τιμές.

15.2 Επιδιωκόμενο Σχήμα

Όταν ένας δεύτερος αλγόριθμος εισέλθει στο πρωτόκολλο, ο επαληθευτής θα διαμορφωθεί για ένα ονομασμένο CryptoProfile (π.χ., ExqubV1) που θα παραθέτει το ακριβές σύνολο επιτρεπόμενων τιμών ανά πρωτεύον — sig_algs, αλυσίδες drand, εκδόσεις περιτυλίγματος, τύπους περιεχομένου. Το προφίλ είναι σταθερό κατά τον χρόνο επαλήθευσης, ποτέ διαπραγματεύσιμο in-band. Οποιαδήποτε τιμή εκτός του ενεργού προφίλ απορρίπτεται.

Αυτό εγγυάται ότι η προσθήκη ML-DSA-87 ή η ενεργοποίηση του Ed25519 δεν μπορεί να αποδυναμώσει αναδρομικά υπάρχουσες διαμορφώσεις επαληθευτή: ένας επαληθευτής v1 παραμένει επαληθευτής v1 ακόμη και αφού δημοσιευθεί ένα προφίλ v2.

15.3 Συνθήκες Ενεργοποίησης

Προωθήστε την §15 σε κανονιστική κατάσταση όταν προταθεί οποιοδήποτε από τα ακόλουθα:

Μέχρι τότε η §15 είναι ένα placeholder που σταθεροποιεί το σχήμα μετάβασης ώστε μελλοντικά PRs να προσγειώνονται σε γνωστό στόχο αντί να επανα-διαπραγματεύονται την επιφάνεια διαπραγμάτευσης από την αρχή.


16. Μητρώο καταγραφής διαφάνειας και βαθμίδες ανθεκτικότητας (Εφαρμόστηκε — η επανεξέταση ολοκληρώθηκε)

Κατάσταση. Αυτή η ενότητα είναι υλοποιημένη (W5/UP-B1, Στάδια 1–8), με το πεδίο εφαρμογής του παραγωγού και της βάσης εμπιστοσύνης να αναφέρονται εδώ. Οι μορφές καλωδίων, ο κατακερματισμός και οι διαδρομές επαλήθευσης είναι ενεργές: οι βασικοί τύποι Merkle + canonical-CBOR (qub-core), ο καθρέφτης TypeScript + το πακέτο ANS-104 (workers/api/src/crypto/), ο χώρος αποθήκευσης κόμβων R2 LogDO ενός συγγραφέα + συντεταγμένων κλειδιών, η προσπάθεια προσάρτησης καταγραφής /upload, τα crons ημερήσιας άγκυρας + bundler-drain, τα τελικά σημεία απόδειξης GET /api/v1/qub/:tx_id/proof (συμπερίληψης) και GET /api/v1/log/consistency (RFC 9162), η δακτυλογραφημένη απόδειξη συμπερίληψης που μεταφέρεται στη δέσμη .qub (§17.5), ο εγγενής επαληθευτής αγκύρωσης ANS-104 (tools/qub-verify) και το άγκιστρο διπλής αυτοδημοσιευμένης κεφαλής (§16.6). Ένα επιτυχημένο /upload είναι πάντα ανθεκτικό στο R2, αλλά καλύπτεται από αρχεία καταγραφής μόνο όταν LOG_DO έχει ρυθμιστεί και η ενσωματωμένη προσάρτηση πετύχει. Μόνο τότε η απόκρισή του φέρει log_seq, receipt και anchor_status. Εάν RECEIPT_SK απουσιάζει ή δεν είναι έγκυρη, η sig_b64url αυτής της απόδειξης είναι κενή και δεν παρέχει μη αποκήρυξη. Οι τρέχουσες διαδρομές δημοσίευσης /seal και συμφώνου προγραμματίζουν μεμονωμένες συναλλαγές Arweave αλλά δεν προσαρτούν ένα φύλλο καταγραφής. Κανένας κώδικας δεν εκτελεί επί του παρόντος την προτεινόμενη μεταγενέστερη συμφωνία του /upload σχολίου μετά από αποτυχία προσάρτησης. Η εξωτερική αναθεώρηση του W5 έχει ολοκληρωθεί: Η §16.15 καταγράφει τις αποφάσεις σχεδιασμού και τους περιορισμούς εκκίνησης, αλλά αυτοί οι περιορισμοί δεν επεκτείνουν την κάλυψη του παραγωγού που μόλις αναφέρθηκε. Τρία στοιχεία εμπιστοσύνης/ανάπτυξης παραμένουν περιφραγμένα: (α) το αποκλειστικό πορτοφόλι αγκύρωσης (ANCHOR_JWK; LogProfile.anchor_owner εξακολουθεί να είναι το [0xAB; 32] σύμβολο κράτησης θέσης). (β) το κλειδί υπογραφής απόδειξης και το αντίστοιχο PIN δημόσιου κλειδιού (το RECEIPT_SK είναι προαιρετικό και LogProfile.receipt_pubkey είναι προς το παρόν κενό). και (γ) το αποθετήριο GitHub + διακριτικό GitHub που δημοσιεύονται μόνοι τους (§16.6). Μέχρι να παρασχεθούν οι καρφίτσες αγκύρωσης/προφίλ, ένας αυτόνομος επαληθευτής αναφέρει την κατάσταση απόδειξης με ειλικρίνεια αντί να διεκδικήσει μια πλήρως αγκυρωμένη, καρφιτσωμένη επαλήθευση. Ο σχεδιασμός είναι αυστηρά πρόσθετος και δεν υπάρχει καμία αλλαγή στη μορφή SealedQub / QubEnvelope σύρμα.

16.1 Σκεπτικό και επίπεδα ανθεκτικότητας

Οι τρέχουσες διαδρομές δημοσίευσης αποσυνδέουν την επιβεβαίωση από την επιβεβαίωση Arweave: αντλούν και υπογράφουν μια μεμονωμένη συναλλαγή, διατηρούν το τεχνούργημα και την ακριβή κατάσταση υποβολής στο R2 και, στη συνέχεια, δημοσιεύουν ασύγχρονα. Το αρχείο καταγραφής διαφάνειας προσθέτει ένα ανεξάρτητα αγκυρωμένο επίπεδο ταξινόμησης για το υποσύνολο των αιτήσεων γενικής /upload των οποίων η LogDO προσάρτηση είναι επιτυχής:

Όνομα Βαθμίδας Εγγύηση Πότε
T1 R2-first synchronous ack Durability floor — τα σφραγισμένα byte και η ακριβής κατάσταση δημοσίευσης εγγράφονται σε ανθεκτικό χώρο αποθήκευσης πριν επιστραφεί η επιτυχία. Υλοποιείται σε όλες τις τρέχουσες διαδρομές δημοσίευσης.
T2 Συμπερίληψη ομαδικού αρχείου καταγραφής διαφάνειας δέσμευση μόνο για προσάρτηση, προφανής παραβίαση + συνολική παραγγελία μόλις συμπεριληφθεί και αγκυρωθεί. Τρέχων παραγωγός: επιτυχής LogDO προσαρτά από /upload. Η απάντηση φέρει την πλειάδα παραλαβής. Δεν είναι καθολική.
T3 Per-qub Μονιμότητα Arweave Μια μεμονωμένη συναλλαγή Arweave για το qub. Επί του παρόντος προετοιμάζεται για κάθε αποδεκτή δημοσίευση και δημοσιεύεται ασύγχρονα. Η ακριβής υπογεγραμμένη συναλλαγή παραμένει στα εξερχόμενα με δυνατότητα αποστράγγισης μέχρι να παραδοθεί.

Οι βαθμίδες περιγράφουν διακριτά στοιχεία και ιδιότητες ανθεκτικότητας, όχι το τρέχον εμπορικό σχέδιο. Ο παρών κώδικας εξακολουθεί να προγραμματίζει μια μεμονωμένη συναλλαγή Arweave για κάθε αποδεκτή δημοσίευση. δεν εκθέτει το T3 μόνο ως πληρωμένη ανοδική πώληση. Τα ανώτατα όρια κλειδιού/λογαριασμού API παραμένουν ξεχωριστοί έλεγχοι εφαρμογών.

Ειλικρίνεια ανθεκτικότητας. Η εγγραφή T1 είναι σύγχρονη, επομένως μια επιτυχημένη απόκριση δημιουργεί ανθεκτικότητα σε επίπεδο εφαρμογής χωρίς να περιμένει μια πύλη Arweave. Δεν δημιουργεί η ίδια μια ανεξάρτητη χρονική σήμανση. Μια επιβεβαιωμένη μεμονωμένη συναλλαγή παρέχει το άνω όριο του χρόνου μπλοκ. Για μια απόκριση που φέρει την πλήρη πλειάδα παραλαβής T2, η επόμενη επιβεβαιωμένη άγκυρα μπορεί να παρέχει την απόδειξη καταγραφής που περιγράφεται παρακάτω. Εάν η πλειάδα απουσιάζει, καμία επιφάνεια δεν μπορεί να υπονοεί ότι αυτό το qub βρίσκεται ήδη στο αρχείο καταγραφής διαφάνειας. Η αγκύρωση και η καθυστέρηση δημοσίευσης δεν έχουν αριθμητικό SLA σε επίπεδο πρωτοκόλλου.

16.2 Δομή LogLeaf (δύο δεσμευμένα σχήματα)

Μια καταχώρηση αρχείου καταγραφής είναι μια LogLeaf, κωδικοποιημένη ως χειρόγραφο κανονικό CBOR σύμφωνα με το προφίλ §3.1 (ορισμένου μήκους, χωρίς ετικέτες, χωρίς δεκαδικούς αριθμούς, ακέραιοι σε συντομότερη μορφή, κείμενο NFC, προαιρετικά πεδία παραλείπονται όταν απουσιάζουν, τα κλειδιά ταξινομούνται κατά αύξουσα σειρά μήκους κωδικοποιημένων byte και στη συνέχεια ανα byte). Η κανονική φρουρά parse → re-encode → compare §3.1 εφαρμόζεται στη διαδρομή κωδικοποίησης πριν το hashing (όχι μόνο κατά την αποκωδικοποίηση), ώστε δύο υλοποιήσεις να μην διαφωνούν στα bytes των φύλλων λόγω διαφοράς πλάτους ακεραίων ή σειράς κλειδιών. Όλοι οι ακέραιοι είναι u8 / u64 / i64· όλοι οι κατακερματισμοί είναι 32-byte byte strings (bstr[32]). Ένα αποθηκευμένο id συναλλαγής Arweave είναι ένας ακατέργαστος 32-byte SHA-256 digest που φέρεται ως bstr[32], ποτέ ως αλφαριθμητικό base64url (συμβαδίζει με το §3.3).

Το φύλλο έχει δύο μορφές που επιλέγονται από ένα byte kind, επειδή η γενική διαδρομή μεταφόρτωσης είναι τυφλή ως προς τα bytes: το POST /api/v1/upload αντιμετωπίζει σκόπιμα και τις δύο αποδεκτές μορφές φορτίου ως αδιαφανείς και λαμβάνει qub_id και unlock_at μόνο ως μη αξιόπιστες δηλώσεις πελάτη. Στη προεπιλεγμένη ιδιωτική διαδρομή, body_hash, drand_round, created_at και drand_chain_version είναι επίσης κρυμμένα μέσα στο εξωτερικό περιτύλιγμα §13, του οποίου το κλειδί δεν κατέχει ποτέ ο Εργαζόμενος. Το σύστημα τύπων ορίζει επίσης μια πιστοποιημένη μορφή για έναν παραγωγό που παράγει body_hash / drand_round ο ίδιος. Η τρέχουσα διαδρομή /seal περιέχει αυτές τις τιμές αλλά δεν καλεί το LogDO, επομένως η παραγωγή εκδίδει επί του παρόντος μόνο δηλωμένα (0x02) φύλλα από επιτυχείς προσθήκες γενικής μεταφόρτωσης. Ο διαχωρισμός διατηρεί κάθε δεσμευμένη τιμή αξιόπιστη χωρίς να προσποιείται ότι ο πιστοποιημένος παραγωγός είναι συνδεδεμένος:

Κλειδί Enc. len Τύπος Παρουσία Σημασία
seq 4 u64 που απαιτούνται Παγκόσμιος δείκτης φύλλων με βάση το 0. τη θέση στην οποία δεσμεύεται η απόδειξη συμπερίληψης.
kind 5 u8 απαιτούμενο 0x01 επιβεβαιωμένο (καθορισμένο, μη εκπέμπεται επί του παρόντος) ή 0x02 διεκδικούμενο (client-seal / byte-blind upload).
ref 4 bstr[32] απαιτείται Αναγνωριστικό αναφοράς φύλλου. Επικυρωμένο → ακατέργαστο qub_id. Υποστηρίζεται → το τυφλωμένο id SHA3-256(qub_id ‖ log_blind_secret) (§16.2.1).
chash 6 bstr[32] που απαιτούνται διεύθυνση περιεχομένου SHA3-256(stored_bytes) — τη μία σύνδεση περιεχομένου που ο εργαζόμενος μπορεί πάντα να υπολογίσει με ειλικρίνεια, και στις δύο διαδρομές.
unlock_at 10 i64 απαιτείται Αντιγράφηκε (βεβαιώθηκε) ή βεβαιώθηκε (βεβαιώθηκε). επικυρωμένο > 0 πριν μπει στο φύλλο.
received_at 12 i64 απαιτείται Ρολόι τοίχου εργάτη στο R2-ack. Μη αποδεικτικό (με διεκδίκηση από τον χειριστή, §16.6). Παρόν για αυτοπεριγραφή, ποτέ απόδειξη. Επικυρωμένο > 0.
body_hash 10 bstr[32] kind=0x01 μόνο Παραλείπεται στο 0x02 — ο Εργάτης δεν το έχει σύμφωνα με την §13.
drand_round 12 u64 kind=0x01 μόνο Παραλείπεται στις 0x02.

Ένα φύλλο kind=0x02 σκόπιμα δεν διαπράττει ούτε body_hash ούτε drand_round: πιστοποιεί τη δέσμευση και τη διάταξη ενός αδιαφανούς κρυπτογραφημένου κειμένου στο chash διεύθυνσης περιεχομένου, διεκδικώντας qub_id και unlock_at — όχι το απλό κείμενο ή το στρογγυλό του. Τα σκέλη απλού κειμένου/στρογγυλού κειμένου για ένα ισχυριζόμενο qub προέρχονται από την υπάρχουσα επαλήθευση δέσμης .qub §11, όχι από το αρχείο καταγραφής (§16.11). drand_chain_version δεν βρίσκεται στο φύλλο (βρίσκεται μέσα στο περιτύλιγμα στην προεπιλεγμένη διαδρομή). Η κοκκοποίηση της αλυσίδας ζει στην άγκυρα (§16.7). Πειθαρχία κωδικοποιητή: απορρίψτε ένα ref ή chash με το μηδέν και απορρίψτε τα μη θετικά unlock_at / received_at, αντικατοπτρίζοντας τον φρουρό φρουρού outcome_at > 0 σε cbor.rs.

16.2.1 Τύφλωση ιδιωτικού qub

Το αρχείο καταγραφής δεν πρέπει να γίνει ο χρησμός απαρίθμησης που υπάρχει για να αποτρέψει το εξωτερικό περιτύλιγμα §13 (§13.1). Για ένα ιδιωτικό (τυλιγμένο) qub το φύλλο asserted δεσμεύει το τυφλό αναγνωριστικό SHA3-256(qub_id ‖ log_blind_secret), όπου log_blind_secret είναι μυστικό που κατέχεται από τον διακομιστή, και παραλείπει body_hash. Ένα τρίτο μέρος δεν μπορεί να συνδέσει ένα τέτοιο φύλλο με ένα συγκεκριμένο qub_id. Ο κάτοχος του qub, ο οποίος έχει τη διεύθυνση URL παράδοσης και επομένως qub_id, μπορεί να υπολογίσει εκ νέου το blind για να επιβεβαιώσει τη δική του συμπερίληψη. Ένα δημόσιο qub (ήδη αριθμήσιμο, που φέρει ήδη την ετικέτα Arweave Visibility: public σύμφωνα με την §13.8) δεσμεύει το ακατέργαστο qub_id. Αυτό είναι το μόνο μέρος όπου η αυτόνομη επαληθευσιμότητα υποχωρεί σκόπιμα σε μια φέρουσα αμετάβλητη ιδιωτικότητα. Η αυτόνομη ισοπαλία για ιδιωτικά qubs είναι chash (§16.9).

log_blind_secret φύλαξη (επιλύθηκε — §16.15 Q4). Το blind προστατεύει την αποσύνδεση φύλλων, όχι την εμπιστευτικότητα απλού κειμένου (το περιτύλιγμα §13 το κρατά ανεξάρτητα). Σε έναν log_blind_secret συμβιβασμό, για κάθε qub_id που ο αντίπαλος κατέχει ήδη ή μπορεί να ανακατασκευάσει (κάθε qub του οποίου το πακέτο/URL έχει, συν οποιαδήποτε χαμηλή εντροπία ή δημόσιο qub_id) υπολογίζει εκ νέου το φύλλο ref σε ένα hash και το συνδέει — αυτή είναι άμεση σύνδεση ενός γνωστού πληθυσμού, όχι ωμή βία σε έναν άγνωστο χώρο. Ταξινομήστε log_blind_secret ως μυστικό συσχέτισης/βαθμού Sybil στην ίδια βαθμίδα φύλαξης με άλλα μυστικά διακομιστή και περιστρέψτε μόνο προς τα εμπρός (μια περιστροφή τυφλώνει εκ νέου τα μελλοντικά φύλλα, δεν μπορεί να αποσυνδέσει αναδρομικά τα ήδη αγκυρωμένα).

16.3 Κατακερματισμός φύλλων και κόμβων

RFC 6962 §2.1 κατακερματισμός διαχωρισμένος από τομέα με το SHA-256 να αντικαθίσταται από το 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

Τα byte προθέματος τομέα 0x02 (αλυσίδα εισόδου, §16.4) και 0x03 (κατακερματισμός STH, §16.6) είναι δεσμευμένα και ασύνδετα από αυτά. Είναι μεμονωμένα byte και έτσι δεν μπορούν να συγκρουστούν με τους υπάρχοντες διαχωριστές τομέα ASCII 10 byte (QUB_ID_V2, κ.λπ.). Το δέντρο είναι το δέντρο RFC 6962 left-full unbalanced (κάθε εσωτερικό χωρίζεται με τη μεγαλύτερη ισχύ των δύο αυστηρά μικρότερη από τον αριθμό φύλλων του υποδέντρου), το οποίο επιτρέπει στις αποδείξεις συμπερίληψης και συνέπειας να μοιράζονται έναν αλγόριθμο διαδρομής ελέγχου. Η προδιαγραφή αναφοράς φέρει ρητό ψευδοκώδικα αριστερής/δεξιάς παραγωγής και καρφιτσώνει ένα διάνυσμα δοκιμής χωρίς ισχύ των δύο (5 φύλλων) έτσι ώστε να ασκείται η περίπτωση προώθησης στη δεξιά άκρη — την οποία κρύβει ένα διάνυσμα 4 φύλλων.

16.4 Αλυσίδα κατακερματισμού (εσωτερική)

Το LogDO διατηρεί μια εσωτερική αλυσίδα εισόδου μόνο για συνέπεια σφαλμάτων. Δεν δημοσιεύεται ποτέ και ποτέ δεν αντιμετωπίζει επαληθευτή:

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

Η δημοσιευμένη αρχή μόνο για προσάρτηση είναι η αθροιστική ρίζα Merkle + η άγκυρά της (§16.5–16.6), ποτέ η ακατέργαστη σειρά με την οποία ο χειριστής τυχαίνει να εξυπηρετεί φύλλα: η αλυσίδα υπολογίζει εκ νέου για οποιαδήποτε σειρά εξυπηρετείται, επομένως μόνο οι αγκυρωμένες καρφίτσες ρίζας κανονικής θέσης.

16.5 Αθροιστικό Merkle Tree και Batching

Υπάρχει ένα συνεχώς αναπτυσσόμενο δέντρο RFC 6962 πάνω από όλα τα φύλλα με seq σειρά — όχι μεμονωμένα δέντρα ανά παρτίδα. (Μια κατασκευή με αλυσίδα μεταφοράς ανά παρτίδα απορρίφθηκε: δεν είναι μια πραγματική σχέση προθέματος, επομένως οι "αποδείξεις συνέπειας" της είναι αβάσιμες.) Το αθροιστικό δέντρο δίνει γνήσιες αποδείξεις συνέπειας RFC 9162 και επιτρέπει σε μια μόνο πρόσφατη άγκυρα να αποδείξει τη συμπερίληψη για οποιοδήποτε παλαιότερο qub.

Το LogDO Durable Object είναι ο μοναδικός συγγραφέας (blockConcurrencyWhile, mirroring QuotaDO / EntitlementDO) — η προσάρτηση σε ένα κοινόχρηστο αρχείο καταγραφής είναι ανάγνωση-τροποποίηση-εγγραφή σε κοινόχρηστη κατάσταση και επομένως ΠΡΕΠΕΙ να περάσει από ένα DO, ποτέ KV. Αποθηκεύει προσωρινά το σύνορο της δεξιάς άκρης του δέντρου (O(log n) κατακερματισμούς), επομένως το κλείσιμο μιας παρτίδας είναι O(batch). Μια παρτίδα είναι το σύνολο των φύλλων που είναι αγκυρωμένα μεταξύ τους. Οι ενεργοποιητές που έχουν υλοποιηθεί είναι μια tree_size πρόοδος τουλάχιστον LOG_BATCH_MAX_LEAVES (προεπιλογή 4096), η ηλικία που φτάνει στον ρυθμό αγκύρωσης ή ένα ρητό διοικητικό/cron force-close. root_i είναι το αθροιστικό Merkle Tree Hash πάνω από τα φύλλα 0 .. tree_size_i.

16.6 Υπογεγραμμένο κεφάλι δέντρου μέσω άγκυρας Arweave

Η συναλλαγή αγκύρωσης Arweave είναι η υπογεγραμμένη κεφαλή δέντρου και αντικαθιστά μια υπογραφή χειριστή για την ίδια την κεφαλή δέντρου: η ημερήσια άγκυρα δεν χρειάζεται κλειδί qub επειδή το Arweave tx owner είναι η υπογραφή. Η διατριβή της τάφρου ισχύει — το αμετάβλητο υπόστρωμα, όχι ένα μυστικό που κρατιέται από το qub, είναι φέρον για την αγκυρωμένη ρίζα.

Ο σχεδιασμός του αρχείου καταγραφής απαιτεί ένα θερμό κλειδί απόδειξης επιτυχούς προσάρτησης (§16.10), καρφιτσωμένο στο LogProfile και διασταυρωμένο υπογεγραμμένο από anchor_owner. Η τρέχουσα υλοποίηση δεν έχει ολοκληρώσει αυτήν την παροχή ρίζας εμπιστοσύνης: το RECEIPT_SK είναι προαιρετικό, ένα απών/μη έγκυρο κλειδί αποδίδει sig_b64url: "" και η μεταγλωττισμένη LogProfile.receipt_pubkey είναι κενή. Μια τέτοια απόδειξη μπορεί να περιγράψει το προσαρτημένο φύλλο, αλλά δεν είναι μια υπογεγραμμένη απόδειξη που δεν μπορεί να αποκηρυχθεί. Ο ισχυρισμός ισχυρότερου σχεδιασμού ισχύει μόνο αφού ένας επαληθευτής καρφιτσώσει το αντίστοιχο δημόσιο κλειδί και ο κάτοχος της άγκυρας το διασταυρώσει. Μια απόκριση δημοσίευσης χωρίς την πλήρη πλειάδα απόδειξης δεν κάνει καμία αξίωση αποδοχής αρχείου καταγραφής. Κάποιος με κενή υπογραφή κάνει αξίωση θέσης προσάρτησης αλλά όχι αξίωση επαλήθευσης υπογραφής.

Η SignedTreeHead είναι κανονική CBOR (κλειδιά κατά κωδικοποιημένο μήκος): size:u64, root:bstr[32], batch:u64, prev:bstr[32] (προηγούμενη sth_hash, γένεση = 32 μηδέν byte), log_id:bstr[32], first_seq:u64, anchored_at:i64. Ο κατακερματισμός του είναι sth_hash = SHA3-256(0x03 || canonical_cbor(SignedTreeHead)).

Καρφιτσωμένη ρίζα εμπιστοσύνης. log_id = SHA3-256("QUB_TLOG_V1" || anchor_owner_address). Ένας συμμορφούμενος επαληθευτής ΠΡΕΠΕΙ να απαιτεί anchor_tx.owner == LogProfile.anchor_owner, όπου anchor_owner (και το δημόσιο κλειδί απόδειξης-κλειδί) ψήνεται σε qub_core ως LogProfile — μαζί με τις σταθερές quicknet που υπάρχουν ήδη σε DrandTimelockProvider::quicknet() — και διανέμεται με το δυαδικό αρχείο επαληθευτή. Ο επαληθευτής ΠΡΕΠΕΙ επίσης να επαληθεύσει ότι τα δεδομένα Arweave tx → tx_id δεσμεύονται τοπικά αντί να εμπιστεύονται μια πύλη /raw/ απόκριση. Αυτό κλείνει την τρύπα ασάφειας του απατεώνα-πορτοφολιού: το "αγκυροβολημένο στο Arweave" δεν έχει νόημα έως ότου ο επαληθευτής καρφιτσώσει ποιο πορτοφόλι.

Η περιστροφή είναι μια επέκταση διακυβέρνησης §15, όχι μια επαναχρησιμοποίηση (επιλύθηκε — §16.15 Q3). Η επιφάνεια προφίλ της §15.2 απαριθμεί επί του παρόντος μόνο sig_algs / αλυσίδες drand / εκδόσεις περιτυλίγματος / τύπους περιεχομένου και τα εναύσματα της §15.3 δεν απαριθμούν κανένα από αυτά — LogProfile / anchor_owner δεν είναι ακόμα στην επιφάνεια της §15. Επομένως, η διακυβέρνηση περιστροφής πρέπει να κατασκευαστεί: η §15.3 επεκτείνεται (παρακάτω) για να προσθέσει το έναυσμα LogProfile και μια περιστροφή είναι ένα υπογεγραμμένο LogProfile χτύπημα που αποστέλλεται σε μια ενημέρωση επαληθευτή. Μια προγραμματισμένη περιστροφή φέρει μια εξερχόμενη → εισερχόμενη διασταυρούμενη υπογραφή. Μια περιστροφή που βασίζεται σε συμβιβασμούς δεν μπορεί (το εξερχόμενο κλειδί δεν είναι αξιόπιστο/μη διαθέσιμο ακριβώς τότε) και πέφτει πίσω στο χτύπημα που διέπεται από την §15, με τον έλεγχο του πιρουνιού προηγούμενης άγκυρας (παρακάτω) να οριοθετεί τη ζημιά στο ενδιάμεσο.

Παράθυρο ισοδυναμίας (παράμετρος εμπιστοσύνης πρώτης κατηγορίας). Ένα φύλλο είναι ανθεκτικό στην ισοφάριση μόνο όταν η άγκυρα που καλύπτει το Arweave-confirmed. Το παράθυρο είναι received_at → anchor confirmation (ρυθμός + οριστικότητα Arweave, χωρίς εγγύηση καθυστέρησης πρωτοκόλλου). Πριν από την παροχή ρίζας εμπιστοσύνης, η τρέχουσα υλοποίηση παρέχει τη λειτουργική ακεραιότητα του qub συν οποιαδήποτε ανυπόγραφα μεταδεδομένα προσάρτησης υπάρχουν. δεν παρέχει την προγραμματισμένη εγγύηση μη άρνησης. Τρία τεχνουργήματα λογοδοσίας καθορίζουν τον ολοκληρωμένο σχεδιασμό (το μοντέλο μάρτυρα είναι η ανάλυση της §16.15 Q2):

  1. Απόδειξη σφραγίδας (εξαρτώμενη από την παροχή) — το ανάλογο SCT που επιστρέφεται όταν η προσάρτηση αρχείου καταγραφής μιας μεταφόρτωσης είναι επιτυχής (§16.10). Γίνεται μη αποκηρύξιμη μόνο όταν sig_b64url δεν είναι κενή και η αντίστοιχη σχέση δημόσιου κλειδιού/άγκυρας-κατόχου είναι καρφιτσωμένη στον επαληθευτή. Η τρέχουσα κενή καρφίτσα προφίλ παραγωγής δεν μπορεί να υποστηρίξει αυτήν την ετυμηγορία. Αυτός ο έλεγχος δεν ισχύει για μια πλειάδα παραλαβής που έχει παραλειφθεί ή μια ανυπόγραφη απόδειξη.
  2. Δημοσιευμένη μεθοδολογία παρακολούθησης + περπάτημα προηγούμενης αλυσίδας — η άγκυρα prev η αλυσίδα περπατιέται με κεφαλή→γένεση. ένα πιρούνι (δύο άγκυρες σε ένα size με διαφορετικά root ή ένα σπασμένο prev) είναι δημοσιεύσιμη απόδειξη κακής συμπεριφοράς. Η ανίχνευση ασάφειας είναι μια δηλωμένη επιχειρησιακή δέσμευση, όχι μια σιωπηλή υπόθεση.
  3. Διπλές αυτοδημοσιευμένες κεφαλές — κάθε νέο {sth_hash, tree_size} κεφαλίδας δημοσιεύεται σε ένα αποκλειστικό δημόσιο, μόνο προσαρτημένο αποθετήριο GitHub που ανήκει στο qub (το φέρον σκέλος αυτοδημοσίευσης που είναι προφανές για παραβίαση), με μια ανάρτηση κοινωνικής δικτύωσης μόνο ως επιβεβαίωση βέλτιστης προσπάθειας. Μια αποτυχημένη σελίδα MUST ανάρτησης (όχι αθόρυβη αποτυχία). Υλοποιήθηκε (Στάδιο 8) ως το publishHead άγκιστρο στο anchor cron (workers/api/src/utils/heads-publish.ts): μια PUT στο API περιεχομένων χωρίς sha είναι μόνο προσαρτημένη (ένα 422 σημαίνει ότι η κεφαλίδα είναι ήδη δημοσιευμένη, ποτέ αντικατάσταση). opt-in / deploy-gated στο PUBLISH_HEAD_GITHUB_{TOKEN,OWNER,REPO} και αδρανές μέχρι να παρασχεθεί το αποθετήριο. Μια σκληρή αποτυχία GitHub σελίδων μέσω του καναλιού health_alert και προσκρούει σε μια ανθεκτική μέτρηση αποτυχίας (m:tlog_publish_head_fail). Η ίδια η άγκυρα Arweave δεν επανέρχεται ποτέ σε μια αποτυχία δημοσίευσης. Το "Not fail silent" είναι εγγυημένο από αυτήν την ανθεκτική μέτρηση — στην οποία ΠΡΕΠΕΙ να ειδοποιείται ο πίνακας ελέγχου — ακόμα κι αν δεν μπορεί να παραδοθεί η σελίδα email με την καλύτερη προσπάθεια. Δύο ειλικρινείς περιορισμοί προκύπτουν από το "anchor-on-advance" (το cron δημοσιεύει μόνο όταν το μέγεθος προχωρεί): μια παροδική αποτυχία του GitHub αφήνει ένα κενό στην ακολουθία δημοσιευμένων κεφαλών για αυτό το μέγεθος — οριοθετημένο, όχι σιωπηλό (σελίδες it) και επειδή κάθε κεφαλή δεσμεύει ένα δέντρο υπερσυνόλου, μια απόδειξη συνέπειας §16.9 γεφυρώνει το χάσμα. Κυρίως, αυτή η απόδειξη συνέπειας υπολογίζεται από το έγκυρο δέντρο αγκύρωσης Arweave, όχι από την επιφάνεια του GitHub, επομένως ένα κενό GitHub δεν αποδυναμώνει ποτέ την επαληθευσιμότητα. Μια συμπλήρωση που καλύπτει τα κενά των δημοσιευμένων κεφαλών είναι μια αναβαλλόμενη βελτίωση.

Δέσμευση ειλικρίνειας (δεσμευτικός περιορισμός). Επειδή το qub ελέγχει και τις δύο προγραμματισμένες επιφάνειες ανάρτησης, αυτό είναι αυτοδημοσιευμένο, όχι ανεξάρτητο μάρτυρας. Κανένα προϊόν, μάρκετινγκ ή νομική επιφάνεια δεν μπορεί να ισχυριστεί ότι το αρχείο καταγραφής είναι "ανεξάρτητα μάρτυρας". Μετά την παροχή των πυλών απόδειξης/προφίλ/κεφαλής, ο επιτρεπόμενος ισχυρισμός είναι ότι η ασάφεια είναι ανιχνεύσιμη και μια επιτυχώς υπογεγραμμένη προσάρτηση αφήνει μια μη αποκηρυχθείσα απόδειξη. Πριν από αυτό, αυτός ο ισχυρισμός δεν είναι διαθέσιμος. Ένας πραγματικός ανεξάρτητος τρίτος μάρτυρας αναβάλλεται σε ένα μελλοντικό χτύπημα διακυβέρνησης §15.

received_at υποστηρίζεται από τον χειριστή και κανένας ισχυρισμός δεν μπορεί να στηριχθεί σε αυτό — δεν εμφανίζεται ποτέ ως απόδειξη ή ως επιβεβαίωση διαφωνίας σε οποιοδήποτε προϊόν / νομικό / API / επιφάνεια απόδοσης απόδειξης. Η χρονική T μπλοκ αγκύρωσης Arweave είναι η μόνη χρονική σήμανση χωρίς εμπιστοσύνη (ένα άνω όριο στο "καταγράφηκε από"). Οποιοσδήποτε έλεγχος λογικής οθόνης σε received_at ΠΡΕΠΕΙ να συγκριθεί με T, όχι με το πεδίο STH που ελέγχεται από τον χειριστή anchored_at. Ένας τέτοιος έλεγχος είναι μια προστασία μόνο από το σφάλμα ρολογιού ενός έντιμου χειριστή, όχι έλεγχος λογοδοσίας έναντι ενός κακόβουλου χειριστή (§16.15 Q5).

16.7 Μορφή και ρυθμός συναλλαγής αγκύρωσης

Το AnchorBundle είναι το σώμα συναλλαγών Canonical-CBOR Arweave, γραμμένο μέσω του πακέτου §16.8: ver:u8, sth:bstr (κανονικό SignedTreeHead bytes), prev_anchor:bstr (προηγούμενη άγκυρα tx id raw bytes, παραλείπεται στη γένεση), chain_hash:tstr (η αλυσίδα drand σε ισχύ — quicknet) και η ροή φύλλων-CBOR της παρτίδας με seq σειρά έτσι ώστε η άγκυρα να είναι αυτόνομη: μια οθόνη αντλεί εκ νέου root από το σώμα με μηδενική εξάρτηση qub. (Εάν η ροή φύλλων γίνει μεγάλη σε μεγάλο όγκο, μια μελλοντική αναθεώρηση μπορεί να δεσμεύσει μόνο μια σειρά φύλλων με αναφορά· σημειώθηκε, δεν υιοθετήθηκε στην έκδοση 1.)

Οι ετικέτες Arweave είναι σκόπιμα αριθμήσιμες — το αρχείο καταγραφής προορίζεται να βρεθεί, σε αντίθεση με τα ιδιωτικά qubs: App-Name: qub-tlog, Anchor-Format: 1, Log-Id: <hex>, Batch: <n>, Tree-Size: <n>, Root: <hex>, Prev-Anchor: <tx>, Content-Type: application/cbor. Οι ετικέτες είναι μη αξιόπιστες υποδείξεις. Το σώμα CBOR είναι η μόνη αρχή.

Ρυθμός: καθημερινά από προεπιλογή, επανεξετάζεται με όγκο (η σκανδάλη μεγέθους μειώνει αυτόματα τον αποτελεσματικό ρυθμό υπό φορτίο). Ο τρέχων παραγωγός δεν εφαρμόζει άγκιστρο αγκύρωσης δύναμης σφράγισης επί πληρωμή. Το πορτοφόλι άγκυρας είναι αποκλειστικό και χαμηλής ταχύτητας, ξεχωριστό από το πορτοφόλι μεταφόρτωσης — ΠΡΕΠΕΙ να είναι το δικό του JWK** (ένα ξεχωριστό κλειδί, όχι ένας λογικός ρόλος στο πορτοφόλι μεταφόρτωσης), επομένως ένας συμβιβασμός στο πορτοφόλι μεταφόρτωσης δεν μπορεί να σφυρηλατήσει άγκυρες — με σκληρό προϋπολογισμό ανά ημέρα συναλλαγής άγκυρας. Η στάση φύλαξης δηλώνεται ξεκάθαρα: ένα πλήκτρο συντόμευσης στενής εμβέλειας με σφιχτό διακόπτη κυκλώματος και χαμηλή ισορροπία, όχι "κρύο" — ένα πορτοφόλι που υπογράφει αυτόματα καθημερινά δεν μπορεί να είναι κρύο και η προδιαγραφή δεν προσποιείται το αντίθετο.

16.8 Πακέτο ANS-104

Ένας εσωτερικός κωδικοποιητής ANS-104 DataItem και υπογράφων deep-hash, περίπου 300 γραμμές, μόνο Web Crypto, μηδενικές εξαρτήσεις npm (και τα δύο Turbo SDK αποτυγχάνουν στην npm ci --ignore-scripts πύλη εφοδιαστικής αλυσίδας). Διάταξη byte 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

Η υπογραφή είναι το Arweave deepHash — μια αναδρομική σύνοψη SHA-384 (απαίτηση καλωδίου Arweave, crypto.subtle.digest("SHA-384")) πάνω από ["dataitem", "1", sig_type, owner, target, anchor, encoded_tags, data] — στη συνέχεια RSA-PSS πάνω από το βαθύ κατακερματισμό με το πορτοφόλι JWK μέσω crypto.subtle. id = base64url(SHA-256(signature)). Το SHA-384 εδώ είναι σε καραντίνα ως πρωτόγονο μόνο με σύρμα Arweave, ποτέ πρωτόγονο qub trust (η §15 καταγράφει τον φράχτη, ο κατακερματισμός εμπιστοσύνης qub είναι SHA3-256 παντού).

Η διαδρομή κώδικα ANS-104 εξυπηρετεί τον μηχανισμό αναβαλλόμενης εναλλακτικής/αποστράγγισης και γράφει AnchorBundle DataItems. Η συνηθισμένη διαδρομή δημοσίευσης δημιουργεί πρώτα μια ακριβή υπογεγραμμένη συναλλαγή Arweave και διατηρεί το JSON της σε ένα ανθεκτικό εξερχόμενο. Η άμεση ανάρτηση είναι μια βελτιστοποίηση λανθάνοντος χρόνου και η διαδρομή αποστράγγισης επιχειρεί ξανά την ίδια συναλλαγή πριν εφαρμόσει την εναλλακτική της δέσμης. Σχήμα υπογραφής (επιλύθηκε — §16.15 Q8): πινακίδες v1 με RSA-PSS (τύπος υπογραφής 1) επαναχρησιμοποίηση του υπάρχοντος μηχανισμού JWK πορτοφολιού Arweave (μηδέν νέα μακροχρόνια φύλαξη κλειδιού, που εξυπηρετεί τη διατριβή «ένα μυστικό λιγότερο»). Το Ed25519 αναβάλλεται στη διαδρομή μετεγκατάστασης PQ §15.

Ο χειροποίητος βαθύς κατακερματισμός είναι ο κωδικός υψηλότερου κινδύνου και χαμηλότερης φυσικής κάλυψης στο W5, επομένως η πύλη του είναι αδιαπραγμάτευτη (§16.15 Q8):

  1. Η διεπαφή μεταξύ γλωσσών tlog_v1.json (Rust + TS, το πρότυπο §14.5 wrapper_v1.json) καλύπτει deep-hash, bytes + id του DataItem, leaf hashes, μια ρίζα 5 φύλλων + audit path, ένα hash STH, μια απόδειξη ένταξης και μια απόδειξη συνέπειας — σε και τις δύο κατευθύνσεις υπογραφής και επαλήθευσης (η κατεύθυνση επαλήθευσης έχει σημασία επειδή ο έλεγχος τοπικού tx → tx_id της §16.6 τραβάει το deep hash σε κάθε αυτόνομο επαληθευτή, όχι μόνο στον συγγραφέα).
  2. Ένας εφάπαξ γύρος διαλειτουργικότητας μέσω ενός αναφοράς ANS-104 bundler, που χρησιμοποιείται ως στατικά δεδομένα δοκιμής μόνο — ποτέ ως εξάρτηση χρόνου εκτέλεσης npm (η στάση μόνο Web-Crypto / χωρίς scripts εγκατάστασης παραμένει).
  3. Το path deep-hash + RSA-PSS πρέπει να κάνει round-trip μέσω των ίδιων crypto.subtle primitives που χρησιμοποιούνται στην παραγωγή, έτσι ώστε ο εσωτερικός encoder να είναι συμβατός σε byte.
  4. Ένας συνεχιζόμενος monitor αποδοχής μετά το bundle επιβεβαιώνει ότι κάθε anchor / fallback DataItem επιτυγχάνει πραγματικά την αποδοχή στο Arweave, με συναγερμό + circuit breaker — επειδή το deep hash εξυπηρετεί επίσης την ουρά fallback για την μη διαθέσιμη κατάσταση στο Arweave, επομένως μια σιωπηλή παλινδρόμηση θα γεμίσει αυτή την ουρά με αντικείμενα που απορρίφθηκαν από το δίκτυο κατά τη διάρκεια της ακριβούς διακοπής που υπάρχει για να καλύψει.

16.9 Αποδείξεις Ένταξης και Συνέπειας

Και οι δύο είναι RFC 9162, SHA3-256, σε canonical CBOR.

InclusionProof — GET /api/v1/qub/:tx_id/proof: ver:u8, leaf:bstr (το ακριβές leaf CBOR — ο επαληθευτής επαναϋπολογίζει ο ίδιος το leaf_hash και ποτέ δεν εμπιστεύεται ένα παρεχόμενο hash), index:u64, size:u64, audit:[bstr[32]], root:bstr[32], anchor:{ txid:bstr[32], batch:u64, sth:bstr[32], log_id:bstr[32], block_height?:u64, anchored_at?:i64 }.

ConsistencyProof — GET /api/v1/log/consistency?first=<size_a>&second=<size_b>: ver:u8, first_size:u64, second_size:u64, first_root:bstr[32], second_root:bstr[32], nodes:[bstr[32]], first_anchor, second_anchor. Μια μοναδική σαφής λίστα κλειδιών, καθορισμένη από vector δοκιμής.

Αυτόνομη επαλήθευση (χωρίς qub server, επεκτείνει το §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).

Ο χώρος αποθήκευσης που εξυπηρετεί αποδείξεις ΠΡΕΠΕΙ να είναι με συντεταγμένες (επιλύθηκε — §16.15 Q7, προϋπόθεση αποκλεισμού). Η δημιουργία απόδειξης ψυχρών φύλλων είναι ουδέτερη ως προς την ορθότητα μόνο εάν το υλικό ελέγχου R2 είναι ένας μόνιμος χώρος αποθήκευσης Merkle-node που κλειδώνεται με απόλυτη συντεταγμένη δέντρου (level, index) — όχι δέλτα κόμβων ανά batch. Με έναν χώρο αποθήκευσης με συντεταγμένα κλειδιά, οποιαδήποτε διαδρομή ελέγχου (leaf i, size N) είναι ένα σύνολο O(log N) άμεσων R2 GET χωρίς χωρίς επανυπολογισμό πέρα από τα όρια παρτίδας. με έναν χώρο αποθήκευσης με κλειδί παρτίδας δεν είναι, το οποίο είναι το κενό διάταξης αποθήκευσης που κλείνει αυτή η ανάλυση. Τα σώματα των φύλλων μπορούν επίσης να διευθυνσιοδοτηθούν από seq. Ένα διάνυσμα δοκιμής W5 ΠΡΕΠΕΙ να αποδείξει ένα κρύο φύλλο της εποχής της γένεσης έναντι μιας πολύ μεταγενέστερης ρίζας χρησιμοποιώντας μόνο R2 + Arweave με τον χώρο αποθήκευσης LogDO σβησμένο, επομένως ο ισχυρισμός ασφάλειας ανάκτησης στην §16.13 υποστηρίζεται αντί να υποστηρίζεται. Τα O(log N) διαδοχικά R2 GET ανήκουν μόνο στο ασύγχρονο τελικό σημείο απόδειξης — ποτέ στη θερμή διαδρομή σφράγισης (§16.10) ή σε ένα cron ανά τικ.

16.10 R2-Πρώτη παραγγελία Ack

Η ακολουθία POST /api/v1/upload που υλοποιείται είναι:

  1. Μπροστινές μισές πύλες (έλεγχος ταυτότητας, επικύρωση, κλειδί θραύσματος idempotency) — αμετάβλητες.
  2. Δημιουργήστε, προσθέστε ετικέτες και υπογράψτε την ακριβή μεμονωμένη συναλλαγή Arweave. Αυτό προέρχεται tx_id τοπικά, αν και η δημιουργία συναλλαγής μπορεί να ανακτήσει μεταδεδομένα ανταμοιβής/αγκύρωσης από μια πύλη. Μια αποτυχία προετοιμασίας εξακολουθεί να αποτυγχάνει στο αίτημα πριν από την επιβεβαίωση.
  3. Συγχρονισμένα γράψτε το επιλεγμένο τεχνούργημα στο qub-cache/<tx_id> και διατηρήστε τις σταθερές εγγραφές δημιουργίας-λειτουργίας/εξερχόμενων. Αυτά είναι το κατώτατο όριο ανθεκτικότητας και επανάληψης. αποτυχίες πριν από την επιστροφή διακανονισμού 503.
  4. Όταν έχει ρυθμιστεί LOG_DO, σύγχρονη προσπάθεια LogDO.append(leaf). Ο μεμονωμένος συγγραφέας εκχωρεί seq, επεκτείνει την αλυσίδα εισόδου και ενημερώνει τα σύνορα. Το RPC προσάρτησης κάνει μόνο αυτό. Το κλείσιμο παρτίδας εκτελείται εκτός διαδρομής στον συναγερμό. Μια αποτυχία μεταφοράς/εφαρμογής προσάρτησης είναι επί του παρόντος fail-soft: η απόκριση μπορεί ακόμα να πετύχει χωρίς log_seq, receipt ή anchor_status. Παρά το σχόλιο υλοποίησης, δεν υπάρχει αυτόματη μεταγενέστερη συμφωνία καταγραφής σήμερα.
  5. Επιστρέψτε την επιβεβαίωση. Συμπεριλάβετε { log_seq, anchor_status: "pending", receipt } μόνο όταν η προσάρτηση επέστρεψε την πλήρη επιτυχημένη πλειάδα. receipt.sig_b64url είναι κενή όταν ο υπογράφων απόδειξης δεν είναι διαθέσιμος. Οι πελάτες ΔΕΝ ΠΡΕΠΕΙ να αποκαλούν αυτή την τιμή υπογεγραμμένη ή μη αποκηρυχθείσα. Η απουσία της πλειάδας σημαίνει μόνο ανθεκτική δημοσίευση, όχι αποδοχή καταγραφής διαφάνειας.
  6. Χρησιμοποιήστε μια αναβαλλόμενη εργασία για να δημοσιεύσετε την ακριβή υπογεγραμμένη συναλλαγή. Η επιτυχία αφαιρεί τα εξερχόμενα. Η αποτυχία το αφήνει για το δεσμευμένο cron αποστράγγισης και δεν πρέπει να αλλάξει την ήδη αναγνωρισμένη tx_id. Τα προσωρινά μεταδεδομένα και άλλα sidecars καλύτερης προσπάθειας αναβάλλονται επίσης.

Όριο καθυστέρησης. Η διαδρομή αιτήματος περιλαμβάνει εργασία εξουσιοδότησης/ποσόστωσης στο μπροστινό μισό, προετοιμασία/υπογραφή συναλλαγής, ανθεκτικές εγγραφές R2 και (όταν έχει διαμορφωθεί) την προσπάθεια LogDO. < 300 ms εμφανίζεται στην αναθεώρηση σχεδιασμού ως επιχειρησιακός στόχος, όχι ως εγγύηση πρωτοκόλλου. Το τρέχον βήμα προετοιμασίας συναλλαγής μπορεί να εκτελέσει ένα αίτημα μεταδεδομένων πύλης. Οι συναγερμοί καθυστέρησης και οι πύλες εκκίνησης είναι λειτουργικοί έλεγχοι και όχι αποδεικτικά στοιχεία διαθέσιμα σε έναν επαληθευτή.

16.11 Μοντέλο εμπιστοσύνης — ο ακριβής ισχυρισμός, με βάση το είδος του φύλλου

Για kind=0x01 (επιβεβαιωμένο): *"Αυτό το περιεχόμενο — body_hash αντιστοίχισης σώματος, που προσδιορίζεται από qub_id — δεσμεύτηκε στο αρχείο καταγραφής μόνο προσάρτησης του qub στη θέση seq και υπήρχε το αργότερο μέχρι το χρόνο μπλοκ Arweave T. ήταν κρυπτογραφικά μη αναγνώσιμο μέχρι το drand round R = unlock_round(unlock_at)." * Αυτό είναι το πλήρες {tlock round binding + Merkle inclusion + anchored root} τριπλό.

Για kind=0x02 (υποστηρίζεται, η προεπιλογή): *"Ένα αδιαφανές κρυπτογραφημένο κείμενο με chash διεύθυνσης περιεχομένου, που διεκδικεί qub_id και unlock_at, δεσμεύτηκε στο αρχείο καταγραφής μόνο για προσάρτηση στη θέση seq και υπήρχε το αργότερο με το χρόνο αποκλεισμού Arweave T." * Τα στρογγυλά και τα σκέλη του σώματος παρέχονται από την υπάρχουσα επαλήθευση §11 .qub-bundle (qub_core::unlock), όχι από το αρχείο καταγραφής. Αυτό που προσθέτει το αρχείο καταγραφής σε μια συναλλαγή γυμνού ανά qub είναι η προφανής παραγγελία, ο χρόνος δέσμευσης ανώτερου ορίου χωρίς εμπιστοσύνη και η αντίσταση στην ασάφεια.

Και οι δύο ισχυρισμοί αποκλείουν, σύμφωνα με την §11: συγγραφή χωρίς sig_alg ≥ 0x01, πρόθεση και χρονισμό υπο-αγκύρωσης. Κανένας από τους δύο δεν αφήνει κανέναν ισχυρισμό να στηριχθεί σε received_at.

Ανώτατο όριο αξίωσης (δεσμευτικός περιορισμός εκκίνησης — επιλύθηκε §16.15 Q1). Για ένα διεκδικούμενο (kind=0x02) φύλλο, η παραπάνω αξίωση εμβέλειας είναι το ανώτατο όριο για το τι μπορεί να διεκδικήσει οποιοδήποτε προϊόν, μάρκετινγκ, όροι ή επιφάνεια απόδοσης απόδειξης. Καμία επιφάνεια δεν μπορεί να δηλώνει ή να υπονοεί ότι το αρχείο καταγραφής αποδεικνύει το περιεχόμενο ή τον γύρο ξεκλειδώματος μιας μεταφόρτωσης με τυφλά byte — το αρχείο καταγραφής αποδεικνύει παραγγελία + έναν αξιόπιστο χρόνο δέσμευσης άνω ορίου ενός αδιαφανούς κρυπτογραφημένου κειμένου. Το περιεχόμενο και η στρογγυλή απόδειξη προέρχονται αποκλειστικά από την υπάρχουσα επαλήθευση δέσμης .qub §11, η οποία είναι ανεξάρτητη από το αρχείο καταγραφής. Μια δημοσίευση χωρίς επιτυχή προσάρτηση/παραλαβή δεν έχει καθόλου αξίωση καταγραφής.

16.12 Διαχείριση εκδόσεων και συντονισμός W3

Δεν υπάρχει κανένα SealedQub χτύπημα καλωδίου** και επομένως κανένα χτύπημα έκδοσης πρωτοκόλλου (§12.2): το αρχείο καταγραφής είναι ένα πλαϊνό καλάθι που δεσμεύεται σε υπάρχοντα πεδία και byte, επομένως δεν εισέρχεται στο ιστορικό εκδόσεων πρωτοκόλλου §12.3. Το προαιρετικό drand_chain_version του W3 είναι ανέγγιχτο και παραμένει το μόνο προαιρετικό πεδίο SealedQub. Αντίθετα, το αρχείο καταγραφής εισάγει τους δικούς του ανεξάρτητους χώρους έκδοσης — LOG_VERSION_1, ANCHOR_FORMAT_1, InclusionProof.ver — αντικατοπτρίζοντας την ανεξαρτησία της έκδοσης περιτυλίγματος §12.5 (το περιτύλιγμα φέρει ένα byte έκδοσης ανεξάρτητο από την έκδοση πρωτοκόλλου και οι εκδόσεις καταγραφής ακολουθούν τον ίδιο διαχωρισμό).

Η παράδοση απόδειξης λαμβάνεται από προεπιλογή, με προαιρετική διαδρομή. Δεν μπορεί να υπάρχει απόδειξη κατά τη στιγμή της σφράγισης (η άγκυρα δεν έχει γραφτεί ακόμα), επομένως η δέσμη .qub κατά τη σφράγιση παραμένει χωρίς απόδειξη. Ο επαληθευτής του W7 ανακτά GET …/proof μία φορά ή σε λειτουργία πλήρως εκτός σύνδεσης ανακατασκευάζει την απόδειξη από τη δημόσια AnchorBundle μέσω ενός ερωτήματος Arweave στο Log-Id. Η δέσμη .qub (W7) διατηρεί ένα προαιρετικό μέλος inclusion_proof — απουσιάζει στη σφραγίδα, συμπληρώνεται από μια επανεξαγωγή μετά την άγκυρα για ψυχρή αρχειοθέτηση — ακολουθώντας το ίδιο μοτίβο "προαιρετικό, παραλειπόμενο από προεπιλογή, πρόσθετο" με το drand_chain_version του W3.

16.13 Διατήρηση

Τα παράθυρα συγκράτησης για την ανοιχτή ουρά LogDO, το υπόστρωμα απόδειξης R2, τους μετρητές διακόπτη κυκλώματος αγκύρωσης και την εφεδρική ουρά δέσμης καθορίζονται στο docs/DATA-RETENTION.md. Αρχή: ο θερμός χώρος αποθήκευσης ανά είσοδο του αρχείου καταγραφής (LogDO) είναι ανακτήσιμος μετά την αγκύρωση. Το υλικό ελέγχου του — ο χώρος αποθήκευσης (level, index) κόμβου Merkle με συντεταγμένες + τα σώματα φύλλων με διεύθυνση seq (§16.9) + οι άγκυρες Arweave — είναι μόνιμο. Η ανάκτηση ενός κρύου φύλλου από το DO δεν ακυρώνει ποτέ μια εκδοθείσα απόδειξη, επειδή μια απόδειξη επιλύεται έναντι αυτού του μόνιμου χώρου αποθήκευσης κόμβων R2 και της άγκυρας Arweave, όχι του DO (και το διάνυσμα δοκιμής σβησμένου DO §16.9 το αποδεικνύει).

16.14 Διανύσματα δοκιμής

Το W5 αποστέλλει το διαγλωσσικό εξάρτημα tlog_v1.json (§16.8) συν επεξεργασμένα διανύσματα: ένα kind=0x01 και ένα kind=0x02 φύλλο → leaf_hash. η αθροιστική ρίζα 5 φύλλων. μία απόδειξη συμπερίληψης. μία απόδειξη συνέπειας. ένα AnchorBundle? και ένα αναγνωριστικό DataItem. Αυτά ζουν παράλληλα με τα διανύσματα εξωτερικού περιτυλίγματος §14.5 και ασκούνται τόσο από τις υλοποιήσεις Rust (qub-core) όσο και από TypeScript (Worker).

16.15 Αποφάσεις επανεξέτασης (W5 — επιλύθηκε)

Η εξωτερική αναθεώρηση του W5 (πάσο αντιδικίας + υπογραφή ιδιοκτήτη) έχει ολοκληρωθεί. Κάθε απόφαση παρακάτω διευθετείται και αντικατοπτρίζεται στο παραπάνω κείμενο §16. Οι δεσμευτικοί περιορισμοί εκκίνησης επαναδιατυπώνονται στο τέλος. Η εφαρμογή μπορεί να προχωρήσει βάσει αυτών.

  1. Ειλικρίνεια φύλλου προεπιλεγμένης διαδρομής (kind=0x02) — ΕΠΙΛΥΘΗΚΕ. Στείλτε τον διαχωρισμό τύπου δύο φύλλων όπως καθορίζεται: kind=0x02 δεν δεσμεύει ούτε body_hash ούτε drand_round. Δεν υπάρχει πεδίο *_body_hash στη διαδρομή τυφλού byte (θα ήταν το πιο ευανάγνωστο ψευδές "επαληθευμένο" σήμα για τους ολοκληρωτές και είναι μια ευκολία που παρέχει ήδη η §11 από τη δέσμη). Μην απαιτείτε σφραγίδα διακομιστή για qubs που έχουν πιστοποιηθεί από αρχεία καταγραφής (που θα ανάγκαζαν το απλό κείμενο να περάσει μέσα από το Worker και θα κατέστρεφε την τάφρο τεμαχισμού κρυπτογράφησης). Οποιοδήποτε αυτοπεριγραφόμενο βραχυκύκλωμα ανήκει στη δέσμη .qub / φάκελο απόδειξης ως πεδίο που υπολογίζεται εκ νέου από τον επαληθευτή, ποτέ ως πεδίο φύλλου. Ανώτατο όριο αξίωσης επιβεβαιωμένο από τον ιδιοκτήτη: §16.11.

  2. Λογοδοσία ασάφειας / παράλειψης — Ο ΣΧΕΔΙΑΣΜΟΣ ΕΠΙΛΥΘΗΚΕ, Η ΠΑΡΟΧΗ ΔΕΝ ΟΛΟΚΛΗΡΩΘΗΚΕ. Ο σχεδιασμός απαιτεί το κλειδί σφραγίδας-απόδειξης να καρφιτσωθεί σε LogProfile και να υπογραφεί από anchor_owner, καθώς και μεθοδολογία παρακολούθησης, περπάτημα προηγούμενης αλυσίδας και διπλές αυτοδημοσιευμένες κεφαλές. Το μεταγλωττισμένο προφίλ και τα άγκιστρα ανάπτυξης εξακολουθούν να είναι σύμβολα κράτησης θέσης/προαιρετικά όπως περιγράφεται στην §16.6, επομένως η ισχυρότερη αξίωση ανιχνεύσιμη + παραλαβή δεν είναι τρέχουσα μέχρι να κλείσουν αυτές οι πύλες. Δεν πρέπει ποτέ να διατίθεται στην αγορά ως ανεξάρτητα μάρτυρας. Ένας πραγματικός μάρτυρας τρίτου μέρους αναβάλλεται σε ένα χτύπημα διακυβέρνησης §15.

  3. Καρφιτσωμένη ρίζα εμπιστοσύνης ιδιοκτήτη άγκυρας + περιστροφή — ΕΠΙΛΥΘΗΚΕ. Υιοθετήστε τον LogProfile ακροδέκτη (§16.6). ο επαληθευτής ελέγχει anchor_tx.owner == anchor_owner και επαληθεύει τα δεδομένα TX → tx_id δεσμευτικά τοπικά. Η διακυβέρνηση περιστροφής είναι μια §15 επέκταση για κατασκευή (προστέθηκε η σκανδάλη §15.3), όχι μια επαναχρησιμοποίηση. Οι προγραμματισμένες περιστροφές διασταυρούμενης υπογραφής, οι περιστροφές που βασίζονται σε συμβιβασμούς επιστρέφουν στο χτύπημα §15 με τη ζημιά οριοθέτησης του ελέγχου πιρουνιού.

  4. Τύφλωση φύλλων ιδιωτικού qub — ΕΠΙΛΥΘΗΚΕ. Διατηρήστε την τύφλωση για ιδιωτικά qubs (ref = SHA3-256(qub_id ‖ log_blind_secret)), ακατέργαστα qub_id για δημόσια qubs (ήδη §16.2.1) chash ως αυτόνομη ισοπαλία. log_blind_secret είναι ένα μυστικό συσχέτισης/βαθμού Sybil, μόνο περιστροφή προς τα εμπρός (§16.2.1).

  5. received_at — ΕΠΙΛΥΘΗΚΕ. Κρατήστε το στο φύλλο, δεσμευμένο αλλά ρητά μη αποδεικτικό. ποτέ δεν εμφανίστηκε ως απόδειξη ή αμφισβήτηση επιβεβαίωσης σε οποιαδήποτε επιφάνεια. Οποιοσδήποτε έλεγχος λογικής οθόνης συγκρίνεται με το T χρόνου μπλοκ Arweave, όχι με το anchored_at που ελέγχεται από τον χειριστή (§16.6).

  6. Κλιμακωτός αποδείξιμος χρονισμός — ΑΝΑΛΥΣΗ ΣΧΕΔΙΑΣΜΟΥ, ΟΧΙ ΤΡΕΧΟΥΣΑ ΔΡΟΜΟΛΟΓΗΣΗ. Ο αναθεωρημένος σχεδιασμός εκχωρεί χρονισμό μπλοκ αγκύρωσης στη βαθμίδα παρτίδας και απόδειξη ακριβούς ώρας στο πληρωμένο T3, χωρίς αριθμητικό SLA για το πρώτο. Οι τρέχουσες διαδρομές δεν έχουν ενσωματώσει αυτήν την εμπορική διάκριση: προγραμματίζουν μια μεμονωμένη συναλλαγή για κάθε αποδεκτή δημοσίευση και η κάλυψη καταγραφής παραμένει υπό όρους όπως αναφέρεται στην §16.1/§16.10. Το αντίγραφο προϊόντος πρέπει να περιγράφει την υλοποίηση, όχι αυτόν τον μελλοντικό διαχωρισμό βαθμίδας.

  7. Σωρευτικό δέντρο σε Εργαζόμενους — ΕΠΙΛΥΘΗΚΕ. Ενιαίο σωρευτικό RFC 9162 δέντρο + frontier-cached LogDO ενός συγγραφέα (άνετο περιθώριο σε σχέση με το όριο ~1k εγγραφών/δευτερόλεπτο του DO· αναβολή του Merkle-of-shard-roots sharding μέχρι να πλησιάσει). Ο κόμβος αποθήκευσης (level, index) R2 με κλειδί συντονισμού + το wiped-DO cold-leaf test vector έχουν υλοποιηθεί (§16.9). Ο < 300 ms παραμένει στόχος σχεδίασης/λειτουργίας, όχι υπόσχεση πρωτοκόλλου (§16.10).

  8. Σχήμα υπογραφής ANS-104 + deep-hash — ΕΠΙΛΥΘΗΚΕ. RSA-PSS (τύπος υπογραφής 1, επαναχρησιμοποίηση του αφιερωμένου anchor-wallet JWK); Ed25519 αναβλήθηκε για τη διαδρομή PQ της §15. Το χειροποίητο SHA-384 deep hash ελέγχεται με τη διασταυρούμενη υλοποίηση και στις δύο κατευθύνσεις, μέσω ενός μόνο στατικού ελέγχου συμβατότητας reference-bundler, του shared-crypto.subtle round-trip, και του monitor αποδοχής Arweave μετά το bundle (§16.8).

Δεσμευτικοί περιορισμοί εκκίνησης (να μεταφερθούν στην υλοποίηση + ανασκόπηση προϊόντος/νομική):

17. Φορητή Δέσμη Επαλήθευσης (.qub)

Κατάσταση. Αυτή η ενότητα είναι υλοποιημένη (W7 / UP-C2): το qub_core::export παράγει και αναλύει τη δέσμη και το tools/qub-verify είναι ένα δημόσιο, αυτοτελές CLI που την επαληθεύει εκτός σύνδεσης. Οι §§11 και 16.9 αναφέρονται ήδη στη «δέσμη .qub» ως τη μονάδα που καταναλώνει ένας αυτόνομος επαληθευτής· αυτή η ενότητα προδιαγράφει τα bytes της και τη διαδικασία επαλήθευσης. Είναι αυστηρά προσθετική — η δέσμη συσκευάζει τις υπάρχουσες εισόδους της §11 και δεν αλλάζει κανένα μορφότυπο σύρματος στην αλυσίδα.

17.1 Σκοπός

Η §11 καθιερώνει ότι κάθε τρίτο μέρος μπορεί να επαληθεύσει το κρυπτογραφικό τεκμήριο ενός qub χωρίς συνεργασία του qub. Η δέσμη .qub καθιστά αυτή την επαλήθευση φορητή και εκτός σύνδεσης: συσκευάζει το σφραγισμένο CBOR και την υπογραφή γύρου drand που το ξεκλειδώνει σε ένα αυτοτελές τεκμήριο, ώστε ο παραλήπτης να επαληθεύσει την ακεραιότητα του περιεχομένου, τη δέσμευση στον γύρο και τυχόν υπογραφές συγγραφής χωρίς καμία κλήση δικτύου — χωρίς ανάκτηση αποθήκευσης, ζωντανό αίτημα drand ή API του qub. Μια δέσμη από μόνη της δεν αποδεικνύει πότε δημιουργήθηκε το κρυπτοκείμενό της· μια ανεξάρτητα επαληθευμένη συναλλαγή αποθήκευσης ή αγκυρωμένη απόδειξη αρχείου παρέχει αυτόν τον ξεχωριστό ισχυρισμό χρόνου ύπαρξης (§11, §17.5).

17.2 Μορφότυπο Δέσμης

Ένα QubBundle είναι χειρόγραφο κανονικό CBOR σύμφωνα με το προφίλ της §3.1: καθορισμένου μήκους, χωρίς ετικέτες ή floats, ακέραιοι συντομότερης μορφής, κείμενο NFC, προαιρετικά πεδία που παραλείπονται όταν απουσιάζουν και κλειδιά ταξινομημένα πρώτα κατά μήκος κωδικοποιημένων bytes και έπειτα λεξικογραφικά. Τα τρία κλειδιά 15 χαρακτήρων ταξινομούνται d < i < s. Ένα ακατέργαστο αρχείο .qub αποτελείται ακριβώς από αυτά τα bytes· για μεταφορά μέσω URL ή αντιγραφής/επικόλλησης, τα ίδια bytes είναι base64url χωρίς padding.

Κλειδί Κωδ. μήκος Τύπος Παρουσία Σημασία
version 8 u8 υποχρεωτικό Έκδοση μορφότυπου δέσμης (0x01).
sealed_at 10 i64 προαιρετικό Χρόνος σφράγισης που δηλώνει ο δημιουργός (δευτερόλεπτα Unix)· αυτοπεριγραφικός, μη αποδεικτικός.
drand_round 12 u64 υποχρεωτικό Ο γύρος στον οποίο είναι κλειδωμένο το qub. Προβολή του ενσωματωμένου σφραγισμένου qub.
arweave_tx_id 14 tstr υποχρεωτικό Το αναγνωριστικό συναλλαγής κάτω από το οποίο αποθηκεύτηκαν τα σφραγισμένα bytes, ως δείκτης προέλευσης.
drand_chain_id 15 tstr υποχρεωτικό Η αλυσίδα drand σε hex. Προβολή του ενσωματωμένου σφραγισμένου qub.
drand_signature 16 bstr υποχρεωτικό Η υπογραφή φάρου drand για το drand_round — η τιμή που ξεκλειδώνει το κρυπτοκείμενο.
inclusion_proof 16 bstr προαιρετικό Η απόδειξη συμπερίληψης Merkle του αρχείου διαφάνειας της §16, αφού αγκυρωθεί (§17.5).
sealed_qub_cbor 16 bstr υποχρεωτικό Τα εσωτερικά bytes SealedQubCbor μετά το ξεπεριτύλιγμα της §13, δηλαδή η είσοδος επαλήθευσης της §11.

Τα drand_round και drand_chain_id είναι βολικές προβολές του sealed_qub_cbor, ώστε τα εργαλεία να μπορούν να τα διαβάσουν χωρίς ανάλυση του εσωτερικού CBOR. Παράγονται κατά την κατασκευή και ελέγχονται εκ νέου κατά την αποκωδικοποίηση έναντι του αναλυμένου σφραγισμένου qub· δέσμη της οποίας το πεδίο ανώτερου επιπέδου διαφωνεί με το payload απορρίπτεται. Η πειθαρχία του κωδικοποιητή αντικατοπτρίζει το υπόλοιπο μορφότυπο σύρματος: απορρίπτει κενό drand_signature ή arweave_tx_id και οριοθετεί κάθε πεδίο μεταβλητού μήκους.

17.3 Τι Αποδεικνύει η Ενσωματωμένη Υπογραφή drand

Η δέσμη μεταφέρει την υπογραφή drand αντί να απαιτεί από τον επαληθευτή να την ανακτήσει. Η αποκρυπτογράφηση timelock, δηλαδή tlock πάνω στην αλυσίδα drand (§8), μπορεί να επιτύχει μόνο με τη γνήσια υπογραφή φάρου για τον δεσμευμένο γύρο — μια τιμή που η αλυσίδα δημοσιεύει μόνο όταν παρέλθει αυτός ο γύρος και η οποία είναι έγκυρη υπογραφή BLS κάτω από το δημόσιο κλειδί της αλυσίδας. Μια πλαστή ή λανθασμένη υπογραφή αποτυγχάνει στην επαλήθευση BLS ή στην αποκρυπτογράφηση IBE/AEAD. Μια δέσμη που αποκρυπτογραφείται αποδεικνύει συνεπώς ότι το κρυπτοκείμενο δεσμεύεται στον γύρο R και ο γύρος R έχει παρέλθει. Ο επαληθευτής καρφιτσώνει την αλυσίδα (DrandTimelockProvider::quicknet()) και εφαρμόζει τον έλεγχο δέσμευσης γύρου της §11, επομένως μια δέσμη δεν μπορεί να ισχυριστεί γύρο στον οποίο δεν δεσμεύεται το κρυπτοκείμενό της.

Αυτό αποτελεί απόδειξη συνθήκης απελευθέρωσης, όχι χρονοσήμανση δημιουργίας. Αφού παρέλθει ο γύρος R, οποιοσδήποτε μπορεί να δημιουργήσει νέο κρυπτοκείμενο για τον R και να συσκευάσει την ήδη δημόσια υπογραφή του. Επομένως η δέσμη από μόνη της ΔΕΝ ΠΡΕΠΕΙ να περιγράφεται ως απόδειξη ότι το κρυπτοκείμενο ή το περιεχόμενο υπήρχε πριν από τον R, πριν από το unlock_at ή πριν από οποιοδήποτε γεγονός.

17.4 Διαδικασία Επαλήθευσης Εκτός Σύνδεσης

Το qub-verify <file.qub> εκτελεί την τυπική διαδικασία της §11 εξ ολοκλήρου από τη δέσμη, οδηγώντας το qub_core::unlock::unlock με καρφιτσωμένο DrandTimelockProvider:

1. Parse the .qub bytes → QubBundle (canonical-CBOR guard; bound every field;
   re-check drand_round / drand_chain_id against the embedded sealed qub).
2. BLS-verify bundle.drand_signature for the pinned chain and round, then
   tlock_decrypt(sealed.tlock_ciphertext, bundle.drand_signature) → QubEnvelope.
3. Verify SHA3-256(body) == body_hash               (§11 step 8).
4. Verify QubEnvelope.qub_id   == SealedQub.qub_id   (§11 step 9).
5. Verify QubEnvelope.unlock_at == SealedQub.unlock_at (§11 step 10).
6. Verify ciphertext round == unlock_round(unlock_at) and the chain binding.
7. If sig_alg != 0x00: verify author_signature (and any cosigner; §9.4).
8. Report integrity, round-elapsed/round-binding, authorship, and cosigner
   verdicts separately, plus the recovered body. Do not report a commitment
   timestamp unless step 9 succeeds.
9. Optional existence-time leg: verify an included §16 proof through its pinned
   anchor, or independently verify the referenced storage transaction. Report
   its block time as an upper bound on ciphertext existence.

Το CLI τερματίζει με 0 για επιτυχή επαλήθευση, 1 για αποτυχία επαλήθευσης — ακόμη κλειδωμένο, ασυμφωνία σύνοψης σώματος, σπασμένη δέσμευση γύρου/αλυσίδας ή αποτυχημένη υπογραφή — ή 2 για σφάλμα χρήσης ή κακοσχηματισμένη δέσμη. Μια αναφορά --json μεταφέρει τις ίδιες ετυμηγορίες για αυτοματισμό. Επειδή η δέσμη είναι αυτοτελής, το crate επαληθευτή (qub-core) και το CLI (qub-verify) είναι το μόνο λογισμικό που χρειάζεται τρίτο μέρος· και τα δύο είναι δημόσια και επαναχρησιμοποιούν την υπάρχουσα διαδρομή επαλήθευσης του πρωτοκόλλου, χωρίς ειδική κρυπτογραφία.

17.5 Σχέση με το Αρχείο Διαφάνειας

Το inclusion_proof είναι προαιρετική θέση για την απόδειξη συμπερίληψης Merkle της §16. Η επαλήθευση μόνο της δέσμης (§17.4) είναι πλήρης για ακεραιότητα, δέσμευση/παρέλευση γύρου και προαιρετική συγγραφή, αλλά σκόπιμα δεν περιλαμβάνει ανεξάρτητα χρονοσημασμένο ισχυρισμό ύπαρξης. Ένα συμπληρωμένο inclusion_proof που έχει επαληθευτεί πλήρως μέχρι την αγκύρωσή του προσθέτει τη δέσμευση ανά είδος φύλλου και τον ανώτατο χρόνο της §16.11 χωρίς αλλαγή της έκδοσης μορφότυπου δέσμης. Η απουσία απόδειξης σημαίνει μόνο «δεν περιλαμβάνεται απόδειξη» — όχι «μη έγκυρο» ούτε κατ' ανάγκη «μη αγκυρωμένο».

Στην υλοποίηση αναφοράς η θέση είναι πλέον τυποποιημένη: το qub_core::export::QubBundle::inclusion_proof_typed() επιστρέφει ένα Option<InclusionProof> που μεταφέρει την πλήρη δομή της §16.9 — φύλλο, διαδρομή ελέγχου, αγκυρωμένη ρίζα και AnchorRef — μέσω του ίδιου αδιαφανούς πεδίου CBOR, χωρίς αύξηση έκδοσης του μορφότυπου δέσμης. Το αυτόνομο CLI qub-verify την καταναλώνει μέσω του σκέλους --anchor και, μέχρι να παρασχεθεί το πορτοφόλι αγκύρωσης (§16, Κατάσταση), αναφέρει απόδειξη με συμπληρωμένο προσωρινό κάτοχο μόνο ως συμπερίληψη και όχι ως πλήρως επαληθευμένη αγκύρωση.