區(qū)塊
一個(gè)包含最關(guān)鍵信息的簡化版本的區(qū)塊,其數(shù)據(jù)結(jié)構(gòu)在go語言定義如下:
type Block struct {
Timestamp int64
Data []byte
PrevBlockHash []byte
Hash []byte
}
我們先不管復(fù)雜的區(qū)塊頭是如何定義的,Hash字段是如何計(jì)算的呢?
Hash = SHA256(PrevBlockHash + Timestamp + Data)
區(qū)塊鏈
區(qū)塊鏈就是將區(qū)塊有序鏈起來,然后通過區(qū)塊的hash能快速檢索到一個(gè)塊辐怕。
為了實(shí)現(xiàn)鏈起區(qū)塊和檢索區(qū)塊的功能,在go語言里从绘,用一個(gè)array和map的數(shù)據(jù)結(jié)構(gòu)就能解決問題寄疏。
type Blockchain struct {
blocks []*Block
}
簡單的版本一初現(xiàn)雛形
區(qū)塊鏈原型:一個(gè)數(shù)組存了一些有序的區(qū)塊,每一個(gè)區(qū)塊都跟前一個(gè)區(qū)塊相關(guān)聯(lián)僵井,這里加入新的區(qū)塊是很容易的赁还,但真實(shí)的區(qū)塊鏈要復(fù)雜多,
需要工作量證明(PoW)驹沿,當(dāng)然本質(zhì)上是一個(gè)共識(shí)機(jī)制,就是一個(gè)節(jié)點(diǎn)添加區(qū)塊蹈胡,需要獲得其他節(jié)點(diǎn)的認(rèn)同渊季,從而形成的一個(gè)共識(shí)(consensus)朋蔫。
main.go
package main
import (
"time"
"strconv"
"bytes"
"crypto/sha256"
"fmt"
)
type Block struct {
Timestamp int64
PrevBlockHash []byte
Hash []byte
Data []byte
}
type BlockChain struct {
blocks []*Block
}
func NewBlock(data string,prevBlockHash []byte) *Block{
block := &Block{
Timestamp:time.Now().Unix(),
PrevBlockHash:prevBlockHash,
Hash:[]byte{},
Data:[]byte(data)}
block.SetHash()
return block
}
// Hash = sha256(PrevBlockHash + Data + Timestamp)
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[:]
}
func NewGenesisBlock() *Block{
return NewBlock("Genesis Block",[]byte{})
}
// 創(chuàng)建一個(gè)有創(chuàng)世塊的鏈
func NewBlockChain() *BlockChain{
return &BlockChain{[]*Block{NewGenesisBlock()}}
}
func (blockchain *BlockChain) AddBlock(data string){
prevBlock := blockchain.blocks[len(blockchain.blocks)-1]
newBlock := NewBlock(data,prevBlock.Hash)
blockchain.blocks = append(blockchain.blocks,newBlock)
}
func main() {
blockchain := NewBlockChain()
blockchain.AddBlock("Send 1 BTC to Silver")
blockchain.AddBlock("send 2 BTC to Silver again")
for _,block := range blockchain.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()
}
}