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).

Toto je druhý článok o blockchaine pre priemysel, prvý .
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:
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:
Š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:
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
