Πώς σχεδίασα μπλοκ και συναλλαγές στο Go blockchain μου

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

  • Περιγραφή της δομής και των μεθόδων δεδομένων μπλοκ
  • Περιγραφή της δομής δεδομένων και των μεθόδων συναλλαγής
  • Λειτουργίες blockchain που αποθηκεύουν μπλοκ σε μια βάση δεδομένων και τα βρίσκουν εκεί με βάση τον κατακερματισμό ή το ύψος τους (ή κάτι άλλο).

Πώς σχεδίασα μπλοκ και συναλλαγές στο Go blockchain μου

Αυτό είναι το δεύτερο άρθρο σχετικά με το blockchain για τη βιομηχανία, το πρώτο εδώ.

Υπενθυμίζοντας τις ερωτήσεις που μου έκαναν οι αναγνώστες σχετικά με το προηγούμενο άρθρο αυτής της σειράς, θα πρέπει να σημειωθεί: σε αυτήν την περίπτωση, η βάση δεδομένων LevelDB χρησιμοποιείται για την αποθήκευση δεδομένων blockchain, αλλά τίποτα δεν σας εμποδίζει να χρησιμοποιήσετε οποιαδήποτε άλλη, ας πούμε, MySQL. Τώρα ας δούμε τη δομή αυτών των δεδομένων.

Ας ξεκινήσουμε με τις συναλλαγές: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Εδώ είναι η δομή δεδομένων του:

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() συγκρίνει τον κατακερματισμό που προκύπτει από το πεδίο κατακερματισμού συναλλαγής με τον κατακερματισμό που λαμβάνεται ως αποτέλεσμα του κατακερματισμού αυτής της συναλλαγής (αγνοώντας το πεδίο κατακερματισμού).

Οι συναλλαγές προστίθενται στο μπλοκ: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Η δομή δεδομένων μπλοκ είναι πιο ογκώδης:

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: github.com/Rusldv/bcstartup/tree/master/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

Προσθέστε ένα σχόλιο