Hur jag designade block och transaktioner i min Go blockchain

För att i slutändan få en blockkedja och inte bara en databas, måste vi lägga till tre viktiga element till vårt projekt:

  • Beskrivning av blockdatastrukturen och metoder
  • Beskrivning av datastruktur och transaktionsmetoder
  • Blockkedjefunktioner som sparar block i en databas och hittar dem där genom deras hash eller höjd (eller något annat).

Hur jag designade block och transaktioner i min Go blockchain

Detta är den andra artikeln om blockchain för industrin, den första här.

Kom ihåg frågorna som läsarna ställde mig om den tidigare artikeln i den här serien, bör det noteras: i det här fallet används LevelDB-databasen för att lagra blockchain-data, men ingenting hindrar dig från att använda någon annan, säg, MySQL. Låt oss nu titta på strukturen för dessa data.

Låt oss börja med transaktioner: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Här är dess datastruktur:

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 lagrar datatypen (för transaktion 2), hashen för den transaktionen, typen av själva transaktionen, en tidsstämpel och in- och utdata. TxIn-ingångar lagrar hashen för transaktionen vars utgång refereras till, numret på denna utgång och bytekod, och TxOut-utgångar lagrar ett visst värde och även bytekod.

Låt oss nu se vilka åtgärder en transaktion kan utföra på sina data, dvs. Låt oss titta på metoderna.

För att skapa en transaktion, använd funktionen transaction.NewTransaction(TXtype byte) *TX.

Metoden AddTxIn(thattxhash []byte, txoutn int, kod []byte) (*TxIn, fel) lägger till en indata till transaktionen.

Metoden AddTxOut(värde int, data []byte) (*TxOut, fel) lägger till en utdata till transaktionen.

Metoden ToBytes() []byte förvandlar transaktionen till en bytedel.

Den interna funktionen preByteHash(bytes []byte)-strängen används i Build() och Check() för att göra den genererade transaktionshashen kompatibel med transaktionshashar som genereras från JavaScript-applikationer.

Metoden Build() ställer in transaktionshashen enligt följande: tx.TxHash = preByteHash(tx.ToBytes()).

Strängmetoden ToJSON() konverterar en transaktion till en JSON-sträng.

FromJSON(data []byte)-felmetoden läser in en transaktion från JSON-formatet som skickas som ett bytesegment.

Check() bool-metoden jämför den resulterande hashen från transaktionshashfältet med hashen som erhålls som ett resultat av hashning av denna transaktion (ignorerar hashfältet).

Transaktioner läggs till i blocket: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Blockdatastrukturen är mer voluminös:

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 lagrar datatypen, noden använder den och skiljer blocket från en transaktion eller annan data. För ett block är detta värde 1.

BlockHeight lagrar höjden på blocket.
Tidsstämpel tidsstämpel.
HeaderSize är blockstorleken i byte.
PrevBlockHash är hashen för det föregående blocket och SelfBlockHash är hashen för det nuvarande.
TxsHash är en allmän hash av transaktioner.
MerkleRoot är roten till Merkleträdet.

Längre i fälten finns den publika nyckeln för skaparen av blocket, signaturen för skaparen, versionen av blocket, antalet transaktioner i blocket och dessa transaktioner själva.

Låt oss titta på dess metoder:
För att skapa ett block, använd block.NewBlock()-funktionen: NewBlock(prevBlockHash-sträng, höjd int) *Block, som tar hashen för det föregående blocket och höjden för det skapade blocket i blockkedjan. Blocktypen ställs också in från typens paketkonstant:

b.DataType = types.BLOCK_TYPE.

Metoden AddTx(tx *transaction.TX) lägger till en transaktion i ett block.

Build()-metoden laddar in värden i blockets fält och genererar och ställer in dess nuvarande hash.

Metoden ToBytesHeader() []byte konverterar blockhuvudet (utan transaktioner) till ett bytesegment.

Strängmetoden ToJSON() konverterar blocket till JSON-format i en strängrepresentation av data.

FromJSON(data []byte)-felmetoden laddar data från JSON till en blockstruktur.

Check() bool-metoden genererar en blockhash och jämför den med den som anges i blockhashfältet.

Strängmetoden GetTxsHash() returnerar den totala hashen för alla transaktioner i blocket.

Metoden GetMerkleRoot() specificerar roten till Merkle-trädet för transaktioner i ett block.

Metoden Sign(privk string) signerar ett block med blockskaparens privata nyckel.

Metoden SetHeight(height int) skriver höjden på blocket till blockstrukturfältet.

Metoden GetHeight() int returnerar höjden på blocket som specificerats i motsvarande fält i blockstrukturen.

Metoden ToGOBBytes() []byte kodar ett block i GOB-format och returnerar det som ett bytesegment.

FromGOBBytes(data []byte)-felmetoden skriver blockdata till blockstrukturen från den skickade byte-delen i GOB-format.

Strängmetoden GetHash() returnerar hashen för det givna blocket.

Strängmetoden GetPrevHash() returnerar hashen för föregående block.

Metoden SetPublicKey(pubk string) skriver den publika nyckeln för blockskaparen till blocket.

Således, med metoderna för Block-objektet, kan vi enkelt konvertera det till ett format för överföring över nätverket och spara till LevelDB-databasen.

Funktionerna i blockchain-paketet är ansvariga för att spara till blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

För att göra detta måste blocket implementera IBlock-gränssnittet:

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

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

}

Databasanslutningen skapas en gång när paketet initieras i funktionen init():

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

CloseDB() är en wrapper för db.Cloce() - anropad efter att ha arbetat med paketfunktionerna för att stänga anslutningen till databasen.

Felfunktionen SetTargetBlockHash(hash-sträng) skriver hashen för det aktuella blocket med nyckeln som anges av BLOCK_HASH-konstanten till databasen.

Funktionen GetTargetBlockHash() (sträng, fel) returnerar hashen för det aktuella blocket som är lagrat i databasen.

Felfunktionen SetTargetBlockHeight(height int) skriver till databasen värdet för blockkedjehöjden för noden med nyckeln specificerad av BLOCK_HEIGHT-konstanten.

Funktionen GetTargetBlockHeight() (int, error) returnerar höjden på blockkedjan för en given nod, lagrad i databasen.

CheckBlock (block IBlock) bool-funktionen kontrollerar att ett block är korrekt innan det läggs till detta block i blockkedjan.

Felfunktionen AddBlock (block IBlock) lägger till ett block till blockkedjan.

Funktionerna för att hämta och visa block finns i filen explore.go i blockchain-paketet:

Funktionen GetBlockByHash(hash-sträng) (*block.Block, error) skapar ett tomt blockobjekt, laddar in ett block i det från databasen, vars hash skickades till det, och returnerar en pekare till det.

Skapandet av ett genesisblock utförs av Genesis()-felfunktionen från filen genesis.go i blockchain-paketet.

Nästa artikel kommer att prata om att ansluta klienter till en nod med hjälp av WebSocket-mekanismen.

Källa: will.com

Lägg en kommentar