Kako sam dizajnirao blokove i transakcije u svom Go blockchainu

Kako bismo u konačnici dobili blockchain, a ne samo bazu podataka, našem projektu moramo dodati 3 važna elementa:

  • Opis strukture blok podataka i metoda
  • Opis strukture podataka i transakcijskih metoda
  • Blockchain funkcije koje spremaju blokove u bazu podataka i tamo ih pronalaze po hash vrijednosti ili visini (ili nečem drugom).

Kako sam dizajnirao blokove i transakcije u svom Go blockchainu

Ovo je drugi članak o blockchainu za industriju, prvi ovdje.

Sjećajući se pitanja koja su mi čitatelji postavili o prethodnom članku u ovoj seriji, valja napomenuti: u ovom slučaju baza podataka LevelDB koristi se za pohranu podataka blockchaina, ali ništa vas ne sprječava da koristite bilo koji drugi, recimo, MySQL. Sada pogledajmo strukturu ovih podataka.

Počnimo s transakcijama: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Ovo je njegova struktura podataka:

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 pohranjuje tip podataka (za transakciju 2), hash te transakcije, tip same transakcije, vremensku oznaku te ulaze i izlaze. TxIn ulazi pohranjuju hash transakcije čiji je izlaz referenciran, broj ovog izlaza i bajt kod, a TxOut izlazi pohranjuju neku vrijednost i također bajt kod.

Sada da vidimo koje radnje transakcija može izvesti na svojim podacima, tj. Pogledajmo metode.

Za izradu transakcije upotrijebite funkciju transaction.NewTransaction(txtype byte) *TX.

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

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

Metoda ToBytes() []byte pretvara transakciju u isječak bajta.

Niz interne funkcije preByteHash(bytes []byte) koristi se u Build() i Check() kako bi generirani hash transakcije bio kompatibilan s hashovima transakcija generiranim iz JavaScript aplikacija.

Metoda Build() postavlja hash transakcije na sljedeći način: tx.TxHash = preByteHash(tx.ToBytes()).

ToJSON() string metoda pretvara transakciju u JSON string.

Metoda pogreške FromJSON(data []byte) učitava transakciju iz JSON formata proslijeđenog kao isječak bajta.

Metoda Check() bool uspoređuje dobiveni hash iz hash polja transakcije s hashom dobivenim kao rezultat hashiranja ove transakcije (ignorirajući hash polje).

Transakcije se dodaju u blok: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Struktura blok podataka je voluminoznija:

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 pohranjuje tip podataka, čvor ga koristi i razlikuje blok od transakcije ili drugih podataka. Za blok ova vrijednost je 1.

BlockHeight pohranjuje visinu bloka.
vremenska oznaka vremenska oznaka.
HeaderSize je veličina bloka u bajtovima.
PrevBlockHash je hash prethodnog bloka, a SelfBlockHash je hash trenutnog.
TxsHash je opći hash transakcija.
MerkleRoot je korijen stabla Merkle.

Dalje u poljima nalazi se javni ključ kreatora bloka, potpis kreatora, verzija bloka, broj transakcija u bloku i same te transakcije.

Pogledajmo njegove metode:
Za izradu bloka upotrijebite funkciju block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, koji uzima hash prethodnog bloka i postavljenu visinu za stvoreni blok u blockchainu. Tip bloka se također postavlja iz konstante paketa tipova:

b.DataType = types.BLOCK_TYPE.

Metoda AddTx(tx *transaction.TX) dodaje transakciju u blok.

Metoda Build() učitava vrijednosti u polja bloka te generira i postavlja njegov trenutni hash.

Metoda ToBytesHeader() []byte pretvara zaglavlje bloka (bez transakcija) u isječak bajta.

Metoda niza ToJSON() pretvara blok u JSON format u prikazu niza podataka.

Metoda pogreške FromJSON(data []byte) učitava podatke iz JSON-a u strukturu bloka.

Metoda Check() bool generira hash bloka i uspoređuje ga s onim navedenim u polju hash bloka.

Metoda niza GetTxsHash() vraća ukupni hash svih transakcija u bloku.

Metoda GetMerkleRoot() navodi korijen Merkleovog stabla za transakcije u bloku.

Metoda Sign(privk string) potpisuje blok privatnim ključem kreatora bloka.

Metoda SetHeight(height int) upisuje visinu bloka u polje strukture bloka.

Metoda GetHeight() int vraća visinu bloka kako je navedeno u odgovarajućem polju strukture bloka.

Metoda ToGOBBytes() []byte kodira blok u GOB formatu i vraća ga kao isječak bajta.

Metoda pogreške FromGOBBytes(data []byte) zapisuje podatke bloka u strukturu bloka iz presjeka proslijeđenog bajta u GOB formatu.

Metoda niza GetHash() vraća hash zadanog bloka.

Metoda niza GetPrevHash() vraća hash prethodnog bloka.

Metoda SetPublicKey(pubk string) upisuje javni ključ kreatora bloka u blok.

Dakle, koristeći metode Block objekta, možemo ga jednostavno pretvoriti u format za prijenos preko mreže i spremanje u LevelDB bazu podataka.

Funkcije blockchain paketa odgovorne su za spremanje u blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

Da biste to učinili, blok mora implementirati IBlock sučelje:

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

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

}

Veza s bazom podataka stvara se jednom kada se paket inicijalizira u funkciji init():

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

CloseDB() je omotač za db.Cloce() - poziva se nakon rada s funkcijama paketa za zatvaranje veze s bazom podataka.

Funkcija pogreške SetTargetBlockHash(hash string) zapisuje hash trenutnog bloka s ključem navedenim u konstanti BLOCK_HASH u bazu podataka.

Funkcija GetTargetBlockHash() (string, error) vraća hash trenutačnog bloka pohranjenog u bazi podataka.

Funkcija pogreške SetTargetBlockHeight(height int) zapisuje u bazu podataka vrijednost visine blockchaina za čvor s ključem navedenim konstantom BLOCK_HEIGHT.

Funkcija GetTargetBlockHeight() (int, error) vraća visinu blockchaina za dati čvor, pohranjenu u bazi podataka.

CheckBlock(block IBlock) bool funkcija provjerava ispravnost bloka prije dodavanja tog bloka u blockchain.

Funkcija pogreške AddBlock(block IBlock) dodaje blok u blockchain.

Funkcije za dohvaćanje i pregled blokova nalaze se u explore.go datoteci blockchain paketa:

Funkcija GetBlockByHash(hash string) (*block.Block, error) stvara prazan objekt bloka, učitava blok u njega iz baze podataka čiji mu je hash proslijeđen i vraća pokazivač na njega.

Stvaranje genesis bloka provodi funkcija pogreške Genesis() iz genesis.go datoteke blockchain paketa.

Sljedeći članak će govoriti o povezivanju klijenata na čvor pomoću mehanizma WebSocket.

Izvor: www.habr.com

Dodajte komentar