Cara saya mereka bentuk blok dan transaksi dalam blok Go saya

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).

Cara saya mereka bentuk blok dan transaksi dalam blok Go saya

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

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: github.com/Rusldv/bcstartup/blob/master/transaction/builder.go

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: github.com/Rusldv/bcstartup/blob/master/block/builder.go

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: github.com/Rusldv/bcstartup/tree/master/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

Tambah komen