Kako sem oblikoval bloke in transakcije v svoji verigi blokov Go

Da bi na koncu imeli verigo blokov in ne samo bazo podatkov, moramo našemu projektu dodati 3 pomembne elemente:

  • Opis podatkovne strukture in metod bloka
  • Opis strukture podatkov in transakcijskih metod
  • Blockchain funkcije, ki shranjujejo bloke v zbirko podatkov in jih tam najdejo po zgoščeni vrednosti ali višini (ali čem drugem).

Kako sem oblikoval bloke in transakcije v svoji verigi blokov Go

To je drugi članek o blockchainu za industrijo, prvi tukaj.

Če se spomnimo vprašanj, ki so mi jih bralci zastavili o prejšnjem članku v tej seriji, je treba opozoriti: v tem primeru se baza podatkov LevelDB uporablja za shranjevanje podatkov verige blokov, vendar vam nič ne preprečuje uporabe katerega koli drugega, recimo MySQL. Zdaj pa poglejmo strukturo teh podatkov.

Začnimo s transakcijami: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Tukaj je njegova struktura podatkov:

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 shrani vrsto podatkov (za transakcijo 2), zgoščeno vrednost te transakcije, vrsto same transakcije, časovni žig ter vhode in izhode. Vhodi TxIn shranijo zgoščeno vrednost transakcije, katere izhod se sklicuje, številko tega izhoda in bajtno kodo, izhodi TxOut pa shranijo nekaj vrednosti in tudi bajtno kodo.

Zdaj pa poglejmo, katera dejanja lahko transakcija izvede na svojih podatkih, tj. Poglejmo si metode.

Če želite ustvariti transakcijo, uporabite funkcijo transaction.NewTransaction(txtype byte) *TX.

Metoda AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) transakciji doda vnos.

Metoda AddTxOut(value int, data []byte) (*TxOut, error) transakciji doda izhod.

Metoda ToBytes() []byte spremeni transakcijo v bajtno rezino.

Niz notranje funkcije preByteHash(bytes []byte) se uporablja v Build() in Check(), da naredi ustvarjeno zgoščeno vrednost transakcije združljivo z zgoščeno vrednostjo transakcije, ustvarjeno iz aplikacij JavaScript.

Metoda Build() nastavi zgoščeno vrednost transakcije na naslednji način: tx.TxHash = preByteHash(tx.ToBytes()).

Metoda niza ToJSON() pretvori transakcijo v niz JSON.

Metoda napake FromJSON(data []byte) naloži transakcijo iz formata JSON, posredovanega kot bajtna rezina.

Metoda Check() bool primerja dobljeno zgoščeno vrednost iz polja zgoščene vrednosti transakcije z zgoščeno vrednostjo, pridobljeno kot rezultat zgoščevanja te transakcije (brez upoštevanja polja zgoščene vrednosti).

Transakcije se dodajo v blok: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Podatkovna struktura blokov je bolj obsežna:

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 shrani podatkovni tip, vozlišče ga uporabi in loči blok od transakcije ali drugih podatkov. Za blok je ta vrednost 1.

BlockHeight shrani višino bloka.
Časovni žig časovni žig.
HeaderSize je velikost bloka v bajtih.
PrevBlockHash je zgoščena vrednost prejšnjega bloka, SelfBlockHash pa zgoščena vrednost trenutnega.
TxsHash je splošno zgoščevanje transakcij.
MerkleRoot je koren drevesa Merkle.

Nadalje v poljih je javni ključ kreatorja bloka, podpis kreatorja, različica bloka, število transakcij v bloku in te transakcije same.

Oglejmo si njegove metode:
Če želite ustvariti blok, uporabite funkcijo block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, ki vzame zgoščeno vrednost prejšnjega bloka in višino, nastavljeno za ustvarjeni blok v verigi blokov. Tip bloka je nastavljen tudi iz konstante paketa tipov:

b.DataType = types.BLOCK_TYPE.

Metoda AddTx(tx *transaction.TX) doda transakcijo v blok.

Metoda Build() naloži vrednosti v polja bloka ter ustvari in nastavi njegovo trenutno zgoščeno vrednost.

Metoda ToBytesHeader() []byte pretvori glavo bloka (brez transakcij) v bajtno rezino.

Metoda nizov ToJSON() pretvori blok v format JSON v nizski predstavitvi podatkov.

Metoda napake FromJSON(data []byte) naloži podatke iz JSON v strukturo blokov.

Metoda Check() bool generira zgoščeno vrednost bloka in jo primerja s tisto, navedeno v polju zgoščene vrednosti bloka.

Metoda niza GetTxsHash() vrne skupno zgoščeno vrednost vseh transakcij v bloku.

Metoda GetMerkleRoot() podaja koren drevesa Merkle za transakcije v bloku.

Metoda Sign(privk string) podpiše blok z zasebnim ključem ustvarjalca bloka.

Metoda SetHeight(height int) zapiše višino bloka v polje strukture bloka.

Metoda GetHeight() int vrne višino bloka, kot je določeno v ustreznem polju strukture bloka.

Metoda ToGOBBytes() []byte kodira blok v formatu GOB in ga vrne kot bajtno rezino.

Metoda napake FromGOBBytes(data []byte) zapiše podatke bloka v strukturo bloka iz posredovane rezine bajta v formatu GOB.

Metoda niza GetHash() vrne zgoščeno vrednost danega bloka.

Metoda niza GetPrevHash() vrne zgoščeno vrednost prejšnjega bloka.

Metoda SetPublicKey(pubk string) zapiše javni ključ ustvarjalca bloka v blok.

Tako ga z metodami objekta Block enostavno pretvorimo v obliko za prenos po omrežju in shranjevanje v bazo LevelDB.

Funkcije paketa blockchain so odgovorne za shranjevanje v blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

Če želite to narediti, mora blok izvajati vmesnik IBlock:

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

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

}

Povezava z bazo podatkov se ustvari enkrat, ko je paket inicializiran v funkciji init():

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

CloseDB() je ovoj za db.Cloce() - poklican po delu s funkcijami paketa za zapiranje povezave z bazo podatkov.

Funkcija napake SetTargetBlockHash(hash string) v bazo podatkov zapiše zgoščeno vrednost trenutnega bloka s ključem, ki ga določa konstanta BLOCK_HASH.

Funkcija GetTargetBlockHash() (niz, napaka) vrne zgoščeno vrednost trenutnega bloka, shranjenega v bazi podatkov.

Funkcija napake SetTargetBlockHeight(height int) zapiše v bazo podatkov vrednost višine verige blokov za vozlišče s ključem, ki ga določa konstanta BLOCK_HEIGHT.

Funkcija GetTargetBlockHeight() (int, error) vrne višino verige blokov za dano vozlišče, shranjeno v bazi podatkov.

Funkcija CheckBlock(block IBlock) bool preveri pravilnost bloka, preden ga doda v verigo blokov.

Funkcija napake AddBlock(block IBlock) doda blok v verigo blokov.

Funkcije za pridobivanje in ogled blokov so v datoteki explore.go paketa blockchain:

Funkcija GetBlockByHash(hash string) (*block.Block, error) ustvari prazen objekt bloka, vanj naloži blok iz baze podatkov, katere hash je bil posredovan vanj, in vrne kazalec nanj.

Ustvarjanje bloka genesis izvede funkcija napake Genesis() iz datoteke genesis.go paketa blockchain.

Naslednji članek bo govoril o povezovanju odjemalcev z vozliščem z uporabo mehanizma WebSocket.

Vir: www.habr.com

Dodaj komentar