区块链的简单代码实现,基于Web服务器的Pow实例

区块(生成创世区块、生成新区块)

package block

import (
	"crypto/sha256"
	"encoding/hex"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

const Diff =3

//区块
type  Block struct {
	Index int
	PreHash string
	HashCode string
	TimeStamp int
	Diff int
	Data string
	Nonce int
}
//生成哈希值
func  GenerateHashCode(block Block)string{
	hashData:=strconv.Itoa(block.Nonce)+strconv.Itoa(block.Diff)+strconv.Itoa(block.Index)+block.PreHash
	h:=sha256.New()
	h.Write([]byte(hashData))
	restmp := h.Sum(nil)
	res := hex.EncodeToString(restmp)
	return res
}
//生成一个创世区块
func CreateFirstBlock(data string)(firstBlock Block){
	firstBlock.PreHash="0"
	firstBlock.TimeStamp=int(time.Now().Unix())
	firstBlock.Diff=Diff
	firstBlock.Data=data
	firstBlock.Index=0
	firstBlock.Nonce=123
	firstBlock.HashCode=GenerateHashCode(firstBlock)
	return
}

//共识算法pow
func Pow(block *Block)string{
	for  {
		hashCode := GenerateHashCode(*block)
		if strings.HasPrefix(hashCode,strings.Repeat("0",block.Diff)) {
			return hashCode
		}
		rand.Seed(time.Now().Unix())
		block.Nonce+=rand.Intn(100)
	}
}

//生成新区块
func CreatNewBlock(preBlock Block, data string)(newBlock Block){
	newBlock.PreHash=preBlock.HashCode
	newBlock.Data=data
	newBlock.Index=preBlock.Index+1
	newBlock.Diff=Diff
	newBlock.Nonce=123
	newBlock.TimeStamp=int(time.Now().Unix())
	hash := Pow(&newBlock)
	newBlock.HashCode=hash
	return
}

链(生成节点,添加新节点)

package chain

import (
	"blockChain/block"
)

//链表主要结构是指针域和数据域
type Node struct {
	NextNode *Node
	Data *block.Block
}

//创建第一个节点
func CreateFirstNode(block *block.Block)*Node{
	firstNode:=new(Node)
	firstNode.NextNode=nil
	firstNode.Data=block
	return firstNode
}

//判断节点中的区块是否合法
func CheckBlock(data *block.Block,preNode *Node)bool{
	if data.PreHash!=preNode.Data.HashCode {
		return false
	}
	if data.Index!=preNode.Data.Index+1 {
		return false
	}
	return true
}


//添加节点,当挖矿成功的话添加新节点
func Add(data *block.Block,preNode *Node) *Node{
	if CheckBlock(data,preNode){
		nextNode:=new(Node)
		nextNode.NextNode=nil
		nextNode.Data=data
		preNode.NextNode=nextNode
		return nextNode
	}
	return nil
}

//查看链表中的数据
func ShowNodeList(node *Node)[]block.Block{
	tmp:=node
	list:=make([]block.Block,0)
	for {
		if tmp.NextNode==nil {
			list=append(list,*tmp.Data)
			break
		}
		list=append(list,*tmp.Data)
		tmp=tmp.NextNode
	}
	return list
}

http接口

  • 基于gorilla/mux包实现的http请求(格式话返回所有的区块链信息)
  • GET请求实现查看所有的区块链信息;
  • POST请求增加新节点;
  • init生成创世区块并在后面追加节点
//导入的包
import (
	"blockChain/block"
	"blockChain/chain"
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"io/ioutil"
	"log"
	"net/http"
)
var (
	hostname string
	port int
	firstNode  *chain.Node
)
//初始化生成创世区块
func init(){
	flag.StringVar(&hostname,"hostname","127.0.0.1","service IP or hostname")
	flag.IntVar(&port,"port",8001,"service listen port")
	firstBlock := block.CreateFirstBlock("创世区块")
	firstNode = chain.CreateFirstNode(&firstBlock)
}
//flag解析,生成路由,并开启监听服务
func Run(){
	flag.Parse()
	address := fmt.Sprintf("%s:%v", hostname, port)
	log.Println("REST service on",address)
	router := mux.NewRouter().StrictSlash(true)
	router.HandleFunc("/blockChain/list",GetListHandle).Methods("GET")
	router.HandleFunc("/blockChain/add",PostAddHandle).Methods("POST")
	err := http.ListenAndServe(address, router)
	if err != nil {
		log.Println("service listen err:",err)
	}
}
//get请求handle
//reponse格式化的json链信息
func GetListHandle(writer http.ResponseWriter, request *http.Request) {
	list := chain.ShowNodeList(firstNode)
	writer.Header().Set("Content-Type","application/json")
	indent, err := json.MarshalIndent(list, "", "\t")
	if err != nil {
		writer.WriteHeader(http.StatusNotFound)
		writer.Write([]byte("not found"))
		log.Println("json.MarshalIndent",err)
		return
	}
	writer.WriteHeader(http.StatusOK)
	writer.Write(indent)
}
//post请求handle
//读取提交的data数据,基于pow得到新区块并追加到链中;设置返回数据格式
func PostAddHandle(writer http.ResponseWriter, request *http.Request) {
	bytes, err := ioutil.ReadAll(request.Body)
	if err != nil {
		log.Panic("ioutil.readall:",err)
	}
	defer request.Body.Close()
	var req map[string]interface{}
	err = json.Unmarshal(bytes, &req)
	if err != nil {
		log.Panic("json.Unmarshal failed;err:",err)
	}
	data:=req["data"].(string)
	pre:=firstNode
	for pre.NextNode!=nil{
		pre=pre.NextNode
	}
	newBlock := block.CreatNewBlock(*pre.Data, data)
	newnode := chain.Add(&newBlock, pre)
	list := chain.ShowNodeList(firstNode)
	rep:=make(map[string]interface{})
	if newnode == nil {
		rep["status"]="add failed!!!"
		log.Println("Add new node failed")
	}
	log.Println("Add new node success")
	rep["status"]="add success!!!"
	rep["result"]=list

	writer.Header().Set("content-Type","application/json")
	indent, err:= json.MarshalIndent(rep, "", "\t")
	if err != nil {
		writer.WriteHeader(http.StatusNotFound)
		writer.Write([]byte("not found!!!"))
	}
	writer.WriteHeader(http.StatusOK)
	writer.Write(indent)
}

func main(){
	service.Run()
}
//服务端
D:\www\Blockchain_go\pow>go run main.go
2020/07/05 22:41:53 REST service on 127.0.0.1:8001
2020/07/05 22:42:20 Add new node success
2020/07/05 22:43:00 Add new node success
//客户端
D:\www\Blockchain_go\pow>curl -X GET http://localhost:8001/blockChain/list
[
        {
                "Index": 0,
                "PreHash": "0",
                "HashCode": "38fc3af258669791206922284800c53a0eab92b0d602253e447a71b802f5c77f",
                "TimeStamp": 1593960113,
                "Diff": 3,
                "Data": "创世区块",
                "Nonce": 123
        },
        {
                "Index": 1,
                "PreHash": "38fc3af258669791206922284800c53a0eab92b0d602253e447a71b802f5c77f",
                "HashCode": "0001bed84d1c2c3a2913f067865824effe66d20152eff783af17b532b2fe577d",
                "TimeStamp": 1593960140,
                "Diff": 3,
                "Data": "second node",
                "Nonce": 132996
        },
        {
                "Index": 2,
                "PreHash": "0001bed84d1c2c3a2913f067865824effe66d20152eff783af17b532b2fe577d",
                "HashCode": "0001f89dc9b82c524c0e3e0c36fd56749c97ddc7fb2b1c2d3bb5baeca1142698",
                "TimeStamp": 1593960180,
                "Diff": 3,
                "Data": "third node",
                "Nonce": 105283
        }
]
D:\www\Blockchain_go\pow>curl -X POST -d  "{\"data\":\"third node\"}"   http://localhost:8001/blockChain/add
{
        "result": [
                {
                        "Index": 0,
                        "PreHash": "0",
                        "HashCode": "38fc3af258669791206922284800c53a0eab92b0d602253e447a71b802f5c77f",
                        "TimeStamp": 1593960113,
                        "Diff": 3,
                        "Data": "创世区块",
                        "Nonce": 123
                },
                {
                        "Index": 1,
                        "PreHash": "38fc3af258669791206922284800c53a0eab92b0d602253e447a71b802f5c77f",
                        "HashCode": "0001bed84d1c2c3a2913f067865824effe66d20152eff783af17b532b2fe577d",
                        "TimeStamp": 1593960140,
                        "Diff": 3,
                        "Data": "second node",
                        "Nonce": 132996
                },
                {
                        "Index": 2,
                        "PreHash": "0001bed84d1c2c3a2913f067865824effe66d20152eff783af17b532b2fe577d",
                        "HashCode": "0001f89dc9b82c524c0e3e0c36fd56749c97ddc7fb2b1c2d3bb5baeca1142698",
                        "TimeStamp": 1593960180,
                        "Diff": 3,
                        "Data": "third node",
                        "Nonce": 105283
                }
        ],
        "status": "add success!!!"
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值