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).
Dette er den andre artikkelen om blockchain for industri, den første
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:
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:
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:
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