Kā es izstrādāju blokus un darījumus savā Go blokķēdē

Lai galu galā iegūtu blokķēdi, nevis tikai datu bāzi, mums mūsu projektam jāpievieno 3 svarīgi elementi:

  • Bloku datu struktūras un metožu apraksts
  • Datu struktūras un darījumu metožu apraksts
  • Blockchain funkcijas, kas saglabā blokus datu bāzē un atrod tos tur pēc to jaukšanas vai augstuma (vai kaut kā cita).

Kā es izstrādāju blokus un darījumus savā Go blokķēdē

Šis ir otrais raksts par blokķēdi nozarei, pirmais šeit.

Atceroties jautājumus, ko lasītāji man uzdeva par iepriekšējo šīs sērijas rakstu, jāatzīmē: šajā gadījumā LevelDB datu bāze tiek izmantota blokķēdes datu glabāšanai, taču nekas neliedz izmantot kādu citu, teiksim, MySQL. Tagad apskatīsim šo datu struktūru.

Sāksim ar darījumiem: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Šeit ir tā datu struktūra:

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 saglabā datu tipu (2. darījumam), šī darījuma jaucējkodu, paša darījuma veidu, laikspiedolu, kā arī ievades un izvades. TxIn ieejas saglabā transakcijas jaucējkodu, kura izvadei ir atsauce, šīs izvades un baitkoda numuru, un TxOut izvadi saglabā kādu vērtību un arī baitkodu.

Tagad apskatīsim, kādas darbības darījums var veikt ar saviem datiem, t.i. Apskatīsim metodes.

Lai izveidotu transakciju, izmantojiet transakciju.NewTransaction(txtype byte) *TX funkciju.

Metode AddTxIn(thattxhash []baits, txoutn int, kods []baits) (*TxIn, kļūda) pievieno transakcijai ievadi.

Metode AddTxOut(vērtība int, datu []baits) (*TxOut, kļūda) pievieno transakcijai izvadi.

ToBytes() []baitu metode pārvērš darījumu par baitu šķēli.

Iekšējā funkcijas virkne preByteHash(baiti []baits) tiek izmantota Build() un Check(), lai padarītu ģenerēto transakcijas jaucēju saderīgu ar darījumu jaucējkodiem, kas ģenerēti no JavaScript lietojumprogrammām.

Metode Build() iestata darījuma jaucējkodu šādi: tx.TxHash = preByteHash(tx.ToBytes()).

ToJSON() virknes metode pārvērš darījumu par JSON virkni.

Kļūdas metode FromJSON(data []baits) ielādē darījumu no JSON formāta, kas nodots kā baita daļa.

Pārbaudes() bool metode salīdzina iegūto jaucējkodu no darījuma jaukšanas lauka ar jaucējkodu, kas iegūts šīs transakcijas jaukšanas rezultātā (ignorējot jaucējlauku).

Darījumi tiek pievienoti blokam: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Bloku datu struktūra ir apjomīgāka:

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 saglabā datu tipu, mezgls to izmanto un atšķir bloku no darījuma vai citiem datiem. Blokam šī vērtība ir 1.

BlockHeight saglabā bloka augstumu.
Laika zīmogs laikspiedols.
HeaderSize ir bloka lielums baitos.
PrevBlockHash ir iepriekšējā bloka jaucējvārds, un SelfBlockHash ir pašreizējā bloka jaucējvārds.
TxsHash ir vispārējs darījumu hash.
MerkleRoot ir Merkles koka sakne.

Tālāk laukos ir bloka izveidotāja publiskā atslēga, izveidotāja paraksts, bloka versija, blokā veikto darījumu skaits un paši šie darījumi.

Apskatīsim tās metodes:
Lai izveidotu bloku, izmantojiet funkciju block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, kas ņem iepriekšējā bloka jaucējvērtību un izveidotajam blokam blokķēdē iestatīto augstumu. Bloka veids tiek iestatīts arī no tipu pakotnes konstantes:

b.DataType = types.BLOCK_TYPE.

Metode AddTx(tx *transaction.TX) pievieno darījumu blokam.

Metode Build() ielādē vērtības bloka laukos un ģenerē un iestata tā pašreizējo jaucējkodu.

ToBytesHeader() []baitu metode pārvērš bloka galveni (bez transakcijām) par baitu šķēli.

ToJSON() virknes metode pārvērš bloku JSON formātā datu virknes attēlojumā.

Kļūdas metode FromJSON (datu []baits) ielādē datus no JSON bloku struktūrā.

Pārbaudes() bool metode ģenerē bloka jaucējkodu un salīdzina to ar bloka jaucējkoda laukā norādīto.

GetTxsHash() virknes metode atgriež visu blokā esošo darījumu kopējo jaucējvērtību.

Metode GetMerkleRoot() norāda Merkle koka sakni darījumiem blokā.

Metode Sign (privk string) paraksta bloku ar bloka veidotāja privāto atslēgu.

Metode SetHeight(height int) ieraksta bloka augstumu bloka struktūras laukā.

GetHeight() int metode atgriež bloka augstumu, kas norādīts attiecīgajā bloka struktūras laukā.

ToGOBBytes() []baitu metode kodē bloku GOB formātā un atgriež to kā baitu šķēli.

Kļūdas metode FromGOBBytes(data []byte) ieraksta bloka datus bloka struktūrā no nodotā ​​baita šķēluma GOB formātā.

GetHash() virknes metode atgriež dotā bloka jaucējvērtību.

Virknes metode GetPrevHash() atgriež iepriekšējā bloka jaucējvērtību.

Metode SetPublicKey (pubk string) ieraksta bloka veidotāja publisko atslēgu blokā.

Tādējādi, izmantojot Block objekta metodes, mēs varam to viegli pārvērst formātā pārraidei pa tīklu un saglabāšanai LevelDB datu bāzē.

Blokķēdes pakotnes funkcijas ir atbildīgas par saglabāšanu blokķēdē: github.com/Rusldv/bcstartup/tree/master/blockchain

Lai to izdarītu, blokam ir jāievieš IBlock saskarne:

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

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

}

Datu bāzes savienojums tiek izveidots vienreiz, kad pakotne tiek inicializēta funkcijā init():

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

CloseDB() ir db.Cloce() iesaiņojums — tiek izsaukts pēc darba ar pakotnes funkcijām, lai aizvērtu savienojumu ar datu bāzi.

Kļūdas funkcija SetTargetBlockHash(jaucējvirkne) ieraksta datu bāzē pašreizējā bloka jaucējvārdu ar atslēgu, ko nosaka konstante BLOCK_HASH.

Funkcija GetTargetBlockHash() (virkne, kļūda) atgriež datubāzē saglabātā pašreizējā bloka jaucējvērtību.

Kļūdas funkcija SetTargetBlockHeight(height int) ieraksta datu bāzē blokķēdes augstuma vērtību mezglam ar atslēgu, kas norādīta ar konstanti BLOCK_HEIGHT.

Funkcija GetTargetBlockHeight() (int, error) atgriež blokķēdes augstumu konkrētajam mezglam, kas saglabāts datu bāzē.

Funkcija CheckBlock (block IBlock) pārbauda bloka pareizību pirms šī bloka pievienošanas blokķēdei.

Kļūdas funkcija AddBlock (block IBlock) pievieno bloku ķēdei.

Bloku izgūšanas un apskatīšanas funkcijas ir blokķēdes pakotnes failā explore.go:

Funkcija GetBlockByHash(hash string) (*block.Block, error) izveido tukšu bloka objektu, ielādē tajā bloku no datu bāzes, kura hash tika nodots tam, un atgriež uz to rādītāju.

Genesis bloka izveidi veic Genesis() kļūdas funkcija no blokķēdes pakotnes faila genesis.go.

Nākamajā rakstā tiks runāts par savienojuma izveidi ar klienta mezglu, izmantojot WebSocket mehānismu.

Avots: www.habr.com

Pievieno komentāru