Kuidas ma oma Go plokiahelas plokke ja tehinguid kujundasin

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.

Kuidas ma oma Go plokiahelas plokke ja tehinguid kujundasin

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

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: 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), 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: github.com/Rusldv/bcstartup/blob/master/block/builder.go

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: github.com/Rusldv/bcstartup/tree/master/blockchain

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

Ostke DDoS-kaitsega saitide jaoks usaldusvÀÀrne hostimine, VPS VDS-serverid đŸ”„ Osta usaldusvÀÀrne veebimajutus DDoS-kaitsega, VPS VDS serverid | ProHoster