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.
Bu, endüstri için blockchain hakkındaki ikinci makale, ilki
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:
İş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:
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:
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