Go语言通关指南:零基础玩转高并发编程(第Ⅴ部分)(第15章)-现代Go编程-项目实战开发(案例9:区块链简易实现)
文章目录
-
- Go语言通关指南:零基础玩转高并发编程(第Ⅴ部分)(第15章)-现代Go编程-项目实战开发(案例9:区块链简易实现)
-
- 案例9:区块链简易实现
-
- 1. 功能点与技术点简介
- 2. 完整代码实现
-
- 2.1. 工程结构
- 2.2. 源码文件说明与完整代码
-
- 2.2.1. `main.go`
- 2.2.2. `config/network.go`
- 2.2.3. `config/blockchain.go`
- 2.2.4. `handlers/blockchain.go`
- 2.2.5. `handlers/transaction.go`
- 2.2.6. `handlers/node.go`
- 2.2.7. `services/blockchain.go`
- 2.2.8. `services/transaction.go`
- 2.2.9. `services/p2p.go`
- 2.2.10. `models/block.go`
- 2.2.11. `models/transaction.go`
- 2.2.12. `models/wallet.go`
- 2.2.13. `middleware/auth.go`
- 2.2.14. `middleware/rate_limiter.go`
- 2.2.15. `utils/crypto.go`
- 2.2.16. `utils/db.go`
- 2.2.17. `utils/network.go`
- 2.2.18. `docker-compose.yml`
- 生产级实践总结
案例9:区块链简易实现
1. 功能点与技术点简介
1.1. 功能点
- 区块生成:实现区块数据结构与链式存储
- 共识机制:简单的工作量证明(PoW)算法
- 交易验证:验证交易签名与余额
- P2P网络:节点间通信与数据同步
- API接口:提供区块链查询与交易提交接口
1.2. 技术点
- 使用Go实现区块链核心逻辑
- 使用椭圆曲线加密(ECDSA)实现交易签名
- 使用WebSocket实现P2P网络通信
- 使用LevelDB存储区块链数据
- 使用Gin框架提供HTTP API
2. 完整代码实现
2.1. 工程结构
blockchain/
├── main.go # 程序入口
├── config/ # 配置模块
│ ├── network.go # 网络配置
│ └── blockchain.go # 区块链配置
├── handlers/ # HTTP处理器
│ ├── blockchain.go # 区块链查询接口
│ ├── transaction.go # 交易提交接口
│ └── node.go # 节点管理接口
├── services/ # 核心服务
│ ├── blockchain.go # 区块链服务
│ ├── transaction.go # 交易服务
│ └── p2p.go # P2P网络服务
├── models/ # 数据模型
│ ├── block.go # 区块模型
│ ├── transaction.go # 交易模型
│ └── wallet.go # 钱包模型
├── middleware/ # 中间件
│ ├── auth.go # 鉴权中间件
│ └── rate_limiter.go # 限流中间件
├── utils/ # 工具类
│ ├── crypto.go # 加密工具
│ ├── db.go # 数据库工具
│ └── network.go # 网络工具
├── docker-compose.yml # 容器化部署配置
└── README.md # 项目说明
2.2. 源码文件说明与完整代码
2.2.1. main.go
- 作用:程序入口,启动HTTP服务和P2P网络
package main
import (
"log"
"blockchain/config"
"blockchain/handlers"
"blockchain/services"
"github.com/gin-gonic/gin"
)
func main() {
// 初始化配置
config.InitBlockchain()
config.InitNetwork()
// 启动P2P网络
go services.StartP2PNetwork()
// 创建Gin引擎
r := gin.Default()
// 注册路由
r.GET("/blockchain", handlers.GetBlockchain)
r.POST("/transaction", handlers.SubmitTransaction)
r.GET("/nodes", handlers.ListNodes)
// 启动HTTP服务
log.Println("Blockchain service running on :8080")
if err := r.Run(":8080"); err != nil {
log.Fatalf("Service startup failed: %v", err)
}
}
2.2.2. config/network.go
- 作用:配置P2P网络参数
package config
var (
P2PPort = 5000 // P2P网络端口
BootstrapNode = "127.0.0.1:5000" // 初始节点地址
MaxPeers = 10 // 最大连接节点数
)
// InitNetwork 初始化网络配置
func InitNetwork() {
// 配置网络参数
}
2.2.3. config/blockchain.go
- 作用:配置区块链参数
package config
var (
Difficulty = 4 // 工作量证明难度
BlockReward = 50 // 区块奖励
GenesisBlockHash = "00000000000000000000000000000000" // 创世区块哈希
)
// InitBlockchain 初始化区块链配置
func InitBlockchain() {
// 配置区块链参数
}
2.2.4. handlers/blockchain.go
- 作用:提供区块链查询接口
package handlers
import (
"blockchain/services"
"github.com/gin-gonic/gin"
"net/http"
)
// GetBlockchain 获取区块链数据
func GetBlockchain(c *gin.Context) {
chain, err := services.GetBlockchain()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "获取区块链失败"})
return
}
c.JSON(http.StatusOK, chain)
}
2.2.5. handlers/transaction.go
- 作用:处理交易提交请求
package handlers
import (
"blockchain/models"
"blockchain/services"
"github.com/gin-gonic/gin"
"net/http"
)
// SubmitTransaction 提交交易
func SubmitTransaction(c *gin.Context) {
var tx models.Transaction
if err := c.BindJSON(&tx); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "无效交易"})
return
}
if err := services.ValidateTransaction(&tx); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": "交易验证失败"})
return
}
if err := services.AddTransaction(&tx); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"error": "交易提交失败"})
return
}
c.JSON(http.StatusOK, gin.H{
"message": "交易已提交"})
}
2.2.6. handlers/node.go
- 作用:管理P2P网络节点
package handlers
import (
"blockchain/services"
"github.com/gin-gonic/gin"
"net/http"
)
// ListNodes 获取当前连接的节点列表
func ListNodes(c *gin.Context) {
nodes := services.GetNodes()
c.JSON(http.StatusOK, nodes)
}
2.2.7. services/blockchain.go
- 作用:实现区块链核心逻辑
package services
import (
"blockchain/config"
"blockchain/models"
"blockchain/utils"
"time"
)
var Blockchain []models.Block
// CreateBlock 创建新区块
func CreateBlock(transactions []models.Transaction) (*models.Block, error) {
prevBlock := Blockchain[len(Blockchain)-1]
block := models.Block{
Index: prevBlock.Index + 1,
Timestamp: time.Now().Unix(),
Transactions: transactions,
PrevHash: prevBlock.Hash,
}
// 工作量证明
nonce := 0
for !utils.IsValidHash(block.Hash(), config.Difficulty) {
nonce++
block.Nonce = nonce
}
Blockchain = append(Blockchain, block)
return &block, nil
}
// GetBlockchain 获取当前区块链
func GetBlockchain() ([]models.Block, error) {
return Blockchain, nil
}
2.2.8. services/transaction.go
- 作用:实现交易验证与提交逻辑
package services
import (
"blockchain/models"
"blockchain/utils"
"fmt"
)
// ValidateTransaction 验证交易合法性
func ValidateTransaction(tx *models.Transaction) error {
// 验证签名
if !utils.VerifySignature(tx.Sender, tx.Signature, tx.Hash()) {
return fmt.Errorf("签名验证失败")
}
// 验证余额
balance := GetBalance(tx.Sender)
if balance < tx.Amount {
return fmt.Errorf("余额不足")
}
return nil
}
// AddTransaction 添加交易到待处理池
func AddTransaction(tx *models.Transaction) error {
// 将交易添加到待处理交易池
// 实现略...
return nil
}
2.2.9. services/p2p.go
- 作用:实现P2P网络通信
package services
import (
"blockchain/config"
"blockchain/utils"
"golang.org/x/net/websocket"
)
var connections []*websocket.Conn
// StartP2PNetwork 启动P2P网络
func StartP2PNetwork() {
// 连接到初始节点
conn, err := utils.ConnectToNode(config.BootstrapNode)
if err != nil {
log.Println("无法连接到初始节点:", err)
return
}
connections = append(connections, conn)
// 监听P2P端口
// 实现略...
}
// GetNodes 获取当前连接的节点
func GetNodes() []string {
var nodes []string
for _, conn := range connections {
nodes = append(nodes, conn.RemoteAddr().String())
}
return nodes
}
2.2.10. models/block.go
- 作用:定义区块数据结构
package models
import (
"time"
)
// Block 定义区块结构
type Block struct {
Index int64 `json:"index"` // 区块高度
Timestamp int64 `json:"timestamp"` // 时间戳
Transactions []Transaction `json:"transactions"` // 交易列表
PrevHash string `json:"prev_hash"` // 前一个区块哈希
Nonce int64 `json:"nonce"` // 工作量证明随机数
Hash string `json:"hash"` // 当前区块哈希
}
2.2.11. models/transaction.go
- 作用:定义交易数据结构
package models
// Transaction 定义交易结构
type Transaction struct {
Sender string `json:"sender"` // 发送方地址
Recipient string `json:"recipient"` // 接收方地址
Amount float64 `json:"amount"` // 交易金额
Signature string `json:"signature"` // 交易签名
}
2.2.12. models/wallet.go
- 作用:定义钱包数据结构
package models
// Wallet 定义钱包结构
type Wallet struct {
Address string `json:"address"` // 钱包地址
PrivateKey string `json:"private_key"` // 私钥
Balance float64 `json:"balance"` // 余额
}
2.2.13. middleware/auth.go
- 作用:JWT鉴权中间件,验证请求合法性
package middleware
import (
"blockchain/utils"
"github.com/gin-gonic/gin"
"strings"
)
// Auth 鉴权中间件
func Auth() gin.HandlerFunc {
return func(c *gin.Context) {
token := strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer ")
if token == "" {
c.AbortWithStatusJSON(401, gin.H{
"error": "未提供访问令牌"})
return
}
claims, err := utils.ParseJWT(token)
if err != nil {
c.AbortWithStatusJSON(403, gin.H{
"error": "无效令牌"})
return
}
c.Set("userID", claims.UserID)
c.Set("roles", claims.Roles)
c.Next()
}
}
2.2.14. middleware/rate_limiter.go
- 作用:动态限流中间件,区分用户和IP
package middleware
import (
"blockchain/services"
"github.com/gin-gonic/gin"
)
// RateLimiter 限流中间件
func RateLimiter() gin.HandlerFunc {
return func(c *gin.Context) {
var key string
if userID, exists := c.Get("userID"); exists {
key = "user:" + string(userID.(uint))
} else {
key = "ip:" + c.ClientIP()
}
if !services.AllowRequest(c.Request.Context(), key, 100, time.Minute) {
c.AbortWithStatusJSON(429, gin.H{
"error": "请求过于频繁"})
return
}
c.Next()
}
}
2.2.15. utils/crypto.go
- 作用:实现加密与签名功能
package utils
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"math/big"
)
// GenerateKeyPair 生成密钥对
func GenerateKeyPair() (*ecdsa.PrivateKey, string) {
privateKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
address := hex.EncodeToString(privateKey.PublicKey.X.Bytes())
return privateKey, address
}
// SignTransaction 对交易进行签名
func SignTransaction(privateKey *ecdsa.PrivateKey, txHash string) string {
r, s, _ := ecdsa.Sign(rand.Reader, privateKey, []byte(txHash))
return hex.EncodeToString(r.Bytes()) + hex.EncodeToString(s.Bytes())
}
// VerifySignature 验证交易签名
func VerifySignature(address, signature, txHash string) bool {
x, y := new(big.Int), new(big.Int)
x.SetString(address[:64], 16)
y.SetString(address[64:], 16)
publicKey := ecdsa.PublicKey{
Curve: elliptic.P256(), X: x, Y: y}
r, s := new(big.Int), new(big.Int)
r.SetString(signature[:64], 16)
s.SetString(signature[64:], 16)
return ecdsa.Verify(&publicKey, []byte(txHash), r, s)
}
2.2.16. utils/db.go
- 作用:封装LevelDB操作工具函数
package utils
import (
"github.com/syndtr/goleveldb/leveldb"
)
var DB *leveldb.DB
// InitDB 初始化LevelDB
func InitDB() error {
db, err := leveldb.OpenFile("blockchain.db", nil)
if err != nil {
return err
}
DB = db
return nil
}
// SaveBlock 保存区块到数据库
func SaveBlock(block *models.Block) error {
key := []byte(block.Hash)
value, _ := json.Marshal(block)
return DB.Put(key, value, nil)
}
// GetBlock 从数据库获取区块
func GetBlock(hash string) (*models.Block, error) {
value, err := DB.Get([]byte(hash), nil)
if err != nil {
return nil, err
}
var block models.Block
json.Unmarshal(value, &block)
return &block, nil
}
2.2.17. utils/network.go
- 作用:封装P2P网络工具函数
package utils
import (
"blockchain/config"
"golang.org/x/net/websocket"
)
// ConnectToNode 连接到指定节点
func ConnectToNode(address string) (*websocket.Conn, error) {
conn, err := websocket.Dial("ws://"+address, "", "http://"+config.P2PPort)
if err != nil {
return nil, err
}
return conn, nil
}
// BroadcastMessage 广播消息到所有节点
func BroadcastMessage(message []byte) {
for _, conn := range connections {
conn.Write(message)
}
}
2.2.18. docker-compose.yml
- 作用:容器化部署全链路服务
version: '3.8'
services:
blockchain:
build: .
ports:
- "8080:8080"
volumes:
- blockchain_data:/app/data
environment:
- P2P_PORT=5000
- BOOTSTRAP_NODE=127.0.0.1:5000
volumes:
blockchain_data:
生产级实践总结
-
高可用架构:
- P2P网络支持多节点连接与数据同步
- LevelDB持久化存储区块链数据
-
安全机制:
- ECDSA签名保障交易不可篡改
// 交易签名示例 signature := utils.SignTransaction(privateKey, tx.Hash())
- 工作量证明防止区块篡改
-
性能优化:
- 并行计算工作量证明
- LevelDB批量写入区块数据
-
可扩展性:
- 支持动态添加节点
- 可扩展共识机制(如PoS、DPoS)
-
监控与告警:
- Prometheus监控节点状态
- Grafana展示区块链数据