Ako som navrhoval bloky a transakcie vo svojom blockchaine na Go

Aby sa nakoniec vytvoril blockchain, a nie len jednoduchá databáza, musíme pridať do projektu 3 dôležité prvky:

  • Popis štruktúry dát a metód bloku
  • Popis štruktúry dát a metód transakcie
  • Funkcie blockchainu, ktoré uchovávajú bloky v databáze a nachádzajú ich tam na základe ich hash alebo výšky (alebo iným spôsobom).

Ako som navrhoval bloky a transakcie vo svojom blockchaine na Go

Toto je druhý článok o blockchaine pre priemysel, prvý tu.

Pamätajúc na otázky, ktoré mi čitatelia položili k predchádzajúcemu článku tejto série, je potrebné poznamenať: na ukladanie dát blockchainu sa v tomto prípade používa databáza LevelDB, ale nič nebráni použitiu akejkoľvek inej, povedzme tej istej MySQL. Teraz sa pozrime na štruktúru týchto dát.

Začneme s transakciami: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Tu je jej štruktúra dát:

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
}

V TX sú uložené typ dát (pre transakciu 2), hash tejto transakcie, typ samotnej transakcie, časová pečiatka, ako aj vstupy a výstupy. Vstupy TxIn uchovávajú hash transakcie, na výstup ktorého sa odkazuje, číslo tohto výstupu a bytecode, a výstupy TxOut uchovávajú nejakú hodnotu a tiež bytecode.

Teraz sa pozrime, aké akcie môže transakcia vykonávať s vlastnými dátami, teda si rozoberieme metódy.

Na vytvorenie transakcie slúži funkcia transaction.NewTransaction(txtype byte) *TX.

Metóda AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) pridáva vstup k transakcii.

Metóda AddTxOut(value int, data []byte) (*TxOut, error) pridáva výstup k transakcii.

Metóda ToBytes() []byte premieňa transakciu na byte slice.

Interná funkcia preByteHash(bytes []byte) string sa používa v Build() a Check() na zabezpečenie kompatibility vytvoreného hash transakcií s hashmi transakcií generovanými z aplikácií v JavaScripte.

Metóda Build() nastavuje hash transakcie nasledovne: tx.TxHash = preByteHash(tx.ToBytes()).

Metóda ToJSON() string transformuje transakciu na JSON reťazec.

Metóda FromJSON(data []byte) error načítava transakciu z formátu JSON, ktorý bol zaslaný vo forme byte slice.

Metóda Check() bool porovnáva získaný hash z poľa hash transakcie s hashom získaným z hashovania tejto transakcie (bez ohľadu na pole hash).

Transakcie sa pridávajú do bloku: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Štruktúra dát bloku je rozsiahlejšia:

typ Block štruktúra {
	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 uchováva typ údajov, podľa ktorého uzol rozlišuje blok od transakcie alebo iných údajov. Pre blok je táto hodnota rovná 1.

BlockHeight uchováva výšku bloku.
Timestamp je časová pečať.
HeaderSize je veľkosť bloku v bajtoch.
PrevBlockHash je hash predchádzajúceho bloku, a SelfBlockHash je aktuálny.
TxsHash je celkový hash transakcií.
MerkleRoot je koreň Merkleho stromu.

Ďalej v poliach sa nachádza verejný kľúč autora bloku, podpis autora, verzia bloku, počet transakcií v bloku a vlastne tieto transakcie.

Poďme si priblížiť jeho metódy:
Na vytvorenie bloku sa používa funkcia block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, ktorá prijíma hash predchádzajúceho bloku a výšku nastavenú pre vytvorený blok v blockchaine. Taktiež sa určuje typ bloku z konštanty balíka types:

b.DataType = types.BLOCK_TYPE.

Metóda AddTx(tx *transaction.TX) pridáva transakciu do bloku.

Metóda Build() načítava hodnoty do polí bloku a generuje a nastavuje jeho aktuálny hash.

Metóda ToBytesHeader() []byte prevádza hlavičku bloku (bez transakcií) na bajtový slice.

Metóda ToJSON() string prevádza blok do formátu JSON v reťazcovej reprezentácii údajov.

Metóda FromJSON(data []byte) error načítava údaje z JSONu do štruktúry bloku.

Metóda Check() bool generuje hash bloku a porovnáva ho s určeným v poli hashu bloku.

Metóda GetTxsHash() string vracia celkový hash všetkých transakcií v bloku.

Metóda GetMerkleRoot() nastavuje koreň Merkleho stromu pre transakcie v bloku.

Metóda Sign(privk string) podpisuje blok súkromným kľúčom autora bloku.

Metóda SetHeight(height int) zapisuje výšku bloku do poľa štruktúry bloku.

Metóda GetHeight() int vracia výšku bloku tak, ako je uvedené v príslušnom poli štruktúry bloku.

Metóda ToGOBBytes() []byte kóduje blok do GOB formátu a vracia ho vo forme bajtového slice.

Metóda FromGOBBytes(data []byte) error zapisuje údaje bloku do štruktúry bloku z odovzdaného bajtového slice v formáte GOB.

Metóda GetHash() string vracia hash daného bloku.

Metóda GetPrevHash() string vracia hash predchádzajúceho bloku.

Metóda SetPublicKey(pubk string) zapisuje do bloku verejný kľúč autora bloku.

Takto môžeme pomocou metód objektu Block ľahko konvertovať jeho formát na prenos cez sieť a uloženie do databázy LevelDB.

Za ukladanie do blockchainu sú zodpovedné funkcie balíka blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

Na tento účel musí blok implementovať rozhranie IBlock:

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

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

}

Pripojenie k databáze sa vytvára jednorazovo pri inicializácii balíka vo funkcii init():

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

CloseDB() je obal pre db.Close() — je volaná po práci s funkciami balíka, aby sa uzavrelo pripojenie k DB.

Funkcia SetTargetBlockHash(hash string) error zapisuje do DB hash aktuálneho bloku s kľúčom daným konštantou BLOCK_HASH.

Funkcia GetTargetBlockHash() (string, error) vracia hash aktuálneho bloku, uložený v DB.

Funkcia SetTargetBlockHeight(height int) error zapisuje do DB hodnotu výšky blockchainu pre uzol s kľúčom daným konštantou BLOCK_HEIGHT.

Funkcia GetTargetBlockHeight() (int, error) vracia výšku blockchainu pre daný uzol, uloženú v DB.

Funkcia CheckBlock(block IBlock) bool vykonáva kontrolu bloku na správnosť pred pridaním tohto bloku do blockchainu.

Funkcia AddBlock(block IBlock) error pridáva blok do blockchainu.

Funkcie na získanie a zobrazenie blokov sa nachádzajú v súbore explore.go balíka blockchain:

Funkcia GetBlockByHash(hash string) (*block.Block, error) vytvára prázdny objekt bloku, načíta tam blok z DB, ktorého hash je poskytnutý, a vracia naň ukazovateľ.

Vytvorenie bloku genézy sa vykonáva funkciou Genesis() error zo súboru genesis.go balíka blockchain.

V nasledujúcom článku sa bude hovoriť o pripojení k uzlu klientov pomocou mechanizmu WebSocket.

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster