1.區(qū)塊鏈數(shù)據(jù)結(jié)構(gòu)圖
2.簡易版區(qū)塊結(jié)構(gòu) Block
//區(qū)塊結(jié)構(gòu)
type Block struct {
//GO語言首字母大寫外部可以訪問
Hase []byte //hase值
Data []byte //交易數(shù)據(jù)
PrevBlockHash []byte //存儲(chǔ)前一個(gè)區(qū)塊的Hase值
Timestamp int64 //生成區(qū)塊的時(shí)間
}
3.區(qū)塊體的Hash值的生成方式
采用sha256對(duì)區(qū)塊體數(shù)據(jù)進(jìn)行二次加密,從而構(gòu)成區(qū)塊鏈上要得到下一個(gè)區(qū)塊的hash值媚狰,是要通過計(jì)算才能得出新的hash
Hash = sha256(Data+PrevBlockHash+Timestamp)
//生成區(qū)塊hase值
func (b *Block) SetHash() {
timestamp := []byte(strconv.FormatInt(b.Timestamp, 10))
headers := bytes.Join([][]byte{b.PrevBlockHash, b.Data, timestamp}, []byte{})
hash := sha256.Sum256(headers)
b.Hash = hash[:]
}
4.構(gòu)造一個(gè)新的區(qū)塊體函數(shù)方法
每次生成新的區(qū)塊都要計(jì)算一下hash值十性。
//生成一個(gè)新的區(qū)塊方法
func NewBlock(data string, prevBlockHash []byte) *Block{
block := &Block{Timestamp:time.Now().Unix(), Data:[]byte(data), PrevBlockHash:prevBlockHash, Hash:[]byte{}}
block.SetHash()
return block
}
5.區(qū)塊鏈Blockchian
區(qū)塊鏈?zhǔn)且环N==有序衷恭、反向鏈接鏈表==的數(shù)據(jù)結(jié)乙各,構(gòu)如圖1-1杖狼。這意味著塊按照插入順序存儲(chǔ)披蕉,并且每個(gè)塊都鏈接到前一個(gè)塊梆暖。該結(jié)構(gòu)允許快速獲取鏈中的最新塊伞访,并通過其哈希(有效)獲取塊。
在Golang中轰驳,這個(gè)結(jié)構(gòu)可以通過使用數(shù)組和地圖來實(shí)現(xiàn):數(shù)組可以保持有序散列(數(shù)組在Go中排序)厚掷,并且映射可以保持hash → block對(duì)(地圖無序)。但是對(duì)于我們的區(qū)塊鏈原型级解,我們只需要使用一個(gè)數(shù)組冒黑,因?yàn)槲覀儸F(xiàn)在不需要通過它們的哈希來獲取塊。
// 區(qū)塊鏈
type Blockchain struct {
Blocks []*Block
}
// 保存區(qū)塊數(shù)據(jù)
func (bc *Blockchain) AddBlock(data string) {
//獲取上一個(gè)區(qū)塊
prevBlock := bc.Blocks[len(bc.Blocks)-1]
//創(chuàng)建一個(gè)新的區(qū)塊
newBlock := NewBlock(data, prevBlock.Hash)
//新的區(qū)塊添加到數(shù)組中
bc.Blocks = append(bc.Blocks, newBlock)
}
6.創(chuàng)世塊
我們知道區(qū)塊鏈中必須有一個(gè)創(chuàng)世塊勤哗,也就是我們數(shù)組中的第一個(gè)元素抡爹,下面分別在block和Blockchian將定義一個(gè)創(chuàng)世塊的方法。
//創(chuàng)世塊方法
func NewGenesisBlock() *Block {
return NewBlock("Genesis Block", []byte{})
}
// 創(chuàng)建創(chuàng)世塊
func NewBlockchain() *Blockchain {
//go語言&表示獲取存儲(chǔ)的內(nèi)存地址
return &Blockchain{[]*Block{NewGenesisBlock()}}
}
7.創(chuàng)建一個(gè)main演示區(qū)塊查看區(qū)塊信息
func main() {
//創(chuàng)世塊
bc :=block.NewBlockchain()
//添加第2塊
bc.AddBlock("Send 1 BTC to even")
//添加第3塊
bc.AddBlock("Send 2 more BTC to even")
//迭代數(shù)組里面的數(shù)據(jù)
for _, block := range bc.Blocks {
fmt.Printf("Prev. hash: %x\n", block.PrevBlockHash)
fmt.Printf("Data: %s\n", block.Data)
fmt.Printf("Hash: %x\n", block.Hash)
fmt.Println()
}
}
輸出結(jié)果:
Prev. hash:
Data: Genesis Block
Hash: 865d72643b2e266ec4ec47613090cb98d1944f8bd388907dc4376332f06f4e21
Prev. hash: 865d72643b2e266ec4ec47613090cb98d1944f8bd388907dc4376332f06f4e21
Data: Send 1 BTC to even
Hash: fe7f424421604eed708a1276ae75f70521ecf355bb9a3c4400a7cc0565016d02
Prev. hash: fe7f424421604eed708a1276ae75f70521ecf355bb9a3c4400a7cc0565016d02
Data: Send 2 more BTC to even
Hash: fcd625b2c35ff8cbe24fda49a43a6c8cd2723a4275631ecc813025f6f10fbc87
Process finished with exit code 0
資料
- 原文來源:https://jeiwan.cc/posts/building-blockchain-in-go-part-1/
- java學(xué)習(xí):http://www.reibang.com/p/66c065018c7a
- 本文源碼:https://github.com/Even521/study-bitcion-go/tree/part1
- 區(qū)塊鏈基礎(chǔ)視頻學(xué)習(xí):https://www.bilibili.com/video/av19620321/
- 區(qū)塊鏈測(cè)試demo:https://anders.com/blockchain/blockchain.html
- 區(qū)塊鏈Q(jìng)Q交流群:489512556