当前位置:   article > 正文

用go实现简单的区块链

用go实现简单的区块链

1.项目文件创建

  • 首先创建demochain目录,在该目录下创建两个目录,分别是blc目录,和server目录
  • 在blc中创建两个文件,分别是Block.go和Blockchain.go
  • 在server中创建一个Server.go

2.代码阶段

  • Block.go中的代码如下:
  1. package blc
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "time"
  6. )
  7. //定义一个区块的结构体
  8. type Block struct{
  9. Index int64 //区块编号
  10. Timestamp int64 //区块时间戳
  11. PrevBlockHash string//上一个区块的哈希值
  12. Hash string //当前区块哈希值
  13. Data string //区块数据
  14. }
  15. //计算区块hash值
  16. func calculateHash(b Block) string {
  17. blockData := string(b.Index) + string(b.Timestamp) +b.PrevBlockHash +b.Data
  18. hashInBytes := sha256.Sum256([]byte(blockData))
  19. return hex.EncodeToString(hashInBytes[:])
  20. }
  21. //生产一个新区块
  22. func generateNewBlock(preBlock Block,data string) Block{
  23. newBlock :=Block{}
  24. newBlock.Index = preBlock.Index +1
  25. newBlock.PrevBlockHash =preBlock.Hash
  26. newBlock.Timestamp = time.Now().Unix()
  27. newBlock.Data =data
  28. newBlock.Hash = calculateHash(newBlock)
  29. return newBlock
  30. }
  31. //生产创世区块
  32. func generateGenesisBlock() Block {
  33. generBlock := Block{}
  34. generBlock.Index = 0
  35. generBlock.Hash = "0x0000000000000000000000000000000000000000000000000000000000000000"
  36. return generateNewBlock(generBlock,"Genesis Block")
  37. }
  • Blockchain.go中的代码如下:
  1. package blc
  2. import (
  3. "log"
  4. )
  5. //定义一个区块链的结构体
  6. type Blockchain struct {
  7. Blocks []*Block
  8. }
  9. //创建一个新的区块链
  10. func NewBlockchain() *Blockchain {
  11. genesisBlcok := generateGenesisBlock()
  12. blockchain := Blockchain{}
  13. blockchain.AppendBlock(&genesisBlcok)
  14. return &blockchain
  15. }
  16. //发送数据也会产生新的区块
  17. func (bc *Blockchain) SendData(data string) {
  18. preBlock := bc.Blocks[len(bc.Blocks)-1]
  19. newBlock := generateNewBlock(*preBlock,data)
  20. bc.AppendBlock(&newBlock)
  21. }
  22. //把新增的区块添加到区块链中
  23. func (bc *Blockchain) AppendBlock(newBlock *Block) {
  24. if len(bc.Blocks)==0{
  25. bc.Blocks = append(bc.Blocks,newBlock)
  26. return
  27. }
  28. if isValid(*newBlock,*bc.Blocks[len(bc.Blocks)-1]) {
  29. bc.Blocks = append(bc.Blocks,newBlock)
  30. }else {
  31. log.Fatal("invalid block")
  32. }
  33. }
  34. //判断新区块的有效性
  35. func isValid(newBlock Block,oldBlock Block) bool {
  36. if newBlock.Index -1 !=oldBlock.Index{
  37. return false
  38. }
  39. if newBlock.PrevBlockHash !=oldBlock.Hash{
  40. return false
  41. }
  42. if calculateHash(newBlock) !=newBlock.Hash{
  43. return false
  44. }
  45. return true
  46. }
  • Server.go中的代码如下:
  1. package main
  2. import (
  3. "demochain/blc"
  4. "encoding/json"
  5. "io"
  6. "net/http"
  7. )
  8. var blockchain *blc.Blockchain
  9. func run(){
  10. //获取链上的数据
  11. http.HandleFunc("/blockchain/get", blockchainGetHandler)
  12. //写数据到链上
  13. http.HandleFunc("/blockchain/write", blockchainWriteHandler)
  14. //启动对端口的监听
  15. http.ListenAndServe("localhost:8080", nil)
  16. }
  17. //获取链上的数据
  18. func blockchainGetHandler(w http.ResponseWriter, r *http.Request){
  19. //转化为json数据格式
  20. bytes, error := json.Marshal(blockchain)
  21. //如果error不为空
  22. if error != nil {
  23. http.Error(w, error.Error(), http.StatusInternalServerError)
  24. return
  25. }
  26. io.WriteString(w, string(bytes))
  27. }
  28. //往区块链上写数据
  29. func blockchainWriteHandler(w http.ResponseWriter, r *http.Request){
  30. blockData := r.URL.Query().Get("data")
  31. //发送数据
  32. blockchain.SendData(blockData)
  33. //把最新的区块链数据会显给调用者
  34. blockchainGetHandler(w, r)
  35. }
  36. func main() {
  37. blockchain = blc.NewBlockchain()
  38. run()
  39. }

3.测试阶段

编译运行Server.go启动服务

启动之后访问: http://localhost:8080/blockchain/get会看到一个创世区块的结构
添加数据到区块链: http://localhost:8080/blockchain/write?data=send 1 eth to Alice,会产生一个新的区块

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/931503
推荐阅读
相关标签
  

闽ICP备14008679号