import (
"crypto/sha256"
"encoding/hex"
"time"
)
type Block struct {
Index int64 //编号
Timestamp int64 //时间戳
PrevBlockHash string //上一个块的哈希值
Hash string //哈希值
Data string //数值
}
func CalculateHash(b Block)string{//计算哈希值
blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash + b.Data
hashInBytes:= sha256.Sum256([]byte(blockData))
return hex.EncodeToString(hashInBytes[:]) // 删除固定大小 [:]
}
func CreateNewBlock(preBlcok Block, data string)Block{//创建一个新块(从零开始,也是最初的一个块)
newBlock := Block{}
newBlock.Index = preBlcok.Index + 1
newBlock.Timestamp = time.Now().Unix()
newBlock.PrevBlockHash = preBlcok.Hash
newBlock.Data = data
newBlock.Hash = CalculateHash(newBlock)
return newBlock
}
func GenerateBlock(data string)Block{//生成一个新的块(基于上一个块)
preBlock := Block{}
preBlock.Index = -1
preBlock.Hash = ""
return CreateNewBlock(preBlock,data)
}
func IsVaild(newBlock,oldBlock Block)bool {//校验 (新块和老块的哈希)
return newBlock.Index-1 == oldBlock.Index && newBlock.PrevBlockHash == oldBlock.Hash && CalculateHash(newBlock) == newBlock.Hash
}
///以上完成 块的创建工作.
//下面来完成链的工作
import "fmt"
type BlockChain struct {
Blocks []*Block//需要外部使用时,一定要使用大写
}
func NewBlockChain()*BlockChain{
genesisBlock := GenerateBlock("first data")
bc:=BlockChain{}
bc.ApendBlock(&genesisBlock)
return &bc
}
func (bc *BlockChain)SendData(data string){
preBlock := bc.Blocks[len(bc.Blocks)-1]
newBlock := CreateNewBlock(*preBlock,data)
bc.ApendBlock(&newBlock)
bc.RangeItem()
}
func (bc *BlockChain)RangeItem(){
for _,item:=range bc.Blocks {
fmt.Println("index:",item.Index)
fmt.Println("Timestamp:",item.Timestamp)
fmt.Println("PrevHash:",item.PrevBlockHash)
fmt.Println("CurHash:",item.Hash)
fmt.Println("Data:",item.Data)
fmt.Println()
}
}
func (bc *BlockChain)ApendBlock(newBlock *Block){//添加区块链
size := len(bc.Blocks)
if 0 == size || IsVaild(*newBlock,*bc.Blocks[size-1]){
bc.Blocks = append(bc.Blocks, newBlock)
}else{
fmt.Println("apend error!")
}
}
///咱们尝试跑跑看
import (
"net/http"
. "../block" //这是块 和 链 的包
"encoding/json"
"io"
"fmt"
)
var blockChain *core.BlockChain
func run(){
http.HandleFunc("/blockchain/get",blockchainGetHandle)
http.HandleFunc("/blockchain/write",blockchainWriteHandle)
http.ListenAndServe("localhost:8888",nil)
}
func blockchainGetHandle(w http.ResponseWriter , r *http.Request) {
blockChain.RangeItem()
bytes,err:=json.Marshal(blockChain)
if err!=nil{//输出一下错误信息
http.Error(w,err.Error(),http.StatusInternalServerError)
return
}
fmt.Println("----Get",string(bytes))
io.WriteString(w,string(bytes))
}
func blockchainWriteHandle(w http.ResponseWriter , r *http.Request) {
fmt.Println("----Write")
blockData := r.URL.Query().Get("data")
blockChain.SendData(blockData)
blockchainGetHandle(w,r)
}
func main(){
blockChain = NewBlockChain()
run()
}
浏览器输入信息 :
localhost:8888/blockchain/write?data=4444
以上的"4444"是保存至区域的数据.
读取数据:
localhost:8888/blockchain/get
这仅是一个极其简单的区块链实现.