Hvernig ég hannaði blokkir og viðskipti í Go blockchain mínum

Til þess að enda með blockchain en ekki bara gagnagrunn þurfum við að bæta þremur mikilvægum þáttum við verkefnið okkar:

  • Lýsing á uppbyggingu blokkgagna og aðferðum
  • Lýsing á uppbyggingu gagna og viðskiptaaðferðum
  • Blockchain aðgerðir sem vista blokkir í gagnagrunni og finna þær þar eftir kjötkássa eða hæð (eða einhverju öðru).

Hvernig ég hannaði blokkir og viðskipti í Go blockchain mínum

Þetta er önnur greinin um blockchain fyrir iðnað, sú fyrsta hér.

Minnist spurninganna sem lesendur spurðu mig um fyrri greinina í þessari röð, það skal tekið fram: í þessu tilfelli er LevelDB gagnagrunnurinn notaður til að geyma blockchain gögn, en ekkert kemur í veg fyrir að þú notir annað, segjum, MySQL. Nú skulum við líta á uppbyggingu þessara gagna.

Byrjum á viðskiptum: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Hér er gagnauppbygging þess:

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 geymir gagnategundina (fyrir færslu 2), kjötkássa þeirrar færslu, gerð færslunnar sjálfrar, tímastimpil og inntak og úttak. TxIn inntak geymir kjötkássa færslunnar sem vísað er í úttakið, númer þessa úttaks og bætikóða, og TxOut úttak geymir eitthvað gildi og einnig bækikóða.

Nú skulum við sjá hvaða aðgerðir viðskipti geta framkvæmt á gögnum sínum, þ.e. Við skulum skoða aðferðirnar.

Til að búa til færslu, notaðu aðgerðina transaction.NewTransaction(TXtype bæti) *TX aðgerðina.

Aðferðin AddTxIn(thattxhash []bæti, txoutn int, kóða []bæti) (*TxIn, villa) bætir inntak við færsluna.

AddTxOut(gildi int, gögn []bæti) (*TxOut, villa) aðferðin bætir úttaki við færsluna.

ToBytes() []bætaaðferðin breytir færslunni í bætissneið.

Innri aðgerðin preByteHash(bæti []bæti) strengurinn er notaður í Build() og Check() til að gera myndaða færslukássa samhæft við færslukássa sem myndast úr JavaScript forritum.

Build() aðferðin stillir viðskiptakássið sem hér segir: tx.TxHash = preByteHash(tx.ToBytes()).

ToJSON() strengjaaðferðin breytir færslu í JSON streng.

FromJSON(data []bæti) villuaðferðin hleður færslu frá JSON sniðinu sem er sent sem bætissneið.

Check() bool aðferðin ber saman kjötkássa sem myndast úr færslukássareitnum við kjötkássa sem fæst vegna þess að kjötkássa þessa færslu (hundar kjötkássareitinn).

Viðskiptum er bætt við blokkina: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Uppbygging blokkgagna er fyrirferðarmeiri:

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 geymir gagnategundina, hnúturinn notar hana og greinir blokkina frá færslu eða öðrum gögnum. Fyrir blokk er þetta gildi 1.

BlockHeight geymir hæð blokkarinnar.
Tímastimpill tímastimpill.
HeaderSize er blokkastærðin í bætum.
PrevBlockHash er kjötkássa fyrri blokkarinnar og SelfBlockHash er kjötkássa núverandi.
TxsHash er almennt kjötkássa af færslum.
MerkleRoot er rót Merkle trésins.

Lengra á reitunum er almenni lykill þess sem skapar blokkina, undirskrift skapara, útgáfa af blokkinni, fjölda viðskipta í blokkinni og þessi viðskipti sjálf.

Við skulum skoða aðferðir þess:
Til að búa til blokk, notaðu block.NewBlock() aðgerðina: NewBlock(prevBlockHash string, height int) *Block, sem tekur kjötkássa fyrri blokkar og hæðina sem er stillt á stofnuðu blokkina í blokkinni. Blokkgerðin er einnig stillt frá tegundarpakkansföstum:

b.DataType = types.BLOCK_TYPE.

AddTx(tx *transaction.TX) aðferðin bætir viðskiptum við blokk.

Build() aðferðin hleður gildum inn í reiti blokkarinnar og býr til og stillir núverandi kjötkássa.

ToBytesHeader() []bætaaðferðin breytir blokkhausnum (án færslu) í bætissneið.

ToJSON() strengjaaðferðin breytir kubbnum í JSON snið í strengjaframsetningu gagna.

FromJSON(data []byte) villuaðferðin hleður gögnum frá JSON inn í blokkarbyggingu.

Check() bool aðferðin býr til kubba kjötkássa og ber það saman við þann sem tilgreindur er í reitnum fyrir kubba.

GetTxsHash() strengjaaðferðin skilar heildar kjötkássa allra færslna í reitnum.

GetMerkleRoot() aðferðin tilgreinir rót Merkle trésins fyrir viðskipti í blokk.

Sign(privk string) aðferðin undirritar blokk með einkalykli blokkarhöfundarins.

SetHeight(height int) aðferðin skrifar hæð kubbsins í reitinn fyrir uppbyggingu blokkar.

GetHeight() int aðferðin skilar hæð blokkarinnar eins og tilgreint er í samsvarandi reit blokkarbyggingarinnar.

ToGOBBytes() []bætaaðferðin kóðar blokk á GOB sniði og skilar henni sem bætissneið.

FromGOBBytes(data []byte) villuaðferðin skrifar blokkargögn í blokkarbygginguna frá samþykktri bætissneiðinni á GOB sniði.

GetHash() strengjaaðferðin skilar kjötkássa tiltekinnar blokkar.

GetPrevHash() strengjaaðferðin skilar kjötkássa fyrri blokkar.

SetPublicKey(pubk string) aðferðin skrifar almenningslykil blokkarhöfundarins í blokkina.

Þannig, með því að nota aðferðir Block hlutarins, getum við auðveldlega umbreytt honum í snið til að senda yfir netið og vista í LevelDB gagnagrunninn.

Aðgerðir blockchain pakkans eru ábyrgar fyrir vistun í blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

Til að gera þetta verður blokkin að útfæra IBlock viðmótið:

type IGOBBytes interface {
	ToGOBBytes() []byte
	FromGOBBytes(data []byte) error
}

type IBlock interface {
	IGOBBytes
	GetHash() string
	GetPrevHash() string
	GetHeight() int
	Check() bool

}

Gagnagrunnstengingin er búin til einu sinni þegar pakkinn er frumstilltur í init() aðgerðinni:

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

CloseDB() er umbúðir fyrir db.Cloce() - kallað eftir að hafa unnið með pakkaaðgerðirnar til að loka tengingunni við gagnagrunninn.

SetTargetBlockHash(hash string) villuaðgerðin skrifar kjötkássa núverandi blokkar með lyklinum sem tilgreindur er af BLOCK_HASH fastanum í gagnagrunninn.

GetTargetBlockHash() (strengur, villa) aðgerðin skilar kjötkássa núverandi blokkar sem er geymdur í gagnagrunninum.

SetTargetBlockHeight(height int) villuaðgerðin skrifar í gagnagrunninn gildi blokkaheðjuhæðarinnar fyrir hnútinn með lyklinum sem tilgreindur er af BLOCK_HEIGHT fastanum.

GetTargetBlockHeight() (int, villa) aðgerðin skilar hæð blockchain fyrir tiltekinn hnút, geymdan í gagnagrunninum.

CheckBlock (block IBlock) bool aðgerðin athugar hvort blokk sé rétt áður en þessari blokk er bætt við blockchain.

AddBlock (blokk IBlock) villuaðgerðin bætir blokk við blockchain.

Aðgerðirnar til að sækja og skoða blokkir eru í explore.go skránni í blockchain pakkanum:

GetBlockByHash(kássastrengur) (*block.Block, villa) aðgerðin býr til tóman blokkhlut, hleður blokk inn í hann úr gagnagrunninum, kjötkássa þess var send til hans, og skilar bendi á hann.

Stofnun genesis blokk fer fram með Genesis() villuaðgerðinni frá genesis.go skránni í blockchain pakkanum.

Næsta grein mun tala um að tengja viðskiptavini við hnút með því að nota WebSocket vélbúnaðinn.

Heimild: www.habr.com

Bæta við athugasemd