Ինչպես ես նախագծեցի բլոկներ և գործարքներ իմ Go բլոկչեյնում

Որպեսզի ի վերջո հայտնվենք բլոկչեյնով և ոչ միայն տվյալների բազայով, մենք պետք է մեր նախագծին ավելացնենք 3 կարևոր տարր.

  • Բլոկի տվյալների կառուցվածքի և մեթոդների նկարագրությունը
  • Տվյալների կառուցվածքի և գործարքների մեթոդների նկարագրությունը
  • Blockchain-ի գործառույթներ, որոնք պահում են բլոկները տվյալների բազայում և գտնում դրանք այնտեղ իրենց հեշով կամ բարձրությամբ (կամ այլ բանով):

Ինչպես ես նախագծեցի բլոկներ և գործարքներ իմ Go բլոկչեյնում

Սա արդյունաբերության համար բլոկչեյնի մասին երկրորդ հոդվածն է, առաջինը այստեղ.

Հիշելով այս շարքի նախորդ հոդվածի վերաբերյալ ընթերցողների կողմից տրված հարցերը, հարկ է նշել. այս դեպքում LevelDB տվյալների բազան օգտագործվում է բլոկչեյնի տվյալները պահելու համար, բայց ոչինչ չի խանգարում ձեզ օգտագործել որևէ այլ, ասենք, MySQL: Հիմա եկեք նայենք այս տվյալների կառուցվածքին:

Սկսենք գործարքներից. github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Ահա դրա տվյալների կառուցվածքը.

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-ը պահպանում է տվյալների տեսակը (գործարք 2-ի համար), այդ գործարքի հեշը, բուն գործարքի տեսակը, ժամանակի դրոշմը և մուտքերն ու ելքերը: TxIn մուտքերը պահում են գործարքի հեշը, որի ելքը նշված է, այս ելքի և բայթկոդի քանակը, իսկ TxOut ելքերը պահում են որոշակի արժեք և նաև բայթ կոդը:

Այժմ տեսնենք, թե ինչ գործողություններ կարող է կատարել գործարքն իր տվյալների վրա, այսինքն. Եկեք նայենք մեթոդներին:

Գործարք ստեղծելու համար օգտագործեքtransaction.NewTransaction(txtype byte) *TX ֆունկցիան:

AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) մեթոդը մուտք է ավելացնում գործարքին։

AddTxOut(value int, data []byte) (*TxOut, error) մեթոդը ելք է ավելացնում գործարքին:

ToBytes() []byte մեթոդը գործարքը վերածում է բայթ հատվածի:

Ներքին ֆունկցիայի preByteHash(bytes []byte) տողը օգտագործվում է Build()-ում և Check()-ում՝ ստեղծվող գործարքի հեշը համատեղելի դարձնելու JavaScript հավելվածներից ստեղծված գործարքների հեշերի հետ:

Build() մեթոդը սահմանում է գործարքի հեշը հետևյալ կերպ. tx.TxHash = preByteHash(tx.ToBytes()):

ToJSON() տողի մեթոդը գործարքը փոխակերպում է JSON տողի:

FromJSON(data []byte) սխալի մեթոդը բեռնում է գործարքը JSON ձևաչափից, որը փոխանցվել է որպես բայթ հատված:

Check() bool մեթոդը համեմատում է գործարքի հեշ դաշտից ստացված հեշը այս գործարքի հեշավորման արդյունքում ստացված հեշի հետ (անտեսելով հեշ դաշտը):

Գործարքները ավելացվում են բլոկին. github.com/Rusldv/bcstartup/blob/master/block/builder.go

Բլոկի տվյալների կառուցվածքը ավելի ծավալուն է.

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-ը պահպանում է տվյալների տեսակը, հանգույցն օգտագործում է այն և տարբերակում բլոկը գործարքից կամ այլ տվյալներից: Բլոկի համար այս արժեքը 1 է:

BlockHeight-ը պահպանում է բլոկի բարձրությունը:
Ժամացույցի ժամանակի դրոշմ.
HeaderSize-ը բայթերի բլոկի չափն է:
PrevBlockHash-ը նախորդ բլոկի հեշն է, իսկ SelfBlockHash-ը ներկայիս բլոկի հեշն է:
TxsHash-ը գործարքների ընդհանուր հեշ է:
MerkleRoot-ը Merkle ծառի արմատն է:

Այնուհետև դաշտերում կա բլոկի ստեղծողի հանրային բանալին, ստեղծողի ստորագրությունը, բլոկի տարբերակը, բլոկում գործարքների քանակը և հենց այդ գործարքները:

Դիտարկենք դրա մեթոդները.
Բլոկ ստեղծելու համար օգտագործեք block.NewBlock() ֆունկցիան. Բլոկի տեսակը սահմանվում է նաև տիպերի փաթեթի հաստատունից.

b.DataType = types.BLOCK_TYPE.

AddTx(tx *transaction.TX) մեթոդը գործարք է ավելացնում բլոկին:

Build() մեթոդը բեռնում է արժեքները բլոկի դաշտերում և ստեղծում և սահմանում դրա ընթացիկ հեշը:

ToBytesHeader() []byte մեթոդը բլոկի վերնագիրը (առանց գործարքների) փոխակերպում է բայթ հատվածի։

ToJSON() լարային մեթոդը բլոկը փոխակերպում է JSON ձևաչափի՝ տվյալների տողային ներկայացման մեջ:

FromJSON(data []byte) սխալի մեթոդը JSON-ից տվյալները բեռնում է բլոկի կառուցվածքում:

Check() bool մեթոդը ստեղծում է բլոկի հեշ և համեմատում այն ​​բլոկի հեշ դաշտում նշվածի հետ։

GetTxsHash() լարային մեթոդը վերադարձնում է բլոկի բոլոր գործարքների ընդհանուր հեշը:

GetMerkleRoot() մեթոդը սահմանում է Merkle ծառի արմատը բլոկում գործարքների համար:

Sign (privk string) մեթոդը ստորագրում է բլոկը բլոկ ստեղծողի անձնական բանալիով:

SetHeight(height int) մեթոդը գրում է բլոկի բարձրությունը բլոկի կառուցվածքի դաշտում։

GetHeight() int մեթոդը վերադարձնում է բլոկի բարձրությունը, ինչպես նշված է բլոկի կառուցվածքի համապատասխան դաշտում։

ToGOBBytes() []byte մեթոդը կոդավորում է GOB ձևաչափով բլոկը և վերադարձնում այն ​​որպես բայթ հատված:

FromGOBBytes(data []byte) սխալի մեթոդը բլոկի տվյալները գրում է բլոկի կառուցվածքում անցած բայթի հատվածից GOB ձևաչափով:

GetHash() լարային մեթոդը վերադարձնում է տվյալ բլոկի հեշը։

GetPrevHash() լարային մեթոդը վերադարձնում է նախորդ բլոկի հեշը։

SetPublicKey (pubk string) մեթոդը բլոկի վրա գրում է բլոկ ստեղծողի հանրային բանալին:

Այսպիսով, օգտագործելով Block օբյեկտի մեթոդները, մենք հեշտությամբ կարող ենք այն վերածել ցանցի միջոցով փոխանցման և LevelDB տվյալների բազայում պահպանման ձևաչափի։

Բլոկչեյն փաթեթի գործառույթները պատասխանատու են բլոկչեյնին խնայելու համար. github.com/Rusldv/bcstartup/tree/master/blockchain

Դա անելու համար բլոկը պետք է իրականացնի IBlock ինտերֆեյսը.

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

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

}

Տվյալների բազայի կապը ստեղծվում է մեկ անգամ, երբ փաթեթը սկզբնավորվում է init() ֆունկցիայում.

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

CloseDB()-ը db.Cloce()-ի փաթաթիչ է, որը կոչվում է փաթեթի ֆունկցիաների հետ աշխատելուց հետո՝ տվյալների բազայի հետ կապը փակելու համար:

SetTargetBlockHash(hash string) սխալ ֆունկցիան տվյալների բազայում գրում է ընթացիկ բլոկի հեշը BLOCK_HASH հաստատունով նշված բանալիով:

GetTargetBlockHash() (string, error) ֆունկցիան վերադարձնում է տվյալների բազայում պահվող ընթացիկ բլոկի հեշը։

SetTargetBlockHeight(height int) սխալ ֆունկցիան տվյալների բազայում գրում է հանգույցի համար բլոկչեյնի բարձրության արժեքը BLOCK_HEIGHT հաստատունով նշված բանալիով:

GetTargetBlockHeight() (int, error) ֆունկցիան վերադարձնում է տվյալների բազայում պահվող բլոկչեյնի բարձրությունը տվյալ հանգույցի համար:

CheckBlock (block IBlock) bool ֆունկցիան ստուգում է բլոկի ճշգրտությունը՝ նախքան այս բլոկը բլոկչեյնին ավելացնելը:

AddBlock(block IBlock) սխալ ֆունկցիան բլոկ է ավելացնում բլոկչեյնին:

Բլոկների առբերման և դիտման գործառույթները գտնվում են blockchain փաթեթի explore.go ֆայլում.

GetBlockByHash(hash string) (*block.Block, error) ֆունկցիան ստեղծում է դատարկ բլոկ օբյեկտ, բեռնում է դրա մեջ բլոկ տվյալների բազայից, որի հեշը փոխանցվել է նրան և վերադարձնում ցուցիչ։

Genesis բլոկի ստեղծումն իրականացվում է Genesis() սխալ ֆունկցիայի միջոցով բլոկչեյն փաթեթի genesis.go ֆայլից:

Հաջորդ հոդվածում կխոսվի WebSocket մեխանիզմի միջոցով հաճախորդներին հանգույցին միացնելու մասին:

Source: www.habr.com

Добавить комментарий