package main
import (
"sync"
"time"
//"hash"
"strings"
"strconv"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"github.com/gorilla/mux"
"encoding/json"
"io"
"github.com/davecgh/go-spew/spew"
"os"
"log"
"github.com/joho/godotenv"
)
//设置难度系数
const difficulty =4
//定义区块
type Block struct {
Index int
Timestamp string
BMP int
Hash string
PreHash string
Difficulty int
Nonce int
}
//通过数组,维护区块链
var Blockchain []Block
//Message为通过POST实现数据求发送的数据类型
type Message struct {
BPM int
}
//控制线程异步访问
var mutex = &sync.Mutex{}
//生成区块
func generateBlock(oldBlock Block,BMP int)Block{
var newBlock Block
t:=time.Now()
newBlock.Index= oldBlock.Index +1
newBlock.Timestamp=t.String()
newBlock.BMP = BMP
newBlock.Difficulty = difficulty
for i:=0;;i++ {
newBlock.Nonce++
//打印哈希
fmt.Println(calculateHash(newBlock))
if isHashValid(calculateHash(newBlock),newBlock.Difficulty){
fmt.Println("挖矿成功")
return newBlock
}
}
}
//创建isHashValid ,判断哈希的0个的数是否与难度系数一直
func isHashValid(hash string ,difficulty int) bool {
prefix:=strings.Repeat("0",difficulty)
return strings.HasPrefix(hash,prefix)
}
//按照规则,生成Hash值
func calculateHash(block Block) string {
record:= strconv.Itoa(block.Index)+block.Timestamp+strconv.Itoa(block.Nonce)+
strconv.Itoa(block.BMP)+block.PreHash
sha:=sha256.New()
sha.Write([]byte(record))
hashed:=sha.Sum(nil)
return hex.EncodeToString(hashed)
}
//通过run函数作为http服务器的启动函数
func run() error {
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,
MaxHeaderBytes: 1 << 20,
}
if err := s.ListenAndServe(); err != nil {
return err
}
return nil
}
//get,post 请求处理
func makeMuxRouter() http.Handler {
//负责get,post的请求处理的
muxRouter:=mux.NewRouter()
//handGetClockchain 回调函数
muxRouter.HandleFunc("/",handGetClockchain).Methods("GET")
//handWriteBlock 也是回调函数
muxRouter.HandleFunc("/",handWriteBlock).Methods("POST")
return muxRouter
}
//处理http的GET请求
func handGetClockchain(w http.ResponseWriter, r *http.Request) {
bytes, err := json.MarshalIndent(Blockchain, "", " ")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
io.WriteString(w, string(bytes))
}
//处理Http的POST请求
func handWriteBlock(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var m Message
//当服务器错误,返回相应信息500
decoder := json.NewDecoder(r.Body)
if err := decoder.Decode(&m); err != nil {
respondWithJSON(w, r, http.StatusBadRequest, r.Body)
return
}
defer r.Body.Close()
//ensure atomicity when creating new block
//产生区块
mutex.Lock()
newBlock := generateBlock(Blockchain[len(Blockchain)-1], m.BPM)
mutex.Unlock()
//判断区块的合法性
if isBlockValid(newBlock, Blockchain[len(Blockchain)-1]) {
//通过数组维护区块链
Blockchain = append(Blockchain, newBlock)
spew.Dump(Blockchain)
}
respondWithJSON(w, r, http.StatusCreated, newBlock)
}
//如果错误,返回服务器500错误
func respondWithJSON(w http.ResponseWriter, r *http.Request, code int, payload interface{}) {
w.Header().Set("Content-Type", "application/json")
response, err := json.MarshalIndent(payload, "", " ")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("HTTP 500: Internal Server Error"))
return
}
w.WriteHeader(code)
w.Write(response)
}
//判断产生hash的合法性
func isBlockValid(newBlock, oldBlock Block) bool {
if oldBlock.Index+1 != newBlock.Index {
return false
}
if oldBlock.Hash != newBlock.PreHash {
return false
}
if calculateHash(newBlock) != newBlock.Hash {
return false
}
return true
}
func main() {
//var firstBlock Block
//firstBlock.Difficulty = 4
//firstBlock.Nonce = 0
//firstBlock.PreHash = "0"
//firstBlock.BMP = 1
//firstBlock.Index = 0
//firstBlock.Hash = "0"
//
//generateBlock(firstBlock,1)
//加载.env文件
err := godotenv.Load()
if err != nil {
log.Fatal(err)
}
go func() {
t := time.Now()
genesisBlock := Block{}
genesisBlock = Block{0, t.String(), 0, calculateHash(genesisBlock), "", difficulty, 0}
spew.Dump(genesisBlock)
mutex.Lock()
Blockchain = append(Blockchain, genesisBlock)
mutex.Unlock()
}()
log.Fatal(run())
}
2018-05-21服务器pow共识算法
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...