Η απόδειξη εργασίας Argon2id με απλά λόγια

· Ανάγνωση: 7 λεπ.

Αυτό το άρθρο εξηγεί τι είναι το Argon2id, πώς το Blocknet το μετατρέπει σε απόδειξη εργασίας, γιατί ανταμείβει την άφθονη και γρήγορη μνήμη και πώς το seine βγάζει τα περισσότερα hashes από κάθε CPU στην οποία τρέχει.

Τι είναι το Argon2id;

Σύντομη απάντηση

Το Argon2id είναι μια memory-hard συνάρτηση hash που ορίζεται στο RFC 9106 για hashing κωδικών πρόσβασης και για απόδειξη εργασίας. Γεμίζει μια μεγάλη περιοχή μνήμης με μπλοκ του 1 KiB, φτιάχνοντας κάθε μπλοκ από το προηγούμενο και από ένα παλαιότερο μπλοκ που επιλέγεται από άλλο σημείο της μνήμης, οπότε ο υπολογισμός ενός hash απαιτεί πραγματική μνήμη και όχι μόνο χρόνο επεξεργαστή.

Το RFC 9106, που δημοσιεύτηκε το 2021 από την Crypto Forum Research Group του IRTF, περιγράφει «τη memory-hard συνάρτηση Argon2 για hashing κωδικών πρόσβασης και εφαρμογές απόδειξης εργασίας». Το Argon2 έχει τρεις παραλλαγές:

Στο εσωτερικό του, το Argon2 αντιμετωπίζει τη μνήμη ως μια μεγάλη σειρά από μπλοκ των 1.024 bytes. Κάθε νέο μπλοκ είναι η έξοδος μιας συνάρτησης συμπίεσης G που εφαρμόζεται σε δύο εισόδους: το μπλοκ ακριβώς πριν από αυτό και ένα μπλοκ αναφοράς από παλαιότερο σημείο της μνήμης. Η G βασίζεται στους γύρους ανάμειξης της συνάρτησης hash BLAKE2b, που δουλεύουν σε λέξεις των 64 bits με προσθέσεις, XOR και περιστροφές.

Πώς χρησιμοποιεί το Blocknet το Argon2id ως απόδειξη εργασίας;

Το Blocknet ορίζει κάθε ρύθμιση του Argon2id στον κώδικα συναίνεσής του, ώστε κάθε miner και κάθε κόμβος να υπολογίζει ακριβώς την ίδια συνάρτηση:

Παράμετρος Τιμή στο Blocknet Τι σημαίνει
Παραλλαγή Argon2id, έκδοση 1.3 Η κύρια παραλλαγή του RFC 9106
Μνήμη 2 GiB (2.097.152 KiB) 2.097.152 μπλοκ του 1 KiB γεμίζουν ανά hash
Επαναλήψεις 1 Ένα πέρασμα πάνω από τη μνήμη
Παραλληλισμός 1 Μία λωρίδα, οπότε ένα hash τρέχει σε ένα νήμα
Έξοδος 32 bytes Η τιμή που συγκρίνεται με τον στόχο
Password Nonce 8 bytes, little-endian Ο αριθμός που αλλάζει ο miner σε κάθε προσπάθεια
Salt Κεφαλίδα μπλοκ χωρίς το nonce Δένει το hash με ένα συγκεκριμένο πρότυπο μπλοκ

Η εξόρυξη είναι αναζήτηση. Ένας miner παίρνει την κεφαλίδα του μπλοκ που θέλει να δημοσιεύσει, επιλέγει ένα nonce και υπολογίζει το hash Argon2id. Αν το αποτέλεσμα των 32 bytes, διαβασμένο ως αριθμός, είναι ίσο ή μικρότερο από τον στόχο του δικτύου, το μπλοκ είναι έγκυρο. Αν όχι, ο miner δοκιμάζει το επόμενο nonce.

Ο στόχος προκύπτει απευθείας από τη δυσκολία: είναι (2^256 − 1) διαιρεμένο με τη δυσκολία. Έτσι η δυσκολία ισούται περίπου με τον αριθμό των hashes που αναμένεται να υπολογίσει ολόκληρο το δίκτυο για να βρει ένα μπλοκ. Το Blocknet στοχεύει σε ένα μπλοκ κάθε πέντε λεπτά, οπότε το hashrate του δικτύου είναι περίπου η δυσκολία διαιρεμένη με 300 δευτερόλεπτα. Η ίδια η δυσκολία ακολουθεί τους πρόσφατους χρόνους μπλοκ μέσω ενός σταθμισμένου κινητού μέσου όρου 60 μπλοκ.

Τα pools λειτουργούν με τον ίδιο τρόπο, με ευκολότερο στόχο. Στο bntpool.com, το seine υποβάλλει shares που πληρούν μια χαμηλότερη δυσκολία ανά σύνδεση, και κάθε share που πληροί επίσης τον στόχο του δικτύου είναι ένα μπλοκ που βρέθηκε.

Γιατί η memory-hard απόδειξη εργασίας ταιριάζει στους συνηθισμένους υπολογιστές;

Οι παραπάνω ρυθμίσεις κάνουν τη μνήμη το κέντρο κάθε hash. Με ένα πέρασμα και μία λωρίδα, το δεύτερο μισό του περάσματος εξαρτάται από τα δεδομένα: η θέση του μπλοκ αναφοράς κάθε μπλοκ λαμβάνεται από την πρώτη λέξη των 64 bits του μπλοκ που υπολογίστηκε ακριβώς πριν. Ένας miner δεν μπορεί να ξέρει ποιο προηγούμενο μπλοκ θα χρειαστεί μέχρι τη στιγμή που το χρειάζεται, οπότε κρατά ολόκληρη την περιοχή των 2 GiB στη μνήμη.

Ένας miner θα μπορούσε να προσπαθήσει να αποθηκεύει λιγότερα μπλοκ και να υπολογίζει ξανά όσα λείπουν όταν χρειαστούν. Το RFC 9106 τα ονομάζει συμβιβασμούς χρόνου-μνήμης (time-memory trade-offs): εξοικονομούν μνήμη «με κόστος περισσότερες κλήσεις στην εσωτερική συνάρτηση συμπίεσης». Κάθε μπλοκ που αφαιρείται από την περιοχή πρέπει να πληρωθεί ξανά με επιπλέον υπολογισμούς.

Αυτό κάνει τον σχεδιασμό φιλικό προς το συνηθισμένο hardware. Οι επιτραπέζιοι, οι φορητοί και οι διακομιστές έρχονται ήδη με gigabytes RAM και ελεγκτές μνήμης φτιαγμένους για να την τροφοδοτούν. Ένα chip σχεδιασμένο μόνο για hashing θα χρειαζόταν και πάλι gigabytes γρήγορης μνήμης δίπλα στους πυρήνες hashing. Η πρώτη προτεινόμενη ρύθμιση του RFC 9106 είναι το Argon2id με ένα πέρασμα πάνω από 2 GiB μνήμης, τον ίδιο αριθμό περασμάτων και το ίδιο μέγεθος μνήμης που χρησιμοποιεί το Blocknet, και το RFC αναφέρει ότι αυτή η ρύθμιση «μεγιστοποιεί το κόστος του αντιπάλου σε εξειδικευμένο hardware brute-force». Ο κώδικας του daemon του Blocknet περιγράφει την επιλογή του ως memory-hard απόδειξη εργασίας «για αντίσταση στα ASIC και δίκαιη εξόρυξη». Το Argon2id είναι σχεδιασμένο να αντιστέκεται στα ASIC και η ρύθμιση των 2 GiB αξιοποιεί αυτόν τον σχεδιασμό, ώστε η εξόρυξη να μένει ανοιχτή στους υπολογιστές που ήδη έχει ο κόσμος. Ο οδηγός proof of work ή proof of stake εξηγεί πώς αυτό συγκρίνεται με το staking.

Γιατί η RAM και το εύρος ζώνης μνήμης καθορίζουν το hashrate;

Σύντομη απάντηση

Κάθε νήμα εξόρυξης κρατά τη δική του περιοχή των 2 GiB, οπότε η RAM σας καθορίζει πόσα νήματα μπορείτε να τρέξετε. Κάθε hash επίσης γράφει 2 GiB και διαβάζει περίπου άλλα τόσα από διάσπαρτα σημεία, οπότε η ταχύτητα και ο χρόνος απόκρισης της μνήμης σας καθορίζουν πόσο γρήγορα τελειώνουν αυτά τα νήματα. Η μνήμη μετράει όσο και ο αριθμός πυρήνων.

Η RAM καθορίζει τον αριθμό νημάτων. Παραλληλισμός 1 σημαίνει ότι ένα hash τρέχει σε ένα νήμα, και κάθε νήμα χρειάζεται ολόκληρη τη δική του περιοχή των 2 GiB. Ένας υπολογιστής με 16 GB μπορεί να τρέξει περίπου έξι έως επτά νήματα, αφού αφήσει χώρο για το σύστημα. Το seine μετρά τη μνήμη σας, κρατά 5% ως απόθεμα και επιλέγει τον αριθμό νημάτων για εσάς.

Το εύρος ζώνης και ο χρόνος απόκρισης καθορίζουν την ταχύτητα κάθε νήματος. Ένα hash δημιουργεί 2.097.152 νέα μπλοκ, και καθένα διαβάζει ένα μπλοκ αναφοράς του 1 KiB από κάποιο σημείο της περιοχής. Αυτό σημαίνει περίπου 2 GiB εγγραφής και περίπου 2 GiB ανάγνωσης για κάθε hash. Στα 10 H/s, ένας υπολογιστής μετακινεί περίπου 40 GiB δεδομένων μέσω της μνήμης κάθε δευτερόλεπτο. Στο μισό που εξαρτάται από τα δεδομένα, κάθε διεύθυνση ανάγνωσης γίνεται γνωστή μόνο όταν ολοκληρωθεί το προηγούμενο μπλοκ, οπότε ο χρόνος που χρειάζεται η μνήμη για να απαντήσει μετράει όσο και η καθαρή απόδοση.

Γι’ αυτό η σελίδα επιδόσεων του seine αναφέρει ότι το hashrate «εξαρτάται εξίσου από το εύρος ζώνης και τον χρόνο απόκρισης της μνήμης όσο και από τον αριθμό πυρήνων». Ο οδηγός hardware για εξόρυξη Blocknet δείχνει το καλύτερο αποτέλεσμα για κάθε γενιά hardware.

Οι huge pages βοηθούν για τον ίδιο λόγο. Μια περιοχή 2 GiB καλύπτει 524.288 συνηθισμένες σελίδες των 4 KiB ή 1.024 σελίδες των 2 MiB. Λιγότερες και μεγαλύτερες σελίδες σημαίνουν λιγότερες αστοχίες μετάφρασης διευθύνσεων σε αυτές τις διάσπαρτες αναγνώσεις, κάτι που πρόσθεσε περίπου 4–6% στον υπολογιστή επικύρωσης του seine. Ο οδηγός για huge pages έχει τη ρύθμιση.

Πώς αξιοποιούν στο έπακρο το Argon2id οι kernels CPU του seine;

Ο kernel είναι ο εσωτερικός βρόχος που υπολογίζει τα μπλοκ. Οι εκδόσεις x86 του seine περιέχουν kernels scalar, AVX2 και AVX-512 καθώς και μια παραλλαγή streaming, και οι εκδόσεις Arm περιέχουν NEON με γρήγορη διαδρομή SHA3. Ο καθένας αντιμετωπίζει την εργασία που περιορίζεται από τη μνήμη με διαφορετικό τρόπο:

Στο hardware που δοκιμάσαμε, ο σωστός kernel έκανε μεγάλη διαφορά. Αυτές είναι ζευγαρωτές εκτελέσεις στον ίδιο υπολογιστή με τον ίδιο αριθμό νημάτων, από τη σελίδα επιδόσεων του seine:

Υπολογιστής Αλλαγή kernel Κέρδος
AWS Graviton4 (Neoverse V2), 16 νήματα Από NEON σε SHA3 με prefetch +56% (από 13,80 σε 21,50 H/s)
AWS Graviton3 (Neoverse V1), 16 νήματα Από NEON σε SHA3 με prefetch +45% (από 12,52 σε 18,17 H/s)
AMD EPYC 9R45 (Zen 5), 24 νήματα Από AVX2 σε streaming +30% (από 34,47 σε 44,74 H/s)
Intel Xeon 8375C (Ice Lake), 1–4 νήματα Από AVX2 σε AVX-512 +21–29%

Δεν χρειάζεται να επιλέξετε τίποτα από αυτά μόνοι σας. Το seine συγκρίνει τους kernels που υποστηρίζει η CPU σας σε πραγματική εργασία εξόρυξης, αλλάζει μόνο μετά από δύο επιβεβαιωμένα κέρδη και αποθηκεύει τον νικητή για την επόμενη εκκίνηση. Ο καλύτερος kernel εξαρτάται από τον αριθμό νημάτων, το μέγεθος σελίδας και την τοποθέτηση στην CPU, γι’ αυτό το seine μετρά στον δικό σας υπολογιστή αντί να ορίζει μια σταθερή επιλογή.

Για να βάλετε τη δική σας μνήμη να δουλέψει, κατεβάστε το seine, τρέξτε το και επικολλήστε τη διεύθυνσή σας. Ο οδηγός εξόρυξης καλύπτει τα υπόλοιπα.

Συχνές ερωτήσεις

Ποιες παραμέτρους Argon2id χρησιμοποιεί το Blocknet για την απόδειξη εργασίας;

Το Blocknet τρέχει το Argon2id έκδοση 1.3 με 2 GiB μνήμης, μία επανάληψη, παραλληλισμό 1 και έξοδο 32 bytes. Το nonce των 8 bytes είναι το password και η κεφαλίδα του μπλοκ χωρίς το nonce είναι το salt. Ένα hash κερδίζει ένα μπλοκ όταν είναι ίσο ή μικρότερο από τον στόχο που ορίζει η δυσκολία του δικτύου.

Γιατί κάθε νήμα εξόρυξης Blocknet χρειάζεται 2 GB μνήμης RAM;

Κάθε hash Argon2id γεμίζει μια περιοχή μνήμης 2 GiB με μπλοκ του 1 KiB, και στο δεύτερο μισό του περάσματος κάθε νέο μπλοκ διαβάζει ένα προηγούμενο, που επιλέγεται από δεδομένα που ο miner δεν μπορεί να προβλέψει. Ένα νήμα πρέπει να κρατά ολόκληρη την περιοχή του στη μνήμη, οπότε κάθε νήμα που τρέχετε χρειάζεται περίπου 2 GB μνήμης RAM.

Γιατί το Argon2id είναι σχεδιασμένο να αντιστέκεται στα ASIC;

Το Argon2id κάνει τη μνήμη το ακριβό μέρος κάθε hash. Κάθε hash του Blocknet χρειάζεται 2 GiB γρήγορης μνήμης και μετακινεί gigabytes μέσα από αυτήν, οπότε ένα chip φτιαγμένο μόνο για hashing θα χρειαζόταν και πάλι μεγάλες ποσότητες RAM ανά πυρήνα. Ο κώδικας του daemon περιγράφει την επιλογή ως memory-hard απόδειξη εργασίας για αντίσταση στα ASIC και δίκαιη εξόρυξη.

Μπορεί μια κάρτα γραφικών να κάνει εξόρυξη στο Argon2id του Blocknet;

Ναι. Σε Windows και Linux, το seine κάνει εξόρυξη με κάθε κάρτα γραφικών NVIDIA του υπολογιστή ταυτόχρονα με την CPU, και τα hashrate αθροίζονται. Οι kernels μεταγλωττίζονται κατά την εκκίνηση και η πρώτη εκτέλεση ρυθμίζει κάθε κάρτα και αποθηκεύει το αποτέλεσμα, οπότε δεν υπάρχει τίποτα να ρυθμίσετε πριν ξεκινήσετε.