Kuidas ma oma Go plokiahelas plokke ja tehinguid kujundasin

Selleks, et lõpuks saaksime plokiahela, mitte ainult andmebaasi, peame oma projekti lisama kolm olulist elementi:

  • Ploki andmestruktuuri ja meetodite kirjeldus
  • Andmestruktuuri ja tehingumeetodite kirjeldus
  • Blockchaini funktsioonid, mis salvestavad plokid andmebaasi ja leiavad need sealt räsi või kõrguse (või millegi muu) järgi.

Kuidas ma oma Go plokiahelas plokke ja tehinguid kujundasin

See on teine ​​​​artikkel tööstusele mõeldud plokiahela kohta, esimene siin.

Meenutades küsimusi, mida lugejad mulle selle sarja eelmise artikli kohta esitasid, tuleb märkida: antud juhul kasutatakse plokiahela andmete salvestamiseks LevelDB andmebaasi, kuid miski ei takista teil kasutada mõnda muud, näiteks MySQL-i. Vaatame nüüd nende andmete struktuuri.

Alustame tehingutega: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

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), selle tehingu räsi, tehingu enda tüübi, ajatempli ning sisendid ja väljundid. TxIn sisendid salvestavad selle tehingu räsi, mille väljundile viidatakse, selle väljundi numbri ja baitkoodi ning TxOut väljundid salvestavad mingi väärtuse ja ka baitkoodi.

Nüüd vaatame, milliseid toiminguid saab tehing oma andmetega teha, s.t. Vaatame meetodeid.

Tehingu loomiseks kasutage tehingu.NewTransaction(txtype byte) *TX funktsiooni.

Meetod AddTxIn(thattxhash []bait, txoutn int, kood []bait) (*TxIn, error) lisab tehingule sisendi.

Meetod AddTxOut(väärtus int, data []bait) (*TxOut, error) lisab tehingule väljundi.

Meetod ToBytes() []byte muudab tehingu baidilõikeks.

Sisefunktsiooni stringi preByteHash(baitid []bait) kasutatakse funktsioonides Build() ja Check(), et genereeritud tehinguräsi ühilduks JavaScripti rakendustest genereeritud tehinguräsidega.

Meetod Build() määrab tehingu räsi järgmiselt: tx.TxHash = preByteHash(tx.ToBytes()).

Stringimeetod ToJSON() teisendab tehingu JSON-stringiks.

Tõrkemeetod FromJSON(data []byte) laadib tehingu JSON-vormingust, mis edastatakse baidilõikena.

Meetod Check() võrdleb tehingu räsiväljalt saadud räsi selle tehingu räsimise tulemusel saadud räsiga (räsivälja ignoreerimine).

Tehingud lisatakse plokki: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Plokkide andmestruktuur 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
}

DataType salvestab andmetüübi, sõlm kasutab seda ja eristab plokki tehingust või muudest andmetest. Ploki puhul on see väärtus 1.

BlockHeight salvestab ploki kõrguse.
Ajatempli ajatempel.
HeaderSize on ploki suurus baitides.
PrevBlockHash on eelmise ploki räsi ja SelfBlockHash on praeguse ploki räsi.
TxsHash on üldine tehingute räsi.
MerkleRoot on Merkle puu juur.

Edasi on väljadel ploki looja avalik võti, looja allkiri, ploki versioon, tehingute arv plokis ja need tehingud ise.

Vaatame selle meetodeid:
Ploki loomiseks kasuta funktsiooni block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, mis võtab plokiahelas eelmise ploki räsi ja loodud ploki kõrguse. Ploki tüüp määratakse ka tüübipaketi konstandist:

b.DataType = types.BLOCK_TYPE.

AddTx(tx *transaction.TX) meetod lisab plokki tehingu.

Meetod Build() laadib väärtused ploki väljadele ning genereerib ja määrab selle praeguse räsi.

Meetod ToBytesHeader() []byte teisendab ploki päise (ilma tehinguteta) baidilõiguks.

Stringimeetod ToJSON() teisendab ploki JSON-vormingusse andmete stringi esituses.

Tõrkemeetod FromJSON(data []byte) laadib andmed JSON-ist plokistruktuuri.

Check() bool-meetod genereerib ploki räsi ja võrdleb seda ploki räsiväljal määratud räsiga.

Stringimeetod GetTxsHash() tagastab kõigi ploki tehingute koguräsi.

Meetod GetMerkleRoot() määrab plokis tehtavate tehingute jaoks Merkle'i puu juure.

Sign(privk string) meetod allkirjastab ploki ploki looja privaatvõtmega.

SetHeight(height int) meetod kirjutab ploki kõrguse ploki struktuuri väljale.

GetHeight() int meetod tagastab ploki kõrguse, mis on määratud ploki struktuuri vastaval väljal.

Meetod ToGOBBytes() []byte kodeerib ploki GOB-vormingus ja tagastab selle baidilõikena.

Tõrkemeetod FromGOBBytes(data []byte) kirjutab plokiandmed plokistruktuuri läbitud baidilõigust GOB-vormingus.

Stringi meetod GetHash() tagastab antud ploki räsi.

Stringi meetod GetPrevHash() tagastab eelmise ploki räsi.

SetPublicKey(pubk string) meetod kirjutab ploki looja avaliku võtme plokki.

Seega, kasutades Block-objekti meetodeid, saame selle hõlpsalt teisendada vormingusse võrgu kaudu edastamiseks ja LevelDB andmebaasi salvestamiseks.

Plokiahela paketi funktsioonid vastutavad plokiahelasse salvestamise eest: github.com/Rusldv/bcstartup/tree/master/blockchain

Selleks peab plokk rakendama IBlocki liidest:

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 initsialiseeritakse funktsioonis init():

db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).

CloseDB() on db.Cloce() ümbris – kutsutakse välja pärast paketifunktsioonidega töötamist, et sulgeda ühendus andmebaasiga.

Veafunktsioon SetTargetBlockHash(hash string) kirjutab praeguse ploki räsi konstandi BLOCK_HASH määratud võtmega andmebaasi.

Funktsioon GetTargetBlockHash() (string, viga) tagastab praeguse andmebaasi salvestatud ploki räsi.

Veafunktsioon SetTargetBlockHeight(height int) kirjutab andmebaasi sõlme plokiahela kõrguse väärtuse konstandiga BLOCK_HEIGHT määratud võtmega.

Funktsioon GetTargetBlockHeight() (int, error) tagastab antud sõlme plokiahela kõrguse, mis on salvestatud andmebaasi.

Tõhendusfunktsioon CheckBlock(block IBlock) kontrollib ploki õigsust enne selle ploki plokiahelasse lisamist.

AddBlock(block IBlock) tõrkefunktsioon lisab plokiahelasse ploki.

Plokkide allalaadimise ja vaatamise funktsioonid on plokiahela paketi explore.go failis:

Funktsioon GetBlockByHash(hash string) (*block.Block, error) loob tühja plokiobjekti, laeb sellesse andmebaasist ploki, mille räsi talle edastati ja tagastab sellele osuti.

Genesis-ploki loomine toimub veafunktsiooni Genesis() abil plokiahela paketi genesis.go failist.

Järgmises artiklis räägitakse klientide ühendamisest sõlmega WebSocketi mehhanismi abil.

Allikas: www.habr.com

Lisa kommentaar