使用go语言编写简易Blockchain实现web调用RPC过程

在本机端口进行查询 由于是第一次运行该链 生成创世区块

通过http实现RPC命令的调用  实现添加块

查询当前所有块的信息  

 这里只做了两个命令 分别是get和write

源代码如下

基础功能的实现

package core

import (
	"crypto/sha256"
	"encoding/hex"
	"time"
)

//定义区块
type Block struct {
	Index         int64  //区块编号
	Timestamp     int64  //区块时间戳
	PrevBlockHash string //上一个区块的hash值
	Hash          string //当前区块哈希值

	Data string //区块数据
}

//计算Hash
func calculateHash(b *Block) string {
	blockData := string(b.Index) + string(b.Timestamp) + b.PrevBlockHash
	hashInBytes := sha256.Sum256([]byte(blockData))
	return hex.EncodeToString(hashInBytes[:])
}

//生成新的区块
func GenerateNewBlock(preBlock *Block, data string) *Block {
	newBlock := &Block{}
	newBlock.Index = preBlock.Index + 1
	newBlock.PrevBlockHash = preBlock.Hash
	newBlock.Timestamp = time.Now().Unix()
	newBlock.Hash = calculateHash(newBlock)
	newBlock.Data = data
	return newBlock
}

//生成创始区块
func GenerateGenesisBlock() *Block {
	preBlock := &Block{}
	preBlock.Index = -1
	preBlock.Hash = ""
	return GenerateNewBlock(preBlock, "Genesis Block")
}

将基础功能实现的块进行链接 实现blockchain

package core

import (
	"fmt"
	"log"
)

//定义区块链
type BlockChain struct {
	Blocks []*Block
}

//创建一个区块链
func NewBlockChain() *BlockChain {
	genesisBlock := GenerateGenesisBlock()
	blockChain := &BlockChain{}
	blockChain.AppendBlock(genesisBlock)
	return blockChain
}

//记录区块数据
func (bc *BlockChain) SendData(data string) {
	preBlock := bc.Blocks[len(bc.Blocks)-1]
	newBlock := GenerateNewBlock(preBlock, data)
	bc.AppendBlock(newBlock)
}

//往区块链添加区块
func (bc *BlockChain) AppendBlock(newBlock *Block) {
	if len(bc.Blocks) == 0 {
		bc.Blocks = append(bc.Blocks, newBlock)
		return
	}
	if isValid(newBlock, bc.Blocks[len(bc.Blocks)-1]) {
		bc.Blocks = append(bc.Blocks, newBlock)
	} else {
		log.Fatal("invalid block")
	}
	return
}

//输出区块链信息
func (bc *BlockChain) Print() {
	for _, block := range bc.Blocks {
		fmt.Printf("Index : %d\n", block.Index)
		fmt.Printf("Prev.Hash : %s\n", block.PrevBlockHash)
		fmt.Printf("Curr.Hash : %s\n", block.Hash)
		fmt.Printf("Curr.Data : %s\n", block.Data)
		fmt.Printf("Curr.Timestamp : %d\n", block.Timestamp)
		fmt.Println("==========================================")
	}
}

//验证区块
func isValid(newBlock *Block, oldBlock *Block) bool {
	if newBlock.Index-1 != oldBlock.Index {
		return false
	}
	if newBlock.PrevBlockHash != oldBlock.Hash {
		return false
	}
	if calculateHash(newBlock) != newBlock.Hash {
		return false
	}
	return true
}

实现RPC接口的交互

package main

import (
	"encoding/json"
	"BlockChain/core"
	"io"
	"net/http"
)

var blockChain *core.BlockChain

func run() {
	http.HandleFunc("/block_chain/get", blockChainGetHandle)
	http.HandleFunc("/block_chain/write", blockChainWriteHandle)
	http.ListenAndServe(":8332", nil)
}

func blockChainGetHandle(w http.ResponseWriter, r *http.Request) {
	bytes, err := json.Marshal(blockChain)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	io.WriteString(w, string(bytes))
}

func blockChainWriteHandle(w http.ResponseWriter, r *http.Request) {
	blockData := r.URL.Query().Get("data")
	blockChain.SendData(blockData)
	blockChainGetHandle(w, r)
}

func main() {
	blockChain = core.NewBlockChain()
	run()
}

通过两部分代码实现简易区块链的RPC调用

扫描二维码关注公众号,回复: 4018731 查看本文章

猜你喜欢

转载自blog.csdn.net/weixin_42654444/article/details/83932496