Për të arritur në fund të fundit një blokçain dhe jo thjesht një bazë të dhënash, na nevojiten tre elementë të rëndësishëm në projektin tonë:
- Përshkrimi i strukturës së të dhënave dhe metodave të bllokut
- Përshkrimi i strukturës së të dhënave dhe metodave të transaksionit
- Funksionet e blokçainit që ruajnë blloqet në bazën e të dhënave dhe i gjejnë atje nëpërmjet hash-it të tyre ose lartësisë (apo ndonjë forme tjetër).

Ky është artikulli i dytë për blokçainin për industrinë, i pari .
Duke u rikujtuar pyetjet që më bënë lexuesit në artikullin e mëparshëm të këtij cikli, duhet të theksoj: për ruajtjen e të dhënave të blokçainit në këtë rast përdoret një bazë të dhënash LevelDB, por asgjë nuk e ndalon përdorimin e një të tjerës, le të themi MySQL-në e njëjtë. Tani le të shqyrtojmë strukturën e këtyre të dhënave.
Le të fillojmë me transaksionet:
Këtu është struktura e saj e të dhënave:
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
}Në TX ruhen tipin e të dhënave (për transaksionin 2), hash-i i këtij transaksioni, tipi i vetë transaksionit, timestamp-i, si dhe hyrjet dhe daljet. Hyrjet TxIn ruajnë hash-in e transaksionit, në daljen e të cilit referohen, numrin e kësaj daljeje dhe bytecode, ndërsa daljet TxOut ruajnë një vlerë dhe gjithashtu bytecode.
Tani le të shohim cilat veprime mund të kryejnë transaksionet mbi të dhënat e tyre, pra t'i shqyrtojmë metodat.
Funksioni transaction.NewTransaction(txtype byte) *TX shërben për krijimin e një transaksioni.
Metoda AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) shton një hyrje në transaksion.
Metoda AddTxOut(value int, data []byte) (*TxOut, error) shton një dalje në transaksion.
Metoda ToBytes() []byte e kthen transaksionin në një slice bajtësh.
Funksioni i brendshëm preByteHash(bytes []byte) string aplikohet në Build() dhe Check() për t'u siguruar që hash-i i krijuar i transaksioneve të jetë në përputhje me hash-et e transaksioneve të gjeneruara nga aplikacionet në JavaScript.
Metoda Build() përcakton hash-in e transaksionit kështu: tx.TxHash = preByteHash(tx.ToBytes()).
Metoda ToJSON() string e kthen transaksionin në një varg JSON.
Metoda FromJSON(data []byte) error ngarkon transaksionin nga formati JSON, i dërguar si një slice bajtësh.
Metoda Check() bool krahasohet hash-i i marrës nga fusha e hash-it të transaksionit me hash-in e marrë si rezultat i hash-it të këtij transaksioni (pa marrë parasysh fushën e hash-it).
Transaksionet shtohen në bllok:
Struktura e të dhënave të bllokut është më e gjerë:
tip 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 ruan tipin e dhënave, me të cilin nodi dallon blokun nga transaksionet ose të dhëna të tjera. Për blokun, kjo vlerë është e barabartë me 1.
BlockHeight ruan lartësinë e blokut.
Timestamp është stampë e kohës.
HeaderSize është madhësia e blokut në byte.
PrevBlockHash është hash-i i blokut të mëparshëm, ndërsa SelfBlockHash është aktuali.
TxsHash është hash-i total i transaksioneve.
MerkleRoot është rrënjës i pemës Merkle.
Më poshtë në fushat ndodhet çelësi publik i krijuesit të blokut, nënshkrimi i krijuesit, versioni i blokut, numri i transaksioneve në bllok dhe vetë këto transaksione.
Le të shqyrtojmë metodat e tij:
Për të krijuar një blok, përdoret funksioni block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, i cili pranon hash-in e blokut të mëparshëm dhe lartësinë e vendosur për blokun e krijuar në blockchain. Gjithashtu, vendoset tipi i blokut nga konstanta e paketës types:
b.DataType = types.BLOCK_TYPE.Metoda AddTx(tx *transaction.TX) shton një transaksion në bllok.
Metoda Build() ngarkon vlerat në fushat e blokut dhe gjeneron dhe vendos hash-in e tij aktual.
Metoda ToBytesHeader() []byte shndërron header-in e blokut (pa transaksionet) në një slice byte.
Metoda ToJSON() string shndërron blokun në formatin JSON në një përfaqësim string të të dhënave.
Metoda FromJSON(data []byte) error ngarkon të dhënat nga JSON në strukturën e blokut.
Metoda Check() bool gjeneron hash-in e blokut dhe e krahason me atë të caktuar në fushën e hash-it të blokut.
Metoda GetTxsHash() string kthen hash-in total të të gjitha transaksioneve në bllok.
Metoda GetMerkleRoot() vendos rrënjën e pemës Merkle për transaksionet në bllok.
Metoda Sign(privk string) nënshkruan bllokun me çelësin privat të krijuesit të bllokut.
Metoda SetHeight(height int) shkruan lartësinë e bllokut në fushën e strukturës së bllokut.
Metoda GetHeight() int kthen lartësinë e bllokut ashtu siç tregohet në fushën përkatëse të strukturës së bllokut.
Metoda ToGOBBytes() []byte kodon bllokun në formatin GOB dhe e kthen atë si një slice byte.
Metoda FromGOBBytes(data []byte) error shkruan të dhënat e bllokut në strukturën e bllokut nga slice byte i dërguar në formatin GOB.
Metoda GetHash() string kthen hash-in e këtij blloku.
Metoda GetPrevHash() string kthen hash-in e bllokut të mëparshëm.
Metoda SetPublicKey(pubk string) shkruan në bllok çelësin publik të krijuesit të bllokut.
Kështu, me metodat e objektit Block, ne mund të konvertojmë lehtësisht atë në një format për transferim rrjeti dhe ruajtje në bazën e të dhënave LevelDB.
Funksionet e paketës blockchain janë përgjegjëse për ruajtjen në blockchain:
Për këtë, blloku duhet të implementojë ndërfaqen IBlock:
type IGOBBytes interface {
ToGOBBytes() []byte
FromGOBBytes(data []byte) error
}
type IBlock interface {
IGOBBytes
GetHash() string
GetPrevHash() string
GetHeight() int
Check() bool
}Kconnection to the database is created once during the initialization of the package in the function init():
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).CloseDB() Ă«shtĂ« njĂ« mbĂ«shtjellĂ«s pĂ«r db.Close() â thirret pas punĂ«s me funksionet e paketĂ«s pĂ«r tĂ« mbyllur lidhjen me DB.
Funksioni SetTargetBlockHash(hash string) error shkruan në DB hash-in e bllokut aktual me çelësin e caktuar nga konstanta BLOCK_HASH.
Funksioni GetTargetBlockHash() (string, error) kthen hash-in e bllokut aktual, i cili ruhet në DB.
Funksioni SetTargetBlockHeight(height int) error shkruan në DB vlerën e lartësisë së blockchain për noden me çelësin e caktuar nga konstanta BLOCK_HEIGHT.
Funksioni GetTargetBlockHeight() (int, error) kthen lartësinë e blockchain për këtë nodë, e ruajtur në DB.
Funksioni CheckBlock(block IBlock) bool kryen verifikimin e bllokut për korrektësinë para se ta shtojmë këtë bllok në blockchain.
Funksioni AddBlock(block IBlock) error shton një bllok në blockchain.
Funksionet për marrjen dhe shikimin e bllokëve ndodhen në skedarin explore.go të paketës blockchain:
Funksioni GetBlockByHash(hash string) (*block.Block, error) krijon një objekt bosh blloku, ngarkon bllokun e tij nga DB me hash-in e dhënë dhe kthen një pointer ndaj tij.
Krijimi i bllokut të gjenesis kryhet nga funksioni Genesis() error nga skedari genesis.go i paketës blockchain.
Në artikullin e ardhshëm do të flasim për lidhjen me nodin e klientëve duke përdorur mekanizmin WebSocket.
Burimi: habr.com
