准备工作:
-
安装go开发环境
-
用go搭建web服务
-
go语言基础
安装go开发环境
到https://golang.org/dl/这个地址下载对应的安装包,mac ,windows,linux都有(需要科学上网)。以mac为例,下载成功后双击安装下一步即可,很简单。安装成功后运行go version查看版本(如果没有的话,就重启一下终端)
用go搭建web服务
在这里咱们用的是Gorilla/mux包。步骤:
-
创建NewRouter
-
设置端口号
-
设置http的参数字典
-
调用ListenAndServe方法,启动服务
go语言基础
-
导包:多个包用小括号括起来
-
import (
"sync"
"time"
)
-
使用点调用方法:
-
time.Now()
-
声明变量:
-
var coin int 用空格隔开,类型写到后面,变量名写中间,最后是个var
-
coin := 10 也可以省略var,用:=来赋值,但是必须保证coin没有声明过,否则会报错
-
coin1,coin2 := 10,20 。 多变量声明是这样的
-
条件控制:
-
if a<b {
return 10
}else{
return 20
}
-
循环控制:
-
for a := 0; a < 10; a++ {
fmt.Printf("a: %d ", a)
}
-
函数定义,传参:
-
/* 函数返回两个数的最大值 */
-
func max(num1, num2 int) int {
}
-
num1, num2 int表示两个整形参数,是可选的,也可以不填,
-
最后的int是返回值的类型
-
调用函数通过这样方式:n := max(a, b)
-
结构体定义,赋值,调用:
-
定义:type Article struct { title string id int}
-
赋值:var a1 Article
a1.title = "写代码"
-
调用:fmt.Printf( "title : %s ", a1.title)
了解这些,今天的代码就能看懂了,当然go语言还有很多要学习的知识点,可以到这里来http://www.runoob.com/go/go-tutorial.html学习
整理思路:
根据之前了解的区块链原理和共识算法,我们整理一下需要实现哪些方法:
-
一个区块需要包含哪些信息:
-
Index :这个区块在整个链中的索引
-
Timestamp : 区块生成时的时间戳
-
Hash : 区块通过 SHA256 算法生成的哈希值
-
PrevHash : 前一个区块的 SHA256 哈希值
-
content : 需要记录的内容
-
计算哈希值的函数
-
生成新区块的函数
-
根据不可篡改性,我们还需要一个验证区块是否被篡改的函数
-
启动web服务的函数
创建区块结构体:
type Block struct {
Index int
Timestamp string
Content string
Hash string
PrevHash string
}
计算哈希值:(把区块结构体中的信息都拼在一起,然后Hash算出来)
func calculateHash(block Block) string {
record := strconv.Itoa(block.Index) + block.Timestamp + strconv.Itoa(block.Content) + block.PrevHash
h := sha256.New()
h.Write([]byte(record))
hashed := h.Sum(nil)
return hex.EncodeToString(hashed)
}
生成新区块:(上一个区块的索引加1,上一个区块的Hash赋值给当前区块的PrevHash,当前区块的Hash由calculateHash函数生成)
func generateBlock(oldBlock Block, Content string) Block {
var newBlock Block
t := time.Now()
newBlock.Index = oldBlock.Index + 1
newBlock.Timestamp = t.String()
newBlock.Content = Content
newBlock.PrevHash = oldBlock.Hash
newBlock.Hash = calculateHash(newBlock)
return newBlock
}
验证区块:(根据索引和Hash值判断,老索引加1应该等于新索引,新的PrevHash应该等于老的Hash,最后还要重新计算一个新区块的Hash,看是否和传过来的一样)
func isBlockValid(newBlock, oldBlock Block) bool {
if oldBlock.Index+1 != newBlock.Index {
return false
}
if oldBlock.Hash != newBlock.PrevHash {
return false
}
if calculateHash(newBlock) != newBlock.Hash {
return false
}
return true
}
启动web服务:
//设置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
}
//生成NewRouter对象
func makeMuxRouter() http.Handler {
muxRouter := mux.NewRouter()
muxRouter.HandleFunc("/", handleGetBlockchain).Methods("GET")
muxRouter.HandleFunc("/", handleWriteBlock).Methods("POST")
return muxRouter
}
好的,需要的函数都已经列好,下面把它们组装起来即可,然后放到一个main.go的文件中,启动终端,进入到main.go文件夹并输入go run main.go命令。
打开http://localhost:8080/地址,会看到一个创世区块,如果想添加一个新区块则需要使用postman 传一个content参数过去,如图:
然后再刷新浏览器,会返回新的区块信息,如图:
好的,先到这里,下一次我们把共识算法加进去。
总结:
今天实现了生成新区块、哈希计算、区块校验这些基本功能。代码在:https://github.com/sunqichao/createblockchain