My Go Blok Zincirinde Blokları ve İşlemleri Nasıl Tasarladım?

Nihayetinde sadece bir veritabanı değil, bir blok zinciri elde etmek için projemize 3 önemli unsur eklememiz gerekiyor:

  • Veri yapısının ve blok yöntemlerinin açıklaması
  • Veri yapısının ve işlem yöntemlerinin açıklaması
  • Blokları veritabanında depolayan ve onları orada karma değerlerine veya yüksekliklerine (veya her neyse) göre bulan blok zinciri işlevleri.

My Go Blok Zincirinde Blokları ve İşlemleri Nasıl Tasarladım?

Bu, endüstri için blockchain hakkındaki ikinci makale, ilki burada.

Okuyucuların bu dizideki önceki makale için bana sorduğu soruları hatırlatarak, not edilmelidir: bu durumda, LevelDB veritabanı blok zinciri verilerini depolamak için kullanılır, ancak hiçbir şey, örneğin aynı MySQL'in kullanılmasını engellemez. Şimdi bu verinin yapısına bakalım.

İşlemlerle başlayalım: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

İşte veri yapısı:

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, veri türünü (işlem 2 için), bu işlemin karmasını, işlemin türünü, zaman damgasını ve girdileri ve çıktıları saklar. TxIn girişleri, çıktısı referans alınan işlemin karmasını, bu çıktının numarasını ve bayt kodunu saklar ve TxOut çıktıları, bir miktar değeri ve ayrıca bayt kodunu saklar.

Şimdi bir işlemin verileri üzerinde hangi eylemleri gerçekleştirebileceğini görelim, yani. Yöntemlere bir göz atalım.

process.NewTransaction(txtype byte) *TX işlevi, bir işlem oluşturmak için kullanılır.

AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) yöntemi, işleme bir girdi ekler.

AddTxOut(value int, data []byte) (*TxOut, error) yöntemi, işleme bir çıktı ekler.

ToBytes() []bayt yöntemi, bir işlemi bir bayt dilimine dönüştürür.

PreByteHash(bytes []byte) string dahili işlevi, oluşturulan işlem sağlamasını JavaScript uygulamalarından oluşturulan işlem sağlamalarıyla uyumlu hale getirmek için Build() ve Check()'te kullanılır.

Build() yöntemi, işlem karmasını şu şekilde ayarlar: tx.TxHash = preByteHash(tx.ToBytes()).

ToJSON() dize yöntemi, işlemi bir JSON dizesine dönüştürür.

FromJSON(data []byte) hata yöntemi, bayt dilimi olarak iletilen JSON biçiminden bir işlemi yükler.

Check() bool yöntemi, işlemin hash alanından alınan hash'i, bu işlemin hash'lenmesi sonucunda elde edilen hash ile karşılaştırır (hash alanı hariç).

İşlemler bloğa eklenir: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Blok veri yapısı daha hacimlidir:

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, düğümün bloğu işlemden veya diğer verilerden ayırdığı veri türünü depolar. Bir blok için bu değer 1'dir.

BlockHeight, bloğun yüksekliğini saklar.
zaman damgası zaman damgası.
Bayt cinsinden HeaderSize blok boyutu.
PrevBlockHash önceki bloğun hash'idir ve SelfBlockHash mevcut bloğun hash'idir.
TxsHash, toplam işlem karma değeridir.
MerkleRoot, Merkle ağacının köküdür.

Ayrıca alanlar, blok yaratıcısının genel anahtarını, yaratıcının imzasını, blok sürümünü, bloktaki işlem sayısını ve bu işlemlerin kendisini içerir.

Yöntemlerini düşünün:
Bir blok oluşturmak için, block.NewBlock() işlevi kullanılır: NewBlock(prevBlockHash string, height int) *Önceki bloğun karmasını ve blok zincirinde oluşturulan blok için ayarlanan yüksekliği alan Blok. Blok tipi ayrıca tipler paket sabitinden ayarlanır:

b.DataType = types.BLOCK_TYPE.

AddTx(tx *transaction.TX) yöntemi, bir bloğa işlem ekler.

Build() yöntemi, değerleri blok alanlarına yükler ve mevcut hash'ini oluşturur ve ayarlar.

ToBytesHeader() []bayt yöntemi, blok başlığını (işlemler olmadan) bir bayt dilimine çevirir.

ToJSON() dize yöntemi, bloğu, verilerin dize gösteriminde JSON formatına dönüştürür.

FromJSON(data []byte) hata yöntemi, verileri JSON'dan bir blok yapısına yükler.

Check() bool yöntemi, bloğun karmasını oluşturur ve bunu bloğun hash alanında belirtilenle karşılaştırır.

GetTxsHash() string yöntemi, bloktaki tüm işlemlerin toplam karmasını döndürür.

GetMerkleRoot() yöntemi, bir bloktaki işlemler için Merkle ağacının kökünü ayarlar.

Sign(privk string) yöntemi, bloğu, blok oluşturucunun özel anahtarıyla imzalar.

SetHeight(height int) yöntemi, bloğun yüksekliğini blok yapı alanına yazar.

GetHeight() int yöntemi, blok yapısının karşılık gelen alanında belirtilen bloğun yüksekliğini döndürür.

ToGOBBytes() []bayt yöntemi, bir bloğu GOB biçiminde kodlar ve onu bir bayt dilimi olarak döndürür.

FromGOBBytes(data []byte) hata yöntemi, blok verilerini GOB formatında geçirilen bayt diliminden blok yapısına yazar.

GetHash() string yöntemi, verilen bloğun karmasını döndürür.

GetPrevHash() string yöntemi, önceki bloğun karmasını döndürür.

SetPublicKey(pubk string) yöntemi, blok oluşturucunun ortak anahtarını bloğa yazar.

Böylece, Block nesnesinin yöntemlerini kullanarak, onu ağ üzerinden iletmek ve LevelDB veritabanına kaydetmek için kolayca bir formata dönüştürebiliriz.

Blok zinciri paketinin işlevleri, blok zincirinde tasarruf etmekten sorumludur: github.com/Rusldv/bcstartup/tree/master/blockchain

Bunu yapmak için blok, IBlock arayüzünü uygulamalıdır:

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

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

}

Veritabanı bağlantısı, paket init() işlevinde başlatıldığında bir kez oluşturulur:

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

CloseDB(), veritabanı bağlantısını kapatmak için paket işlevleriyle çalıştıktan sonra çağrılan db.Cloce() için bir sarıcıdır.

SetTargetBlockHash(hash string) hata fonksiyonu, BLOCK_HASH sabiti ile belirtilen anahtar ile mevcut bloğun hash'ini veritabanına yazar.

GetTargetBlockHash() (dize, hata) işlevi, veritabanında depolanan geçerli bloğun karmasını döndürür.

SetTargetBlockHeight(height int) hata işlevi, BLOCK_HEIGHT sabiti tarafından belirtilen anahtara sahip düğüm için blockchain yükseklik değerini veritabanına yazar.

GetTargetBlockHeight() (int, error) işlevi, veritabanında saklanan verilen düğüm için blok yüksekliğini döndürür.

CheckBlock(block IBlock) bool işlevi, bu bloğu blok zincirine eklemeden önce bloğun geçerliliğini kontrol eder.

AddBlock(block IBlock) hata işlevi, blok zincirine bir blok ekler.

Blokları alma ve görüntüleme işlevleri, blockchain paketinin explore.go dosyasında bulunur:

GetBlockByHash(hash string) (*block.Block, error) işlevi, boş bir blok nesnesi oluşturur, hash'i kendisine iletilen veritabanından oraya bir blok yükler ve ona bir işaretçi döndürür.

Genesis bloğunun oluşturulması, blockchain paketinin genesis.go dosyasından Genesis() hata işlevi tarafından gerçekleştirilir.

Bir sonraki yazımızda, WebSocket mekanizmasını kullanarak istemcileri düğüme bağlamaktan bahsedeceğiz.

Kaynak: habr.com

Yorum ekle