Kuidas ma projekteerisin plokid ja tehingud oma plokiahelas Go keeles

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.

Kuidas ma projekteerisin plokid ja tehingud oma plokiahelas Go keeles

See on teine artikkel plokiahela kohta tööstuses, esimene siin.

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

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

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

Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster