Kuna saaksime lõpuks luua plokiahela, mitte lihtsalt andmebaasi, peame lisama oma projekti kolm olulist elementi:
- Andmestruktuuri ja blokimeetodite kirjeldus
- Tehingustruktuuri ja meetodite kirjeldus
- Plokiahela funktsioonid, mis salvestavad plokid andmebaasi ja leiavad need seal nende räsiväärtuse või kõrguse (või muul viisil) järgi.

See on teine artikkel plokiahela kohta tööstuses, esimene .
Käies läbi küsimusi, mida lugejad küsisid eelneva artikli kohta, tuleb märkida: plokiahela andmete salvestamiseks kasutatakse antud juhul LevelDB andmebaasi, kuid pole midagi, mis takistaks kasutada mõnda muud, 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-s hoitavad andmetüübid (tehingu 2 jaoks), selle tehingu hash, tehingu tüüp, ajatempli kood ning sisendid ja väljundid. Sisendid TxIn sisaldavad selle tehingu hash'i, millele viidatakse, selle väljundi numbrit ja bytekoodi, samas kui väljundid TxOut hoiavad mingit väärtust ja ka bytekoodi.
Vaadakem nüüd, milliseid toiminguid saab tehing oma andmetega teha, st uurime meetodeid.
Tehingu loomiseks kasutatakse funktsiooni transaction.NewTransaction(txtype byte) *TX.
Meetod AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) lisab tehingule sisendi.
Meetod AddTxOut(value int, data []byte) (*TxOut, error) lisab tehingule väljundi.
Meetod ToBytes() []byte muudab tehingu byte-slice'iks.
Sisemine funktsioon preByteHash(bytes []byte) string rakendatakse Build() ja Check() funktsioonides, et tagada loodud tehingu hash'i ühilduvus JavaScript'i rakendustest genereeritud tehingu hash'idega.
Meetod Build() määrab tehingu hash'i järgmiselt: tx.TxHash = preByteHash(tx.ToBytes()).
Meetod ToJSON() string muundab tehingu JSON stringiks.
Meetod FromJSON(data []byte) error laadib tehingu JSON-formaadist, mis on edastatud byte-slice'ina.
Meetod Check() bool võrreldab saadud hash'i tehingu hash'alalt tehingu hash'iga, mis saadakse selle tehingu hash'imise tulemusena (ilma hash'i alampunktita).
Tehingud lisatakse plokki:
Ploki andmestruktuur on suurem:
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 hoiab andmetüüpi, mille põhjal node eristab plokki tehingust või muudest andmetest. Ploki puhul on see väärtus 1.
BlockHeight hoiab ploki kõrgust.
Timestamp ajatemplit.
HeaderSize ploki suurust baitides.
PrevBlockHash on eelmise ploki hash ja SelfBlockHash on praegune.
TxsHash on tehingute koguhash.
MerkleRoot on Merkle puu juur.
Edasi, välistes väljadest, on ploki looja avalik võti, looja allkiri, ploki versioon, tehingute arv plokis ja muidugi ise need tehingud.
Vaadakem tema meetodeid:
Ploki loomisel kasutatakse funktsiooni block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, mis võtab vastu eelmise ploki hash'i ja kõrguse, mis on määratud loodud plokile plokiahelas. Samuti määratakse ploki tüüp paketist types konstantide abil:
b.DataType = types.BLOCK_TYPE.Meetod AddTx(tx *transaction.TX) lisab plokki tehingu.
Meetod Build() laadib ploki väljadele väärtused ja genereerib ning määrab selle hetke hash'i.
Meetod ToBytesHeader() []byte muundab ploki päise (ilma tehinguteta) baitide lõiguks.
Meetod ToJSON() string muundab ploki JSON-vormingusse stringi kujul.
Meetod FromJSON(data []byte) error laadib andmed JSON'ist ploki struktuuri.
Meetod Check() bool genereerib ploki hash'i ja võrdleb seda ploki hash'i väljas määratud väärtusega.
Meetod GetTxsHash() string tagastab kõigi plokis olevate tehingute koguhash'i.
Meetod GetMerkleRoot() määrab plokis olevate tehingute Merkle puu juure.
Meetod Sign(privk string) allkirjastab ploki looja privaatsuse võtmega.
Meetod SetHeight(height int) salvestab ploki kõrguse ploki struktuuri väljal.
Meetod GetHeight() int tagastab ploki kõrguse, nagu on määratud ploki struktuuri vastavas väljas.
Meetod ToGOBBytes() []byte kodeerib ploki GOB formaati ja tagastab selle baitide lõiguna.
Meetod FromGOBBytes(data []byte) error kirjutab ploki andmed struktuuri plokist edastatud baitide lõigus GOB formaadis.
Meetod GetHash() string tagastab selle ploki rümba.
Meetod GetPrevHash() string tagastab eelmise ploki rümba.
Meetod SetPublicKey(pubk string) kirjutab plokki looja avaliku võtme.
Nii et, objektide Block meetodite abil saame kergesti konverteerida need formaati edastamiseks võrgu kaudu ja salvestamiseks LevelDB andmebaasi.
Bloki salvestamise eest vastutavad blockchain paketi funktsioonid:
Selleks peab plokk rakendama liidest IBlock:
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 paketi initsialiseerimise ajal funktsioonis init():
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).CloseDB() on db.Cloce() ümbrik — kutsutakse välja pärast paketi funktsioonidega töötamist, et sulgeda ühendus andmebaasiga.
Funktsioon SetTargetBlockHash(hash string) error salvestab andmebaasi praeguse ploki rümbas võti, mille on määranud konstandi BLOCK_HASH.
GetTargetBlockHash() (string, error) funktsioon tagastab praeguse ploki hash'i, mis on salvestatud andmebaasi.
SetTargetBlockHeight(height int) error funktsioon kirjutab andmebaasi blockchain'i kõrguse väärtuse sõlmele, mille võti on määratud konstant BLOCK_HEIGHT.
GetTargetBlockHeight() (int, error) funktsioon tagastab blockchain'i kõrguse selle sõlme jaoks, mis on salvestatud andmebaasi.
CheckBlock(block IBlock) bool funktsioon kontrollib ploki korrektsust enne, kui see plokk lisatakse blockchain'i.
AddBlock(block IBlock) error funktsioon lisab ploki blockchain'i.
Plokkide saamise ja vaatamise funktsioonid on failis explore.go blockchain'i paketis:
GetBlockByHash(hash string) (*block.Block, error) funktsioon loob tühja ploki objekti, laadib sinna ploki andmebaasist, mille hash on edastatud, ja tagastab sellele näitaja.
Genesis() error funktsioon, mis asub failis genesis.go blockchain'i paketis, vastutab geenesisploki loomise eest.
Järgmises artiklis käsitletakse, kuidas ühendada klientide sõlmega WebSocket'i mehhanismi abil.
Allikas: habr.com
