Hvordan jeg designede blokke og transaktioner i min Go blockchain

For i sidste ende at ende med en blockchain og ikke bare en database, skal vi tilføje 3 vigtige elementer til vores projekt:

  • Beskrivelse af blokdatastrukturen og metoder
  • Beskrivelse af datastruktur og transaktionsmetoder
  • Blockchain-funktioner, der gemmer blokke i en database og finder dem der ved deres hash eller højde (eller noget andet).

Hvordan jeg designede blokke og transaktioner i min Go blockchain

Dette er den anden artikel om blockchain til industrien, den første her.

Når man husker de spørgsmål, som læserne stillede mig om den forrige artikel i denne serie, skal det bemærkes: i dette tilfælde bruges LevelDB-databasen til at gemme blockchain-data, men intet forhindrer dig i at bruge andre, f.eks. MySQL. Lad os nu se på strukturen af ​​disse data.

Lad os starte med transaktioner: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Her er dens 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 gemmer datatypen (for transaktion 2), hashen for den pågældende transaktion, typen af ​​selve transaktionen, et tidsstempel og input og output. TxIn-input gemmer hashen for transaktionen, hvis output refereres til, antallet af denne output og bytekode, og TxOut-output gemmer en vis værdi og også bytekode.

Lad os nu se, hvilke handlinger en transaktion kan udføre på sine data, dvs. Lad os se på metoderne.

For at oprette en transaktion skal du bruge funktionen transaktion.NewTransaction(TXtype byte) *TX.

Metoden AddTxIn(thattxhash []byte, txoutn int, kode []byte) (*TxIn, fejl) tilføjer et input til transaktionen.

Metoden AddTxOut(værdi int, data []byte) (*TxOut, fejl) tilføjer et output til transaktionen.

ToBytes() []byte-metoden gør transaktionen til en byte-slice.

Den interne funktion preByteHash(bytes []byte) streng bruges i Build() og Check() for at gøre den genererede transaktions-hash kompatibel med transaktions-hash genereret fra JavaScript-applikationer.

Build()-metoden indstiller transaktionens hash som følger: tx.TxHash = preByteHash(tx.ToBytes()).

ToJSON()-strengmetoden konverterer en transaktion til en JSON-streng.

FromJSON(data []byte)-fejlmetoden indlæser en transaktion fra JSON-formatet, der sendes som et byteudsnit.

Check() bool-metoden sammenligner den resulterende hash fra transaktions-hash-feltet med den hash, der er opnået som et resultat af hash af denne transaktion (ignorerer hash-feltet).

Transaktioner tilføjes til blokken: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Blokdatastrukturen er mere omfangsrig:

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 gemmer datatypen, noden bruger den og adskiller blokken fra en transaktion eller andre data. For en blok er denne værdi 1.

BlockHeight gemmer blokkens højde.
Tidsstempel tidsstempel.
HeaderSize er blokstørrelsen i bytes.
PrevBlockHash er hashen af ​​den forrige blok, og SelfBlockHash er hashen af ​​den nuværende.
TxsHash er en generel hash af transaktioner.
MerkleRoot er roden til Merkle-træet.

Længere i felterne er der den offentlige nøgle for skaberen af ​​blokken, underskriften af ​​skaberen, versionen af ​​blokken, antallet af transaktioner i blokken og disse transaktioner selv.

Lad os se på dens metoder:
For at oprette en blok skal du bruge block.NewBlock()-funktionen: NewBlock(prevBlockHash-streng, højde int) *Blok, som tager hashen fra den forrige blok og højden indstillet for den oprettede blok i blokkæden. Bloktypen indstilles også fra typepakkekonstanten:

b.DataType = types.BLOCK_TYPE.

Metoden AddTx(tx *transaction.TX) tilføjer en transaktion til en blok.

Build()-metoden indlæser værdier i blokkens felter og genererer og indstiller dens aktuelle hash.

ToBytesHeader() []byte-metoden konverterer blokhovedet (uden transaktioner) til et byteudsnit.

ToJSON()-strengmetoden konverterer blokken til JSON-format i en strengrepræsentation af dataene.

FromJSON(data []byte) fejlmetoden indlæser data fra JSON til en blokstruktur.

Check() bool-metoden genererer en blokhash og sammenligner den med den, der er angivet i blokhashfeltet.

Strengmetoden GetTxsHash() returnerer den samlede hash for alle transaktioner i blokken.

GetMerkleRoot()-metoden angiver roden af ​​Merkle-træet for transaktioner i en blok.

Sign(privk string) metoden signerer en blok med den private nøgle fra blokopretteren.

Metoden SetHeight(height int) skriver blokkens højde til blokstrukturfeltet.

GetHeight() int-metoden returnerer højden af ​​blokken som angivet i det tilsvarende felt i blokstrukturen.

ToGOBBytes() []byte-metoden koder en blok i GOB-format og returnerer den som et byteudsnit.

FromGOBBytes(data []byte) fejlmetoden skriver blokdata til blokstrukturen fra det beståede byteudsnit i GOB-format.

Strengmetoden GetHash() returnerer hashen for den givne blok.

Strengmetoden GetPrevHash() returnerer hashen fra den forrige blok.

Metoden SetPublicKey(pubk string) skriver den offentlige nøgle for blokopretteren til blokken.

Ved hjælp af Block-objektets metoder kan vi således nemt konvertere det til et format til transmission over netværket og gemme til LevelDB-databasen.

Funktionerne i blockchain-pakken er ansvarlige for at gemme til blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

For at gøre dette skal blokken implementere IBlock-grænsefladen:

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

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

}

Databaseforbindelsen oprettes én gang, når pakken initialiseres i funktionen init():

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

CloseDB() er en wrapper for db.Cloce() - kaldet efter at have arbejdet med pakkefunktionerne for at lukke forbindelsen til databasen.

Fejlfunktionen SetTargetBlockHash(hash-streng) skriver hashen for den aktuelle blok med nøglen angivet af BLOCK_HASH-konstanten til databasen.

Funktionen GetTargetBlockHash() (streng, fejl) returnerer hashen for den aktuelle blok, der er gemt i databasen.

Fejlfunktionen SetTargetBlockHeight(height int) skriver til databasen værdien af ​​blockchain-højden for noden med nøglen angivet af BLOCK_HEIGHT-konstanten.

Funktionen GetTargetBlockHeight() (int, fejl) returnerer højden af ​​blokkæden for en given node, gemt i databasen.

CheckBlock (blok IBlock) bool-funktionen kontrollerer en blok for korrekthed, før denne blok føjes til blockchain.

Fejlfunktionen AddBlock (blok IBlock) tilføjer en blok til blokkæden.

Funktionerne til at hente og se blokke er i explore.go-filen i blockchain-pakken:

Funktionen GetBlockByHash(hash-streng) (*blok.Blok, fejl) opretter et tomt blokobjekt, indlæser en blok i det fra databasen, hvis hash blev sendt til det, og returnerer en pointer til det.

Oprettelsen af ​​en genesis-blok udføres af Genesis()-fejlfunktionen fra genesis.go-filen i blockchain-pakken.

Den næste artikel vil tale om at forbinde klienter til en node ved hjælp af WebSocket-mekanismen.

Kilde: www.habr.com

Tilføj en kommentar