Hvordan jeg designet blokker og transaksjoner i Go-blokkjeden min

For til slutt å ende opp med en blokkjede og ikke bare en database, må vi legge til 3 viktige elementer i prosjektet vårt:

  • Beskrivelse av blokkdatastrukturen og metoder
  • Beskrivelse av datastruktur og transaksjonsmetoder
  • Blokkjedefunksjoner som lagrer blokker i en database og finner dem der etter hash eller høyde (eller noe annet).

Hvordan jeg designet blokker og transaksjoner i Go-blokkjeden min

Dette er den andre artikkelen om blockchain for industri, den første her.

Når du husker spørsmålene som leserne spurte meg om den forrige artikkelen i denne serien, bør det bemerkes: i dette tilfellet brukes LevelDB-databasen til å lagre blokkjededata, men ingenting hindrer deg i å bruke andre, for eksempel, MySQL. La oss nå se på strukturen til disse dataene.

La oss starte med transaksjoner: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Her er datastrukturen:

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 lagrer datatypen (for transaksjon 2), hashen for den transaksjonen, typen av selve transaksjonen, et tidsstempel og innganger og utganger. TxIn-innganger lagrer hashen til transaksjonen hvis utgang refereres til, nummeret på denne utgangen og bytekoden, og TxOut-utgangene lagrer en viss verdi og også bytekode.

La oss nå se hvilke handlinger en transaksjon kan utføre på dataene sine, dvs. La oss se på metodene.

For å opprette en transaksjon, bruk transaksjon.NewTransaction(TXtype byte) *TX-funksjonen.

Metoden AddTxIn(thattxhash []byte, txoutn int, kode []byte) (*TxIn, feil) legger til en inngang til transaksjonen.

Metoden AddTxOut(verdi int, data []byte) (*TxOut, feil) legger til en utdata til transaksjonen.

ToBytes() []byte-metoden gjør transaksjonen til en bytedel.

Den interne funksjonen preByteHash(bytes []byte)-strengen brukes i Build() og Check() for å gjøre den genererte transaksjons-hashen kompatibel med transaksjons-hasher generert fra JavaScript-applikasjoner.

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

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

FromJSON(data []byte)-feilmetoden laster inn en transaksjon fra JSON-formatet som sendes som en bytedel.

Check() bool-metoden sammenligner den resulterende hashen fra transaksjons-hash-feltet med hashen oppnådd som et resultat av hash av denne transaksjonen (ignorerer hash-feltet).

Transaksjoner legges til blokken: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Blokkdatastrukturen er 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 lagrer datatypen, noden bruker den og skiller blokken fra en transaksjon eller andre data. For en blokk er denne verdien 1.

BlockHeight lagrer høyden på blokken.
Tidsstempel tidsstempel.
HeaderSize er blokkstørrelsen i byte.
PrevBlockHash er hashen til forrige blokk, og SelfBlockHash er hashen til den nåværende.
TxsHash er en generell hash av transaksjoner.
MerkleRoot er roten til Merkle-treet.

Videre i feltene er det den offentlige nøkkelen til skaperen av blokken, signaturen til skaperen, versjonen av blokken, antall transaksjoner i blokken, og disse transaksjonene i seg selv.

La oss se på metodene:
For å lage en blokk, bruk block.NewBlock()-funksjonen: NewBlock(prevBlockHash string, height int) *Block, som tar hashen til forrige blokk og høyden satt for den opprettede blokken i blokkjeden. Blokktypen er også satt fra type-pakkekonstanten:

b.DataType = types.BLOCK_TYPE.

AddTx(tx *transaction.TX)-metoden legger til en transaksjon til en blokk.

Build()-metoden laster verdier inn i blokkens felt og genererer og setter gjeldende hash.

ToBytesHeader() []byte-metoden konverterer blokkhodet (uten transaksjoner) til et bytestykke.

ToJSON()-strengmetoden konverterer blokken til JSON-format i en strengrepresentasjon av dataene.

FromJSON(data []byte) feilmetoden laster data fra JSON inn i en blokkstruktur.

Check() bool-metoden genererer en blokkhash og sammenligner den med den som er spesifisert i blokkhash-feltet.

GetTxsHash()-strengmetoden returnerer den totale hashen av alle transaksjoner i blokken.

GetMerkleRoot()-metoden spesifiserer roten til Merkle-treet for transaksjoner i en blokk.

Sign(privk string)-metoden signerer en blokk med den private nøkkelen til blokkskaperen.

SetHeight(height int)-metoden skriver høyden på blokken til blokkstrukturfeltet.

GetHeight() int-metoden returnerer høyden på blokken som spesifisert i det tilsvarende feltet i blokkstrukturen.

ToGOBBytes() []byte-metoden koder en blokk i GOB-format og returnerer den som en bytedel.

FromGOBBytes(data []byte) feilmetoden skriver blokkdata til blokkstrukturen fra den beståtte bytedelen i GOB-format.

GetHash()-strengmetoden returnerer hashen til den gitte blokken.

Strengmetoden GetPrevHash() returnerer hashen til forrige blokk.

Metoden SetPublicKey(pubk string) skriver den offentlige nøkkelen til blokkskaperen til blokken.

Dermed, ved å bruke metodene til Block-objektet, kan vi enkelt konvertere det til et format for overføring over nettverket og lagring til LevelDB-databasen.

Funksjonene til blokkjedepakken er ansvarlige for å lagre til blokkjeden: github.com/Rusldv/bcstartup/tree/master/blockchain

For å gjøre dette må blokken implementere IBlock-grensesnittet:

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

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

}

Databasetilkoblingen opprettes én gang når pakken initialiseres i init()-funksjonen:

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

CloseDB() er en wrapper for db.Cloce() - kalt etter å ha jobbet med pakkefunksjonene for å lukke forbindelsen til databasen.

Feilfunksjonen SetTargetBlockHash(hash-streng) skriver hashen til gjeldende blokk med nøkkelen spesifisert av BLOCK_HASH-konstanten til databasen.

Funksjonen GetTargetBlockHash() (streng, feil) returnerer hashen til gjeldende blokk som er lagret i databasen.

Feilfunksjonen SetTargetBlockHeight(height int) skriver til databasen verdien av blokkjedehøyden for noden med nøkkelen spesifisert av BLOCK_HEIGHT-konstanten.

Funksjonen GetTargetBlockHeight() (int, error) returnerer høyden på blokkjeden for en gitt node, lagret i databasen.

CheckBlock (blokk IBlock) bool-funksjonen sjekker en blokk for korrekthet før denne blokken legges til i blokkjeden.

AddBlock (blokk IBlock) feilfunksjonen legger til en blokk til blokkjeden.

Funksjonene for å hente og vise blokker er i explore.go-filen til blokkjedepakken:

Funksjonen GetBlockByHash(hash-streng) (*block.Block, error) oppretter et tomt blokkobjekt, laster inn en blokk fra databasen, hvis hash ble sendt til den, og returnerer en peker til den.

Opprettelsen av en genesis-blokk utføres av Genesis()-feilfunksjonen fra genesis.go-filen til blokkjedepakken.

Den neste artikkelen vil snakke om å koble til en klientnode ved hjelp av WebSocket-mekanismen.

Kilde: www.habr.com

Legg til en kommentar