Kuinka suunnittelin lohkoja ja tapahtumia Go-lohkoketjussani

Jotta lopulta päätyisimme lohkoketjuun eikä vain tietokantaan, meidän on lisättävä projektiimme kolme tärkeää elementtiä:

  • Lohkotietorakenteen ja -menetelmien kuvaus
  • Tietorakenteen ja tapahtumamenetelmien kuvaus
  • Blockchain-funktiot, jotka tallentavat lohkot tietokantaan ja löytävät ne sieltä niiden tiivisteen tai korkeuden (tai jonkin muun) perusteella.

Kuinka suunnittelin lohkoja ja tapahtumia Go-lohkoketjussani

Tämä on toinen artikkeli teollisuuden lohkoketjusta, ensimmäinen täällä.

Muistaakseni kysymykset, joita lukijat kysyivät minulta tämän sarjan edellisestä artikkelista, on syytä huomata: tässä tapauksessa LevelDB-tietokantaa käytetään lohkoketjutietojen tallentamiseen, mutta mikään ei estä sinua käyttämästä jotain muuta, esimerkiksi MySQL:ää. Katsotaanpa nyt näiden tietojen rakennetta.

Aloitetaan kaupoista: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Tässä on sen tietorakenne:

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 tallentaa tietotyypin (tapahtumalle 2), tapahtuman tiivisteen, itse tapahtuman tyypin, aikaleiman sekä tulot ja lähdöt. TxIn-tulot tallentavat tapahtuman tiivisteen, jonka ulostuloon viitataan, tämän lähdön numeron ja tavukoodin, ja TxOut-tulot tallentavat jonkin arvon ja myös tavukoodin.

Katsotaan nyt, mitä toimintoja tapahtuma voi tehdä tiedoilleen, ts. Katsotaanpa menetelmiä.

Luo tapahtuma käyttämällä transaktio.NewTransaction(txtype byte) *TX-funktiota.

AddTxIn(thattxhash []tavu, txoutn int, koodi []tavu) (*TxIn, virhe) -menetelmä lisää tapahtumaan syötteen.

AddTxOut(arvo int, data []tavu) (*TxOut, error) -menetelmä lisää tapahtumaan tulosteen.

ToBytes() []byte-menetelmä muuttaa tapahtuman tavuviipaleeksi.

Sisäistä funktion preByteHash(bytes []byte) -merkkijonoa käytetään Build()- ja Check()-kohdissa, jotta luotu tapahtumatiiviste on yhteensopiva JavaScript-sovelluksista luotujen tapahtumatiivisteiden kanssa.

Build()-metodi asettaa tapahtuman hajautusarvon seuraavasti: tx.TxHash = preByteHash(tx.ToBytes()).

ToJSON()-merkkijonomenetelmä muuntaa tapahtuman JSON-merkkijonoksi.

FromJSON(data []byte) -virhemenetelmä lataa tapahtuman tavuviipaleena välitetystä JSON-muodosta.

Check() bool -menetelmä vertaa tapahtuman hajautuskentän tuloksena olevaa tiivistettä tämän tapahtuman hajauttamisen tuloksena saatuun tiivisteeseen (hajautuskenttä huomioimatta).

Tapahtumat lisätään lohkoon: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Lohkotietorakenne on laajempi:

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 tallentaa tietotyypin, solmu käyttää sitä ja erottaa lohkon tapahtumasta tai muusta tiedosta. Lohkolle tämä arvo on 1.

BlockHeight tallentaa lohkon korkeuden.
Aikaleima aikaleima.
HeaderSize on lohkon koko tavuina.
PrevBlockHash on edellisen lohkon tiiviste ja SelfBlockHash on nykyisen lohkon tiiviste.
TxsHash on yleinen tapahtumien tiiviste.
MerkleRoot on Merkle-puun juuri.

Edelleen kentissä on lohkon luojan julkinen avain, luojan allekirjoitus, lohkon versio, lohkon tapahtumien määrä ja itse nämä tapahtumat.

Katsotaanpa sen menetelmiä:
Lohkon luomiseen käytetään toimintoa block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, joka ottaa edellisen lohkon hashin ja luodun lohkon korkeuden lohkoketjussa. Lohkon tyyppi asetetaan myös tyyppipaketin vakiosta:

b.DataType = types.BLOCK_TYPE.

AddTx(tx *transaction.TX) -menetelmä lisää tapahtuman lohkoon.

Build()-menetelmä lataa arvot lohkon kenttiin ja luo ja asettaa sen nykyisen hajautusarvon.

ToBytesHeader() []byte-menetelmä muuntaa lohkootsikon (ilman tapahtumia) tavuviipaleeksi.

ToJSON()-merkkijonomenetelmä muuntaa lohkon JSON-muotoon tietojen merkkijonoesityksessä.

FromJSON(data []byte) -virhemenetelmä lataa tiedot JSONista lohkorakenteeseen.

Check() bool -menetelmä luo lohkohajautusarvon ja vertaa sitä lohkohajautuskentässä määritettyyn.

GetTxsHash()-merkkijonomenetelmä palauttaa lohkon kaikkien tapahtumien kokonaistiivisteen.

GetMerkleRoot()-metodi määrittää Merkle-puun juuren lohkon tapahtumille.

Sign(privk string) -metodi allekirjoittaa lohkon lohkon luojan yksityisellä avaimella.

SetHeight(height int) -menetelmä kirjoittaa lohkon korkeuden lohkorakennekenttään.

GetHeight() int-metodi palauttaa lohkon korkeuden sellaisena kuin se on määritetty lohkorakenteen vastaavassa kentässä.

ToGOBBytes() []byte-menetelmä koodaa lohkon GOB-muodossa ja palauttaa sen tavuviipaleena.

FromGOBBytes(data []byte) -virhemenetelmä kirjoittaa lohkodataa lohkorakenteeseen välitetystä tavuviipaleesta GOB-muodossa.

GetHash()-merkkijonomenetelmä palauttaa annetun lohkon tiivisteen.

GetPrevHash()-merkkijonomenetelmä palauttaa edellisen lohkon hajautusarvon.

SetPublicKey(pubk string) -menetelmä kirjoittaa lohkon luojan julkisen avaimen lohkoon.

Siten Block-objektin menetelmiä käyttämällä voimme helposti muuntaa sen muotoon lähetettäväksi verkon yli ja tallennettavaksi LevelDB-tietokantaan.

Lohkoketjupaketin toiminnot vastaavat tallentamisesta lohkoketjuun: github.com/Rusldv/bcstartup/tree/master/blockchain

Tätä varten lohkon on toteutettava IBlock-liitäntä:

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

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

}

Tietokantayhteys luodaan kerran, kun paketti alustetaan init()-funktiossa:

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

CloseDB() on kääre tiedostolle db.Cloce() - kutsutaan sen jälkeen, kun pakettifunktiot on työskennellyt yhteyden sulkemiseksi tietokantaan.

SetTargetBlockHash(hash string) -virhetoiminto kirjoittaa tietokantaan nykyisen lohkon tiivisteen BLOCK_HASH-vakion määrittämällä avaimella.

GetTargetBlockHash() (merkkijono, virhe) -funktio palauttaa tietokantaan tallennetun nykyisen lohkon tiivisteen.

SetTargetBlockHeight(height int) -virhetoiminto kirjoittaa tietokantaan solmun lohkoketjun korkeuden arvon BLOCK_HEIGHT-vakion määrittelemällä avaimella.

GetTargetBlockHeight() (int, error) -funktio palauttaa tietokantaan tallennetun lohkoketjun korkeuden tietylle solmulle.

CheckBlock(block IBlock) bool-funktio tarkistaa lohkon oikeellisuuden ennen tämän lohkon lisäämistä lohkoketjuun.

AddBlock(block IBlock) -virhetoiminto lisää lohkon lohkoketjuun.

Lohkojen haku- ja katselutoiminnot ovat blockchain-paketin explore.go-tiedostossa:

Funktio GetBlockByHash(hash string) (*block.Block, error) luo tyhjän lohkoobjektin, lataa siihen tietokannasta lohkon, jonka hash välitettiin sille, ja palauttaa osoittimen siihen.

Genesis-lohkon luomisen suorittaa Genesis()-virhefunktio lohkoketjupaketin genesis.go-tiedostosta.

Seuraavassa artikkelissa käsitellään asiakkaiden yhdistämistä solmuun WebSocket-mekanismin avulla.

Lähde: will.com

Lisää kommentti