Για να καταλήξουμε τελικά με μια αλυσίδα μπλοκ και όχι απλώς μια βάση δεδομένων, πρέπει να προσθέσουμε 3 σημαντικά στοιχεία στο έργο μας:
- Περιγραφή της δομής και των μεθόδων δεδομένων μπλοκ
- Περιγραφή της δομής δεδομένων και των μεθόδων συναλλαγής
- Λειτουργίες blockchain που αποθηκεύουν μπλοκ σε μια βάση δεδομένων και τα βρίσκουν εκεί με βάση τον κατακερματισμό ή το ύψος τους (ή κάτι άλλο).
Αυτό είναι το δεύτερο άρθρο σχετικά με το blockchain για τη βιομηχανία, το πρώτο
Υπενθυμίζοντας τις ερωτήσεις που μου έκαναν οι αναγνώστες σχετικά με το προηγούμενο άρθρο αυτής της σειράς, θα πρέπει να σημειωθεί: σε αυτήν την περίπτωση, η βάση δεδομένων LevelDB χρησιμοποιείται για την αποθήκευση δεδομένων blockchain, αλλά τίποτα δεν σας εμποδίζει να χρησιμοποιήσετε οποιαδήποτε άλλη, ας πούμε, MySQL. Τώρα ας δούμε τη δομή αυτών των δεδομένων.
Ας ξεκινήσουμε με τις συναλλαγές:
Εδώ είναι η δομή δεδομένων του:
type TX struct {
DataType byte
TxHash string
TxType byte
Timestamp int64
INs []TxIn
OUTs []TxOut
}
type TxIn struct {
ThatTxHash string
TxOutN int
ByteCode string
}
type TxOut struct {
Value int
ByteCode string
}
Το TX αποθηκεύει τον τύπο δεδομένων (για τη συναλλαγή 2), τον κατακερματισμό αυτής της συναλλαγής, τον τύπο της ίδιας της συναλλαγής, μια χρονική σήμανση και εισόδους και εξόδους. Οι είσοδοι TxIn αποθηκεύουν τον κατακερματισμό της συναλλαγής της οποίας η έξοδος αναφέρεται, τον αριθμό αυτής της εξόδου και του bytecode, και οι έξοδοι TxOut αποθηκεύουν κάποια τιμή και επίσης bytecode.
Ας δούμε τώρα ποιες ενέργειες μπορεί να εκτελέσει μια συναλλαγή στα δεδομένα της, δηλ. Ας δούμε τις μεθόδους.
Για να δημιουργήσετε μια συναλλαγή, χρησιμοποιήστε τη συνάρτησηtransaction.NewTransaction(txtype byte) *TX.
Η μέθοδος AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, σφάλμα) προσθέτει μια είσοδο στη συναλλαγή.
Η μέθοδος AddTxOut(value int, data []byte) (*TxOut, error) προσθέτει μια έξοδο στη συναλλαγή.
Η μέθοδος ToBytes() []byte μετατρέπει τη συναλλαγή σε ένα κομμάτι byte.
Η συμβολοσειρά εσωτερικής συνάρτησης preByteHash(bytes []byte) χρησιμοποιείται στο Build() και στο Check() για να γίνει ο κατακερματισμός συναλλαγής που δημιουργείται συμβατός με τους κατακερματισμούς συναλλαγών που δημιουργούνται από εφαρμογές JavaScript.
Η μέθοδος Build() ορίζει τον κατακερματισμό συναλλαγής ως εξής: tx.TxHash = preByteHash(tx.ToBytes()).
Η μέθοδος συμβολοσειράς ToJSON() μετατρέπει μια συναλλαγή σε συμβολοσειρά JSON.
Η μέθοδος σφάλματος FromJSON(data []byte) φορτώνει μια συναλλαγή από τη μορφή JSON που μεταβιβάζεται ως κομμάτι byte.
Η μέθοδος Bool Check() συγκρίνει τον κατακερματισμό που προκύπτει από το πεδίο κατακερματισμού συναλλαγής με τον κατακερματισμό που λαμβάνεται ως αποτέλεσμα του κατακερματισμού αυτής της συναλλαγής (αγνοώντας το πεδίο κατακερματισμού).
Οι συναλλαγές προστίθενται στο μπλοκ:
Η δομή δεδομένων μπλοκ είναι πιο ογκώδης:
type Block struct {
DataType byte
BlockHeight int
Timestamp int64
HeaderSize int
PrevBlockHash string
SelfBlockHash string
TxsHash string
MerkleRoot string
CreatorPublicKey string
CreatorSig string
Version int
TxsN int
Txs []transaction.TX
}
Το DataType αποθηκεύει τον τύπο δεδομένων, ο κόμβος τον χρησιμοποιεί και διακρίνει το μπλοκ από μια συναλλαγή ή άλλα δεδομένα. Για ένα μπλοκ αυτή η τιμή είναι 1.
Το BlockHeight αποθηκεύει το ύψος του μπλοκ.
Χρονική σήμανση.
HeaderSize είναι το μέγεθος του μπλοκ σε byte.
Το PrevBlockHash είναι ο κατακερματισμός του προηγούμενου μπλοκ και το SelfBlockHash είναι ο κατακερματισμός του τρέχοντος.
Το TxsHash είναι ένας γενικός κατακερματισμός συναλλαγών.
Το MerkleRoot είναι η ρίζα του δέντρου Merkle.
Περαιτέρω στα πεδία υπάρχει το δημόσιο κλειδί του δημιουργού του μπλοκ, η υπογραφή του δημιουργού, η έκδοση του μπλοκ, ο αριθμός των συναλλαγών στο μπλοκ και αυτές οι ίδιες οι συναλλαγές.
Ας δούμε τις μεθόδους του:
Για να δημιουργήσετε ένα μπλοκ, χρησιμοποιήστε τη συνάρτηση block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, που παίρνει τον κατακερματισμό του προηγούμενου μπλοκ και το ύψος που έχει οριστεί για το μπλοκ που δημιουργήθηκε στην αλυσίδα μπλοκ. Ο τύπος μπλοκ ορίζεται επίσης από τη σταθερά του πακέτου τύπων:
b.DataType = types.BLOCK_TYPE.
Η μέθοδος AddTx(tx *transaction.TX) προσθέτει μια συναλλαγή σε ένα μπλοκ.
Η μέθοδος Build() φορτώνει τιμές στα πεδία του μπλοκ και δημιουργεί και ορίζει τον τρέχοντα κατακερματισμό του.
Η μέθοδος ToBytesHeader() []byte μετατρέπει την κεφαλίδα του μπλοκ (χωρίς συναλλαγές) σε ένα κομμάτι byte.
Η μέθοδος συμβολοσειράς ToJSON() μετατρέπει το μπλοκ σε μορφή JSON σε μια αναπαράσταση συμβολοσειράς των δεδομένων.
Η μέθοδος σφάλματος FromJSON(data []byte) φορτώνει δεδομένα από JSON σε μια δομή μπλοκ.
Η μέθοδος Check() bool δημιουργεί έναν κατακερματισμό μπλοκ και τον συγκρίνει με αυτόν που καθορίζεται στο πεδίο κατακερματισμού μπλοκ.
Η μέθοδος συμβολοσειράς GetTxsHash() επιστρέφει το συνολικό κατακερματισμό όλων των συναλλαγών στο μπλοκ.
Η μέθοδος GetMerkleRoot() καθορίζει τη ρίζα του δέντρου Merkle για συναλλαγές σε ένα μπλοκ.
Η μέθοδος Sign (string privk) υπογράφει ένα μπλοκ με το ιδιωτικό κλειδί του δημιουργού του μπλοκ.
Η μέθοδος SetHeight(height int) γράφει το ύψος του μπλοκ στο πεδίο δομής μπλοκ.
Η μέθοδος GetHeight() int επιστρέφει το ύψος του μπλοκ όπως καθορίζεται στο αντίστοιχο πεδίο της δομής του μπλοκ.
Η μέθοδος ToGOBBytes() []byte κωδικοποιεί ένα μπλοκ σε μορφή GOB και το επιστρέφει ως κομμάτι byte.
Η μέθοδος σφάλματος FromGOBBytes(data []byte) εγγράφει δεδομένα μπλοκ στη δομή μπλοκ από το κομμάτι byte που έχει περάσει σε μορφή GOB.
Η μέθοδος συμβολοσειράς GetHash() επιστρέφει τον κατακερματισμό του συγκεκριμένου μπλοκ.
Η μέθοδος συμβολοσειράς GetPrevHash() επιστρέφει τον κατακερματισμό του προηγούμενου μπλοκ.
Η μέθοδος SetPublicKey (συμβολοσειρά pubk) γράφει το δημόσιο κλειδί του δημιουργού μπλοκ στο μπλοκ.
Έτσι, χρησιμοποιώντας τις μεθόδους του αντικειμένου Block, μπορούμε εύκολα να το μετατρέψουμε σε μορφή για μετάδοση μέσω του δικτύου και αποθήκευση στη βάση δεδομένων LevelDB.
Οι λειτουργίες του πακέτου blockchain είναι υπεύθυνες για την αποθήκευση στο blockchain:
Για να γίνει αυτό, το μπλοκ πρέπει να υλοποιήσει τη διεπαφή IBlock:
type IGOBBytes interface {
ToGOBBytes() []byte
FromGOBBytes(data []byte) error
}
type IBlock interface {
IGOBBytes
GetHash() string
GetPrevHash() string
GetHeight() int
Check() bool
}
Η σύνδεση της βάσης δεδομένων δημιουργείται μία φορά όταν το πακέτο αρχικοποιείται στη συνάρτηση init():
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).
Το CloseDB() είναι ένα περιτύλιγμα για το db.Cloce() - καλείται μετά από εργασία με τις συναρτήσεις του πακέτου για να κλείσει η σύνδεση με τη βάση δεδομένων.
Η συνάρτηση σφάλματος SetTargetBlockHash (συμβολοσειρά κατακερματισμού) γράφει τον κατακερματισμό του τρέχοντος μπλοκ με το κλειδί που καθορίζεται από τη σταθερά BLOCK_HASH στη βάση δεδομένων.
Η συνάρτηση GetTargetBlockHash() (string, error) επιστρέφει τον κατακερματισμό του τρέχοντος μπλοκ που είναι αποθηκευμένο στη βάση δεδομένων.
Η συνάρτηση σφάλματος SetTargetBlockHeight(height int) γράφει στη βάση δεδομένων την τιμή του ύψους της αλυσίδας μπλοκ για τον κόμβο με το κλειδί που καθορίζεται από τη σταθερά BLOCK_HEIGHT.
Η συνάρτηση GetTargetBlockHeight() (int, error) επιστρέφει το ύψος του blockchain για έναν δεδομένο κόμβο, που είναι αποθηκευμένος στη βάση δεδομένων.
Η συνάρτηση CheckBlock(block IBlock) bool ελέγχει ένα μπλοκ για ορθότητα πριν προσθέσει αυτό το μπλοκ στο blockchain.
Η συνάρτηση σφάλματος AddBlock(block IBlock) προσθέτει ένα μπλοκ στην αλυσίδα μπλοκ.
Οι λειτουργίες για την ανάκτηση και την προβολή μπλοκ βρίσκονται στο αρχείο explore.go του πακέτου blockchain:
Η συνάρτηση GetBlockByHash(κατακερματισμένη συμβολοσειρά) (*block.Block, error) δημιουργεί ένα κενό αντικείμενο μπλοκ, φορτώνει σε αυτό ένα μπλοκ από τη βάση δεδομένων, του οποίου ο κατακερματισμός μεταβιβάστηκε σε αυτό και επιστρέφει έναν δείκτη σε αυτό.
Η δημιουργία ενός μπλοκ γένεσης πραγματοποιείται από τη συνάρτηση σφάλματος Genesis() από το αρχείο genesis.go του πακέτου blockchain.
Το επόμενο άρθρο θα μιλήσει για τη σύνδεση πελατών σε έναν κόμβο χρησιμοποιώντας τον μηχανισμό WebSocket.
Πηγή: www.habr.com