Jak jsem navrhoval bloky a transakce v mém Go blockchainu

Abychom nakonec skončili u blockchainu a ne jen u databáze, musíme do našeho projektu přidat 3 důležité prvky:

  • Popis datové struktury bloku a metod
  • Popis datové struktury a transakčních metod
  • Funkce blockchainu, které ukládají bloky do databáze a nacházejí je tam podle jejich hashe nebo výšky (nebo něčeho jiného).

Jak jsem navrhoval bloky a transakce v mém Go blockchainu

Toto je druhý článek o blockchainu pro průmysl, první zde.

Při vzpomínce na otázky, které se mě čtenáři ptali na předchozí článek z této série, je třeba poznamenat: v tomto případě databáze LevelDB slouží k ukládání blockchainových dat, ale nic vám nebrání v použití jakékoli jiné, řekněme, MySQL. Nyní se podívejme na strukturu těchto dat.

Začněme transakcemi: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Zde je jeho datová struktura:

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 ukládá typ dat (pro transakci 2), hash této transakce, typ samotné transakce, časové razítko a vstupy a výstupy. Vstupy TxIn ukládají hash transakce, na jejíž výstup se odkazuje, číslo tohoto výstupu a bajtkód, a výstupy TxOut ukládají nějakou hodnotu a také bajtkód.

Nyní se podívejme, jaké akce může transakce provést se svými daty, tzn. Podívejme se na metody.

Chcete-li vytvořit transakci, použijte funkci transakce.NewTransaction(txtype byte) *TX.

Metoda AddTxIn(thattxhash []bajt, txoutn int, kód []byte) (*TxIn, chyba) přidá vstup do transakce.

Metoda AddTxOut(hodnota int, data []byte) (*TxOut, chyba) přidá k transakci výstup.

Metoda ToBytes() []byte změní transakci na bajtový řez.

Řetězec interní funkce preByteHash(bytes []byte) se používá v Build() a Check(), aby byl vygenerovaný hash transakce kompatibilní s hodnotami hash transakcí generovanými z aplikací JavaScript.

Metoda Build() nastavuje hodnotu hash transakce takto: tx.TxHash = preByteHash(tx.ToBytes()).

Řetězcová metoda ToJSON() převede transakci na řetězec JSON.

Chybová metoda FromJSON(data []byte) načte transakci z formátu JSON předanou jako bajtový řez.

Metoda Check() bool porovnává výsledný hash z pole hash transakce s hodnotou hash získanou jako výsledek hashování této transakce (ignorování pole hash).

Do bloku jsou přidány transakce: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Struktura dat bloku je objemnější:

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 ukládá datový typ, uzel jej používá a odlišuje blok od transakce nebo jiných dat. Pro blok je tato hodnota 1.

BlockHeight ukládá výšku bloku.
Časové razítko časové razítko.
HeaderSize je velikost bloku v bajtech.
PrevBlockHash je hash předchozího bloku a SelfBlockHash je hash aktuálního bloku.
TxsHash je obecný hash transakcí.
MerkleRoot je kořen stromu Merkle.

Dále v polích je veřejný klíč tvůrce bloku, podpis tvůrce, verze bloku, počet transakcí v bloku a tyto transakce samotné.

Podívejme se na jeho metody:
Pro vytvoření bloku použijte funkci block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, která převezme hash předchozího bloku a výšku nastavenou pro vytvořený blok v blockchainu. Typ bloku se také nastavuje z konstanty balíčku typů:

b.DataType = types.BLOCK_TYPE.

Metoda AddTx(tx *transaction.TX) přidá transakci do bloku.

Metoda Build() načte hodnoty do polí bloku a vygeneruje a nastaví jeho aktuální hash.

Metoda ToBytesHeader() []byte převede hlavičku bloku (bez transakcí) na bajtový řez.

Řetězcová metoda ToJSON() převede blok do formátu JSON v řetězcové reprezentaci dat.

Chybová metoda FromJSON(data []byte) načte data z JSON do blokové struktury.

Metoda Check() bool generuje blokovou hodnotu hash a porovnává ji s hodnotou uvedenou v poli hash bloku.

Řetězcová metoda GetTxsHash() vrací celkový hash všech transakcí v bloku.

Metoda GetMerkleRoot() určuje kořen stromu Merkle pro transakce v bloku.

Metoda Sign(privk string) podepisuje blok soukromým klíčem tvůrce bloku.

Metoda SetHeight(height int) zapíše výšku bloku do pole struktury bloku.

Metoda GetHeight() int vrací výšku bloku zadanou v odpovídajícím poli struktury bloku.

Metoda ToGOBBytes() []byte zakóduje blok ve formátu GOB a vrátí jej jako bajtový řez.

Chybová metoda FromGOBBytes(data []byte) zapisuje data bloku do struktury bloku z předaného bajtového řezu ve formátu GOB.

Řetězcová metoda GetHash() vrací hash daného bloku.

Řetězcová metoda GetPrevHash() vrací hash předchozího bloku.

Metoda SetPublicKey(pubk string) zapíše veřejný klíč tvůrce bloku do bloku.

Pomocí metod objektu Block jej tedy snadno převedeme do formátu pro přenos po síti a uložení do databáze LevelDB.

Funkce balíčku blockchain jsou zodpovědné za ukládání do blockchainu: github.com/Rusldv/bcstartup/tree/master/blockchain

K tomu musí blok implementovat rozhraní IBlock:

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

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

}

Připojení k databázi se vytvoří jednou, když je balíček inicializován ve funkci init():

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

CloseDB() je obal pro db.Cloce() – volá se po práci s funkcemi balíčku k uzavření připojení k databázi.

Chybová funkce SetTargetBlockHash(řetězec hash) zapíše hash aktuálního bloku s klíčem určeným konstantou BLOCK_HASH do databáze.

Funkce GetTargetBlockHash() (řetězec, chyba) vrací hash aktuálního bloku uloženého v databázi.

Chybová funkce SetTargetBlockHeight(height int) zapíše do databáze hodnotu výšky blockchainu pro uzel s klíčem určeným konstantou BLOCK_HEIGHT.

Funkce GetTargetBlockHeight() (int, chyba) vrací výšku blockchainu pro daný uzel uloženou v databázi.

Bool funkce CheckBlock (blok IBlock) zkontroluje správnost bloku před přidáním tohoto bloku do blockchainu.

Chybová funkce AddBlock (blok IBlock) přidá blok do blockchainu.

Funkce pro načítání a prohlížení bloků jsou v souboru explore.go balíčku blockchain:

Funkce GetBlockByHash(hash string) (*block.Block, error) vytvoří prázdný blokový objekt, načte do něj z databáze blok, jehož hash mu byl předán, a vrátí na něj ukazatel.

Vytvoření bloku genesis se provádí chybovou funkcí Genesis() ze souboru genesis.go balíčku blockchain.

Další článek bude hovořit o připojení klientů k uzlu pomocí mechanismu WebSocket.

Zdroj: www.habr.com

Přidat komentář