Bagaimana saya merancang blok dan transaksi di blockchain Go saya

Untuk menghasilkan blockchain dan bukan hanya database, kita perlu menambahkan 3 elemen penting ke proyek kita:

  • Deskripsi struktur dan metode data blok
  • Deskripsi struktur data dan metode transaksi
  • Fungsi Blockchain yang menyimpan blok dalam database dan menemukannya di sana berdasarkan hash atau tingginya (atau yang lainnya).

Bagaimana saya merancang blok dan transaksi di blockchain Go saya

Ini adalah artikel kedua tentang blockchain untuk industri, yang pertama di sini.

Mengingat pertanyaan yang diajukan pembaca kepada saya tentang artikel sebelumnya dalam seri ini, perlu diperhatikan: dalam hal ini, database LevelDB digunakan untuk menyimpan data blockchain, tetapi tidak ada yang menghalangi Anda untuk menggunakan yang lain, katakanlah, MySQL. Sekarang mari kita lihat struktur data ini.

Mari kita mulai dengan transaksi: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

Berikut 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 tipe data (untuk transaksi 2), hash dari transaksi tersebut, tipe transaksi itu sendiri, stempel waktu, serta input dan output. Input TxIn menyimpan hash dari transaksi yang outputnya direferensikan, jumlah output dan bytecode ini, dan output TxOut menyimpan beberapa nilai dan juga bytecode.

Sekarang mari kita lihat tindakan apa yang dapat dilakukan suatu transaksi pada datanya, mis. Mari kita lihat metodenya.

Untuk membuat transaksi, gunakan fungsi transaksi.NewTransaction(txtype byte) *TX.

Metode AddTxIn(thattxhash []byte, txoutn int, code []byte) (*TxIn, error) menambahkan input ke transaksi.

Metode AddTxOut(value int, data []byte) (*TxOut, error) menambahkan output ke transaksi.

Metode ToBytes() []byte mengubah transaksi menjadi potongan byte.

String fungsi internal preByteHash(bytes []byte) digunakan di Build() dan Check() untuk membuat hash transaksi yang dihasilkan kompatibel dengan hash transaksi yang dihasilkan dari aplikasi JavaScript.

Metode Build() menyetel hash transaksi sebagai berikut: tx.TxHash = preByteHash(tx.ToBytes()).

Metode string ToJSON() mengubah transaksi menjadi string JSON.

Metode kesalahan FromJSON(data []byte) memuat transaksi dari format JSON yang diteruskan sebagai potongan byte.

Metode Check() bool membandingkan hash yang dihasilkan dari bidang hash transaksi dengan hash yang diperoleh dari hashing transaksi ini (mengabaikan bidang hash).

Transaksi ditambahkan ke blok: github.com/Rusldv/bcstartup/blob/master/block/builder.go

Struktur data blok lebih banyak:

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 tipe data, node menggunakannya dan membedakan blok dari transaksi atau data lainnya. Untuk satu blok nilainya adalah 1.

BlockHeight menyimpan ketinggian blok.
Stempel waktu stempel waktu.
HeaderSize adalah ukuran blok dalam byte.
PrevBlockHash adalah hash dari blok sebelumnya, dan SelfBlockHash adalah hash dari blok saat ini.
TxsHash adalah hash umum transaksi.
MerkleRoot adalah akar dari pohon Merkle.

Selanjutnya pada kolom tersebut terdapat kunci publik pembuat blok, tanda tangan pembuat, versi blok, jumlah transaksi dalam blok, dan transaksi itu sendiri.

Mari kita lihat metodenya:
Untuk membuat blok, gunakan fungsi block.NewBlock(): NewBlock(prevBlockHash string, height int) *Block, yang mengambil hash dari blok sebelumnya dan ketinggian yang ditetapkan untuk blok yang dibuat di blockchain. Tipe blok juga diatur dari konstanta paket tipe:

b.DataType = types.BLOCK_TYPE.

Metode AddTx(tx *transaction.TX) menambahkan transaksi ke blok.

Metode Build() memuat nilai ke dalam bidang blok dan menghasilkan serta menyetel hashnya saat ini.

Metode ToBytesHeader() []byte mengubah header blok (tanpa transaksi) menjadi potongan byte.

Metode string ToJSON() mengonversi blok ke format JSON dalam representasi string data.

Metode kesalahan FromJSON(data []byte) memuat data dari JSON ke dalam struktur blok.

Metode Check() bool menghasilkan hash blok dan membandingkannya dengan yang ditentukan dalam bidang hash blok.

Metode string GetTxsHash() mengembalikan total hash dari semua transaksi di blok.

Metode GetMerkleRoot() menentukan akar pohon Merkle untuk transaksi dalam sebuah blok.

Metode Sign(privk string) menandatangani blok dengan kunci pribadi pembuat blok.

Metode SetHeight(height int) menulis tinggi blok ke bidang struktur blok.

Metode int GetHeight() mengembalikan ketinggian blok seperti yang ditentukan dalam bidang struktur blok yang sesuai.

Metode ToGOBBytes() []byte mengkodekan blok dalam format GOB dan mengembalikannya sebagai potongan byte.

Metode kesalahan FromGOBBytes(data []byte) menulis data blok ke struktur blok dari potongan byte yang diteruskan dalam format GOB.

Metode string GetHash() mengembalikan hash dari blok yang diberikan.

Metode string GetPrevHash() mengembalikan hash dari blok sebelumnya.

Metode SetPublicKey(pubk string) menulis kunci publik pembuat blok ke blok.

Jadi, dengan menggunakan metode objek Block, kita dapat dengan mudah mengubahnya menjadi format untuk transmisi melalui jaringan dan disimpan ke database LevelDB.

Fungsi paket blockchain bertanggung jawab untuk menyimpan ke blockchain: github.com/Rusldv/bcstartup/tree/master/blockchain

Untuk melakukan ini, blok harus mengimplementasikan antarmuka IBlock:

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

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

}

Koneksi database dibuat satu kali ketika paket diinisialisasi dalam fungsi init():

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

CloseDB() adalah pembungkus untuk db.Cloce() - dipanggil setelah bekerja dengan fungsi paket untuk menutup koneksi ke database.

Fungsi kesalahan SetTargetBlockHash(hash string) menulis hash dari blok saat ini dengan kunci yang ditentukan oleh konstanta BLOCK_HASH ke database.

Fungsi GetTargetBlockHash() (string, error) mengembalikan hash dari blok saat ini yang disimpan dalam database.

Fungsi kesalahan SetTargetBlockHeight(height int) menulis ke database nilai tinggi blockchain untuk node dengan kunci yang ditentukan oleh konstanta BLOCK_HEIGHT.

Fungsi GetTargetBlockHeight() (int, error) mengembalikan ketinggian blockchain untuk node tertentu, yang disimpan dalam database.

Fungsi bool CheckBlock(block IBlock) memeriksa kebenaran blok sebelum menambahkan blok ini ke blockchain.

Fungsi kesalahan AddBlock(block IBlock) menambahkan blok ke blockchain.

Fungsi untuk mengambil dan melihat blok ada di file explore.go dari paket blockchain:

Fungsi GetBlockByHash(hash string) (*block.Block, error) membuat objek blok kosong, memuat blok ke dalamnya dari database, hash yang diteruskan ke sana, dan mengembalikan pointer ke sana.

Pembuatan blok genesis dilakukan oleh fungsi kesalahan Genesis() dari file genesis.go paket blockchain.

Artikel selanjutnya akan membahas tentang menghubungkan klien ke sebuah node menggunakan mekanisme WebSocket.

Sumber: www.habr.com

Tambah komentar