Në mënyrë që të përfundojmë përfundimisht me një blockchain dhe jo vetëm me një bazë të dhënash, ne duhet të shtojmë 3 elementë të rëndësishëm në projektin tonë:
- Përshkrimi i strukturës dhe metodave të të dhënave të bllokut
- Përshkrimi i strukturës së të dhënave dhe metodave të transaksionit
- Funksionet e Blockchain që ruajnë blloqet në një bazë të dhënash dhe i gjejnë ato sipas hash-it ose lartësisë së tyre (ose diçka tjetër).
Ky është artikulli i dytë në lidhje me blockchain për industrinë, i pari
Duke kujtuar pyetjet që më bënë lexuesit në lidhje me artikullin e mëparshëm në këtë seri, duhet theksuar: në këtë rast, baza e të dhënave LevelDB përdoret për të ruajtur të dhënat e blockchain, por asgjë nuk ju pengon të përdorni ndonjë, të themi, MySQL. Tani le të shohim strukturën e këtyre të dhënave.
Le të fillojmë me transaksionet:
Këtu është struktura e tij 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
}
TX ruan llojin e të dhënave (për transaksionin 2), hash-in e atij transaksioni, llojin e vetë transaksionit, një vulë kohore dhe hyrjet dhe daljet. Inputet TxIn ruajnë hash-in e transaksionit, prodhimi i të cilit është referuar, numrin e këtij outputi dhe bajtkodi, dhe daljet TxOut ruajnë disa vlera dhe gjithashtu bajtkod.
Tani le të shohim se çfarë veprimesh mund të kryejë një transaksion në të dhënat e tij, d.m.th. Le të shohim metodat.
Për të krijuar një transaksion, përdorni funksionin transaksion.NewTransaction(txtype byte) *TX.
Metoda AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, gabim) shton një hyrje në transaksion.
Metoda AddTxOut(value int, data []byte) (*TxOut, gabim) shton një dalje në transaksion.
Metoda ToBytes() []byte e kthen transaksionin në një copë bajt.
Vargu i funksionit të brendshëm preByteHash(bytes []byte) përdoret në Build() dhe Check() për ta bërë hash-in e transaksionit të krijuar të pajtueshëm me hash-et e transaksioneve të krijuara nga aplikacionet JavaScript.
Metoda Build() vendos hash-in e transaksionit si më poshtë: tx.TxHash = preByteHash(tx.ToBytes()).
Metoda e vargut ToJSON() konverton një transaksion në një varg JSON.
Metoda e gabimit FromJSON(data []byte) ngarkon një transaksion nga formati JSON i kaluar si një pjesë bajt.
Metoda Check() bool krahason hash-in që rezulton nga fusha hash e transaksionit me hash-in e marrë si rezultat i hashimit të këtij transaksioni (duke injoruar fushën hash).
Transaksionet shtohen në bllok:
Struktura e të dhënave të bllokut është më voluminoze:
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 ruan llojin e të dhënave, nyja e përdor atë dhe e dallon bllokun nga një transaksion ose të dhëna të tjera. Për një bllok, kjo vlerë është 1.
BlockHeight ruan lartësinë e bllokut.
Vula kohore.
HeaderSize është madhësia e bllokut në bajt.
PrevBlockHash është hash-i i bllokut të mëparshëm dhe SelfBlockHash është hash-i i atij aktual.
TxsHash është një hash i përgjithshëm i transaksioneve.
MerkleRoot është rrënja e pemës Merkle.
Më tej në fusha gjendet çelësi publik i krijuesit të bllokut, nënshkrimi i krijuesit, versioni i bllokut, numri i transaksioneve në bllok dhe vetë këto transaksione.
Le të shohim metodat e tij:
Për të krijuar një bllok, përdorni funksionin block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, i cili merr hash-in e bllokut të mëparshëm dhe lartësinë e vendosur për bllokun e krijuar në blockchain. Lloji i bllokut caktohet gjithashtu nga konstanta e paketës së llojeve:
b.DataType = types.BLOCK_TYPE.
Metoda AddTx(tx *transaction.TX) shton një transaksion në një bllok.
Metoda Build() ngarkon vlerat në fushat e bllokut dhe gjeneron dhe vendos hash-in e tij aktual.
Metoda ToBytesHeader() []byte konverton kokën e bllokut (pa transaksione) në një copë bajt.
Metoda e vargut ToJSON() e konverton bllokun në formatin JSON në një paraqitje string të të dhënave.
Metoda e gabimit FromJSON(data []byte) ngarkon të dhënat nga JSON në një strukturë blloku.
Metoda Check() bool gjeneron një hash blloku dhe e krahason atë me atë të specifikuar në fushën hash të bllokut.
Metoda e vargut GetTxsHash() kthen hash-in total të të gjitha transaksioneve në bllok.
Metoda GetMerkleRoot() specifikon rrënjën e pemës Merkle për transaksionet në një bllok.
Metoda Sign (string privk) nënshkruan një bllok 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 siç specifikohet në fushën përkatëse të strukturës së bllokut.
Metoda ToGOBBytes() []byte kodon një bllok në formatin GOB dhe e kthen atë si një copë bajt.
Metoda e gabimit FromGOBBytes(data []byte) shkruan të dhënat e bllokut në strukturën e bllokut nga pjesa e kaluar e bajtit në formatin GOB.
Metoda e vargut GetHash() kthen hash-in e bllokut të dhënë.
Metoda e vargut GetPrevHash() kthen hash-in e bllokut të mëparshëm.
Metoda SetPublicKey (string pubk) shkruan çelësin publik të krijuesit të bllokut në bllok.
Kështu, duke përdorur metodat e objektit Block, ne mund ta shndërrojmë atë lehtësisht në një format për transmetim në rrjet 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 ta bërë këtë, blloku duhet të zbatojë ndërfaqen IBlock:
type IGOBBytes interface {
ToGOBBytes() []byte
FromGOBBytes(data []byte) error
}
type IBlock interface {
IGOBBytes
GetHash() string
GetPrevHash() string
GetHeight() int
Check() bool
}
Lidhja e bazës së të dhënave krijohet një herë kur paketa inicializohet në funksionin init():
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).
CloseDB() është një mbështjellës për db.Cloce() - thirret pas punës me funksionet e paketës për të mbyllur lidhjen me bazën e të dhënave.
Funksioni i gabimit SetTargetBlockHash (vargu hash) shkruan hash-in e bllokut aktual me çelësin e specifikuar nga konstantja BLOCK_HASH në bazën e të dhënave.
Funksioni GetTargetBlockHash() (string, gabim) kthen hash-in e bllokut aktual të ruajtur në bazën e të dhënave.
Funksioni i gabimit SetTargetBlockHeight(height int) shkruan në bazën e të dhënave vlerën e lartësisë së blockchain për nyjen me çelësin e specifikuar nga konstantja BLOCK_HEIGHT.
Funksioni GetTargetBlockHeight() (int, error) kthen lartësinë e blockchain për një nyje të caktuar, të ruajtur në bazën e të dhënave.
Funksioni CheckBlock(block IBlock) bool kontrollon një bllok për korrektësi përpara se ta shtojë këtë bllok në zinxhirin e bllokut.
Funksioni i gabimit AddBlock(block IBlock) shton një bllok në blockchain.
Funksionet për marrjen dhe shikimin e blloqeve janë në skedarin explore.go të paketës blockchain:
Funksioni GetBlockByHash (vargu hash) (*block.Block, error) krijon një objekt bllok bosh, ngarkon një bllok në të nga baza e të dhënave, hash-i i të cilit i është kaluar dhe i kthen një tregues.
Krijimi i një blloku të gjenezës kryhet nga funksioni i gabimit Genesis() nga skedari genesis.go i paketës blockchain.
Artikulli tjetër do të flasë për lidhjen e klientëve me një nyje duke përdorur mekanizmin WebSocket.
Burimi: www.habr.com