Selleks, et lÔpuks luua plokiahel, mitte ainult andmebaas, peame oma projekti lisama 3 olulist elementi:
- Ploki andmestruktuuri ja meetodite kirjeldus
- Andmestruktuuri ja tehingumeetodite kirjeldus
- Plokiahela funktsioonid, mis salvestavad plokke andmebaasi ja leiavad need sealt rÀsi vÔi kÔrguse (vÔi mÔnel muul viisil) jÀrgi.

See on teine ââartikkel tööstusele mĂ”eldud plokiahela kohta, esimene neist. .
Meenutades lugejate kĂŒsimusi selle sarja eelmise artikli kohta, vÀÀrib mĂ€rkimist: antud juhul kasutatakse plokiahela andmete salvestamiseks LevelDB-d, kuid miski ei takista teil kasutamast mis tahes muud andmebaasi, nĂ€iteks MySQL-i. NĂŒĂŒd vaatame nende andmete struktuuri.
Alustame tehingutest:
Siin on selle andmestruktuur:
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 salvestab andmetĂŒĂŒbi (tehingu 2 jaoks), tehingu rĂ€si, tehingu tĂŒĂŒbi enda, ajatempli ning sisendid ja vĂ€ljundid. TxIn sisendid salvestavad viidatud tehingu vĂ€ljundi rĂ€si, vĂ€ljundnumbri ja baitkoodi, samas kui TxOut vĂ€ljundid salvestavad vÀÀrtuse ja ka baitkoodi.
NĂŒĂŒd vaatame, milliseid toiminguid saab tehing oma andmetega teha, st analĂŒĂŒsime meetodeid.
Tehingu loomiseks kasutage funktsiooni transaction.NewTransaction(txtype byte) *TX.
Meetod AddTxIn(thattxhash[]byte, txoutn int, code[]byte)(*TxIn, error) lisab tehingule sisendi.
Meetod AddTxOut(vÀÀrtus int, andmed[]bait) (*TxOut, viga) lisab tehingule vÀljundi.
ToBytes()[]baidimeetod muudab tehingu baidiviiluks.
Sisemist funktsiooni preByteHash(bytes[]byte) stringi kasutatakse funktsioonides Build() ja Check() genereeritud tehingurĂ€si JavaScripti rakenduste genereeritud tehingurĂ€sidega ĂŒhilduvaks muutmiseks.
Meetod Build() mÀÀrab tehingu rÀsi jÀrgmiselt: tx.TxHash = preByteHash(tx.ToBytes()).
ToJSON() stringimeetod teisendab tehingu JSON-stringiks.
FromJSON(data[]bait) veameetod laadib JSON-vormingus tehingu, mis edastatakse baitiviiluna.
Check() bool-meetod vÔrdleb tehingu rÀsivÀljast saadud rÀsi selle tehingu rÀsimisel saadud rÀsiga (rÀsivÀli vÀlja arvatud).
Tehingud lisatakse plokki:
Plokiandmete struktuur on mahukam:
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
}AndmetĂŒĂŒp (DataType) salvestab andmetĂŒĂŒbi, mida sĂ”lm kasutab ploki eristamiseks tehingust vĂ”i muudest andmetest. Ploki puhul on see vÀÀrtus 1.
BlockHeight salvestab ploki kÔrguse.
Ajatempli ajatempel.
PĂ€ise suurus (HeaderSize) on ploki suurus baitides.
PrevBlockHash on eelmise ploki rÀsi ja SelfBlockHash on praeguse ploki rÀsi.
TxsHash on jagatud tehingu rÀsi.
MerkleRoot on Merkle'i puu juur.
JÀrgmistel vÀljadel on ploki looja avalik vÔti, looja allkiri, ploki versioon, plokis olevate tehingute arv ja tehingud ise.
Vaatame tema meetodeid:
Ploki loomiseks kasutage funktsiooni block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, mis aktsepteerib eelmise ploki rĂ€si ja loodud plokile plokiahelas mÀÀratud kĂ”rgust. Ploki tĂŒĂŒp mÀÀratakse samuti types paketi konstandi abil:
b.DataType = types.BLOCK_TYPE.Meetod AddTx(tx *transaction.TX) lisab plokki tehingu.
Meetod Build() laadib vÀÀrtused ploki vÀljadele ning genereerib ja mÀÀrab selle praeguse rÀsi.
ToBytesHeader()[]baidimeetod teisendab ploki pÀise (ilma tehinguteta) baidilÔiguks.
Stringimeetod ToJSON() teisendab ploki JSON-vormingusse andmete stringiesitusena.
FromJSON(andmed[]bait) veameetod laadib JSON-ist andmed plokkstruktuuri.
Check() bool-meetod genereerib ploki rÀsi ja vÔrdleb seda ploki rÀsivÀljal mÀÀratud rÀsiga.
GetTxsHash() stringimeetod tagastab kÔigi plokis olevate tehingute rÀsi summa.
GetMerkleRoot() meetod mÀÀrab ploki tehingute Merkle'i puu juure.
Meetod Sign(privk string) allkirjastab ploki ploki looja privaatvÔtmega.
Meetod SetHeight(height int) kirjutab ploki kÔrguse ploki struktuuri vÀljale.
GetHeight() int-meetod tagastab ploki kÔrguse, nagu see on mÀÀratud ploki struktuuri vastavas vÀljas.
ToGOBBytes() []baidimeetod kodeerib ploki GOB-vormingus ja tagastab selle baidilÔigu kujul.
FromGOBBytes(andmed[]bait) veameetod kirjutab plokkandmed plokkstruktuuri edastatud GOB-vormingus baitiviilust.
GetHash() stringimeetod tagastab antud ploki rÀsi.
GetPrevHash() stringimeetod tagastab eelmise ploki rÀsi.
Meetod SetPublicKey(pubk string) kirjutab ploki looja avaliku vÔtme plokki.
Seega saame Block-objektimeetodeid kasutades selle hÔlpsalt teisendada vÔrgu kaudu edastamiseks ja LevelDB andmebaasi salvestamiseks sobivasse vormingusse.
JĂ€rgmised plokiahela paketi funktsioonid vastutavad plokiahelasse salvestamise eest:
Selleks peab plokk rakendama IBlock-liidese:
type IGOBBytes interface {
ToGOBBytes() []byte
FromGOBBytes(data []byte) error
}
type IBlock interface {
IGOBBytes
GetHash() string
GetPrevHash() string
GetHeight() int
Check() bool
}AndmebaasiĂŒhendus luuakse ĂŒks kord, kui pakett init() funktsioonis initsialiseeritakse:
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).CloseDB() on db.Cloce() funktsiooni wrapper â seda kutsutakse vĂ€lja pĂ€rast pakettfunktsioonidega töötamist andmebaasiĂŒhenduse sulgemiseks.
Veafunktsioon SetTargetBlockHash(rÀsirÔn) kirjutab praeguse ploki rÀsi andmebaasi BLOCK_HASH konstandiga mÀÀratud vÔtmega.
Funktsioon GetTargetBlockHash() (string, error) tagastab andmebaasis talletatud praeguse ploki rÀsi.
Veafunktsioon SetTargetBlockHeight(height int) kirjutab plokiahela kÔrguse vÀÀrtuse andmebaasi sÔlme jaoks, mille vÔti on mÀÀratud konstandiga BLOCK_HEIGHT.
Funktsioon GetTargetBlockHeight() (int, error) tagastab antud sÔlme plokiahela kÔrguse, mis on salvestatud andmebaasi.
Bool-funktsioon CheckBlock(block IBlock) kontrollib ploki Ôigsust enne selle lisamist plokiahelasse.
Veafunktsioon AddBlock(block IBlock) lisab plokiahelasse ploki.
Plokkide hankimise ja vaatamise funktsioonid asuvad blockchain paketi explore.go failis:
Funktsioon GetBlockByHash(rĂ€sistring) (*block.Block, error) loob tĂŒhja plokkobjekti, laeb andmebaasist ploki, mille rĂ€si sellele edastati, ja tagastab sellele pointeri.
Genesis-ploki loomine toimub blockchain-paketi genesis.go failist pÀrit veafunktsiooni Genesis() abil.
JĂ€rgmises artiklis kĂ€sitletakse klientide ĂŒhendamist sĂ”lmega WebSocketi mehhanismi abil.
Allikas: www.habr.com
