Kako sam dizajnirao blokove i transakcije u svom Go blockchainu

Kako bismo na kraju dobili blok lanac, a ne samo bazu podataka, našem projektu moramo dodati 3 važna elementa:

  • Opis strukture blok podataka i metoda
  • Opis strukture podataka i metoda transakcija
  • Blockchain funkcije koje spremaju blokove u bazu podataka i tamo ih pronalaze po njihovom hashu 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, treba napomenuti: u ovom slučaju se baza podataka LevelDB koristi za pohranjivanje blockchain podataka, ali ništa vas ne sprječava da koristite bilo koji drugi, recimo, MySQL. Pogledajmo sada strukturu ovih podataka.

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

Evo njegove strukture 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 bajtkod, a TxOut izlazi pohranjuju neku vrijednost, a također i bajtkod.

Sada da vidimo koje radnje transakcija može izvršiti nad svojim podacima, tj. Pogledajmo metode.

Za kreiranje transakcije koristite funkciju transakcije.NewTransaction(txtype byte) *TX.

Metoda AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, greška) dodaje ulaz u transakciju.

Metoda AddTxOut(vrijednost int, podaci []bajt) (*TxOut, greška) dodaje izlaz transakciji.

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

Interna funkcija preByteHash(bytes []byte) string se koristi u Build() i Check() kako bi generirani heš transakcije bio kompatibilan sa hešovima transakcija generiranim iz JavaScript aplikacija.

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

Metoda stringa ToJSON() pretvara transakciju u JSON string.

Metoda greške FromJSON(podaci []bajt) učitava transakciju iz JSON formata proslijeđenu kao odsječak bajta.

Check() bool metoda uspoređuje rezultujući heš iz heš polja transakcije sa hešom dobijenim kao rezultat heširanja ove transakcije (zanemarujući heš polje).

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

Blok struktura podataka je obimnija:

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 Merkle drveta.

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

Pogledajmo njegove metode:
Za kreiranje bloka koristite funkciju block.NewBlock(): NewBlock(prevBlockHash string, visina int) *Block, koji uzima hash prethodnog bloka i visinu postavljenu za kreirani 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 i generiše i postavlja njegov trenutni hash.

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

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

Metod greške FromJSON(data []byte) učitava podatke iz JSON-a u blok strukturu.

Check() bool metoda generiše blok heš i upoređuje ga sa onim specificiranim u polju heš bloka.

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

Metoda GetMerkleRoot() specificira korijen Merkle stabla za transakcije u bloku.

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

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

GetHeight() int metoda 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 odsječak bajta.

Metoda greške FromGOBBytes(data []byte) upisuje blok podatke u strukturu bloka iz proslijeđenog bajtnog dijela u GOB formatu.

Metoda stringa GetHash() vraća hash datog bloka.

Metoda stringa 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 lako 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 bi to uradio, 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 baze podataka se kreira jednom kada se paket inicijalizira u funkciji init():

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

CloseDB() je omot za db.Cloce() - poziva se nakon rada sa funkcijama paketa da zatvori vezu s bazom podataka.

Funkcija greške SetTargetBlockHash(hash string) zapisuje hash trenutnog bloka s ključem specificiranim konstantom BLOCK_HASH u bazu podataka.

Funkcija GetTargetBlockHash() (string, greška) vraća hash trenutnog bloka pohranjenog u bazi podataka.

Funkcija greške SetTargetBlockHeight(height int) upisuje u bazu podataka vrijednost visine blockchaina za čvor s ključem specificiranim 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 ovog bloka u blockchain.

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

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

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

Kreiranje genesis bloka vrši se funkcijom greške Genesis() iz genesis.go datoteke paketa blockchain.

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

izvor: www.habr.com

Dodajte komentar