golang 简单的区块链


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

 

这仅是一个极其简单的区块链实现.

如有疑问,请在评论区留言。

展开阅读全文

没有更多推荐了,返回首页