
Σειρά: Zcash από τις πρώτες αρχές . Άρθρο 4 . Δέντρα Merkle Κοινό: νέοι χρήστες. Βασιζόμαστε στο Άρθρο 3 (hashing και commitments). Αν ξέρεις τι είναι ένα αποτύπωμα και ένα commitment, είσαι έτοιμος. Τι θα αποκομίσεις: μια διαισθητική και σωστή εικόνα των δέντρων Merkle, πώς να αποδεικνύεις συμμετοχή χωρίς να αποκαλύπτεις ποιο στοιχείο εννοείς και ακριβώς πώς αυτό γίνεται το δέντρο note commitments του Zcash.
Το Άρθρο 0 περιέγραψε έναν «δημόσιο πίνακα» που περιέχει κάθε note που έχει ποτέ δημιουργηθεί και συνεχώς μεγαλώνει. Μέχρι τώρα μπορείς να μαντέψεις τι είναι καρφιτσωμένο σε αυτόν: commitments (Άρθρο 3), οι σφραγισμένοι φάκελοι. Όμως ένας πραγματικός πίνακας θα περιείχε εκατοντάδες εκατομμύρια από αυτά. Πώς το δίκτυο τα αποθηκεύει, τα επαληθεύει και σου επιτρέπει να αποδείξεις ότι ο φάκελός σου βρίσκεται στον πίνακα χωρίς να τον υποδείξεις; Η απάντηση είναι μία από τις πιο κομψές δομές στην επιστήμη υπολογιστών: το δέντρο Merkle.
Δύο προβλήματα εμφανίζονται μόλις έχεις μια τεράστια δημόσια λίστα commitments.
Πρόβλημα πρώτο: ακεραιότητα σε μεγάλη κλίμακα. Αν η λίστα έχει 300 εκατομμύρια καταχωρίσεις, πώς επιβεβαιώνει κανείς ότι ούτε μία δεν έχει αλλοιωθεί κρυφά; Ο επανέλεγχος 300 εκατομμυρίων στοιχείων με κάθε ματιά είναι αδύνατος.
Πρόβλημα δεύτερο: ιδιωτική συμμετοχή. Για να ξοδέψεις ένα note (Άρθρο 0), πρέπει να αποδείξεις ότι το commitment σου βρίσκεται πράγματι στον πίνακα. Όμως αν το υποδείξεις («είναι η καταχώριση αριθμός 4.201.337!»), μόλις έχεις αποκαλύψει την ταυτότητά σου. Πρέπει να αποδείξεις «ο φάκελός μου βρίσκεται κάπου σε αυτόν τον πίνακα» χωρίς να αποκαλύψεις ποιος είναι.
Ένα δέντρο Merkle λύνει και τα δύο ταυτόχρονα. Συμπιέζει ολόκληρη τη λίστα σε ένα μοναδικό αποτύπωμα και σου επιτρέπει να αποδείξεις συμμετοχή με μια μικροσκοπική απόδειξη που κρύβει τη θέση.
Φαντάσου ένα ταμπλό τουρνουά νοκ άουτ, αλλά αντί να προκρίνονται παίκτες, συνδυάζονται αποτυπώματα.

Η σημαντικότερη ιδιότητα προκύπτει άμεσα από το φαινόμενο χιονοστιβάδας (Άρθρο 3):
Η ρίζα είναι ένα αποτύπωμα όλων όσων βρίσκονται από κάτω της. Άλλαξε οποιοδήποτε φύλλο, έστω και κατά ένα bit, και αλλάζει το αποτύπωμά του, που αλλάζει τον γονέα του, που αλλάζει εκείνον τον γονέα, μέχρι την κορυφή. Η ρίζα αλλάζει. Άρα μία μικρή τιμή ρίζας πιστοποιεί την ακεραιότητα ολόκληρης της λίστας. Αυτό λύνει το Πρόβλημα πρώτο.
Ας δημιουργήσουμε το παραπάνω δέντρο τεσσάρων φύλλων με πραγματικά αποτυπώματα SHA-256 πάνω στα φύλλα A, B, C, D (τα digests εμφανίζονται περικομμένα για ευκολότερη ανάγνωση):
hA = 559aead08264... hB = df7e70e50215...
hC = 6b23c0d5f35d... hD = 3f39d5c348e5...
hAB = H(hA , hB) = 63956f0ce48e...
hCD = H(hC , hD) = 98a2fbfddbc7...
ROOT = H(hAB , hCD) = 1b3faa3fcc5e...
Όλα είναι απλώς «κάνε hash ένα πράγμα και μετά κάνε hash ζεύγη από hashes». Τίποτα πιο εξωτικό από το Άρθρο 3, απλώς οργανωμένο σε δέντρο.
Τώρα το Πρόβλημα δεύτερο. Ας πούμε ότι θέλεις να αποδείξεις πως το φύλλο C βρίσκεται στο δέντρο, σε κάποιον που γνωρίζει μόνο τη ρίζα. Δεν του παραδίδεις ολόκληρο το δέντρο. Του δίνεις μόνο τα αποτυπώματα που χρειάζονται για να ανέβεις από το C στη ρίζα, τα οποία ονομάζονται διαδρομή αυθεντικοποίησης (ή απόδειξη Merkle):
Για να αποδείξεις ότι το
Cβρίσκεται στο δέντρο, παρείχε:
- το αδελφό του
hD, και- τον θείο του
hAB.
Ο επαληθευτής, γνωρίζοντας μόνο τη ρίζα, επανυπολογίζει την ανάβαση:
step 1: H(hC , hD) = hCD (combine C with its sibling)
step 2: H(hAB , hCD) = ROOT? (combine with the uncle)
Υπολογισμένο πραγματικά: αυτό δίνει το 1b3faa3fcc5e..., το οποίο ταιριάζει με τη ρίζα. Το φύλλο αποδεικνύεται ότι βρίσκεται στο δέντρο.

Δύο πράγματα το καθιστούν ισχυρό:
n φύλλα, παρέχεις μόνο περίπου log_2(n) hashes. Για ένα δισεκατομμύριο φύλλα, αυτό είναι περίπου 30 hashes, όχι ένα δισεκατομμύριο. Η απόδειξη σχεδόν δεν μεγαλώνει καθώς το δέντρο εκρήγνυται σε μέγεθος.Τώρα μπορούμε να δηλώσουμε με ακρίβεια τι είναι πραγματικά ο «δημόσιος πίνακας» του Άρθρου 0:
Το δέντρο note commitments είναι ένα δέντρο Merkle του οποίου τα φύλλα είναι note commitments. Κάθε φορά που δημιουργείται ένα note οπουδήποτε στον κόσμο, το commitment του προστίθεται ως το επόμενο φύλλο και η ρίζα ενημερώνεται.
Μερικές πραγματικές λεπτομέρειες:
2^(32) (πάνω από τέσσερα δισεκατομμύρια) notes.
Το δέντρο αποδεικνύει ότι ένα note υπάρχει. Δεν σε εμποδίζει από μόνο του να ξοδέψεις το ίδιο note δύο φορές. Αυτή η δουλειά ανήκει στο σύνολο nullifier από το Άρθρο 0: μια ξεχωριστή συλλογή από «token ακύρωσης». Όταν ξοδεύεις, δημοσιεύεις το nullifier του note και το δίκτυο απορρίπτει κάθε nullifier που έχει ξαναδεί.
Άρα οι δύο δημόσιες δομές παίζουν συμπληρωματικούς ρόλους και το να παραμένουν χωριστές είναι ακριβώς αυτό που διακόπτει τον σύνδεσμο ανάμεσα στη γέννηση και τον θάνατο ενός note:
| Δομή | Ερώτηση που απαντά | Ενημερώνεται όταν |
|---|---|---|
| Δέντρο note commitments | «Υπάρχει αυτό το note;» | Δημιουργείται ένα note (προστίθεται commitment) |
| Σύνολο nullifier | «Έχει ήδη ξοδευτεί αυτό το note;» | Ξοδεύεται ένα note (δημοσιεύεται nullifier) |
Απλοποιήσεις, όπως συνήθως. Τα πραγματικά αυξητικά δέντρα Merkle παρακολουθούν κόμβους «frontier», ώστε η ρίζα να μπορεί να ενημερώνεται χωρίς να ξαναδημιουργούνται όλα· το δίκτυο διατηρεί ένα παράθυρο πρόσφατων anchors, όχι μόνο το νεότερο, ώστε τα πορτοφόλια να μη χαλούν με κάθε νέο μπλοκ· και τα κενά φύλλα χρησιμοποιούν μια καθορισμένη τιμή συμπλήρωσης. Επίσης σχεδιάσαμε δυαδικά δέντρα με τακτοποιημένες δυνάμεις του δύο. Τίποτα από αυτά δεν αλλάζει τη διαίσθηση: φύλλα από commitments, που γίνονται hash ανά ζεύγη μέχρι μία ρίζα, με σύντομες αποδείξεις συμμετοχής. Η ακριβής λογιστική επιστρέφει στο άρθρο του πρωτοκόλλου.
| Όρος | Σημασία με απλά λόγια |
|---|---|
| Merkle tree | Ένα δέντρο από hashes· τα φύλλα είναι αποτυπώματα δεδομένων, ενώ οι γονείς κάνουν hash τα παιδιά τους |
| Leaf | Ένας κόμβος στο κάτω μέρος· στο Zcash, ένα note commitment |
| Merkle root | Το μοναδικό κορυφαίο αποτύπωμα που συνοψίζει ολόκληρο το δέντρο |
| Authentication path / Merkle proof | Τα αδελφά hashes που απαιτούνται για να αποδειχθεί ότι ένα φύλλο βρίσκεται στο δέντρο |
| Incremental Merkle tree | Ένα δέντρο Merkle μόνο με προσθήκες (φύλλα προστίθενται μόνο) |
| Anchor | Μια ρίζα Merkle στην οποία αναφέρεται μια δαπάνη ως «η κατάσταση του δέντρου απέναντι στην οποία αποδεικνύω» |
| Nullifier set | Η ξεχωριστή συλλογή δεικτών δαπάνης που μπλοκάρει τις διπλές δαπάνες |
Γιατί δέντρο και όχι απλώς μια μεγάλη λίστα hashes; Μια επίπεδη λίστα θα σε ανάγκαζε να αποκαλύψεις ή να επεξεργαστείς κάθε καταχώριση για να αποδείξεις συμμετοχή. Ένα δέντρο σου δίνει αποδείξεις λογαριθμικού μεγέθους και μία μοναδική ρίζα για ακεραιότητα.
Χρειάζεται ο επαληθευτής ολόκληρο το δέντρο; Όχι. Ο επαληθευτής χρειάζεται μόνο τη ρίζα μαζί με τη σύντομη διαδρομή αυθεντικοποίησής σου. Αυτό είναι όλο το νόημα.
Γιατί βάθος 32 συγκεκριμένα; Περιορίζει το δέντρο σε περίπου τέσσερα δισεκατομμύρια notes, που προσφέρει άφθονο περιθώριο, ενώ διατηρεί την απόδειξη συμμετοχής (και το κόστος της μέσα στο κύκλωμα) σε σταθερό και διαχειρίσιμο μέγεθος.
Αν η ρίζα αλλάζει με κάθε νέο note, πώς παραμένουν έγκυρες οι παλιές αποδείξεις; Το δίκτυο θυμάται ένα παράθυρο πρόσφατων ριζών (anchors), επομένως μια απόδειξη που δημιουργήθηκε απέναντι σε ένα ελαφρώς παλαιότερο anchor εξακολουθεί να επαληθεύεται. Το άρθρο του πρωτοκόλλου το κάνει ακριβές.
Στο δέντρο μας με 4 φύλλα, ας υποθέσουμε ότι ένας επιτιθέμενος αντικαθιστά κρυφά το φύλλο C με διαφορετική τιμή, αλλά αφήνει τη δημοσιευμένη ρίζα αμετάβλητη. Τι πάει στραβά γι’ αυτόν και γιατί δεν μπορεί να το διορθώσει αθόρυβα; (Απάντηση παρακάτω.)
Η αλλαγή του C αλλάζει το hC (φαινόμενο χιονοστιβάδας), που αλλάζει το hCD = H(hC, hD), που αλλάζει το ROOT = H(hAB, hCD). Επομένως, η επανυπολογισμένη ρίζα δεν ταιριάζει πλέον με τη δημοσιευμένη ρίζα και η αλλοίωση εντοπίζεται. Για να «το διορθώσει αθόρυβα», θα έπρεπε να βρει ένα διαφορετικό C που να παράγει το ίδιο hC, δηλαδή μια σύγκρουση hash, κάτι ανέφικτο σύμφωνα με το Άρθρο 3. Η ακεραιότητα διατηρείται.
Άρθρο 5 . Αποδείξεις μηδενικής γνώσης: η κορύφωση. Τώρα έχουμε δημιουργήσει notes, commitments και το δέντρο, και συνεχίζουμε να λέμε «αποδεικνύεται με μηδενική γνώση». Το Άρθρο 5 εξηγεί επιτέλους πώς μπορείς να αποδείξεις ότι μια δήλωση είναι αληθής, ότι το note σου βρίσκεται στο δέντρο, ότι το nullifier σου είναι σωστό και ότι τα χρήματα ισοσκελίζονται, χωρίς να αποκαλύπτεις τίποτα από αυτά.
Μέρος της σειράς Zcash από τις πρώτες αρχές για το ZecHub. Με άδεια CC BY-SA 4.0.