Kaip sukūriau blokus ir operacijas savo „Go blockchain“.

Kad galiausiai gautume blokų grandinę, o ne tik duomenų bazę, į savo projektą turime įtraukti 3 svarbius elementus:

  • Bloko duomenų struktūros ir metodų aprašymas
  • Duomenų struktūros ir sandorių metodų aprašymas
  • Blockchain funkcijos, kurios išsaugo blokus duomenų bazėje ir randa juos ten pagal maišą ar aukštį (ar ką nors kita).

Kaip sukūriau blokus ir operacijas savo „Go blockchain“.

Tai antrasis straipsnis apie „blockchain“ pramonei, pirmasis čia.

Prisimenant klausimus, kuriuos skaitytojai man uždavė apie ankstesnį šios serijos straipsnį, reikia pastebėti: šiuo atveju LevelDB duomenų bazė naudojama blokų grandinės duomenims saugoti, tačiau niekas netrukdo naudoti bet kokio kito, tarkime, MySQL. Dabar pažvelkime į šių duomenų struktūrą.

Pradėkime nuo sandorių: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Štai jo duomenų 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 saugo duomenų tipą (2 operacijai), tos operacijos maišą, pačios operacijos tipą, laiko žymą ir įvestis bei išvestis. TxIn įvestis saugo operacijos, kurios išvestis yra nuoroda, maišą, šios išvesties numerį ir baitinį kodą, o TxOut išvestėse saugoma tam tikra reikšmė ir baito kodas.

Dabar pažiūrėkime, kokius veiksmus gali atlikti operacija su savo duomenimis, t.y. Pažvelkime į metodus.

Norėdami sukurti operaciją, naudokite funkciją Transaction.NewTransaction(txtype byte) *TX.

Metodas AddTxIn(thattxhash []baitas, txoutn int, kodas []baitas) (*TxIn, klaida) prideda įvestį į operaciją.

AddTxOut(vertė int, duomenų []baitas) (*TxOut, klaida) metodas prideda operacijos išvestį.

ToBytes() []byte metodas paverčia operaciją baitų dalimi.

Vidinės funkcijos eilutė preByteHash(baitai []baitas) naudojama Build() ir Check(), kad sugeneruota operacijų maiša būtų suderinama su operacijų maišais, sugeneruotais iš JavaScript programų.

Metodas Build() nustato operacijos maišą taip: tx.TxHash = preByteHash(tx.ToBytes()).

ToJSON() eilutės metodas konvertuoja operaciją į JSON eilutę.

Klaidos metodas FromJSON (duomenų []baitas) įkelia operaciją iš JSON formato, perduodamo kaip baitų dalis.

Patikrinimo() bool metodas palygina gautą maišą iš operacijos maišos lauko su maiša, gauta atlikus šios operacijos maišą (nepaisant maišos lauko).

Sandoriai pridedami prie bloko: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Bloko duomenų struktūra yra didesnė:

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 saugo duomenų tipą, mazgas jį naudoja ir atskiria bloką nuo operacijos ar kitų duomenų. Bloko atveju ši vertė yra 1.

BlockHeight išsaugo bloko aukštį.
Laiko žyma laiko žyma.
HeaderSize yra bloko dydis baitais.
PrevBlockHash yra ankstesnio bloko maiša, o SelfBlockHash yra dabartinio bloko maiša.
TxsHash yra bendra operacijų maiša.
MerkleRoot yra Merkle medžio šaknis.

Toliau laukeliuose yra bloko kūrėjo viešasis raktas, kūrėjo parašas, bloko versija, operacijų skaičius bloke ir pačios šios operacijos.

Pažvelkime į jo metodus:
Norėdami sukurti bloką, naudokite funkciją block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, kuris paima ankstesnio bloko maišą ir sukurto bloko aukštį blokų grandinėje. Bloko tipas taip pat nustatomas iš tipų paketo konstantos:

b.DataType = types.BLOCK_TYPE.

AddTx(tx *transaction.TX) metodas prideda operaciją prie bloko.

Metodas Build() įkelia reikšmes į bloko laukus ir generuoja bei nustato dabartinę maišą.

ToBytesHeader() []baitų metodas konvertuoja bloko antraštę (be operacijų) į baitų pjūvį.

ToJSON() eilutės metodas konvertuoja bloką į JSON formatą duomenų eilutės vaizde.

Klaidos metodas FromJSON (duomenų []baitas) įkelia duomenis iš JSON į blokų struktūrą.

Patikrinimo() bool metodas generuoja bloko maišą ir lygina ją su bloko maišos lauke nurodytu.

GetTxsHash() eilutės metodas grąžina bendrą visų bloko operacijų maišą.

Metodas GetMerkleRoot() nurodo Merkle medžio šaknį operacijoms bloke.

Metodas Sign(privk string) pasirašo bloką su bloko kūrėjo privačiu raktu.

Metodas SetHeight(height int) įrašo bloko aukštį į bloko struktūros lauką.

Metodas GetHeight() int grąžina bloko aukštį, nurodytą atitinkamame bloko struktūros lauke.

ToGOBBytes() []byte metodas užkoduoja bloką GOB formatu ir grąžina jį kaip baitų skiltį.

Klaidos metodas FromGOBBytes(data []byte) įrašo bloko duomenis į bloko struktūrą iš perduoto baito dalies GOB formatu.

GetHash() eilutės metodas grąžina nurodyto bloko maišą.

GetPrevHash() eilutės metodas grąžina ankstesnio bloko maišą.

Metodas SetPublicKey (pubk string) įrašo bloko kūrėjo viešąjį raktą į bloką.

Taigi, naudodami Block objekto metodus, galime lengvai konvertuoti jį į formatą, skirtą perduoti per tinklą ir išsaugoti LevelDB duomenų bazėje.

„Blockchain“ paketo funkcijos yra atsakingos už išsaugojimą „blockchain“: github.com/Rusldv/bcstartup/tree/master/blockchain

Norėdami tai padaryti, blokas turi įdiegti IBlock sąsają:

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

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

}

Duomenų bazės ryšys sukuriamas vieną kartą, kai paketas inicijuojamas naudojant init() funkciją:

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

CloseDB() yra db.Cloce() paketas – iškviečiamas dirbant su paketo funkcijomis, kad būtų uždarytas ryšys su duomenų baze.

Klaidos funkcija SetTargetBlockHash(hash string) įrašo į duomenų bazę dabartinio bloko maišą su raktu, nurodytu konstantoje BLOCK_HASH.

Funkcija GetTargetBlockHash() (eilutė, klaida) grąžina dabartinio bloko, saugomo duomenų bazėje, maišą.

Klaidos funkcija SetTargetBlockHeight(height int) įrašo į duomenų bazę bloko grandinės aukščio reikšmę mazgui su raktu, nurodytu konstanta BLOCK_HEIGHT.

Funkcija GetTargetBlockHeight() (int, error) grąžina tam tikro mazgo blokų grandinės aukštį, saugomą duomenų bazėje.

CheckBlock(block IBlock) bool funkcija patikrina bloko teisingumą prieš įtraukdama šį bloką į blokų grandinę.

Klaidos funkcija AddBlock (block IBlock) prideda bloką prie blokų grandinės.

Blokų gavimo ir peržiūros funkcijos yra blockchain paketo explore.go faile:

Funkcija GetBlockByHash(hash string) (*block.Block, error) sukuria tuščią bloko objektą, įkelia į jį bloką iš duomenų bazės, kurio maiša jam buvo perduota, ir grąžina į jį rodyklę.

Genesis blokas sukuriamas naudojant Genesis() klaidos funkciją iš blockchain paketo genesis.go failo.

Kitame straipsnyje bus kalbama apie klientų prijungimą prie mazgo naudojant WebSocket mechanizmą.

Šaltinis: www.habr.com

Добавить комментарий