Oxir oqibatda faqat ma'lumotlar bazasi emas, balki blokcheyn bilan yakunlash uchun loyihamizga 3 ta muhim elementni qo'shishimiz kerak:
- Blok ma'lumotlar strukturasi va usullari tavsifi
- Ma'lumotlar tuzilishi va tranzaksiya usullarining tavsifi
- Bloklarni ma'lumotlar bazasida saqlaydigan va ularni xesh yoki balandlik (yoki boshqa narsa) bo'yicha topadigan blokcheyn funktsiyalari.
Bu sanoat uchun blokcheyn haqida ikkinchi maqola, birinchi
O'quvchilarning ushbu seriyadagi oldingi maqola haqida menga bergan savollarini eslab, shuni ta'kidlash kerak: bu holda, LevelDB ma'lumotlar bazasi blokcheyn ma'lumotlarini saqlash uchun ishlatiladi, ammo hech narsa boshqa, aytaylik, MySQL dan foydalanishga to'sqinlik qilmaydi. Endi ushbu ma'lumotlarning tuzilishini ko'rib chiqamiz.
Tranzaktsiyalardan boshlaylik:
Mana uning ma'lumotlar tuzilishi:
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 ma'lumotlar turini (2-tranzaksiya uchun), ushbu tranzaksiyaning xeshini, tranzaktsiyaning o'zi turini, vaqt tamg'asini, kirish va chiqishlarni saqlaydi. TxIn kirishlari chiqishiga havola qilingan tranzaksiya xeshini, ushbu chiqish va bayt kodining sonini, TxOut chiqishi esa ba'zi qiymatlarni va bayt kodini saqlaydi.
Keling, tranzaksiya o'z ma'lumotlarida qanday harakatlarni amalga oshirishi mumkinligini ko'rib chiqaylik, ya'ni. Keling, usullarni ko'rib chiqaylik.
Tranzaksiya yaratish uchun tranzaksiyadan foydalaning.NewTransaction(txtype bayt) *TX funksiyasidan foydalaning.
AddTxIn(thattxhash []bayt, txoutn int, kod []bayt) (*TxIn, xato) usuli tranzaktsiyaga kirish kiritadi.
AddTxOut(value int, data []bayt) (*TxOut, error) usuli tranzaktsiyaga chiqish qo'shadi.
ToBytes() []bayt usuli tranzaksiyani bayt tilimga aylantiradi.
PreByteHash(bayt []bayt) ichki funksiyasi Build() va Check() da yaratilgan tranzaksiya xeshini JavaScript ilovalarida yaratilgan tranzaksiya xeshlari bilan mos qilish uchun ishlatiladi.
Build() usuli tranzaksiya xeshini quyidagicha o'rnatadi: tx.TxHash = preByteHash(tx.ToBytes()).
ToJSON() string usuli tranzaksiyani JSON qatoriga aylantiradi.
FromJSON(ma'lumotlar []bayt) xato usuli bayt tilim sifatida uzatilgan JSON formatidan tranzaksiyani yuklaydi.
Check() bool usuli tranzaksiya xesh maydonidan olingan xeshni ushbu tranzaksiyani xeshlash natijasida olingan xeshni (xesh maydoniga e'tibor bermasdan) solishtiradi.
Bitimlar blokga qo'shiladi:
Blok ma'lumotlar strukturasi yanada hajmli:
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 ma'lumotlar turini saqlaydi, tugun undan foydalanadi va blokni tranzaksiya yoki boshqa ma'lumotlardan ajratib turadi. Blok uchun bu qiymat 1 ga teng.
BlockHeight blokning balandligini saqlaydi.
Vaqt tamg'asi vaqt tamg'asi.
HeaderSize - baytdagi blok hajmi.
PrevBlockHash oldingi blokning xeshi, SelfBlockHash esa joriy blokning xeshidir.
TxsHash - tranzaktsiyalarning umumiy xeshi.
MerkleRoot Merkle daraxtining ildizidir.
Keyinchalik maydonlarda blok yaratuvchisining ochiq kaliti, yaratuvchining imzosi, blok versiyasi, blokdagi tranzaktsiyalar soni va ushbu tranzaktsiyalarning o'zi mavjud.
Keling, uning usullarini ko'rib chiqaylik:
Blok yaratish uchun block.NewBlock() funksiyasidan foydalaning: NewBlock(prevBlockHash string, height int) *Blok, oldingi blokning xeshini va blokcheyndagi yaratilgan blok uchun belgilangan balandlikni oladi. Blok turi ham turlar to'plami konstantasidan o'rnatiladi:
b.DataType = types.BLOCK_TYPE.
AddTx(tx *transaction.TX) usuli tranzaktsiyani blokga qo'shadi.
Build() usuli qiymatlarni blok maydonlariga yuklaydi va joriy xeshni yaratadi va o'rnatadi.
ToBytesHeader() []bayt usuli blok sarlavhasini (tranzaksiyalarsiz) bayt tilimga aylantiradi.
ToJSON() string usuli blokni JSON formatiga ma'lumotlarning satr ko'rinishida o'zgartiradi.
FromJSON(ma'lumotlar []bayt) xato usuli JSON'dan ma'lumotlarni blok tuzilishiga yuklaydi.
Check() bool usuli blok xesh hosil qiladi va uni blok xesh maydonida ko'rsatilgan bilan solishtiradi.
GetTxsHash() string usuli blokdagi barcha tranzaksiyalarning umumiy xeshini qaytaradi.
GetMerkleRoot() usuli blokdagi tranzaktsiyalar uchun Merkle daraxtining ildizini belgilaydi.
Sign(privk string) usuli blok yaratuvchining shaxsiy kaliti bilan blokni imzolaydi.
SetHeight(height int) usuli blokning balandligini blok strukturasi maydoniga yozadi.
GetHeight() int usuli blok strukturasining tegishli maydonida belgilangan blok balandligini qaytaradi.
ToGOBBytes() []bayt usuli blokni GOB formatida kodlaydi va uni bayt tilim sifatida qaytaradi.
FromGOBBytes(ma'lumotlar []bayt) xato usuli blok ma'lumotlarini blok tuzilishiga o'tkazilgan bayt tilimdan GOB formatida yozadi.
GetHash() string usuli berilgan blokning xeshini qaytaradi.
GetPrevHash() string usuli oldingi blokning xeshini qaytaradi.
SetPublicKey(pubk string) usuli blok yaratuvchining ochiq kalitini blokga yozadi.
Shunday qilib, Block ob'ektining usullaridan foydalanib, biz uni tarmoq orqali uzatish va LevelDB ma'lumotlar bazasiga saqlash uchun formatga osongina o'zgartirishimiz mumkin.
Blokcheyn paketining funktsiyalari blokcheynga saqlash uchun javobgardir:
Buning uchun blok IBlock interfeysini amalga oshirishi kerak:
type IGOBBytes interface {
ToGOBBytes() []byte
FromGOBBytes(data []byte) error
}
type IBlock interface {
IGOBBytes
GetHash() string
GetPrevHash() string
GetHeight() int
Check() bool
}
Ma'lumotlar bazasi ulanishi paket init() funksiyasida ishga tushirilganda bir marta yaratiladi:
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).
CloseDB() db.Cloce() uchun oΚ»ram boΚ»lib, maΚΌlumotlar bazasiga ulanishni yopish uchun paket funksiyalari bilan ishlagandan keyin chaqiriladi.
SetTargetBlockHash(xesh string) xato funksiyasi joriy blokning xeshini ma'lumotlar bazasiga BLOCK_HASH doimiysi tomonidan belgilangan kalit bilan yozadi.
GetTargetBlockHash() (string, xato) funksiyasi ma'lumotlar bazasida saqlangan joriy blokning xeshini qaytaradi.
SetTargetBlockHeight(height int) xato funksiyasi maΚΌlumotlar bazasiga BLOCK_HEIGHT doimiysi bilan belgilangan kalit bilan tugun uchun blokcheyn balandligi qiymatini yozadi.
GetTargetBlockHeight() (int, xato) funktsiyasi ma'lumotlar bazasida saqlangan berilgan tugun uchun blokcheyn balandligini qaytaradi.
CheckBlock(block IBlock) bool funksiyasi ushbu blokni blokcheynga qo'shishdan oldin blokning to'g'riligini tekshiradi.
AddBlock(block IBlock) xato funksiyasi blokcheynga blok qoβshadi.
Bloklarni olish va ko'rish funktsiyalari blockchain paketining explore.go faylida joylashgan:
GetBlockByHash(xesh string) (*block.Block, error) funksiyasi bo'sh blok ob'ektini yaratadi, unga ma'lumotlar bazasidan blokni yuklaydi, uning xeshi unga uzatiladi va unga ko'rsatgichni qaytaradi.
Genesis blokini yaratish blokcheyn paketining genesis.go faylidan Genesis() xato funksiyasi orqali amalga oshiriladi.
Keyingi maqolada WebSocket mexanizmi yordamida mijozlarni tugunga ulash haqida gap boradi.
Manba: www.habr.com