Ahhoz, hogy végül blokkláncunk legyen, és ne csupán adatbázis, három fontos elemet kell hozzáadnunk a projektünkhöz:
- A blokk adatainak és módszereinek leírása
- A tranzakció adatai és módszereinek leírása
- A blokklánc funkciói, amelyek a blokkokat tárolják az adatbázisban, és megtalálják őket hash alapján vagy magasság szerint (vagy más módon).

Ez a második cikk a blokkláncról az ipar számára, az első .
Emlékezve a kérdésekre, amelyeket az előző cikkemhez tettek fel az olvasók, érdemes megjegyezni: a blokklánc adatok tárolására ebben az esetben LevelDB adatbázist használunk, de semmi nem akadályozza meg, hogy bármely másikat használjunk, mondjuk a MySQL-t. Most vizsgáljuk meg az adatok struktúráját.
Kezdjük a tranzakciókkal:
Íme, az adatszerkezete:
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
}A TX tárolja az adat típusát (a tranzakciónál 2), a tranzakció hash-ét, a tranzakció típusát, az időbélyeget, valamint a bemeneteket és kimeneteket. A TxIn bemenetek tárolják a hivatkozott tranzakció hash-ét, annak kimenet számát és a byte kódot, míg a TxOut kimenetek tárolnak egy értéket és szintén byte kódot.
Most nézzük meg, milyen műveleteket hajthat végre a tranzakció az adataival, azaz vizsgáljuk meg a módszereket.
A tranzakció létrehozására a transaction.NewTransaction(txtype byte) *TX függvény szolgál.
Az AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) metódus új bemenetet ad a tranzakcióhoz.
Az AddTxOut(value int, data []byte) (*TxOut, error) metódus új kimenetet ad a tranzakcióhoz.
A ToBytes() []byte metódus átalakítja a tranzakciót egy byte sorozattá.
A belső preByteHash(bytes []byte) string függvény a Build() és Check() metódusokban alkalmazásra kerül a generált tranzakciós hash-ek és a JavaScript alkalmazásokból származó hash-ek kompatibilitásának biztosítása érdekében.
A Build() metódus a tranzakció hash-ét a következőképpen állítja be: tx.TxHash = preByteHash(tx.ToBytes()).
A ToJSON() string metódus a tranzakciót JSON stringgé alakítja.
A FromJSON(data []byte) error metódus a tranzakciót betölti a JSON formátumból, amely byte slice formájában lett átadva.
A Check() bool metódus összehasonlítja a tranzakció hash mezőjében lévő hash-t azzal a hash-tel, amely a tranzakció hash-elésének eredményeként keletkezett (a hash mező figyelembevételével nélkül).
A tranzakciókat a blokkokba adjuk hozzá:
A blokk adatszerkezete lényegesen összetettebb:
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
}A DataType tárolja az adat típusát, amely alapján a node meg tudja különböztetni a blokkot a tranzakcióktól vagy egyéb adatforrásoktól. Blokk esetén ez az érték 1.
A BlockHeight tárolja a blokk magasságát.
A Timestamp az időbélyeg.
A HeaderSize a blokk mérete byte-ban.
A PrevBlockHash a megelőző blokk hash értéke, míg a SelfBlockHash a jelenlegi.
A TxsHash a tranzakciók összesített hash értéke.
A MerkleRoot a Merkle fágy gyökere.
Ezután a mezők tartalmazzák a blokk létrehozójának nyilvános kulcsát, a létrehozó aláírását, a blokk verzióját, a blokkban található tranzakciók számát és magukat a tranzakciókat.
Vizsgáljuk meg a metódusait:
A blokk létrehozásához a block.NewBlock() függvényt használjuk: NewBlock(prevBlockHash string, height int) *Block, amely a megelőző blokk hash értékét és a blokkláncban létrehozott blokk magasságát veszi figyelembe. A blokk típusát a types csomag konstansából állítjuk be:
b.DataType = types.BLOCK_TYPE.Az AddTx(tx *transaction.TX) metódus tranzakciót ad hozzá a blokkhoz.
A Build() metódus betölti a mezők értékeit és generálja, valamint beállítja a blokk aktuális hash értékét.
A ToBytesHeader() []byte metódus a blokk fejlécek (tranzakciók nélkül) byte szlájzba konvertálja.
A ToJSON() string metódus a blokkot JSON formátumba alakítja, sztring reprezentációban.
A FromJSON(data []byte) error metódus a JSON-ból betölti az adatokat a blokk struktúrájába.
A Check() bool metódus generálja a blokk hash értékét és összehasonlítja a blokk hash mezőjében megadott értékkel.
A GetTxsHash() string metódus visszaadja a blokkban található tranzakciók összesített hash értékét.
A GetMerkleRoot() metódus beállítja a tranzakciók Merkle fájának gyökér értékét a blokkban.
A Sign(privk string) metódus a blokkot aláírja a blokk létrehozójának privát kulcsával.
A SetHeight(height int) metódus beírja a blokk magasságát a blokk struktúrájának mezőjébe.
A GetHeight() int metódus visszaadja a blokk magasságát, ahogy az a struktúra megfelelő mezőjében van megadva.
A ToGOBBytes() []byte metódus a blokkot GOB formátumban kódolja, és visszaadja byte szlájzként.
A FromGOBBytes(data []byte) error metódus a blokk adatait GOB formátumban írja be a blokk struktúrájába a megadott byte szlájzból.
A GetHash() string metódus visszaadja az adott blokk hash értékét.
A GetPrevHash() string metódus visszaadja a megelőző blokk hash értékét.
A SetPublicKey(pubk string) metódus a blokkba beírja a blokk létrehozójának nyilvános kulcsát.
Így a Block objektum módszereivel könnyen átkonvertálhatjuk azt olyan formátumba, amely alkalmas hálózati továbbításra és a LevelDB adatbázisban való tárolásra.
A blokkláncba való tárolásért a blockchain csomag funkciói felelnek:
Ehhez a blokknak meg kell valósítania az IBlock interfészt:
type IGOBBytes interface {
ToGOBBytes() []byte
FromGOBBytes(data []byte) error
}
type IBlock interface {
IGOBBytes
GetHash() string
GetPrevHash() string
GetHeight() int
Check() bool
}Az adatbázishoz való kapcsolódást egyszer hozzuk létre a csomag inicializálásakor az init() funkcióban:
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).A CloseDB() a db.Close() köré csomagolt hívás — ezt a csomag funkcióival való munka után hívják, hogy bezárja az adatbázis-kapcsolatot.
A SetTargetBlockHash(hash string) error funkció a BLOCK_HASH állandóval megadott kulccsal a jelenlegi blokk hash-ét írja az adatbázisba.
A GetTargetBlockHash() (string, error) funkció visszaadja a jelenlegi blokk hash-ét, amely az adatbázisban található.
A SetTargetBlockHeight(height int) error funkció a BLOCK_HEIGHT állandóval megadott kulccsal az adatbázisba írja a blokklánc magasságát a csomópont számára.
A GetTargetBlockHeight() (int, error) funkció visszaadja a blokk lánc magasságát a megadott csomóponthoz, amely az adatbázisban van tárolva.
A CheckBlock(block IBlock) bool funkció a blokk érvényességének ellenőrzését végzi el, mielőtt ezt a blokkot hozzáadnánk a blokklánchoz.
Az AddBlock(block IBlock) error funkció hozzáadja a blokkot a blokklánchoz.
A blokkok lekérésére és megjelenítésére szolgáló funkciók a blockchain csomag explore.go fájljában találhatók:
A GetBlockByHash(hash string) (*block.Block, error) funkció egy üres blokkobjektumot hoz létre, betölti a blokkot az adatbázisból, amelynek a hash-e át van adva, és visszaadja rá a mutatót.
A genézis blokk létrehozását a Genesis() error funkció végzi a blockchain csomag genesis.go fájljából.
A következő cikkben a kliensek csomóponthoz való csatlakozásáról lesz szó a WebSocket mechanizmus segítségével.
Forrás: habr.com
