购物网站的策划,wordpress分类目录模板,广州行业网站建设,东莞网站设计定制开发本文主要利用 Go 语言对区块链模型进行了简单的实现#xff0c;通过 GoLand 创建链式结构和一个简单的 http server#xff0c;对外暴露读写接口#xff0c;运行 rpc 并以地址访问形式向区块链发送数据和读取数据。 简单区块链的实现大致步骤分为#xff1a;
#xff08;… 本文主要利用 Go 语言对区块链模型进行了简单的实现通过 GoLand 创建链式结构和一个简单的 http server对外暴露读写接口运行 rpc 并以地址访问形式向区块链发送数据和读取数据。 简单区块链的实现大致步骤分为
1创建 Block 2创建 Blockchain 3创建 Http server
在实现之前首先通过 GoLand 创建 blockchainDemo 项目并建立对应的 Block.go、Blockchain.go 以及 Server.go 文件具体的目录如下。 一、创建 Block
创建 Block 文件创建 Block 结构体与相关函数
package core import ( crypto/sha256 encoding/hex time) type Block struct { Index int64 // 区块编号 Timestamp int64 // 区块时间戳 PrevBlochHash string // 上一个区块哈希值 Hash string // 当前区块哈希值 Data string // 区块数据
} // calculateHash 计算哈希值
func calculateHash(b Block) string { blockData : string(b.Index) string(b.Timestamp) b.PrevBlochHash b.Data hashInBytes : sha256.Sum256([]byte(blockData)) return hex.EncodeToString(hashInBytes[:])
} // GenerateNewBlock 创建新区块
func GenerateNewBlock(preBlock Block, data string) Block { newBlock : Block{} newBlock.Index preBlock.Index 1 newBlock.PrevBlochHash preBlock.Hash newBlock.Timestamp time.Now().Unix() newBlock.Data data newBlock.Hash calculateHash(newBlock) return newBlock
} // GenerateGenesisBlock 创建世纪区块
func GenerateGenesisBlock() Block { preBlock : Block{} preBlock.Index -1 preBlock.Hash return GenerateNewBlock(preBlock, Genesis Block)
}
这里需要注意的是在创建世纪区块时考虑到对 GenerateNewBlock 函数的复用因此创建了一个 preBlock 来辅助世纪块的创建实际区块链上世纪块前面不存在其他区块且世纪块以 0 作为索引。
二、创建 Blockchain
创建 Blockchain 文件创建 Blockchain 结构体及相关方法
package core import ( fmt log) type Blockchain struct { Blocks []*Block
} // CreateBlockchain 创建区块链
func CreateBlockchain() *Blockchain { genesisBlock : GenerateGenesisBlock() blockchain : Blockchain{} blockchain.AppendBlock(genesisBlock) return blockchain
} // SendData 向区块链添加数据
func (bc *Blockchain) SendData(data string) { preBlock : bc.Blocks[len(bc.Blocks)-1] newBlock : GenerateNewBlock(*preBlock, data) bc.AppendBlock(newBlock)
} // AppendBlock 向区块链添加新区块
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) } } // 判断新添加的区块是否合法
func isValid(newBlock Block, oldBlock Block) bool { if newBlock.Index-1 ! oldBlock.Index { return false } if newBlock.PrevBlochHash ! oldBlock.Hash { return false } if calculateHash(newBlock) ! newBlock.Hash { return false } return true
} // Print 对区块链上的区块内容进行打印
func (bc *Blockchain) Print() { for _, block : range bc.Blocks { fmt.Printf(Index: %d\n, block.Index) fmt.Printf(Prev.Hash: %s\n, block.PrevBlochHash) fmt.Printf(Curr.Hash: %s\n, block.Hash) fmt.Printf(Data: %s\n, block.Data) fmt.Printf(Timestamp: %d\n, block.Timestamp) }
}三、创建 Http server
创建 http server提供 API 访问接口
package main import ( blockchainDemo/core encoding/json io net/http) var blockchain *core.Blockchain func run() { http.HandleFunc(/blockchain/get, blockchainGetHandler) http.HandleFunc(/blockchain/write, blockchainWriteHandler) http.ListenAndServe(localhost:8888, nil)
} // 读接口
func blockchainGetHandler(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 blockchainWriteHandler(w http.ResponseWriter, r *http.Request) { blockData : r.URL.Query().Get(data) blockchain.SendData(blockData) blockchainGetHandler(w, r)
} func main() { blockchain core.CreateBlockchain() run()
}
四、模型测试
在 GoLand 上运行 http server从代码中可知监听端口为 8888因此读写操作对应的地址是
http://localhost:8888/blockchain/gethttp://localhost:8888/blockchain/write?dataSend 1 BTC to Me 参数 data 的内容可自定义 // 网页显示效果
{Blocks:[{Index:0,Timestamp:1674227301,PrevBlochHash:,Hash:90d7d6d9adc8a6dd4eca1e30d8c1a8556a8e3e508da81f30a9e520c2ee7124b0,Data:Genesis Block},{Index:1,Timestamp:1674227338,PrevBlochHash:90d7d6d9adc8a6dd4eca1e30d8c1a8556a8e3e508da81f30a9e520c2ee7124b0,Hash:1a7c54ce0eaba45d5591640925405d90e74d9da5fa919b4e6eefa2447b2a4fb0,Data:Send 1 BTC to Me}]
}