Untuk akhirnya berakhir dengan blockchain dan bukan hanya pangkalan data, kami perlu menambah 3 elemen penting pada projek kami:
- Penerangan tentang struktur dan kaedah data blok
- Penerangan tentang struktur data dan kaedah transaksi
- Fungsi Blockchain yang menyimpan blok dalam pangkalan data dan mencarinya di sana mengikut cincang atau ketinggiannya (atau sesuatu yang lain).
Ini adalah artikel kedua tentang blockchain untuk industri, yang pertama
Mengingati soalan yang ditanya oleh pembaca kepada saya tentang artikel sebelumnya dalam siri ini, perlu diperhatikan: dalam kes ini, pangkalan data LevelDB digunakan untuk menyimpan data blockchain, tetapi tiada apa yang menghalang anda daripada menggunakan yang lain, katakan, MySQL. Sekarang mari kita lihat struktur data ini.
Mari kita mulakan dengan transaksi:
Berikut ialah struktur datanya:
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 menyimpan jenis data (untuk transaksi 2), cincang transaksi itu, jenis transaksi itu sendiri, cap masa dan input dan output. Input TxIn menyimpan cincang transaksi yang outputnya dirujuk, bilangan output dan kod bait ini, dan output TxOut menyimpan beberapa nilai dan juga kod bait.
Sekarang mari kita lihat tindakan yang boleh dilakukan oleh transaksi pada datanya, i.e. Mari kita lihat kaedahnya.
Untuk membuat transaksi, gunakan transaksi.NewTransaction(txtype byte) *fungsi TX.
Kaedah AddTxIn(thattxhash []bait, txoutn int, kod []bait) (*TxIn, ralat) menambah input pada transaksi.
Kaedah AddTxOut(nilai int, data []bait) (*TxOut, ralat) menambah output pada transaksi.
Kaedah ToBytes() []byte menukar transaksi menjadi kepingan bait.
Rentetan fungsi dalaman preByteHash(bait []bait) digunakan dalam Build() dan Check() untuk menjadikan cincang transaksi yang dijana serasi dengan cincang transaksi yang dijana daripada aplikasi JavaScript.
Kaedah Build() menetapkan cincang transaksi seperti berikut: tx.TxHash = preByteHash(tx.ToBytes()).
Kaedah rentetan ToJSON() menukar transaksi menjadi rentetan JSON.
Kaedah ralat FromJSON(data []bait) memuatkan transaksi daripada format JSON yang diluluskan sebagai kepingan bait.
Kaedah bool Check() membandingkan cincangan yang terhasil daripada medan cincangan transaksi dengan cincangan yang diperoleh hasil daripada pencincangan transaksi ini (mengabaikan medan cincangan).
Urus niaga ditambah pada blok:
Struktur data blok lebih besar:
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 menyimpan jenis data, nod menggunakannya dan membezakan blok daripada transaksi atau data lain. Untuk blok nilai ini ialah 1.
BlockHeight menyimpan ketinggian blok.
Cap masa cap masa.
HeaderSize ialah saiz blok dalam bait.
PrevBlockHash ialah cincangan bagi blok sebelumnya, dan SelfBlockHash ialah cincangan bagi blok semasa.
TxsHash ialah cincang umum transaksi.
MerkleRoot ialah akar pokok Merkle.
Selanjutnya dalam medan terdapat kunci awam pencipta blok, tandatangan pencipta, versi blok, bilangan transaksi dalam blok dan transaksi ini sendiri.
Mari lihat kaedahnya:
Untuk membuat blok, gunakan fungsi blok.NewBlock(): NewBlock(rentetan prevBlockHash, height int) *Blok, yang mengambil cincang blok sebelumnya dan set ketinggian untuk blok yang dicipta dalam blok. Jenis blok juga ditetapkan daripada pemalar pakej jenis:
b.DataType = types.BLOCK_TYPE.
Kaedah AddTx(tx *transaction.TX) menambah transaksi pada blok.
Kaedah Build() memuatkan nilai ke dalam medan blok dan menjana serta menetapkan cincang semasanya.
Kaedah ToBytesHeader() []bait menukarkan pengepala blok (tanpa transaksi) menjadi kepingan bait.
Kaedah rentetan ToJSON() menukarkan blok kepada format JSON dalam perwakilan rentetan data.
Kaedah ralat FromJSON(data []bait) memuatkan data daripada JSON ke dalam struktur blok.
Kaedah Check() bool menjana cincang blok dan membandingkannya dengan yang dinyatakan dalam medan cincang blok.
Kaedah rentetan GetTxsHash() mengembalikan jumlah cincangan semua transaksi dalam blok.
Kaedah GetMerkleRoot() menentukan punca pokok Merkle untuk transaksi dalam blok.
Kaedah Tanda (rentetan privk) menandatangani blok dengan kunci peribadi pencipta blok.
Kaedah SetHeight(height int) menulis ketinggian blok ke medan struktur blok.
Kaedah int GetHeight() mengembalikan ketinggian blok seperti yang dinyatakan dalam medan sepadan struktur blok.
Kaedah ToGOBBytes() []byte mengekod blok dalam format GOB dan mengembalikannya sebagai kepingan bait.
Kaedah ralat FromGOBBytes(data []bait) menulis data blok ke struktur blok daripada kepingan bait yang diluluskan dalam format GOB.
Kaedah rentetan GetHash() mengembalikan cincangan blok yang diberikan.
Kaedah rentetan GetPrevHash() mengembalikan cincangan blok sebelumnya.
Kaedah SetPublicKey(rentetan pubk) menulis kunci awam pencipta blok ke blok.
Oleh itu, menggunakan kaedah objek Blok, kita boleh menukarnya dengan mudah ke dalam format untuk penghantaran melalui rangkaian dan menyimpan ke pangkalan data LevelDB.
Fungsi pakej blockchain bertanggungjawab untuk menyimpan ke blockchain:
Untuk melakukan ini, blok mesti melaksanakan antara muka IBlock:
type IGOBBytes interface {
ToGOBBytes() []byte
FromGOBBytes(data []byte) error
}
type IBlock interface {
IGOBBytes
GetHash() string
GetPrevHash() string
GetHeight() int
Check() bool
}
Sambungan pangkalan data dibuat sekali apabila pakej dimulakan dalam fungsi init():
db, err = leveldb.OpenFile(BLOCKCHAIN_DB_DEBUG, nil).
CloseDB() ialah pembungkus untuk db.Cloce() - dipanggil selepas bekerja dengan fungsi pakej untuk menutup sambungan ke pangkalan data.
Fungsi ralat SetTargetBlockHash(rentetan cincang) menulis cincang blok semasa dengan kunci yang ditentukan oleh pemalar BLOCK_HASH ke pangkalan data.
Fungsi GetTargetBlockHash() (rentetan, ralat) mengembalikan cincangan blok semasa yang disimpan dalam pangkalan data.
Fungsi ralat SetTargetBlockHeight(height int) menulis kepada pangkalan data nilai ketinggian blockchain untuk nod dengan kunci yang ditentukan oleh pemalar BLOCK_HEIGHT.
Fungsi GetTargetBlockHeight() (int, error) mengembalikan ketinggian blockchain untuk nod tertentu, yang disimpan dalam pangkalan data.
Fungsi CheckBlock(block IBlock) bool menyemak blok untuk ketepatan sebelum menambah blok ini pada blockchain.
Fungsi ralat AddBlock(block IBlock) menambah blok pada blockchain.
Fungsi untuk mendapatkan semula dan melihat blok terdapat dalam fail explore.go pakej blockchain:
Fungsi GetBlockByHash(rentetan cincang) (*block.Blok, ralat) mencipta objek blok kosong, memuatkan blok ke dalamnya daripada pangkalan data, cincang yang dihantar kepadanya dan mengembalikan penunjuk kepadanya.
Penciptaan blok genesis dijalankan oleh fungsi ralat Genesis() daripada fail genesis.go pakej blockchain.
Artikel seterusnya akan membincangkan tentang menyambungkan pelanggan ke nod menggunakan mekanisme WebSocket.
Sumber: www.habr.com