当前位置:   article > 正文

区块链学习Day07(Pow案例实现中)

区块链学习Day07(Pow案例实现中)

Pow案例实现上回顾看

基于Web服务器的Pow案例

先装
安装依赖软件**

  • go get github.com/davecgh/go-spew/spew
  • 在控制台格式化输出结果
  • go get github.com/gorilla/mux
  • 编写Web程序的软件包
  • go get github.com/joho/godotenv
  • 用于读取GOPATH/src下的.env文件
    如果安装不了,看下面步骤:
Go 1.13 及以上(推荐)
打开你的终端并执行

$ go env -w GO111MODULE=on
$ go env -w GOPROXY=https://goproxy.cn,direct
完成。

macOS 或 Linux
打开你的终端并执行

$ export GO111MODULE=on
$ export GOPROXY=https://goproxy.cn
或者

$ echo "export GO111MODULE=on" >> ~/.profile
$ echo "export GOPROXY=https://goproxy.cn" >> ~/.profile
$ source ~/.profile
完成。

Windows
打开你的 PowerShell 并执行

C:\> $env:GO111MODULE = "on"
C:\> $env:GOPROXY = "https://goproxy.cn"

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

继续在一遍当中的代码进行修改,不懂得看上一篇

func main() {
   //测试 随便写
   //var firstBlock Block
   //firstBlock.Diff = 4
   //firstBlock.Noce = 0
   //firstBlock.PreHash = "0"
   //firstBlock.BMP = 1
   //firstBlock.Index = 0
   //firstBlock.HashCode = "0"
   //generateBlock(firstBlock, 1)

   //默认加载.env文件,内置名叫就教.env 所以新建的叫.env
   err := godotenv.Load()
   if err != nil {
   	log.Fatal(err)
   }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

结果
在这里插入图片描述
在这里插入图片描述
新增代码

package main

import (
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/davecgh/go-spew/spew"
	"github.com/gorilla/mux"
	"github.com/joho/godotenv"
	"io"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
)

// 设置难度系数,设置为4
const diffculty = 4

// 定义区块
type Block struct {
	//区块高度
	Index int
	//时间戳
	Timestamp string
	//data,保存交易信息
	BMP int
	//当前区块的哈希
	HashCode string
	//上一个区块的哈希
	PreHash string
	//前导0 个数Diff
	Diff int
	//随机值
	Noce int
}

// 用数组去维护区块链
var Blockchain []Block

// 声明个锁,以防止并发问题
var mutex = &sync.Mutex{}

// 生成区块
func generateBlock(oldBlock Block, BMP int) Block {
	//声明个新区块
	var newBlock Block
	newBlock.PreHash = oldBlock.HashCode
	newBlock.Timestamp = time.Now().String()
	//不能写死了
	newBlock.Index = oldBlock.Index + 1
	newBlock.BMP = BMP
	newBlock.Diff = diffculty
	//循环挖矿
	for i := 0; ; i++ {
		//每挖一次,给Noce加1
		newBlock.Noce++
		hash := calculateHash(newBlock)
		fmt.Println(hash)
		//判断前导0
		if isHashValid(hash, newBlock.Diff) {
			//一致
			fmt.Println("挖矿成功")
			newBlock.HashCode = hash
			//将新的区块返回
			return newBlock
		}
	}
}

// 按照规则生成一个Hash值
func calculateHash(block Block) string {
	record := strconv.Itoa(block.Index) + block.Timestamp +
		strconv.Itoa(block.Noce) + strconv.Itoa(block.BMP) + block.PreHash

	sha := sha256.New()
	sha.Write([]byte(record))
	hashed := sha.Sum(nil)
	return hex.EncodeToString(hashed)
}

// 判断哈希值的前导0个数和难度系数是否一直
func isHashValid(hash string, difficulty int) bool {
	prefix := strings.Repeat("0", difficulty)
	//判断这个哈希值是否为这个前缀
	return strings.HasSuffix(hash, prefix)
}

func main() {
	//测试 随便写
	//var firstBlock Block
	//firstBlock.Diff = 4
	//firstBlock.Noce = 0
	//firstBlock.PreHash = "0"
	//firstBlock.BMP = 1
	//firstBlock.Index = 0
	//firstBlock.HashCode = "0"
	//generateBlock(firstBlock, 1)

	//默认加载.env文件,内置名叫就教.env 所以新建的叫.env
	err := godotenv.Load()
	if err != nil {
		log.Fatal(err)
	}

	go func() {
		//创世区块
		genesisBlock := Block{}
		genesisBlock = Block{
			Index:     0,
			Timestamp: time.Now().String(),
			BMP:       0,
			HashCode:  calculateHash(genesisBlock),
			PreHash:   "",
			Diff:      diffculty,
		}
		//将区块添加到区块链
		mutex.Lock()
		Blockchain = append(Blockchain, genesisBlock)
		mutex.Unlock()
		//格式化输出到控制台
		spew.Dump(genesisBlock)
	}()
	//作为Http服务器的启动函数
	log.Fatal(run())
}

// 将run作为Http启动函数
func run() error {
	//声明一个回调函数,处理get还是Post
	mux := makeMuxRouter()

	httpAddr := os.Getenv("ADDR")
	log.Println("Listening on", os.Getenv("ADDR"))

	s := &http.Server{
		Addr:         ":" + httpAddr,
		Handler:      mux,
		ReadTimeout:  10 * time.Second,
		WriteTimeout: 10 * time.Second,
		//设置个最大相应头 1mb
		MaxHeaderBytes: 1 << 20,
	}
	//监听服务打开
	if err := s.ListenAndServe(); err != nil {
		return err
	}
	return nil
}

// 回调函数
func makeMuxRouter() http.Handler {
	muxRoter := mux.NewRouter()
	//get 读,post写的处理
	muxRoter.HandleFunc("/", handGetBlockchain).Methods("GET")
	//写的操作post
	muxRoter.HandleFunc("/", handWriteBlock).Methods("POSt")
	return muxRoter
}

// 处理http的GET请求
// 查看区块链的信息
func handGetBlockchain(w http.ResponseWriter, r *http.Request) {
	//转json
	bytes, err := json.MarshalIndent(Blockchain, "", "\t")
	if err !=nil{
		//服务器的错误
		http.Error(w,err.Error(),http.StatusInternalServerError)
		return
	}
	io.WriteString(w,string(bytes))
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/334225
推荐阅读
相关标签
  

闽ICP备14008679号